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