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" )] |
41 | pub fn from_str<T>(s: &'_ str) -> Result<T, Error> |
42 | where |
43 | T: serde::de::DeserializeOwned, |
44 | { |
45 | T::deserialize(Deserializer::new(input:s)) |
46 | } |
47 | |
48 | /// Errors that can occur when deserializing a type. |
49 | #[derive (PartialEq, Eq, Clone)] |
50 | pub struct Error { |
51 | inner: crate::edit::de::Error, |
52 | } |
53 | |
54 | impl 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 | |
75 | impl serde::de::Error for Error { |
76 | fn custom<T>(msg: T) -> Self |
77 | where |
78 | T: std::fmt::Display, |
79 | { |
80 | Error::new(inner:crate::edit::de::Error::custom(msg)) |
81 | } |
82 | } |
83 | |
84 | impl 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 | |
90 | impl std::fmt::Debug for Error { |
91 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
92 | self.inner.fmt(f) |
93 | } |
94 | } |
95 | |
96 | impl std::error::Error for Error {} |
97 | |
98 | /// Deserialization TOML document |
99 | /// |
100 | /// To deserializes TOML values, instead of documents, see [`ValueDeserializer`]. |
101 | #[cfg (feature = "parse" )] |
102 | pub struct Deserializer<'a> { |
103 | input: &'a str, |
104 | } |
105 | |
106 | #[cfg (feature = "parse" )] |
107 | impl<'a> Deserializer<'a> { |
108 | /// Deserialization implementation for TOML. |
109 | pub fn new(input: &'a str) -> Self { |
110 | Self { input } |
111 | } |
112 | } |
113 | |
114 | #[cfg (feature = "parse" )] |
115 | impl<'de> serde::Deserializer<'de> for Deserializer<'_> { |
116 | type Error = Error; |
117 | |
118 | fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
119 | where |
120 | V: serde::de::Visitor<'de>, |
121 | { |
122 | let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?; |
123 | inner.deserialize_any(visitor).map_err(Error::new) |
124 | } |
125 | |
126 | // `None` is interpreted as a missing field so be sure to implement `Some` |
127 | // as a present field. |
128 | fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> |
129 | where |
130 | V: serde::de::Visitor<'de>, |
131 | { |
132 | let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?; |
133 | inner.deserialize_option(visitor).map_err(Error::new) |
134 | } |
135 | |
136 | fn deserialize_newtype_struct<V>( |
137 | self, |
138 | name: &'static str, |
139 | visitor: V, |
140 | ) -> Result<V::Value, Error> |
141 | where |
142 | V: serde::de::Visitor<'de>, |
143 | { |
144 | let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?; |
145 | inner |
146 | .deserialize_newtype_struct(name, visitor) |
147 | .map_err(Error::new) |
148 | } |
149 | |
150 | fn deserialize_struct<V>( |
151 | self, |
152 | name: &'static str, |
153 | fields: &'static [&'static str], |
154 | visitor: V, |
155 | ) -> Result<V::Value, Error> |
156 | where |
157 | V: serde::de::Visitor<'de>, |
158 | { |
159 | let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?; |
160 | inner |
161 | .deserialize_struct(name, fields, visitor) |
162 | .map_err(Error::new) |
163 | } |
164 | |
165 | // Called when the type to deserialize is an enum, as opposed to a field in the type. |
166 | fn deserialize_enum<V>( |
167 | self, |
168 | name: &'static str, |
169 | variants: &'static [&'static str], |
170 | visitor: V, |
171 | ) -> Result<V::Value, Error> |
172 | where |
173 | V: serde::de::Visitor<'de>, |
174 | { |
175 | let inner = toml_edit::de::Deserializer::parse(self.input).map_err(Error::new)?; |
176 | inner |
177 | .deserialize_enum(name, variants, visitor) |
178 | .map_err(Error::new) |
179 | } |
180 | |
181 | serde::forward_to_deserialize_any! { |
182 | bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq |
183 | bytes byte_buf map unit |
184 | ignored_any unit_struct tuple_struct tuple identifier |
185 | } |
186 | } |
187 | |
188 | /// Deserialization TOML [value][crate::Value] |
189 | /// |
190 | /// # Example |
191 | /// |
192 | /// ``` |
193 | /// use serde::Deserialize; |
194 | /// |
195 | /// #[derive(Deserialize)] |
196 | /// struct Config { |
197 | /// title: String, |
198 | /// owner: Owner, |
199 | /// } |
200 | /// |
201 | /// #[derive(Deserialize)] |
202 | /// struct Owner { |
203 | /// name: String, |
204 | /// } |
205 | /// |
206 | /// let config = Config::deserialize(toml::de::ValueDeserializer::new( |
207 | /// r#"{ title = 'TOML Example', owner = { name = 'Lisa' } }"# |
208 | /// )).unwrap(); |
209 | /// |
210 | /// assert_eq!(config.title, "TOML Example" ); |
211 | /// assert_eq!(config.owner.name, "Lisa" ); |
212 | /// ``` |
213 | #[cfg (feature = "parse" )] |
214 | pub struct ValueDeserializer<'a> { |
215 | input: &'a str, |
216 | } |
217 | |
218 | #[cfg (feature = "parse" )] |
219 | impl<'a> ValueDeserializer<'a> { |
220 | /// Deserialization implementation for TOML. |
221 | pub fn new(input: &'a str) -> Self { |
222 | Self { input } |
223 | } |
224 | } |
225 | |
226 | #[cfg (feature = "parse" )] |
227 | impl<'de> serde::Deserializer<'de> for ValueDeserializer<'_> { |
228 | type Error = Error; |
229 | |
230 | fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
231 | where |
232 | V: serde::de::Visitor<'de>, |
233 | { |
234 | let inner = self |
235 | .input |
236 | .parse::<toml_edit::de::ValueDeserializer>() |
237 | .map_err(Error::new)?; |
238 | inner.deserialize_any(visitor).map_err(Error::new) |
239 | } |
240 | |
241 | // `None` is interpreted as a missing field so be sure to implement `Some` |
242 | // as a present field. |
243 | fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> |
244 | where |
245 | V: serde::de::Visitor<'de>, |
246 | { |
247 | let inner = self |
248 | .input |
249 | .parse::<toml_edit::de::ValueDeserializer>() |
250 | .map_err(Error::new)?; |
251 | inner.deserialize_option(visitor).map_err(Error::new) |
252 | } |
253 | |
254 | fn deserialize_newtype_struct<V>( |
255 | self, |
256 | name: &'static str, |
257 | visitor: V, |
258 | ) -> Result<V::Value, Error> |
259 | where |
260 | V: serde::de::Visitor<'de>, |
261 | { |
262 | let inner = self |
263 | .input |
264 | .parse::<toml_edit::de::ValueDeserializer>() |
265 | .map_err(Error::new)?; |
266 | inner |
267 | .deserialize_newtype_struct(name, visitor) |
268 | .map_err(Error::new) |
269 | } |
270 | |
271 | fn deserialize_struct<V>( |
272 | self, |
273 | name: &'static str, |
274 | fields: &'static [&'static str], |
275 | visitor: V, |
276 | ) -> Result<V::Value, Error> |
277 | where |
278 | V: serde::de::Visitor<'de>, |
279 | { |
280 | let inner = self |
281 | .input |
282 | .parse::<toml_edit::de::ValueDeserializer>() |
283 | .map_err(Error::new)?; |
284 | inner |
285 | .deserialize_struct(name, fields, visitor) |
286 | .map_err(Error::new) |
287 | } |
288 | |
289 | // Called when the type to deserialize is an enum, as opposed to a field in the type. |
290 | fn deserialize_enum<V>( |
291 | self, |
292 | name: &'static str, |
293 | variants: &'static [&'static str], |
294 | visitor: V, |
295 | ) -> Result<V::Value, Error> |
296 | where |
297 | V: serde::de::Visitor<'de>, |
298 | { |
299 | let inner = self |
300 | .input |
301 | .parse::<toml_edit::de::ValueDeserializer>() |
302 | .map_err(Error::new)?; |
303 | inner |
304 | .deserialize_enum(name, variants, visitor) |
305 | .map_err(Error::new) |
306 | } |
307 | |
308 | serde::forward_to_deserialize_any! { |
309 | bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq |
310 | bytes byte_buf map unit |
311 | ignored_any unit_struct tuple_struct tuple identifier |
312 | } |
313 | } |
314 | |