How to specialize serde::deserialize for two different Formats?

I want to deserialize Vec<Rule>. But depending on the used Deserializer (e.g. Json or Postcard) I want to do it slightly different. For that I've created a new trait DeserializeRules which I would then specialize for the Special case and also provide a default impl for it. Unfortunately it doesnt work and yields a compiler error.

Is this one of the limitations of the feature(min_specialization) ?

Or is there a simpler approach to do per format serialization?

#![feature(min_specialization)]
use serde::de::Deserializer;
use serde::Deserialize;
use serde_json::de::StrRead;
use serde_json::Deserializer as JsonDeserializer;

#[derive(Deserialize)]
struct Rule;

pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Rule>, D::Error>
where
    D: Deserializer<'de>,
{
    deserializer.deserialize_rules()
}

trait DeserializeRules<'de>: Deserializer<'de> {
    fn deserialize_rules(self) -> Result<Vec<Rule>, Self::Error>;
}

impl<'de, D: Deserializer<'de>> DeserializeRules<'de> for D {
    default fn deserialize_rules(self) -> Result<Vec<Rule>, Self::Error> {
        todo!()
    }
}

impl<'de> DeserializeRules<'de> for &mut JsonDeserializer<StrRead<'de>> {
    fn deserialize_rules(self) -> Result<Vec<Rule>, Self::Error> {
        Vec::<Rule>::deserialize(self)
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error: specializing impl repeats parameter `'de`
  --> src/lib.rs:27:1
   |
27 | impl<'de> DeserializeRules<'de> for &mut JsonDeserializer<StrRead<'de>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: could not compile `playground` (lib) due to 1 previous error

You should probably consider using Deserializer::is_human_readable() to classify the deserializer instead of trying to muck about with specialization.

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.