serde_tagged/de/
external.rs

1//! Deserialization of externally tagged values.
2//!
3//! See [`ser::external`](::ser::external) 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 an externally 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` to deserialize the tag. This version is equivalent
25/// to `deserialize_seed(deserializer, seed_factory, PhantomData<T>)`
26pub fn deserialize<'de, T, D, F>(deserializer: D, seed_factory: F) -> Result<F::Value, D::Error>
27where
28    T: serde::Deserialize<'de>,
29    D: serde::Deserializer<'de>,
30    F: SeedFactory<'de, T>,
31{
32    deserialize_seed(deserializer, seed_factory, PhantomData::<T>)
33}
34
35
36/// Deserialize an externally tagged value with the given tag-seed.
37///
38/// The deserializer controls the underlying data format while the seed-factory
39/// specifies the instructions (depending on the tag) on how the value should be
40/// deserialized.
41///
42/// See [`de`](::de) for more information on
43/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
44pub fn deserialize_seed<'de, D, F, S>(
45    deserializer: D,
46    seed_factory: F,
47    tag_seed: S,
48) -> Result<F::Value, D::Error>
49where
50    D: serde::Deserializer<'de>,
51    F: SeedFactory<'de, S::Value>,
52    S: serde::de::DeserializeSeed<'de>,
53{
54    deserializer.deserialize_map(Visitor::new(seed_factory, tag_seed))
55}
56
57
58/// A visitor that can be used to deserialize an externally tagged value.
59///
60/// This visitor handles an externally tagged value, which is represented by a
61/// map containing a single entry, where the key is the tag and the value is the
62/// value that should be deserialized. Thus it will return an error if the
63/// visited type is not a map.
64///
65/// The [`SeedFactory`](::de::SeedFactory) provided to this visitor
66/// provides a `serde::de::DeserializeSeed` implementation depending on the tag,
67/// which then determines how the value is going to be deserialized.
68///
69/// See [`de`](::de) for more information on
70/// [`SeedFactory`](::de::SeedFactory) and implementations thereof.
71pub struct Visitor<F, S> {
72    seed_factory: F,
73    tag_seed:     S,
74}
75
76impl<F, S> Visitor<F, S> {
77    /// Creates a new visitor with the given
78    /// [`SeedFactory`](::de::SeedFactory).
79    pub fn new(seed_factory: F, tag_seed: S) -> Self {
80        Visitor {
81            seed_factory,
82            tag_seed,
83        }
84    }
85}
86
87impl<'de, F, S> serde::de::Visitor<'de> for Visitor<F, S>
88where
89    F: SeedFactory<'de, S::Value>,
90    S: serde::de::DeserializeSeed<'de>,
91{
92    type Value = F::Value;
93
94    fn expecting(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
95        write!(fmtr, "a map with exactly one entry")
96    }
97
98    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
99    where
100        A: serde::de::MapAccess<'de>,
101    {
102        use serde::de::Error;
103
104        // try to validate the length
105        match map.size_hint() {
106            Some(n) if n != 1 => Err(serde::de::Error::invalid_length(n, &self))?,
107            _ => {},
108        }
109
110        let tag = map.next_key_seed(self.tag_seed)?
111            .ok_or_else(|| Error::invalid_length(0, &"a map with exactly one entry"))?;
112
113        map.next_value_seed(self.seed_factory.seed(tag)?)
114    }
115}