Expand description
This crate provides traits and an adapter for creating move-oriented sequence and map accessors, as a complement to the remaining serde deserializer traits, which are entirely move-oriented.
It provides SeqAccess, which replaces serde::de::SeqAccess, and
MapKeyAccess / MapValueAccess, which collectively replace
serde::de::MapAccess. These traits are often easier to use when
implementing a Deserializer if you’re focused on
using by-move constructs, and help ensure correctness for callers.
In order to interoperate with serde, it also provides AccessAdapter. This
struct takes any SeqAccess or MapKeyAccess type and converts it into
a serde::de::SeqAccess or serde::de::MapAccess.
§Example
In this example, we’re interested in creating a deserializer that reads from
an iterator of (key, value) pairs and emits them as a map. We create a a
KeyAccess type, which implements MapKeyAccess. We use serde-mobile’s
built-in SubordinateValue type as our MapValueAccess, because we’ll
be using the common pattern where the iterator is stored by both the key and
value accessor. This ends up being easier (if more verbose) to implement: a
serde::de::MapAccess is a single type that needs to deserialize keys and
values separately, and therefore needs some awkward design to capture the state
where a key has been yielded but not a value. serde-mobile, on the other
hand, splits this into a pair of types, so that only correct states can be
expressed.
use std::collections::hash_map::{HashMap, IntoIter};
use std::marker::PhantomData;
use serde::de::{
IntoDeserializer,
Error,
DeserializeSeed,
value::{MapAccessDeserializer, Error as SimpleError},
};
use serde::Deserialize;
use serde_mobile::{
MapKeyAccess,
MapValueAccess,
AccessAdapter,
SubordinateValue
};
struct KeyAccess<I, E>{
entries: I,
error: PhantomData<E>,
}
impl<I, K, V, E> KeyAccess<I, E>
where
I: Iterator<Item=(K, V)>
{
fn new<C>(collection: C) -> Self
where C: IntoIterator<IntoIter=I>
{
Self {
entries: collection.into_iter(),
error: PhantomData,
}
}
}
// MapKeyAccess is the key-getting equivalent of serde::de::MapAccess
impl<'de, I, K, V, E> MapKeyAccess<'de> for KeyAccess<I, E>
where
I: Iterator<Item=(K, V)>,
K: IntoDeserializer<'de, E>,
V: IntoDeserializer<'de, E>,
E: Error,
{
type Error = E;
type Value = SubordinateValue<V::Deserializer, Self>;
// notice that next_key_seed takes self by move and returns Self::Value,
// which is a MapKeyAccess. This forces the caller to get a value before
// they can get another key.
fn next_key_seed<S>(mut self, seed: S) -> Result<Option<(S::Value, Self::Value)>, Self::Error>
where
S: DeserializeSeed<'de>
{
self.entries
.next()
.map(|(key, value)| {
seed
.deserialize(key.into_deserializer())
.map(|key| (
key,
SubordinateValue {
value: value.into_deserializer(),
parent: self
}
))
})
.transpose()
}
fn size_hint(&self) -> Option<usize> {
match self.entries.size_hint() {
(min, Some(max)) if min == max => Some(min),
_ => None,
}
}
}
// Normally we'd have to create a separate struct to implement `MapValueAccess`,
// but this pattern is common enough that serde-mobile provides a type called
// `SubordinateValue` that handles this pattern for us.
let serialized = HashMap::from([
("a", 10),
("b", 20),
]);
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct Data {
a: i32,
b: i32,
}
let seq_access = KeyAccess::new(serialized);
// use an AccessAdapter to turn a serde-mobile access type
// into a serde access type
let deserializer = MapAccessDeserializer::new(AccessAdapter::new(seq_access));
match Data::deserialize(deserializer) {
Ok(data) => assert_eq!(data, Data { a: 10, b: 20 }),
Err(err) => {
let err: SimpleError = err;
panic!("failed to deserialize")
}
}Structs§
- Subordinate
Value - Utility type implementing
MapValueAccessfor the common case where a value-access type consists only of a deserializable value, along with the originalMapKeyAccesstype that produced it, which will be returned after the value is consumed.
Enums§
- Access
Adapter - Adapter type for converting the
serde-mobiletraits into serde’s&mut selforiented traits. It uses an enum to track the state of the accessors.
Traits§
- MapKey
Access - Move-oriented version of
serde::de::MapAccess, for getting keys. - MapValue
Access - Move-oriented version of
serde::de::MapAccessfor getting values associated with keys. - SeqAccess
- Move-oriented version of
serde::de::SeqAccess.
Type Aliases§
- SeqAccess
Adapter - A
SeqAccessAdapteris anAccessAdapterused as ade::SeqAccess. It can never be in theValuestate.