1 | use serde::de::IntoDeserializer as _; |
2 | |
3 | use crate::de::DatetimeDeserializer; |
4 | use crate::de::Error; |
5 | |
6 | /// Deserialization implementation for TOML [values][crate::Value]. |
7 | /// |
8 | /// Can be created either directly from TOML strings, using [`std::str::FromStr`], |
9 | /// or from parsed [values][crate::Value] using [`serde::de::IntoDeserializer::into_deserializer`]. |
10 | /// |
11 | /// # Example |
12 | /// |
13 | /// ``` |
14 | /// # #[cfg (feature = "parse" )] { |
15 | /// # #[cfg (feature = "display" )] { |
16 | /// use serde::Deserialize; |
17 | /// |
18 | /// #[derive(Deserialize)] |
19 | /// struct Config { |
20 | /// title: String, |
21 | /// owner: Owner, |
22 | /// } |
23 | /// |
24 | /// #[derive(Deserialize)] |
25 | /// struct Owner { |
26 | /// name: String, |
27 | /// } |
28 | /// |
29 | /// let value = r#"{ title = 'TOML Example', owner = { name = 'Lisa' } }"# ; |
30 | /// let deserializer = value.parse::<toml_edit::de::ValueDeserializer>().unwrap(); |
31 | /// let config = Config::deserialize(deserializer).unwrap(); |
32 | /// assert_eq!(config.title, "TOML Example" ); |
33 | /// assert_eq!(config.owner.name, "Lisa" ); |
34 | /// # } |
35 | /// # } |
36 | /// ``` |
37 | pub struct ValueDeserializer { |
38 | input: crate::Item, |
39 | validate_struct_keys: bool, |
40 | } |
41 | |
42 | impl ValueDeserializer { |
43 | pub(crate) fn new(input: crate::Item) -> Self { |
44 | Self { |
45 | input, |
46 | validate_struct_keys: false, |
47 | } |
48 | } |
49 | |
50 | pub(crate) fn with_struct_key_validation(mut self) -> Self { |
51 | self.validate_struct_keys = true; |
52 | self |
53 | } |
54 | } |
55 | |
56 | // Note: this is wrapped by `toml::de::ValueDeserializer` and any trait methods |
57 | // implemented here need to be wrapped there |
58 | impl<'de> serde::Deserializer<'de> for ValueDeserializer { |
59 | type Error = Error; |
60 | |
61 | fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> |
62 | where |
63 | V: serde::de::Visitor<'de>, |
64 | { |
65 | let span = self.input.span(); |
66 | match self.input { |
67 | crate::Item::None => visitor.visit_none(), |
68 | crate::Item::Value(crate::Value::String(v)) => visitor.visit_string(v.into_value()), |
69 | crate::Item::Value(crate::Value::Integer(v)) => visitor.visit_i64(v.into_value()), |
70 | crate::Item::Value(crate::Value::Float(v)) => visitor.visit_f64(v.into_value()), |
71 | crate::Item::Value(crate::Value::Boolean(v)) => visitor.visit_bool(v.into_value()), |
72 | crate::Item::Value(crate::Value::Datetime(v)) => { |
73 | visitor.visit_map(DatetimeDeserializer::new(v.into_value())) |
74 | } |
75 | crate::Item::Value(crate::Value::Array(v)) => { |
76 | v.into_deserializer().deserialize_any(visitor) |
77 | } |
78 | crate::Item::Value(crate::Value::InlineTable(v)) => { |
79 | v.into_deserializer().deserialize_any(visitor) |
80 | } |
81 | crate::Item::Table(v) => v.into_deserializer().deserialize_any(visitor), |
82 | crate::Item::ArrayOfTables(v) => v.into_deserializer().deserialize_any(visitor), |
83 | } |
84 | .map_err(|mut e: Self::Error| { |
85 | if e.span().is_none() { |
86 | e.set_span(span); |
87 | } |
88 | e |
89 | }) |
90 | } |
91 | |
92 | // `None` is interpreted as a missing field so be sure to implement `Some` |
93 | // as a present field. |
94 | fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> |
95 | where |
96 | V: serde::de::Visitor<'de>, |
97 | { |
98 | let span = self.input.span(); |
99 | visitor.visit_some(self).map_err(|mut e: Self::Error| { |
100 | if e.span().is_none() { |
101 | e.set_span(span); |
102 | } |
103 | e |
104 | }) |
105 | } |
106 | |
107 | fn deserialize_newtype_struct<V>( |
108 | self, |
109 | _name: &'static str, |
110 | visitor: V, |
111 | ) -> Result<V::Value, Error> |
112 | where |
113 | V: serde::de::Visitor<'de>, |
114 | { |
115 | let span = self.input.span(); |
116 | visitor |
117 | .visit_newtype_struct(self) |
118 | .map_err(|mut e: Self::Error| { |
119 | if e.span().is_none() { |
120 | e.set_span(span); |
121 | } |
122 | e |
123 | }) |
124 | } |
125 | |
126 | fn deserialize_struct<V>( |
127 | self, |
128 | name: &'static str, |
129 | fields: &'static [&'static str], |
130 | visitor: V, |
131 | ) -> Result<V::Value, Error> |
132 | where |
133 | V: serde::de::Visitor<'de>, |
134 | { |
135 | if serde_spanned::__unstable::is_spanned(name, fields) { |
136 | if let Some(span) = self.input.span() { |
137 | return visitor.visit_map(super::SpannedDeserializer::new(self, span)); |
138 | } |
139 | } |
140 | |
141 | if name == toml_datetime::__unstable::NAME && fields == [toml_datetime::__unstable::FIELD] { |
142 | let span = self.input.span(); |
143 | if let crate::Item::Value(crate::Value::Datetime(d)) = self.input { |
144 | return visitor |
145 | .visit_map(DatetimeDeserializer::new(d.into_value())) |
146 | .map_err(|mut e: Self::Error| { |
147 | if e.span().is_none() { |
148 | e.set_span(span); |
149 | } |
150 | e |
151 | }); |
152 | } |
153 | } |
154 | |
155 | if self.validate_struct_keys { |
156 | let span = self.input.span(); |
157 | match &self.input { |
158 | crate::Item::Table(values) => super::validate_struct_keys(&values.items, fields), |
159 | crate::Item::Value(crate::Value::InlineTable(values)) => { |
160 | super::validate_struct_keys(&values.items, fields) |
161 | } |
162 | _ => Ok(()), |
163 | } |
164 | .map_err(|mut e: Self::Error| { |
165 | if e.span().is_none() { |
166 | e.set_span(span); |
167 | } |
168 | e |
169 | })?; |
170 | } |
171 | |
172 | self.deserialize_any(visitor) |
173 | } |
174 | |
175 | // Called when the type to deserialize is an enum, as opposed to a field in the type. |
176 | fn deserialize_enum<V>( |
177 | self, |
178 | name: &'static str, |
179 | variants: &'static [&'static str], |
180 | visitor: V, |
181 | ) -> Result<V::Value, Error> |
182 | where |
183 | V: serde::de::Visitor<'de>, |
184 | { |
185 | let span = self.input.span(); |
186 | match self.input { |
187 | crate::Item::Value(crate::Value::String(v)) => { |
188 | visitor.visit_enum(v.into_value().into_deserializer()) |
189 | } |
190 | crate::Item::Value(crate::Value::InlineTable(v)) => { |
191 | if v.is_empty() { |
192 | Err(Error::custom( |
193 | "wanted exactly 1 element, found 0 elements" , |
194 | v.span(), |
195 | )) |
196 | } else if v.len() != 1 { |
197 | Err(Error::custom( |
198 | "wanted exactly 1 element, more than 1 element" , |
199 | v.span(), |
200 | )) |
201 | } else { |
202 | v.into_deserializer() |
203 | .deserialize_enum(name, variants, visitor) |
204 | } |
205 | } |
206 | crate::Item::Table(v) => v |
207 | .into_deserializer() |
208 | .deserialize_enum(name, variants, visitor), |
209 | e => Err(Error::custom("wanted string or table" , e.span())), |
210 | } |
211 | .map_err(|mut e: Self::Error| { |
212 | if e.span().is_none() { |
213 | e.set_span(span); |
214 | } |
215 | e |
216 | }) |
217 | } |
218 | |
219 | serde::forward_to_deserialize_any! { |
220 | bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq |
221 | bytes byte_buf map unit |
222 | ignored_any unit_struct tuple_struct tuple identifier |
223 | } |
224 | } |
225 | |
226 | impl serde::de::IntoDeserializer<'_, Error> for ValueDeserializer { |
227 | type Deserializer = Self; |
228 | |
229 | fn into_deserializer(self) -> Self::Deserializer { |
230 | self |
231 | } |
232 | } |
233 | |
234 | impl serde::de::IntoDeserializer<'_, Error> for crate::Value { |
235 | type Deserializer = ValueDeserializer; |
236 | |
237 | fn into_deserializer(self) -> Self::Deserializer { |
238 | ValueDeserializer::new(input:crate::Item::Value(self)) |
239 | } |
240 | } |
241 | |
242 | impl crate::Item { |
243 | pub(crate) fn into_deserializer(self) -> ValueDeserializer { |
244 | ValueDeserializer::new(self) |
245 | } |
246 | } |
247 | |
248 | #[cfg (feature = "parse" )] |
249 | impl std::str::FromStr for ValueDeserializer { |
250 | type Err = Error; |
251 | |
252 | /// Parses a value from a &str |
253 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
254 | let v: Value = crate::parser::parse_value(s).map_err(op:Error::from)?; |
255 | Ok(v.into_deserializer()) |
256 | } |
257 | } |
258 | |