serde_tagged/de/adj/tuple.rs
1//! Deserialization of adjacently tagged values using tuples.
2//!
3//! See [`ser::adj::tuple`](::ser::adj::tuple) for a description of this tagging
4//! format.
5
6use de::seed::SeedFactory;
7
8use std::fmt;
9use std::marker::PhantomData;
10
11use serde;
12
13
14/// Deserialize a tuple-based adjacently tagged value.
15///
16/// The deserializer controls the underlying data format while the seed-factory
17/// specifies the instructions (depending on the tag) on how the value should be
18/// deserialized.
19///
20/// See [`de`](::de) for more information on
21/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
22///
23/// See [`deserialize_seed`](deserialize_seed) for a version that allows you to
24/// pass a `DeserializeSeed` implementation to deserialize the tag. This version
25/// is equivalent to `deserialize_seed(deserializer, seed_factory,
26/// PhantomData<T>)`
27pub fn deserialize<'de, T, D, F>(deserializer: D, seed_factory: F) -> Result<F::Value, D::Error>
28where
29 T: serde::Deserialize<'de>,
30 D: serde::Deserializer<'de>,
31 F: SeedFactory<'de, T>,
32{
33 deserialize_seed(deserializer, seed_factory, PhantomData::<T>)
34}
35
36
37/// Deserialize a tuple-based adjacently tagged value with the given tag-seed.
38///
39/// The deserializer controls the underlying data format while the seed-factory
40/// specifies the instructions (depending on the tag) on how the value should be
41/// deserialized.
42///
43/// See [`de`](::de) for more information on
44/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
45pub fn deserialize_seed<'de, D, F, S>(
46 deserializer: D,
47 seed_factory: F,
48 tag_seed: S,
49) -> Result<F::Value, D::Error>
50where
51 D: serde::Deserializer<'de>,
52 F: SeedFactory<'de, S::Value>,
53 S: serde::de::DeserializeSeed<'de>,
54{
55 deserializer.deserialize_tuple(2, Visitor::new(seed_factory, tag_seed))
56}
57
58
59/// A visitor that can be used to deserialize a tuple-based adjacently tagged
60/// value.
61///
62/// This visitor handles a tuple-based adjacently tagged value, which is
63/// represented by a tuple containing exactly two elements. The first element of
64/// this tuple is the tag, the second element the value. Thus this visitor will
65/// return an error if the visited type is not a tuple (i.e. sequence) with two
66/// elements.
67///
68/// The [`SeedFactory`](::de::SeedFactory) provided to this visitor
69/// provides a `serde::de::DeserializeSeed` implementation depending on the tag,
70/// which then determines how the value is going to be deserialized.
71///
72/// See [`de`](::de) for more information on
73/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
74pub struct Visitor<F, S> {
75 seed_factory: F,
76 tag_seed: S,
77}
78
79impl<F, S> Visitor<F, S> {
80 /// Creates a new visitor with the given
81 /// [`SeedFactory`](::de::SeedFactory).
82 pub fn new(seed_factory: F, tag_seed: S) -> Self {
83 Visitor {
84 seed_factory,
85 tag_seed,
86 }
87 }
88}
89
90impl<'de, F, S> serde::de::Visitor<'de> for Visitor<F, S>
91where
92 F: SeedFactory<'de, S::Value>,
93 S: serde::de::DeserializeSeed<'de>,
94{
95 type Value = F::Value;
96
97 fn expecting(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
98 write!(fmtr, "a tuple with exactly two elements")
99 }
100
101 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
102 where
103 A: serde::de::SeqAccess<'de>,
104 {
105 use serde::de::Error;
106
107 // try to validate the length
108 match seq.size_hint() {
109 Some(n) if n != 2 => Err(Error::invalid_length(n, &self))?,
110 _ => {},
111 }
112
113 let tag = seq.next_element_seed(self.tag_seed)?
114 .ok_or_else(|| Error::invalid_length(0, &"a tuple with exactly two elements"))?;
115
116 seq.next_element_seed(self.seed_factory.seed(tag)?)?
117 .ok_or_else(|| Error::invalid_length(1, &"a tuple with exactly two elements"))
118 }
119}