Skip to content

Usage: creating a type-erased "deserializer factory" #107

@fjarri

Description

@fjarri

I have a method in an object-safe trait whose implementation looks generally something like

impl State for MyState {
    fn receive(&self, deserializer: &MyDeserializer, bytes1: &[u8], bytes2: &[u8]) {
        let message1 = deserializer.deserialize::<Message1>(bytes1);
        let message2 = deserializer.deserialize::<Message2>(bytes2);
        // ...
    }
}

In the public API, the user only has Box<dyn State> without knowing the specific type. I want to be able to let the user select the format used by MyDeserializer by supplying some implementation of a trait like

trait DeserializerFactory<'de>
where 
    &'de mut Self::Des: serde::Deserializer<'de>
{
    type Des: 'de;
    fn make_deserializer(bytes: &'de [u8]) -> Self::Des;
}

and the intermediate layer wrapping it into some form of Box<dyn erased_serde::Deserializer>, so that I could use erased_serde::deserialize with it, somewhere within the call to MyDeserializer::deserialize.

The problem is, I can't figure out how to do that. Deserializers returned by the libraries, e.g. serde_json do not implement serde::Deserializer themselves, only their &mut references do. So I can't just wrap what I get from make_deserializer() into Box<dyn erased_serde::Deserializer>, I need to somehow keep the original object and get a mut reference out of it, and the original object must be boxed as well since an object-safe trait doesn't know the concrete type in advance. I experimented with implementations, but keep getting stuck in lifetime errors. Any idea on how it can be implemented, if it can be implemented at all?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions