toml_edit/de/
value.rs

1use serde::de::IntoDeserializer as _;
2
3use crate::de::DatetimeDeserializer;
4use crate::de::Error;
5
6/// Deserialization implementation for TOML [values][crate::Value].
7///
8/// # Example
9///
10/// ```
11/// use serde::Deserialize;
12///
13/// #[derive(Deserialize)]
14/// struct Config {
15///     title: String,
16///     owner: Owner,
17/// }
18///
19/// #[derive(Deserialize)]
20/// struct Owner {
21///     name: String,
22/// }
23///
24/// let value = r#"{ title = 'TOML Example', owner = { name = 'Lisa' } }"#;
25/// let deserializer = value.parse::<toml_edit::de::ValueDeserializer>().unwrap();
26/// let config = Config::deserialize(deserializer).unwrap();
27///
28/// assert_eq!(config.title, "TOML Example");
29/// assert_eq!(config.owner.name, "Lisa");
30/// ```
31pub struct ValueDeserializer {
32    input: crate::Item,
33    validate_struct_keys: bool,
34}
35
36impl ValueDeserializer {
37    pub(crate) fn new(input: crate::Item) -> Self {
38        Self {
39            input,
40            validate_struct_keys: false,
41        }
42    }
43
44    pub(crate) fn with_struct_key_validation(mut self) -> Self {
45        self.validate_struct_keys = true;
46        self
47    }
48}
49
50// Note: this is wrapped by `toml::de::ValueDeserializer` and any trait methods
51// implemented here need to be wrapped there
52impl<'de> serde::Deserializer<'de> for ValueDeserializer {
53    type Error = Error;
54
55    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
56    where
57        V: serde::de::Visitor<'de>,
58    {
59        let span = self.input.span();
60        match self.input {
61            crate::Item::None => visitor.visit_none(),
62            crate::Item::Value(crate::Value::String(v)) => visitor.visit_string(v.into_value()),
63            crate::Item::Value(crate::Value::Integer(v)) => visitor.visit_i64(v.into_value()),
64            crate::Item::Value(crate::Value::Float(v)) => visitor.visit_f64(v.into_value()),
65            crate::Item::Value(crate::Value::Boolean(v)) => visitor.visit_bool(v.into_value()),
66            crate::Item::Value(crate::Value::Datetime(v)) => {
67                visitor.visit_map(DatetimeDeserializer::new(v.into_value()))
68            }
69            crate::Item::Value(crate::Value::Array(v)) => {
70                v.into_deserializer().deserialize_any(visitor)
71            }
72            crate::Item::Value(crate::Value::InlineTable(v)) => {
73                v.into_deserializer().deserialize_any(visitor)
74            }
75            crate::Item::Table(v) => v.into_deserializer().deserialize_any(visitor),
76            crate::Item::ArrayOfTables(v) => v.into_deserializer().deserialize_any(visitor),
77        }
78        .map_err(|mut e: Self::Error| {
79            if e.span().is_none() {
80                e.set_span(span);
81            }
82            e
83        })
84    }
85
86    // `None` is interpreted as a missing field so be sure to implement `Some`
87    // as a present field.
88    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
89    where
90        V: serde::de::Visitor<'de>,
91    {
92        let span = self.input.span();
93        visitor.visit_some(self).map_err(|mut e: Self::Error| {
94            if e.span().is_none() {
95                e.set_span(span);
96            }
97            e
98        })
99    }
100
101    fn deserialize_newtype_struct<V>(
102        self,
103        _name: &'static str,
104        visitor: V,
105    ) -> Result<V::Value, Error>
106    where
107        V: serde::de::Visitor<'de>,
108    {
109        let span = self.input.span();
110        visitor
111            .visit_newtype_struct(self)
112            .map_err(|mut e: Self::Error| {
113                if e.span().is_none() {
114                    e.set_span(span);
115                }
116                e
117            })
118    }
119
120    fn deserialize_struct<V>(
121        self,
122        name: &'static str,
123        fields: &'static [&'static str],
124        visitor: V,
125    ) -> Result<V::Value, Error>
126    where
127        V: serde::de::Visitor<'de>,
128    {
129        if serde_spanned::__unstable::is_spanned(name, fields) {
130            if let Some(span) = self.input.span() {
131                return visitor.visit_map(super::SpannedDeserializer::new(self, span));
132            }
133        }
134
135        if name == toml_datetime::__unstable::NAME && fields == [toml_datetime::__unstable::FIELD] {
136            let span = self.input.span();
137            if let crate::Item::Value(crate::Value::Datetime(d)) = self.input {
138                return visitor
139                    .visit_map(DatetimeDeserializer::new(d.into_value()))
140                    .map_err(|mut e: Self::Error| {
141                        if e.span().is_none() {
142                            e.set_span(span);
143                        }
144                        e
145                    });
146            }
147        }
148
149        if self.validate_struct_keys {
150            let span = self.input.span();
151            match &self.input {
152                crate::Item::Table(values) => super::validate_struct_keys(&values.items, fields),
153                crate::Item::Value(crate::Value::InlineTable(values)) => {
154                    super::validate_struct_keys(&values.items, fields)
155                }
156                _ => Ok(()),
157            }
158            .map_err(|mut e: Self::Error| {
159                if e.span().is_none() {
160                    e.set_span(span);
161                }
162                e
163            })?
164        }
165
166        self.deserialize_any(visitor)
167    }
168
169    // Called when the type to deserialize is an enum, as opposed to a field in the type.
170    fn deserialize_enum<V>(
171        self,
172        name: &'static str,
173        variants: &'static [&'static str],
174        visitor: V,
175    ) -> Result<V::Value, Error>
176    where
177        V: serde::de::Visitor<'de>,
178    {
179        let span = self.input.span();
180        match self.input {
181            crate::Item::Value(crate::Value::String(v)) => {
182                visitor.visit_enum(v.into_value().into_deserializer())
183            }
184            crate::Item::Value(crate::Value::InlineTable(v)) => {
185                if v.is_empty() {
186                    Err(crate::de::Error::custom(
187                        "wanted exactly 1 element, found 0 elements",
188                        v.span(),
189                    ))
190                } else if v.len() != 1 {
191                    Err(crate::de::Error::custom(
192                        "wanted exactly 1 element, more than 1 element",
193                        v.span(),
194                    ))
195                } else {
196                    v.into_deserializer()
197                        .deserialize_enum(name, variants, visitor)
198                }
199            }
200            crate::Item::Table(v) => v
201                .into_deserializer()
202                .deserialize_enum(name, variants, visitor),
203            e => Err(crate::de::Error::custom("wanted string or table", e.span())),
204        }
205        .map_err(|mut e: Self::Error| {
206            if e.span().is_none() {
207                e.set_span(span);
208            }
209            e
210        })
211    }
212
213    serde::forward_to_deserialize_any! {
214        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
215        bytes byte_buf map unit
216        ignored_any unit_struct tuple_struct tuple identifier
217    }
218}
219
220impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for ValueDeserializer {
221    type Deserializer = Self;
222
223    fn into_deserializer(self) -> Self::Deserializer {
224        self
225    }
226}
227
228impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for crate::Value {
229    type Deserializer = ValueDeserializer;
230
231    fn into_deserializer(self) -> Self::Deserializer {
232        ValueDeserializer::new(crate::Item::Value(self))
233    }
234}
235
236impl crate::Item {
237    pub(crate) fn into_deserializer(self) -> ValueDeserializer {
238        ValueDeserializer::new(self)
239    }
240}
241
242impl std::str::FromStr for ValueDeserializer {
243    type Err = Error;
244
245    /// Parses a value from a &str
246    fn from_str(s: &str) -> Result<Self, Self::Err> {
247        let v = crate::parser::parse_value(s).map_err(Error::from)?;
248        Ok(v.into_deserializer())
249    }
250}