toml_edit/de/
value.rs

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