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