serde_mobile/
lib.rs

1/*!
2This crate provides traits and an adapter for creating move-oriented sequence
3and map accessors, as a complement to the remaining serde deserializer traits,
4which are entirely move-oriented.
5
6It provides [`SeqAccess`], which replaces [`serde::de::SeqAccess`], and
7[`MapKeyAccess`] / [`MapValueAccess`], which collectively replace
8[`serde::de::MapAccess`]. These traits are often easier to use when
9implementing a [`Deserializer`][serde::de::Deserializer] if you're focused on
10using by-move constructs, and help ensure correctness for callers.
11
12In order to interoperate with serde, it also provides [`AccessAdapter`]. This
13struct takes any [`SeqAccess`] or [`MapKeyAccess`] type and converts it into
14a [`serde::de::SeqAccess`] or [`serde::de::MapAccess`].
15
16# Example
17
18In this example, we're interested in creating a deserializer that reads from
19an iterator of `(key, value)` pairs and emits them as a map. We create a a
20`KeyAccess` type, which implements [`MapKeyAccess`]. We use `serde-mobile`'s
21built-in [`SubordinateValue`] type as our [`MapValueAccess`], because we'll
22be using the common pattern where the iterator is stored by both the key and
23value accessor. This ends up being easier (if more verbose) to implement: a
24[`serde::de::MapAccess`] is a single type that needs to deserialize keys and
25values separately, and therefore needs some awkward design to capture the state
26where a key has been yielded but not a value. `serde-mobile`, on the other
27hand, splits this into a pair of types, so that only correct states can be
28expressed.
29```
30use std::collections::hash_map::{HashMap, IntoIter};
31use std::marker::PhantomData;
32use serde::de::{
33    IntoDeserializer,
34    Error,
35    DeserializeSeed,
36    value::{MapAccessDeserializer, Error as SimpleError},
37};
38use serde::Deserialize;
39use serde_mobile::{
40    MapKeyAccess,
41    MapValueAccess,
42    AccessAdapter,
43    SubordinateValue
44};
45
46struct KeyAccess<I, E>{
47    entries: I,
48    error: PhantomData<E>,
49}
50
51impl<I, K, V, E> KeyAccess<I, E>
52where
53    I: Iterator<Item=(K, V)>
54{
55    fn new<C>(collection: C) -> Self
56        where C: IntoIterator<IntoIter=I>
57    {
58        Self {
59            entries: collection.into_iter(),
60            error: PhantomData,
61        }
62    }
63}
64
65// MapKeyAccess is the key-getting equivalent of serde::de::MapAccess
66impl<'de, I, K, V, E> MapKeyAccess<'de> for KeyAccess<I, E>
67where
68    I: Iterator<Item=(K, V)>,
69    K: IntoDeserializer<'de, E>,
70    V: IntoDeserializer<'de, E>,
71    E: Error,
72{
73    type Error = E;
74    type Value = SubordinateValue<V::Deserializer, Self>;
75
76    // notice that next_key_seed takes self by move and returns Self::Value,
77    // which is a MapKeyAccess. This forces the caller to get a value before
78    // they can get another key.
79    fn next_key_seed<S>(mut self, seed: S) -> Result<Option<(S::Value, Self::Value)>, Self::Error>
80    where
81        S: DeserializeSeed<'de>
82    {
83        self.entries
84            .next()
85            .map(|(key, value)| {
86                seed
87                    .deserialize(key.into_deserializer())
88                    .map(|key| (
89                        key,
90                        SubordinateValue {
91                            value: value.into_deserializer(),
92                            parent: self
93                        }
94                    ))
95            })
96            .transpose()
97    }
98
99    fn size_hint(&self) -> Option<usize> {
100        match self.entries.size_hint() {
101            (min, Some(max)) if min == max => Some(min),
102            _ => None,
103        }
104    }
105}
106
107// Normally we'd have to create a separate struct to implement `MapValueAccess`,
108// but this pattern is common enough that serde-mobile provides a type called
109// `SubordinateValue` that handles this pattern for us.
110
111let serialized = HashMap::from([
112    ("a", 10),
113    ("b", 20),
114]);
115
116#[derive(Deserialize, Debug, PartialEq, Eq)]
117struct Data {
118    a: i32,
119    b: i32,
120}
121
122let seq_access = KeyAccess::new(serialized);
123
124// use an AccessAdapter to turn a serde-mobile access type
125// into a serde access type
126let deserializer = MapAccessDeserializer::new(AccessAdapter::new(seq_access));
127
128match Data::deserialize(deserializer) {
129    Ok(data) => assert_eq!(data, Data { a: 10, b: 20 }),
130    Err(err) => {
131        let err: SimpleError = err;
132        panic!("failed to deserialize")
133    }
134}
135```
136*/
137
138#![no_std]
139#![deny(missing_docs)]
140
141// mod visitor;
142
143use core::{convert::Infallible, marker::PhantomData, mem};
144
145use serde::de;
146
147/**
148Move-oriented version of [`serde::de::SeqAccess`].
149
150`next_value_seed`  takes `self` by move, and returns an `Option<(S::Value,
151Self)>`, ensuring that it's only possible to get another value if a previous
152call didn't return `None`.
153
154This trait otherwise is identical to its serde counterpart and serves the same
155purpose; see those docs for details.
156
157Use [`AccessAdapter`] to convert this type to a `serde::de::SeqAccess` to pass
158into [`visit_seq`][serde::de::Visitor::visit_seq].
159*/
160pub trait SeqAccess<'de>: Sized {
161    /**
162    The type that can be returned if an error occurs during deserialization.
163    */
164    type Error: de::Error;
165
166    /**
167    This returns `Ok(Some((value, access)))` for the next value in the
168    sequence, or `Ok(None)` if there are no more remaining items. The
169    returned `access` value can be used to read additional items from the
170    sequence.
171
172    The seed allows for passing data into a `Deserialize` implementation
173    at runtime; typically it makes more sense to call [`next_element`][Self::next_element].
174    */
175    fn next_element_seed<S>(self, seed: S) -> Result<Option<(S::Value, Self)>, Self::Error>
176    where
177        S: de::DeserializeSeed<'de>;
178
179    /**
180    This returns `Ok(Some((value, access)))` for the next value in the
181    sequence, or `Ok(None)` if there are no more remaining items. The
182    returned `access` value can be used to read additional items from the
183    sequence.
184    */
185    #[inline]
186    fn next_element<T>(self) -> Result<Option<(T, Self)>, Self::Error>
187    where
188        T: de::Deserialize<'de>,
189    {
190        self.next_element_seed(PhantomData)
191    }
192
193    /**
194    Returns the number of elements remaining in the sequence, if known.
195    */
196    #[inline]
197    fn size_hint(&self) -> Option<usize> {
198        None
199    }
200}
201
202/**
203Move-oriented version of [`serde::de::MapAccess`], for getting keys.
204
205This trait gets around a lot of the shortcomings of serde's `MapAccess` by
206using a move-oriented interface:
207
208- It's not possible to call [`next_key`][Self::next_key] after a previous call
209  to `next_key` returned `Ok(None)`.
210- Accessing the value associated with a key is moved to a different trait,
211  which is returned from [`next_key`][Self::next_key]. By splitting key-access
212  and value-access into different traits, we can ensure that `next_key` and
213  [`next_value`][MapValueAccess::next_value] can never be called out of order,
214  removing the need for potential panics (and the associated state tracking
215  between keys and values).
216
217This trait otherwise is identical to its serde counterpart and serves the same
218purpose; see those docs for details (though note that accessing values is
219handled separately through the [`MapValueAccess`] trait.)
220
221Use [`AccessAdapter`] to convert this type to a `serde::de::SeqAccess` to pass
222into [`visit_seq`][serde::de::Visitor::visit_seq].
223*/
224pub trait MapKeyAccess<'de>: Sized {
225    /**
226    The type that can be returned if an error occurs during deserialization.
227    */
228    type Error: de::Error;
229
230    /**
231    The value accessor associated with this key accessor. A call to
232    [`next_key`][Self::next_key] that returns a key will also return a `Value`
233    object, which can be used to retrieve the value associated with that key.
234    */
235    type Value: MapValueAccess<'de, Error = Self::Error, Key = Self>;
236
237    /**
238    This returns `Ok(Some((key, value_access)))` for the next key in the
239    map, or `Ok(None)` if there are no more entries. The returned
240    `value_access` object can be used to retrieve the value associated
241    with this key.
242
243    The seed allows for passing data into a `Deserialize` implementation
244    at runtime; typically it makes more sense to call [`next_key`][Self::next_key].
245    */
246    #[allow(clippy::type_complexity)]
247    fn next_key_seed<S>(self, seed: S) -> Result<Option<(S::Value, Self::Value)>, Self::Error>
248    where
249        S: de::DeserializeSeed<'de>;
250
251    /**
252    This returns `Ok(Some((key, value_access)))` for the next key in the
253    map, or `Ok(None)` if there are no more entries. The returned
254    `value_access` can be used to retrieve the value associated with this
255    key.
256    */
257    #[inline]
258    fn next_key<T>(self) -> Result<Option<(T, Self::Value)>, Self::Error>
259    where
260        T: de::Deserialize<'de>,
261    {
262        self.next_key_seed(PhantomData)
263    }
264
265    /**
266    This convenience method returns the Ok(Some(((key, value), access)))
267    for the next key-value pair in the map, or Ok(None) of there are no
268    remaining entries. The returned `access` object can be used to retrieve
269    the next entry in the map.
270
271    By default this calls [`next_key_seed`][Self::next_key_seed] followed by
272    [`next_value_seed`][MapValueAccess::next_value_seed]; implementors
273    should override it if a more efficient implementation is possible.
274
275    The seed allows for passing data into a `Deserialize` implementation
276    at runtime; typically it makes more sense to call [`next_entry`][Self::next_entry].
277    */
278    #[allow(clippy::type_complexity)]
279    fn next_entry_seed<K, V>(
280        self,
281        kseed: K,
282        vseed: V,
283    ) -> Result<Option<((K::Value, V::Value), Option<Self>)>, Self::Error>
284    where
285        K: de::DeserializeSeed<'de>,
286        V: de::DeserializeSeed<'de>,
287    {
288        self.next_key_seed(kseed)?
289            .map(|(key, value_access)| {
290                value_access
291                    .next_value_seed(vseed)
292                    .map(|(value, key_access)| ((key, value), key_access))
293            })
294            .transpose()
295    }
296
297    /**
298    This convenience method returns the Ok(Some(((key, value), access)))
299    for the next key-value pair in the map, or Ok(None) of there are no
300    remaining entries. The returned `access` object can be used to retrieve
301    the next entry in the map.
302    */
303    #[inline]
304    #[allow(clippy::type_complexity)]
305    fn next_entry<K, V>(self) -> Result<Option<((K, V), Option<Self>)>, Self::Error>
306    where
307        K: de::Deserialize<'de>,
308        V: de::Deserialize<'de>,
309        Self::Value: MapValueAccess<'de, Error = Self::Error>,
310    {
311        self.next_entry_seed(PhantomData, PhantomData)
312    }
313
314    /**
315    Returns the number of entries remaining in the map, if known.
316    */
317    #[inline]
318    fn size_hint(&self) -> Option<usize> {
319        None
320    }
321}
322
323/**
324Move-oriented version of [`serde::de::MapAccess`] for getting values associated
325with keys.
326
327A `MapValueAccess` object is returned alongside a `key` from a call to
328[`next_key`][MapKeyAccess::next_key], if the map wasn't empty. It can be used
329to retrieve the value associated with that key, and additionally returns a
330new [`MapKeyAccess`] that can be used to retrieve the next entry from the map.
331
332This trait otherwise is identical to its serde counterpart and serves the same
333purpose; see those docs for details (though note that accessing keys and entries
334is handled separately through the [`MapKeyAccess`] trait.)
335*/
336pub trait MapValueAccess<'de>: Sized {
337    /**
338    The type that can be returned if an error occurs during deserialization.
339    */
340    type Error: de::Error;
341
342    /**
343    The value accessor associated with this key accessor. A call to
344    [`next_value`][Self::next_value] will also return a `Key` object, which can
345    be used to retrieve the next key from the map.
346    */
347    type Key: MapKeyAccess<'de, Error = Self::Error, Value = Self>;
348
349    /**
350    This returns the next `value` from the map, associated with the
351    previously accessed key. It additionally returns an optional `key_access`
352    object which can be used to retrieve additional keys from the map, if any.
353
354    The seed allows for passing data into a `Deserialize` implementation
355    at runtime; typically it makes more sense to call [`next_value`][Self::next_value].
356    */
357
358    #[allow(clippy::type_complexity)]
359    fn next_value_seed<S>(self, seed: S) -> Result<(S::Value, Option<Self::Key>), Self::Error>
360    where
361        S: de::DeserializeSeed<'de>;
362
363    /**
364    This returns the next `value` from the map, associated with the
365    previously accessed key. It additionally returns an optional `key_access`
366    object which can be used to retrieve additional keys from the map, if any.
367    */
368    #[inline]
369    fn next_value<T>(self) -> Result<(T, Option<Self::Key>), Self::Error>
370    where
371        T: de::Deserialize<'de>,
372    {
373        self.next_value_seed(PhantomData)
374    }
375
376    /**
377    Returns the number of entries remaining in the map, if known. Note that,
378    because this returns the number of *entries*, the value associated with
379    this particular `MapValueAccess` should not be included.
380    */
381    #[inline]
382    fn size_hint(&self) -> Option<usize> {
383        None
384    }
385}
386
387/**
388Adapter type for converting the `serde-mobile` traits into serde's `&mut self`
389oriented traits. It uses an enum to track the state of the accessors.
390
391Because the underlying traits use a move-oriented interface to prevent calls
392after returning `None`, this object is guaranteed to be "fused", meaning that
393`next_key` or `next_element` will always continue return `None` when the
394underlying collection is exhausted.
395
396This type can be used for both [`serde::de::SeqAccess`] and
397[`serde::de::MapAccess`].
398*/
399#[derive(Debug, Clone)]
400pub enum AccessAdapter<T, V> {
401    /**
402    The `AccessAdapter` is ready to yield the next value from `K`. This is
403    the next `element` for `SeqAccess` or the next `key` for a `MapAccess`.
404    */
405    Ready(T),
406
407    /**
408    The `AccessAdapter` is ready to yield the `value` associated with a
409    recently yielded `key` for a `MapAccess`. `SeqAccess` adapters can never
410    be in this state.
411    */
412    Value(V),
413
414    /**
415    The `AccessAdapter` is empty; no more items will be yielded from it.
416    */
417    Done,
418}
419
420/**
421A [`SeqAccessAdapter`] is an [`AccessAdapter`] used as a [`de::SeqAccess`].
422It can never be in the [`Value`][AccessAdapter::Value] state.
423*/
424pub type SeqAccessAdapter<T> = AccessAdapter<T, Infallible>;
425
426impl<T, V> AccessAdapter<T, V> {
427    /**
428    Replace `self` with [`Done`][AccessAdapter::Done] and return the
429    original state.
430    */
431    fn take(&mut self) -> Self {
432        mem::replace(self, AccessAdapter::Done)
433    }
434
435    /**
436    Create a new `AccessAdapter`, suitable for use as the argument to
437    [`visit_seq`][de::Visitor::visit_seq] or [`visit_map`][de::Visitor::visit_map].
438    This should be created using a [`SeqAccess`] or [`MapKeyAccess`] object,
439    respectively.
440    */
441    pub fn new(access: T) -> Self {
442        Self::Ready(access)
443    }
444}
445
446/**
447Implementation of [`serde::de::SeqAccess`], using [`SeqAccess`]. An internal
448enum is used to track the
449*/
450impl<'de, S> de::SeqAccess<'de> for AccessAdapter<S, Infallible>
451where
452    S: SeqAccess<'de>,
453{
454    type Error = S::Error;
455
456    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
457    where
458        T: de::DeserializeSeed<'de>,
459    {
460        match self.take() {
461            AccessAdapter::Ready(seq) => seq.next_element_seed(seed).map(|opt| {
462                opt.map(|(value, seq)| {
463                    *self = AccessAdapter::Ready(seq);
464                    value
465                })
466            }),
467            AccessAdapter::Value(inf) => match inf {},
468            AccessAdapter::Done => Ok(None),
469        }
470    }
471
472    fn size_hint(&self) -> Option<usize> {
473        match *self {
474            AccessAdapter::Ready(ref seq) => seq.size_hint(),
475            AccessAdapter::Value(inf) => match inf {},
476            AccessAdapter::Done => Some(0),
477        }
478    }
479}
480
481impl<'de, A> de::MapAccess<'de> for AccessAdapter<A, A::Value>
482where
483    A: MapKeyAccess<'de>,
484{
485    type Error = A::Error;
486
487    #[inline]
488    fn next_key_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>, Self::Error>
489    where
490        S: de::DeserializeSeed<'de>,
491    {
492        match self.take() {
493            AccessAdapter::Ready(access) => access.next_key_seed(seed).map(|opt| {
494                opt.map(|(key, value_access)| {
495                    *self = AccessAdapter::Value(value_access);
496                    key
497                })
498            }),
499            AccessAdapter::Value(_access) => panic!("called next_key_seed out of order"),
500            AccessAdapter::Done => Ok(None),
501        }
502    }
503
504    #[inline]
505    fn next_value_seed<S>(&mut self, seed: S) -> Result<S::Value, Self::Error>
506    where
507        S: de::DeserializeSeed<'de>,
508    {
509        match self.take() {
510            AccessAdapter::Ready(_access) => panic!("called next_value_seed out of order"),
511            AccessAdapter::Value(access) => {
512                access.next_value_seed(seed).map(|(value, key_access)| {
513                    if let Some(key_access) = key_access {
514                        *self = AccessAdapter::Ready(key_access)
515                    }
516                    value
517                })
518            }
519            AccessAdapter::Done => panic!("called next_value_seed out of order"),
520        }
521    }
522
523    fn next_entry_seed<K, V>(
524        &mut self,
525        key: K,
526        value: V,
527    ) -> Result<Option<(K::Value, V::Value)>, Self::Error>
528    where
529        K: de::DeserializeSeed<'de>,
530        V: de::DeserializeSeed<'de>,
531    {
532        match self.take() {
533            AccessAdapter::Ready(access) => access.next_entry_seed(key, value).map(|opt| {
534                opt.map(|(entry, access)| {
535                    if let Some(access) = access {
536                        *self = AccessAdapter::Ready(access)
537                    }
538                    entry
539                })
540            }),
541            AccessAdapter::Value(_access) => panic!("called next_entry_seed out of order"),
542            AccessAdapter::Done => Ok(None),
543        }
544    }
545
546    #[inline]
547    fn size_hint(&self) -> Option<usize> {
548        match *self {
549            AccessAdapter::Ready(ref access) => access.size_hint(),
550            AccessAdapter::Value(ref access) => access.size_hint(),
551            AccessAdapter::Done => Some(0),
552        }
553    }
554}
555
556/// Utility type implementing [`MapValueAccess`] for the common case where a
557/// value-access type consists only of a deserializable value, along with the
558/// original [`MapKeyAccess`] type that produced it, which will be returned
559/// after the value is consumed.
560///
561/// See the [crate docs][crate] for an example.
562#[derive(Debug, Clone)]
563pub struct SubordinateValue<V, K> {
564    /// The value that will be deserialized in `next_value_seed`.
565    pub value: V,
566
567    /// The [`MapKeyAccess`] object that will be returned along with `value`,
568    /// after it was deserialized. Usually this will be the same object that
569    /// created this [`SubordinateValue`] in the first place.
570    pub parent: K,
571}
572
573impl<'de, K, V> MapValueAccess<'de> for SubordinateValue<V, K>
574where
575    V: de::Deserializer<'de>,
576    K: MapKeyAccess<'de, Value = Self, Error = V::Error>,
577{
578    type Error = V::Error;
579    type Key = K;
580
581    fn next_value_seed<S>(self, seed: S) -> Result<(S::Value, Option<Self::Key>), Self::Error>
582    where
583        S: de::DeserializeSeed<'de>,
584    {
585        seed.deserialize(self.value)
586            .map(|value| (value, Some(self.parent)))
587    }
588
589    fn size_hint(&self) -> Option<usize> {
590        self.parent.size_hint()
591    }
592}