serde-persistent-deserializer 0.1.0

A wrapper for persistent Serde deserializers
Documentation
  • Coverage
  • 100%
    7 out of 7 items documented0 out of 7 items with examples
  • Size
  • Source code size: 19.09 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 734.85 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 14s Average build duration of successful builds.
  • all releases: 16s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • fjarri/serde-persistent-deserializer
    0 0 3
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • fjarri

A wrapper for persistent serde deserializers

crate Docs License Build Status Coverage

When one writes an implementation of serde::Deserializer for their format, it is commonly written for a &mut of some type, or a wrapper of it --- because it has to be recursively passed down when deserializing nested structs, lists, and so on.

But if someone else wants to be generic over types that implement Deserializer (e.g. when using the erased-serde crate), it necessarily produces higher-ranked bounds on lifetimes (something along the lines of for<'a, 'de> &'a mut D: Deserializer<'de>), which cannot be encapsulated in a trait and will be propagated to all dependent generic code (a current limitation of Rust; see https://github.com/rust-lang/rust/issues/50346 and other related issues). Also, using erased_serde::Deserializer::erase on serde::Deserializer types in a real world code is not trivial (see https://github.com/dtolnay/erased-serde/issues/107 for an example).

To amend that, it would be convenient to additionally implement serde::Deserializer on the object itself, which involves writing a long sheet of boilerplate like

struct MyDeserializerRef<'a, 'de> {
    de: &'a mut MyDeserializer<'de>
}

impl<'a, 'de> Deserializer<'de> for MyDeserializerRef<'a, 'de> {
    // ... actual deserialization logic here
}

impl<'de> MyDeserializer<'de> {
    fn as_mut_deserializer<'a>(&'a mut self) -> MyDeserializerRef<'a, 'de> { ... }
}

impl<'de> Deserializer<'de> for MyDeserializer<'de> {
    fn deserialize_any<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error>
    {
        self.as_mut_deserializer().deserialize_any(visitor)
    }

    fn deserialize_bool<V: Visitor<'de>>(mut self, visitor: V) -> Result<V::Value, Self::Error>
    {
        self.as_mut_deserializer().deserialize_bool(visitor)
    }

    // ... and dozens more methods with the same content
}

This crate instead requires one to only provide an implementation of [AsMutDeserializer] for their type, and then the [PersistentDeserializer] wrapper will automatically derive serde::Deserializer.