Is there a way to implement a trait's generic function, binding a generic parameter to a specific type

Given the function definition in serde::de::Deserialize:

    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>;

Is there a way to implement that, "forcing" the incoming Deserializer to be a specific implementing type (and thus have access to that type's non-trait methods)?

1 Like

(not a contribution)

I find this disproportionately funny. std::thread::spawn is also a good one.

4 Likes

There isn't a way to do that because the caller, not the implementer, decides what types the generic parameters get assigned. Why exactly do you need to know what type the deserializer is?

2 Likes

Well, there is this one weird trick that doctors don't want you to know about, where you downcast a reference to Any, buy it requires the type to not have any non-'static references (i.e. D: 'static). I doubt it's going to work here.

An actually good solution depends on what you want to do, as mentioned.

Yeah, always better to say what I REALLY want than to try and second guess the implementation, eh :slight_smile:

OK... What I have is an existing library that kinda does a double-deserialization that uses serde_json - I'm trying to improve it and make it work properly with simd_json.

The "toplevel" deserialization is done like this...

serde_json::from_str(s).map(AnEnum::into)

AnEnum implements Deserialize. In the deserialize method the first thing it does is this...

        let raw_value: Box<RawValue> = Box::deserialize(deserializer)?;
        let data = raw_value.get();

Then it does a bunch of trial and error

serde_json::from_str(s).map(Whatever.into) //or similar

until one works, which it then uses to return the appropriate variant of AnEnum.

That has two problems ... it's "ugly" (trial an error) AND there's something about simd_json that does not play well with serde_json RawValue (issue logged).

So, what I'm trying to do is have roughly the same approach, but get some kind of minimal interrogable structure out of the deserializer, look for type determinants in that structure, then, based upon the determinant found, directly invoke the second deserialize from that structure to the target type.

serde_json Values work but they are expensive to create - using them runs considerably slower than the RawValue approach (albeit that they work with simd_json - but with no speed up).

Sooooo - simd_json has a "Tape" - a simple structured deserialization that is neither a DOM Value nor a target Type. BUT the only way I can see of turning a Deserializer into a Tape is the to_tape method on the simd_json Deserializer struct.

So I was looking for a way to "know/tell" that the incoming deserializer in the AnEnum deserialize method is, in fact, a simd_json Deserializer. (It's another question, how to take the Tape as input for the next deserialization - but that's for another day).

If it isn't at all possible I do have the option of making deeper cuts to the original library and eliminating the Deserialize semantics of AnEnum - it's all private anyway - it's just that I'm trying to implement a feature that switches out serde_json for simd_json and so my first attempts are trying to keep basically the same code approach.

The closest I've got is an extension trait with a default implementation - but it appears that the default implementation is always called.

Any help would be appreciated.

If AnEnum implements Deserialize, what is the need for the map call? Wouldn't it be better to produce AnEnum directly from the Deserialize call?

If this is all in the Deserialize implementation, then it is definitely doing something odd, because using serde_json there is assuming the format of the serialized data to be JSON. At that point you've moved outside serde's normal use case of making type-agnostic serializers and deserializers, so you could just call serde_json's functions to get a Value or RawValue and work with it outside of any Deserialize implementation.

What is the reason for using this double deserialization approach?

Yeah it's doin 'something odd'... But that bit's not under my control...

In the end I discovered DeserializeSeed and it was exactly what I needed.

Thanks for the response

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.