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