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(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 std::fmt::Debug for Error {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        self.inner.fmt(f)
77    }
78}
79
80impl From<crate::TomlError> for Error {
81    fn from(e: crate::TomlError) -> Error {
82        Self { inner: e }
83    }
84}
85
86impl From<Error> for crate::TomlError {
87    fn from(e: Error) -> crate::TomlError {
88        e.inner
89    }
90}
91
92impl std::error::Error for Error {}
93
94/// Convert a TOML [documents][crate::DocumentMut] into `T`.
95#[cfg(feature = "parse")]
96pub fn from_str<T>(s: &'_ str) -> Result<T, Error>
97where
98    T: DeserializeOwned,
99{
100    let de = Deserializer::parse(s)?;
101    T::deserialize(de)
102}
103
104/// Convert a TOML [documents][crate::DocumentMut] into `T`.
105#[cfg(feature = "parse")]
106pub fn from_slice<T>(s: &'_ [u8]) -> Result<T, Error>
107where
108    T: DeserializeOwned,
109{
110    let s = std::str::from_utf8(s).map_err(|e| Error::custom(e, None))?;
111    from_str(s)
112}
113
114/// Convert a [`DocumentMut`][crate::DocumentMut] into `T`.
115pub fn from_document<T>(d: impl Into<Deserializer>) -> Result<T, Error>
116where
117    T: DeserializeOwned,
118{
119    let deserializer = d.into();
120    T::deserialize(deserializer)
121}
122
123/// Deserialization for TOML [documents][crate::DocumentMut].
124pub struct Deserializer<S = String> {
125    root: crate::Item,
126    raw: Option<S>,
127}
128
129impl Deserializer {
130    /// Deserialization implementation for TOML.
131    #[deprecated(since = "0.22.6", note = "Replaced with `Deserializer::from`")]
132    pub fn new(input: crate::DocumentMut) -> Self {
133        Self::from(input)
134    }
135}
136
137#[cfg(feature = "parse")]
138impl<S: AsRef<str>> Deserializer<S> {
139    /// Parse a TOML document
140    pub fn parse(raw: S) -> Result<Self, Error> {
141        crate::ImDocument::parse(raw)
142            .map(Self::from)
143            .map_err(Into::into)
144    }
145}
146
147impl From<crate::DocumentMut> for Deserializer {
148    fn from(doc: crate::DocumentMut) -> Self {
149        let crate::DocumentMut { root, .. } = doc;
150        Self { root, raw: None }
151    }
152}
153
154impl<S> From<crate::ImDocument<S>> for Deserializer<S> {
155    fn from(doc: crate::ImDocument<S>) -> Self {
156        let crate::ImDocument { root, raw, .. } = doc;
157        let raw = Some(raw);
158        Self { root, raw }
159    }
160}
161
162#[cfg(feature = "parse")]
163impl std::str::FromStr for Deserializer {
164    type Err = Error;
165
166    /// Parses a document from a &str
167    fn from_str(s: &str) -> Result<Self, Self::Err> {
168        let doc: crate::ImDocument<_> = s.parse().map_err(Error::from)?;
169        Ok(Deserializer::from(doc))
170    }
171}
172
173// Note: this is wrapped by `toml::de::Deserializer` and any trait methods
174// implemented here need to be wrapped there
175impl<'de, S: Into<String>> serde::Deserializer<'de> for Deserializer<S> {
176    type Error = Error;
177
178    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
179    where
180        V: serde::de::Visitor<'de>,
181    {
182        let raw = self.raw;
183        self.root
184            .into_deserializer()
185            .deserialize_any(visitor)
186            .map_err(|mut e: Self::Error| {
187                e.inner.set_raw(raw.map(|r| r.into()));
188                e
189            })
190    }
191
192    // `None` is interpreted as a missing field so be sure to implement `Some`
193    // as a present field.
194    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
195    where
196        V: serde::de::Visitor<'de>,
197    {
198        let raw = self.raw;
199        self.root
200            .into_deserializer()
201            .deserialize_option(visitor)
202            .map_err(|mut e: Self::Error| {
203                e.inner.set_raw(raw.map(|r| r.into()));
204                e
205            })
206    }
207
208    fn deserialize_newtype_struct<V>(
209        self,
210        name: &'static str,
211        visitor: V,
212    ) -> Result<V::Value, Error>
213    where
214        V: serde::de::Visitor<'de>,
215    {
216        let raw = self.raw;
217        self.root
218            .into_deserializer()
219            .deserialize_newtype_struct(name, visitor)
220            .map_err(|mut e: Self::Error| {
221                e.inner.set_raw(raw.map(|r| r.into()));
222                e
223            })
224    }
225
226    fn deserialize_struct<V>(
227        self,
228        name: &'static str,
229        fields: &'static [&'static str],
230        visitor: V,
231    ) -> Result<V::Value, Error>
232    where
233        V: serde::de::Visitor<'de>,
234    {
235        let raw = self.raw;
236        self.root
237            .into_deserializer()
238            .deserialize_struct(name, fields, visitor)
239            .map_err(|mut e: Self::Error| {
240                e.inner.set_raw(raw.map(|r| r.into()));
241                e
242            })
243    }
244
245    // Called when the type to deserialize is an enum, as opposed to a field in the type.
246    fn deserialize_enum<V>(
247        self,
248        name: &'static str,
249        variants: &'static [&'static str],
250        visitor: V,
251    ) -> Result<V::Value, Error>
252    where
253        V: serde::de::Visitor<'de>,
254    {
255        let raw = self.raw;
256        self.root
257            .into_deserializer()
258            .deserialize_enum(name, variants, visitor)
259            .map_err(|mut e: Self::Error| {
260                e.inner.set_raw(raw.map(|r| r.into()));
261                e
262            })
263    }
264
265    serde::forward_to_deserialize_any! {
266        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
267        bytes byte_buf map unit
268        ignored_any unit_struct tuple_struct tuple identifier
269    }
270}
271
272impl serde::de::IntoDeserializer<'_, Error> for Deserializer {
273    type Deserializer = Deserializer;
274
275    fn into_deserializer(self) -> Self::Deserializer {
276        self
277    }
278}
279
280impl serde::de::IntoDeserializer<'_, Error> for crate::DocumentMut {
281    type Deserializer = Deserializer;
282
283    fn into_deserializer(self) -> Self::Deserializer {
284        Deserializer::from(self)
285    }
286}
287
288impl serde::de::IntoDeserializer<'_, Error> for crate::ImDocument<String> {
289    type Deserializer = Deserializer;
290
291    fn into_deserializer(self) -> Self::Deserializer {
292        Deserializer::from(self)
293    }
294}
295
296pub(crate) fn validate_struct_keys(
297    table: &crate::table::KeyValuePairs,
298    fields: &'static [&'static str],
299) -> Result<(), Error> {
300    let extra_fields = table
301        .keys()
302        .filter_map(|key| {
303            if !fields.contains(&key.get()) {
304                Some(key.clone())
305            } else {
306                None
307            }
308        })
309        .collect::<Vec<_>>();
310
311    if extra_fields.is_empty() {
312        Ok(())
313    } else {
314        Err(Error::custom(
315            format!(
316                "unexpected keys in table: {}, available keys: {}",
317                extra_fields
318                    .iter()
319                    .map(|k| k.get())
320                    .collect::<Vec<_>>()
321                    .join(", "),
322                fields.join(", "),
323            ),
324            extra_fields[0].span(),
325        ))
326    }
327}