toml_edit/de/
mod.rs

1//! Deserializing TOML into Rust structures.
2//!
3//! This module contains all the Serde support for deserializing TOML documents into Rust structures.
4
5use serde::de::DeserializeOwned;
6
7mod array;
8mod datetime;
9mod key;
10mod spanned;
11mod table;
12mod table_enum;
13mod value;
14
15use array::ArrayDeserializer;
16use datetime::DatetimeDeserializer;
17use key::KeyDeserializer;
18use spanned::SpannedDeserializer;
19use table_enum::TableEnumDeserializer;
20
21pub use value::ValueDeserializer;
22
23/// Errors that can occur when deserializing a type.
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct Error {
26    inner: crate::TomlError,
27}
28
29impl Error {
30    pub(crate) fn custom<T>(msg: T, span: Option<std::ops::Range<usize>>) -> Self
31    where
32        T: std::fmt::Display,
33    {
34        Error {
35            inner: crate::TomlError::custom(msg.to_string(), span),
36        }
37    }
38
39    /// Add key while unwinding
40    pub fn add_key(&mut self, key: String) {
41        self.inner.add_key(key);
42    }
43
44    /// What went wrong
45    pub fn message(&self) -> &str {
46        self.inner.message()
47    }
48
49    /// The start/end index into the original document where the error occurred
50    pub fn span(&self) -> Option<std::ops::Range<usize>> {
51        self.inner.span()
52    }
53
54    pub(crate) fn set_span(&mut self, span: Option<std::ops::Range<usize>>) {
55        self.inner.set_span(span);
56    }
57}
58
59impl serde::de::Error for Error {
60    fn custom<T>(msg: T) -> Self
61    where
62        T: std::fmt::Display,
63    {
64        Error::custom(msg, None)
65    }
66}
67
68impl std::fmt::Display for Error {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        self.inner.fmt(f)
71    }
72}
73
74impl From<crate::TomlError> for Error {
75    fn from(e: crate::TomlError) -> Error {
76        Self { inner: e }
77    }
78}
79
80impl From<Error> for crate::TomlError {
81    fn from(e: Error) -> crate::TomlError {
82        e.inner
83    }
84}
85
86impl std::error::Error for Error {}
87
88/// Convert a TOML [documents][crate::DocumentMut] into `T`.
89#[cfg(feature = "parse")]
90pub fn from_str<T>(s: &'_ str) -> Result<T, Error>
91where
92    T: DeserializeOwned,
93{
94    let de = Deserializer::parse(s)?;
95    T::deserialize(de)
96}
97
98/// Convert a TOML [documents][crate::DocumentMut] into `T`.
99#[cfg(feature = "parse")]
100pub fn from_slice<T>(s: &'_ [u8]) -> Result<T, Error>
101where
102    T: DeserializeOwned,
103{
104    let s = std::str::from_utf8(s).map_err(|e| Error::custom(e, None))?;
105    from_str(s)
106}
107
108/// Convert a [`DocumentMut`][crate::DocumentMut] into `T`.
109pub fn from_document<T>(d: impl Into<Deserializer>) -> Result<T, Error>
110where
111    T: DeserializeOwned,
112{
113    let deserializer = d.into();
114    T::deserialize(deserializer)
115}
116
117/// Deserialization for TOML [documents][crate::DocumentMut].
118pub struct Deserializer<S = String> {
119    root: crate::Item,
120    raw: Option<S>,
121}
122
123impl Deserializer {
124    /// Deserialization implementation for TOML.
125    #[deprecated(since = "0.22.6", note = "Replaced with `Deserializer::from`")]
126    pub fn new(input: crate::DocumentMut) -> Self {
127        Self::from(input)
128    }
129}
130
131#[cfg(feature = "parse")]
132impl<S: AsRef<str>> Deserializer<S> {
133    /// Parse a TOML document
134    pub fn parse(raw: S) -> Result<Self, Error> {
135        crate::ImDocument::parse(raw)
136            .map(Self::from)
137            .map_err(Into::into)
138    }
139}
140
141impl From<crate::DocumentMut> for Deserializer {
142    fn from(doc: crate::DocumentMut) -> Self {
143        let crate::DocumentMut { root, .. } = doc;
144        Self { root, raw: None }
145    }
146}
147
148impl<S> From<crate::ImDocument<S>> for Deserializer<S> {
149    fn from(doc: crate::ImDocument<S>) -> Self {
150        let crate::ImDocument { root, raw, .. } = doc;
151        let raw = Some(raw);
152        Self { root, raw }
153    }
154}
155
156#[cfg(feature = "parse")]
157impl std::str::FromStr for Deserializer {
158    type Err = Error;
159
160    /// Parses a document from a &str
161    fn from_str(s: &str) -> Result<Self, Self::Err> {
162        let doc: crate::ImDocument<_> = s.parse().map_err(Error::from)?;
163        Ok(Deserializer::from(doc))
164    }
165}
166
167// Note: this is wrapped by `toml::de::Deserializer` and any trait methods
168// implemented here need to be wrapped there
169impl<'de, S: Into<String>> serde::Deserializer<'de> for Deserializer<S> {
170    type Error = Error;
171
172    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
173    where
174        V: serde::de::Visitor<'de>,
175    {
176        let raw = self.raw;
177        self.root
178            .into_deserializer()
179            .deserialize_any(visitor)
180            .map_err(|mut e: Self::Error| {
181                e.inner.set_raw(raw.map(|r| r.into()));
182                e
183            })
184    }
185
186    // `None` is interpreted as a missing field so be sure to implement `Some`
187    // as a present field.
188    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
189    where
190        V: serde::de::Visitor<'de>,
191    {
192        let raw = self.raw;
193        self.root
194            .into_deserializer()
195            .deserialize_option(visitor)
196            .map_err(|mut e: Self::Error| {
197                e.inner.set_raw(raw.map(|r| r.into()));
198                e
199            })
200    }
201
202    fn deserialize_newtype_struct<V>(
203        self,
204        name: &'static str,
205        visitor: V,
206    ) -> Result<V::Value, Error>
207    where
208        V: serde::de::Visitor<'de>,
209    {
210        let raw = self.raw;
211        self.root
212            .into_deserializer()
213            .deserialize_newtype_struct(name, visitor)
214            .map_err(|mut e: Self::Error| {
215                e.inner.set_raw(raw.map(|r| r.into()));
216                e
217            })
218    }
219
220    fn deserialize_struct<V>(
221        self,
222        name: &'static str,
223        fields: &'static [&'static str],
224        visitor: V,
225    ) -> Result<V::Value, Error>
226    where
227        V: serde::de::Visitor<'de>,
228    {
229        let raw = self.raw;
230        self.root
231            .into_deserializer()
232            .deserialize_struct(name, fields, visitor)
233            .map_err(|mut e: Self::Error| {
234                e.inner.set_raw(raw.map(|r| r.into()));
235                e
236            })
237    }
238
239    // Called when the type to deserialize is an enum, as opposed to a field in the type.
240    fn deserialize_enum<V>(
241        self,
242        name: &'static str,
243        variants: &'static [&'static str],
244        visitor: V,
245    ) -> Result<V::Value, Error>
246    where
247        V: serde::de::Visitor<'de>,
248    {
249        let raw = self.raw;
250        self.root
251            .into_deserializer()
252            .deserialize_enum(name, variants, visitor)
253            .map_err(|mut e: Self::Error| {
254                e.inner.set_raw(raw.map(|r| r.into()));
255                e
256            })
257    }
258
259    serde::forward_to_deserialize_any! {
260        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
261        bytes byte_buf map unit
262        ignored_any unit_struct tuple_struct tuple identifier
263    }
264}
265
266impl<'de> serde::de::IntoDeserializer<'de, Error> for Deserializer {
267    type Deserializer = Deserializer;
268
269    fn into_deserializer(self) -> Self::Deserializer {
270        self
271    }
272}
273
274impl<'de> serde::de::IntoDeserializer<'de, Error> for crate::DocumentMut {
275    type Deserializer = Deserializer;
276
277    fn into_deserializer(self) -> Self::Deserializer {
278        Deserializer::from(self)
279    }
280}
281
282impl<'de> serde::de::IntoDeserializer<'de, Error> for crate::ImDocument<String> {
283    type Deserializer = Deserializer;
284
285    fn into_deserializer(self) -> Self::Deserializer {
286        Deserializer::from(self)
287    }
288}
289
290pub(crate) fn validate_struct_keys(
291    table: &crate::table::KeyValuePairs,
292    fields: &'static [&'static str],
293) -> Result<(), Error> {
294    let extra_fields = table
295        .keys()
296        .filter_map(|key| {
297            if !fields.contains(&key.get()) {
298                Some(key.clone())
299            } else {
300                None
301            }
302        })
303        .collect::<Vec<_>>();
304
305    if extra_fields.is_empty() {
306        Ok(())
307    } else {
308        Err(Error::custom(
309            format!(
310                "unexpected keys in table: {}, available keys: {}",
311                extra_fields
312                    .iter()
313                    .map(|k| k.get())
314                    .collect::<Vec<_>>()
315                    .join(", "),
316                fields.join(", "),
317            ),
318            extra_fields[0].span(),
319        ))
320    }
321}