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}