toml/
de.rs

1//! Deserializing TOML into Rust structures.
2//!
3//! This module contains all the Serde support for deserializing TOML documents
4//! into Rust structures. Note that some top-level functions here are also
5//! provided at the top of the crate.
6
7/// Deserializes a string into a type.
8///
9/// This function will attempt to interpret `s` as a TOML document and
10/// deserialize `T` from the document.
11///
12/// To deserializes TOML values, instead of documents, see [`ValueDeserializer`].
13///
14/// # Examples
15///
16/// ```
17/// use serde::Deserialize;
18///
19/// #[derive(Deserialize)]
20/// struct Config {
21///     title: String,
22///     owner: Owner,
23/// }
24///
25/// #[derive(Deserialize)]
26/// struct Owner {
27///     name: String,
28/// }
29///
30/// let config: Config = toml::from_str(r#"
31///     title = 'TOML Example'
32///
33///     [owner]
34///     name = 'Lisa'
35/// "#).unwrap();
36///
37/// assert_eq!(config.title, "TOML Example");
38/// assert_eq!(config.owner.name, "Lisa");
39/// ```
40#[cfg(feature = "parse")]
41pub fn from_str<T>(s: &'_ str) -> Result<T, Error>
42where
43    T: serde::de::DeserializeOwned,
44{
45    T::deserialize(Deserializer::new(s))
46}
47
48/// Errors that can occur when deserializing a type.
49#[derive(Debug, PartialEq, Eq, Clone)]
50pub struct Error {
51    inner: crate::edit::de::Error,
52}
53
54impl Error {
55    fn new(inner: crate::edit::de::Error) -> Self {
56        Self { inner }
57    }
58
59    pub(crate) fn add_key(&mut self, key: String) {
60        self.inner.add_key(key);
61    }
62
63    /// What went wrong
64    pub fn message(&self) -> &str {
65        self.inner.message()
66    }
67
68    /// The start/end index into the original document where the error occurred
69    #[cfg(feature = "parse")]
70    pub fn span(&self) -> Option<std::ops::Range<usize>> {
71        self.inner.span()
72    }
73}
74
75impl serde::de::Error for Error {
76    fn custom<T>(msg: T) -> Self
77    where
78        T: std::fmt::Display,
79    {
80        Error::new(crate::edit::de::Error::custom(msg))
81    }
82}
83
84impl std::fmt::Display for Error {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        self.inner.fmt(f)
87    }
88}
89
90impl std::error::Error for Error {}
91
92/// Deserialization TOML document
93///
94/// To deserializes TOML values, instead of documents, see [`ValueDeserializer`].
95#[cfg(feature = "parse")]
96pub struct Deserializer<'a> {
97    input: &'a str,
98}
99
100#[cfg(feature = "parse")]
101impl<'a> Deserializer<'a> {
102    /// Deserialization implementation for TOML.
103    pub fn new(input: &'a str) -> Self {
104        Self { input }
105    }
106}
107
108#[cfg(feature = "parse")]
109impl<'de, 'a> serde::Deserializer<'de> for Deserializer<'a> {
110    type Error = Error;
111
112    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
113    where
114        V: serde::de::Visitor<'de>,
115    {
116        let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
117        inner.deserialize_any(visitor).map_err(Error::new)
118    }
119
120    // `None` is interpreted as a missing field so be sure to implement `Some`
121    // as a present field.
122    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
123    where
124        V: serde::de::Visitor<'de>,
125    {
126        let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
127        inner.deserialize_option(visitor).map_err(Error::new)
128    }
129
130    fn deserialize_newtype_struct<V>(
131        self,
132        name: &'static str,
133        visitor: V,
134    ) -> Result<V::Value, Error>
135    where
136        V: serde::de::Visitor<'de>,
137    {
138        let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
139        inner
140            .deserialize_newtype_struct(name, visitor)
141            .map_err(Error::new)
142    }
143
144    fn deserialize_struct<V>(
145        self,
146        name: &'static str,
147        fields: &'static [&'static str],
148        visitor: V,
149    ) -> Result<V::Value, Error>
150    where
151        V: serde::de::Visitor<'de>,
152    {
153        let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
154        inner
155            .deserialize_struct(name, fields, visitor)
156            .map_err(Error::new)
157    }
158
159    // Called when the type to deserialize is an enum, as opposed to a field in the type.
160    fn deserialize_enum<V>(
161        self,
162        name: &'static str,
163        variants: &'static [&'static str],
164        visitor: V,
165    ) -> Result<V::Value, Error>
166    where
167        V: serde::de::Visitor<'de>,
168    {
169        let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?;
170        inner
171            .deserialize_enum(name, variants, visitor)
172            .map_err(Error::new)
173    }
174
175    serde::forward_to_deserialize_any! {
176        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
177        bytes byte_buf map unit
178        ignored_any unit_struct tuple_struct tuple identifier
179    }
180}
181
182/// Deserialization TOML [value][crate::Value]
183///
184/// # Example
185///
186/// ```
187/// use serde::Deserialize;
188///
189/// #[derive(Deserialize)]
190/// struct Config {
191///     title: String,
192///     owner: Owner,
193/// }
194///
195/// #[derive(Deserialize)]
196/// struct Owner {
197///     name: String,
198/// }
199///
200/// let config = Config::deserialize(toml::de::ValueDeserializer::new(
201///     r#"{ title = 'TOML Example', owner = { name = 'Lisa' } }"#
202/// )).unwrap();
203///
204/// assert_eq!(config.title, "TOML Example");
205/// assert_eq!(config.owner.name, "Lisa");
206/// ```
207#[cfg(feature = "parse")]
208pub struct ValueDeserializer<'a> {
209    input: &'a str,
210}
211
212#[cfg(feature = "parse")]
213impl<'a> ValueDeserializer<'a> {
214    /// Deserialization implementation for TOML.
215    pub fn new(input: &'a str) -> Self {
216        Self { input }
217    }
218}
219
220#[cfg(feature = "parse")]
221impl<'de, 'a> serde::Deserializer<'de> for ValueDeserializer<'a> {
222    type Error = Error;
223
224    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
225    where
226        V: serde::de::Visitor<'de>,
227    {
228        let inner = self
229            .input
230            .parse::<toml_edit::de::ValueDeserializer>()
231            .map_err(Error::new)?;
232        inner.deserialize_any(visitor).map_err(Error::new)
233    }
234
235    // `None` is interpreted as a missing field so be sure to implement `Some`
236    // as a present field.
237    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
238    where
239        V: serde::de::Visitor<'de>,
240    {
241        let inner = self
242            .input
243            .parse::<toml_edit::de::ValueDeserializer>()
244            .map_err(Error::new)?;
245        inner.deserialize_option(visitor).map_err(Error::new)
246    }
247
248    fn deserialize_newtype_struct<V>(
249        self,
250        name: &'static str,
251        visitor: V,
252    ) -> Result<V::Value, Error>
253    where
254        V: serde::de::Visitor<'de>,
255    {
256        let inner = self
257            .input
258            .parse::<toml_edit::de::ValueDeserializer>()
259            .map_err(Error::new)?;
260        inner
261            .deserialize_newtype_struct(name, visitor)
262            .map_err(Error::new)
263    }
264
265    fn deserialize_struct<V>(
266        self,
267        name: &'static str,
268        fields: &'static [&'static str],
269        visitor: V,
270    ) -> Result<V::Value, Error>
271    where
272        V: serde::de::Visitor<'de>,
273    {
274        let inner = self
275            .input
276            .parse::<toml_edit::de::ValueDeserializer>()
277            .map_err(Error::new)?;
278        inner
279            .deserialize_struct(name, fields, visitor)
280            .map_err(Error::new)
281    }
282
283    // Called when the type to deserialize is an enum, as opposed to a field in the type.
284    fn deserialize_enum<V>(
285        self,
286        name: &'static str,
287        variants: &'static [&'static str],
288        visitor: V,
289    ) -> Result<V::Value, Error>
290    where
291        V: serde::de::Visitor<'de>,
292    {
293        let inner = self
294            .input
295            .parse::<toml_edit::de::ValueDeserializer>()
296            .map_err(Error::new)?;
297        inner
298            .deserialize_enum(name, variants, visitor)
299            .map_err(Error::new)
300    }
301
302    serde::forward_to_deserialize_any! {
303        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
304        bytes byte_buf map unit
305        ignored_any unit_struct tuple_struct tuple identifier
306    }
307}