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}