serde_tagged/de/adj/
map.rs

1//! Deserialization of adjacently tagged values using maps.
2//!
3//! See [`ser::adj::map`](::ser::adj::map) for a description of this tagging
4//! format.
5//!
6//! # Warning
7//!
8//! If the deserialization-process depends on the tag (i.e. with
9//! [`deserialize`](deserialize) and/or [`Visitor`](Visitor)),
10//! deserialization of map-based adjacently tagged values is only supported for
11//! self-describing formats.
12
13use de::seed::SeedFactory;
14use util::de::content::{Content, ContentDeserializer};
15
16use std;
17use std::marker::PhantomData;
18
19use serde;
20
21
22/// Deserialize a map-based adjacently tagged value.
23///
24/// The deserializer controls the underlying data format while the seed-factory
25/// specifies the instructions (depending on the tag) on how the value should be
26/// deserialized.
27///
28/// See [`de`](::de) for more information on
29/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
30///
31/// See [`deserialize_seed`](deserialize_seed) for a version that allows you to
32/// pass a `DeserializeSeed` implementation to deserialize the tag. This version
33/// is equivalent to `deserialize_seed(deserializer, seed_factory,
34/// PhantomData<T>)`
35///
36/// # Note
37///
38/// If you do not need to choose a specific deserialization-method based on the
39/// tag, you should prefer [`deserialize_known`](deserialize_known) to this
40/// method.
41pub fn deserialize<'de, 'k, T, K, Kc: ?Sized, D, F>(
42    deserializer: D,
43    tag_key: &'k Kc,
44    value_key: &'k Kc,
45    seed_factory: F,
46) -> Result<F::Value, D::Error>
47where
48    T: serde::Deserialize<'de>,
49    D: serde::Deserializer<'de>,
50    F: SeedFactory<'de, T>,
51    K: serde::Deserialize<'de>,
52    K: std::cmp::PartialEq<&'k Kc>,
53{
54    deserialize_seed::<K, _, _, _, _>(
55        deserializer,
56        tag_key,
57        value_key,
58        seed_factory,
59        PhantomData::<T>,
60    )
61}
62
63
64/// Deserialize a map-based adjacently tagged value with the given tag-seed.
65///
66/// The deserializer controls the underlying data format while the seed-factory
67/// specifies the instructions (depending on the tag) on how the value should be
68/// deserialized.
69///
70/// See [`de`](::de) for more information on
71/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
72///
73/// # Note
74///
75/// If you do not need to choose a specific deserialization-method based on the
76/// tag, you should prefer [`deserialize_known_seed`](deserialize_known_seed) to
77/// this method.
78pub fn deserialize_seed<'de, 'k, K, Kc: ?Sized, D, F, S>(
79    deserializer: D,
80    tag_key: &'k Kc,
81    value_key: &'k Kc,
82    seed_factory: F,
83    tag_seed: S,
84) -> Result<F::Value, D::Error>
85where
86    D: serde::Deserializer<'de>,
87    F: SeedFactory<'de, S::Value>,
88    S: serde::de::DeserializeSeed<'de>,
89    K: serde::Deserialize<'de>,
90    K: std::cmp::PartialEq<&'k Kc>,
91{
92    deserializer.deserialize_map(Visitor::<K, _, _, _>::new(
93        tag_key,
94        value_key,
95        seed_factory,
96        tag_seed,
97    ))
98}
99
100
101/// A visitor that can be used to deserialize a map-based adjacently tagged
102/// value.
103///
104/// This visitor handles a map-based adjacently tagged value, which is
105/// represented by a map containing exactly two entries. One entry of this tuple
106/// is a mapping from tag-key to tag, the other entry contains a mapping from
107/// value-key to value. Thus this visitor will return an error if the visited
108/// type is not a map with two entries.
109///
110/// The [`SeedFactory`](::de::SeedFactory) provided to this visitor
111/// provides a `serde::de::DeserializeSeed` implementation depending on the tag,
112/// which then determines how the value is going to be deserialized.
113///
114/// See [`de`](::de) for more information on
115/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
116///
117/// # Note
118///
119/// If you do not need to choose a specific deserialization-method based on the
120/// tag, you should prefer [`KnownVisitor`](KnownVisitor) to this visitor.
121pub struct Visitor<'a, K, Kc: ?Sized + 'a, F, S> {
122    seed_factory: F,
123    tag_seed:     S,
124    tag_key:      &'a Kc,
125    value_key:    &'a Kc,
126    _phantom_k:   PhantomData<K>,
127}
128
129impl<'a, K, Kc: ?Sized, F, S> Visitor<'a, K, Kc, F, S> {
130    /// Creates a new visitor with the given
131    /// [`SeedFactory`](::de::SeedFactory), tag-key and value-key.
132    pub fn new(tag_key: &'a Kc, value_key: &'a Kc, seed_factory: F, tag_seed: S) -> Self {
133        Visitor {
134            seed_factory,
135            tag_seed,
136            tag_key,
137            value_key,
138            _phantom_k: PhantomData,
139        }
140    }
141}
142
143impl<'de, 'a, K, Kc: ?Sized, F, S> serde::de::Visitor<'de> for Visitor<'a, K, Kc, F, S>
144where
145    K: serde::Deserialize<'de>,
146    K: std::cmp::PartialEq<&'a Kc>,
147    F: SeedFactory<'de, S::Value>,
148    S: serde::de::DeserializeSeed<'de>,
149{
150    type Value = F::Value;
151
152    fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
153        write!(fmt, "a map with exactly two entries")
154    }
155
156    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
157    where
158        A: serde::de::MapAccess<'de>,
159    {
160        use serde::de::DeserializeSeed;
161        use serde::de::Error;
162
163        // try to validate the length
164        match map.size_hint() {
165            Some(n) if n != 2 => Err(Error::invalid_length(n, &self))?,
166            _ => {},
167        }
168
169        let key_1 = map.next_key_seed(KeySeed::<_, K>::new(self.tag_key, self.value_key))?
170            .ok_or_else(|| Error::invalid_length(0, &self))?;
171
172        // if first key is for tag: directly deserialize value
173        if key_1 == Key::Tag {
174            let tag = map.next_value_seed(self.tag_seed)?;
175
176            let value_key = map.next_key_seed(KeySeed::<_, K>::new(self.tag_key, self.value_key))?
177                .ok_or_else(|| Error::invalid_length(1, &"a map with exactly two entries"))?;
178
179            if value_key == Key::Value {
180                map.next_value_seed(self.seed_factory.seed(tag)?)
181            } else {
182                Err(Error::custom("duplicate tag-key"))
183            }
184
185        // if first key is for value: cache value
186        } else {
187            let value: Content = map.next_value()?;
188
189            let tag_key = map.next_key_seed(KeySeed::<_, K>::new(self.tag_key, self.value_key))?
190                .ok_or_else(|| Error::invalid_length(1, &self))?;
191
192            let tag = if tag_key == Key::Tag {
193                map.next_value_seed(self.tag_seed)
194            } else {
195                Err(Error::custom("duplicate value-key"))
196            }?;
197
198            let de = ContentDeserializer::new(value);
199            self.seed_factory.seed(tag)?.deserialize(de)
200        }
201    }
202}
203
204
205/// Deserialize a map-based adjacently tagged value of known type.
206///
207/// The deserializer controls the underlying data format while the seed-factory
208/// specifies the instructions (depending on the tag) on how the value should be
209/// deserialized.
210///
211/// See [`de`](::de) for more information on
212/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
213///
214/// See [`deserialize_known_seed`](deserialize_known_seed) for a version that
215/// allows you to pass `DeserializeSeed` implementations to deserialize the tag
216/// and value. This version is equivalent to
217/// `deserialize_known_seed(deserializer, seed_factory, PhantomData<T>,
218/// PhantomData<V>)`
219///
220/// # Note
221///
222/// If you do not need to choose a specific deserialization-method based on the
223/// tag, you should prefer this method to [`deserialize`](deserialize).
224pub fn deserialize_known<'de, 'a, T, V, K, Kc: ?Sized, D>(
225    deserializer: D,
226    tag_key: &'a Kc,
227    value_key: &'a Kc,
228) -> Result<(T, V), D::Error>
229where
230    T: serde::Deserialize<'de>,
231    V: serde::Deserialize<'de>,
232    D: serde::Deserializer<'de>,
233    K: serde::Deserialize<'de>,
234    K: std::cmp::PartialEq<&'a Kc>,
235{
236    deserialize_known_seed::<K, _, _, _, _>(
237        deserializer,
238        tag_key,
239        value_key,
240        PhantomData::<T>,
241        PhantomData::<V>,
242    )
243}
244
245
246/// Deserialize a map-based adjacently tagged value of known type with the given seeds.
247///
248/// The deserializer controls the underlying data format while the seed-factory
249/// specifies the instructions (depending on the tag) on how the value should be
250/// deserialized.
251///
252/// See [`de`](::de) for more information on
253/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
254///
255/// # Note
256///
257/// If you do not need to choose a specific deserialization-method based on the
258/// tag, you should prefer this method to
259/// [`deserialize_known`](deserialize_known).
260pub fn deserialize_known_seed<'de, 'a, K, Kc: ?Sized, D, T, V>(
261    deserializer: D,
262    tag_key: &'a Kc,
263    value_key: &'a Kc,
264    tag_seed: T,
265    value_seed: V,
266) -> Result<(T::Value, V::Value), D::Error>
267where
268    T: serde::de::DeserializeSeed<'de>,
269    V: serde::de::DeserializeSeed<'de>,
270    D: serde::Deserializer<'de>,
271    K: serde::Deserialize<'de>,
272    K: std::cmp::PartialEq<&'a Kc>,
273{
274    deserializer.deserialize_map(KnownVisitor::<K, _, _, _>::new(
275        tag_seed,
276        value_seed,
277        tag_key,
278        value_key,
279    ))
280}
281
282
283/// A visitor that can be used to deserialize a map-based adjacently tagged
284/// value of known type.
285///
286/// This visitor handles a map-based adjacently tagged value, which is
287/// represented by a map containing exactly two entries. One entry of this tuple
288/// is a mapping from tag-key to tag, the other entry contains a mapping from
289/// value-key to value. Thus this visitor will return an error if the visited
290/// type is not a map with two entries.
291///
292/// This visitor is intended for use of known values, i.e. when no tag-specific
293/// deserialization mehtod is required. Thus it does not need to cache values
294/// which can improve the performance.
295///
296/// # Note
297///
298/// If you do not need to choose a specific deserialization-method based on the
299/// tag, you should prefer this visitor to [`Visitor`](Visitor).
300pub struct KnownVisitor<'a, K, Kc: ?Sized + 'a, T, V> {
301    tag_seed:   T,
302    value_seed: V,
303    tag_key:    &'a Kc,
304    value_key:  &'a Kc,
305    _phantom_k: PhantomData<K>,
306}
307
308impl<'a, K, Kc: ?Sized, T, V> KnownVisitor<'a, K, Kc, T, V> {
309    /// Creates a new visitor with the given tag-key and value-key.
310    pub fn new(tag_seed: T, value_seed: V, tag_key: &'a Kc, value_key: &'a Kc) -> Self {
311        KnownVisitor {
312            tag_seed,
313            value_seed,
314            tag_key,
315            value_key,
316            _phantom_k: PhantomData,
317        }
318    }
319}
320
321impl<'de, 'a, K, Kc: ?Sized, T, V> serde::de::Visitor<'de> for KnownVisitor<'a, K, Kc, T, V>
322where
323    T: serde::de::DeserializeSeed<'de>,
324    V: serde::de::DeserializeSeed<'de>,
325    K: serde::Deserialize<'de>,
326    K: std::cmp::PartialEq<&'a Kc>,
327{
328    type Value = (T::Value, V::Value);
329
330    fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
331        write!(fmt, "a map with exactly two entries")
332    }
333
334    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
335    where
336        A: serde::de::MapAccess<'de>,
337    {
338        use serde::de::Error;
339
340        // try to validate the length
341        match map.size_hint() {
342            Some(n) if n != 2 => Err(Error::invalid_length(n, &self))?,
343            _ => {},
344        }
345
346        let key_1 = map.next_key_seed(KeySeed::<_, K>::new(self.tag_key, self.value_key))?
347            .ok_or_else(|| Error::invalid_length(0, &self))?;
348
349        if key_1 == Key::Tag {
350            let tag = map.next_value_seed(self.tag_seed)?;
351
352            let value_key = map.next_key_seed(KeySeed::<_, K>::new(self.tag_key, self.value_key))?
353                .ok_or_else(|| Error::invalid_length(1, &"a map with exactly two entries"))?;
354
355            if value_key == Key::Value {
356                Ok((tag, map.next_value_seed(self.value_seed)?))
357            } else {
358                Err(Error::custom("duplicate tag-key"))
359            }
360        } else {
361            let value = map.next_value_seed(self.value_seed)?;
362
363            let tag_key = map.next_key_seed(KeySeed::<_, K>::new(self.tag_key, self.value_key))?
364                .ok_or_else(|| Error::invalid_length(1, &"a map with exactly two entries"))?;
365
366            if tag_key == Key::Tag {
367                Ok((map.next_value_seed(self.tag_seed)?, value))
368            } else {
369                Err(Error::custom("duplicate value-key"))
370            }
371        }
372    }
373}
374
375
376#[derive(PartialEq)]
377enum Key {
378    Tag,
379    Value,
380}
381
382
383struct KeySeed<'a, Kc: ?Sized + 'a, Kd> {
384    tag_key:     &'a Kc,
385    value_key:   &'a Kc,
386    _phantom_kd: std::marker::PhantomData<Kd>,
387}
388
389impl<'a, Kc: ?Sized, Kd> KeySeed<'a, Kc, Kd> {
390    fn new(tag_key: &'a Kc, value_key: &'a Kc) -> Self {
391        KeySeed {
392            tag_key:     tag_key,
393            value_key:   value_key,
394            _phantom_kd: std::marker::PhantomData,
395        }
396    }
397}
398
399impl<'de, 'a, Kc: ?Sized, Kd> serde::de::DeserializeSeed<'de> for KeySeed<'a, Kc, Kd>
400where
401    Kd: serde::de::Deserialize<'de>,
402    Kd: std::cmp::PartialEq<&'a Kc>,
403{
404    type Value = Key;
405
406    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
407    where
408        D: serde::Deserializer<'de>,
409    {
410        let key = Kd::deserialize(deserializer)?;
411
412        if key == self.tag_key {
413            Ok(Key::Tag)
414        } else if key == self.value_key {
415            Ok(Key::Value)
416        } else {
417            Err(serde::de::Error::custom(
418                "invalid entry key, expected either the specified tag- or value-key",
419            ))
420        }
421    }
422}