1use serde_core::de::IntoDeserializer as _;
2
3use crate::de::ArrayDeserializer;
4use crate::de::DatetimeDeserializer;
5use crate::de::Error;
6use crate::de::TableDeserializer;
7
8pub struct ValueDeserializer {
41 input: crate::Item,
42 validate_struct_keys: bool,
43}
44
45impl ValueDeserializer {
46 pub(crate) fn new(input: crate::Item) -> Self {
47 Self {
48 input,
49 validate_struct_keys: false,
50 }
51 }
52
53 pub(crate) fn with_struct_key_validation(mut self) -> Self {
54 self.validate_struct_keys = true;
55 self
56 }
57}
58
59impl<'de> serde_core::Deserializer<'de> for ValueDeserializer {
60 type Error = Error;
61
62 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
63 where
64 V: serde_core::de::Visitor<'de>,
65 {
66 let span = self.input.span();
67 match self.input {
68 crate::Item::None => visitor.visit_none(),
69 crate::Item::Value(crate::Value::String(v)) => visitor.visit_string(v.into_value()),
70 crate::Item::Value(crate::Value::Integer(v)) => visitor.visit_i64(v.into_value()),
71 crate::Item::Value(crate::Value::Float(v)) => visitor.visit_f64(v.into_value()),
72 crate::Item::Value(crate::Value::Boolean(v)) => visitor.visit_bool(v.into_value()),
73 crate::Item::Value(crate::Value::Datetime(v)) => {
74 visitor.visit_map(DatetimeDeserializer::new(v.into_value()))
75 }
76 crate::Item::Value(crate::Value::Array(v)) => {
77 ArrayDeserializer::new(v.values, v.span).deserialize_any(visitor)
78 }
79 crate::Item::Value(crate::Value::InlineTable(v)) => {
80 TableDeserializer::new(v.items, v.span).deserialize_any(visitor)
81 }
82 crate::Item::Table(v) => {
83 TableDeserializer::new(v.items, v.span).deserialize_any(visitor)
84 }
85 crate::Item::ArrayOfTables(v) => {
86 ArrayDeserializer::new(v.values, v.span).deserialize_any(visitor)
87 }
88 }
89 .map_err(|mut e: Self::Error| {
90 if e.span().is_none() {
91 e.set_span(span);
92 }
93 e
94 })
95 }
96
97 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
100 where
101 V: serde_core::de::Visitor<'de>,
102 {
103 let span = self.input.span();
104 visitor.visit_some(self).map_err(|mut e: Self::Error| {
105 if e.span().is_none() {
106 e.set_span(span);
107 }
108 e
109 })
110 }
111
112 fn deserialize_newtype_struct<V>(
113 self,
114 _name: &'static str,
115 visitor: V,
116 ) -> Result<V::Value, Error>
117 where
118 V: serde_core::de::Visitor<'de>,
119 {
120 let span = self.input.span();
121 visitor
122 .visit_newtype_struct(self)
123 .map_err(|mut e: Self::Error| {
124 if e.span().is_none() {
125 e.set_span(span);
126 }
127 e
128 })
129 }
130
131 fn deserialize_struct<V>(
132 self,
133 name: &'static str,
134 fields: &'static [&'static str],
135 visitor: V,
136 ) -> Result<V::Value, Error>
137 where
138 V: serde_core::de::Visitor<'de>,
139 {
140 if serde_spanned::de::is_spanned(name) {
141 if let Some(span) = self.input.span() {
142 return visitor.visit_map(
143 serde_spanned::de::SpannedDeserializer::<Self, Error>::new(self, span),
144 );
145 } else {
146 return Err(Error::custom("value is missing a span", None));
147 }
148 }
149
150 if toml_datetime::de::is_datetime(name) {
151 let span = self.input.span();
152 if let crate::Item::Value(crate::Value::Datetime(d)) = self.input {
153 return visitor
154 .visit_map(DatetimeDeserializer::new(d.into_value()))
155 .map_err(|mut e: Self::Error| {
156 if e.span().is_none() {
157 e.set_span(span);
158 }
159 e
160 });
161 }
162 }
163
164 if self.validate_struct_keys {
165 let span = self.input.span();
166 match &self.input {
167 crate::Item::Table(values) => validate_struct_keys(&values.items, fields),
168 crate::Item::Value(crate::Value::InlineTable(values)) => {
169 validate_struct_keys(&values.items, fields)
170 }
171 _ => Ok(()),
172 }
173 .map_err(|mut e: Self::Error| {
174 if e.span().is_none() {
175 e.set_span(span);
176 }
177 e
178 })?;
179 }
180
181 self.deserialize_any(visitor)
182 }
183
184 fn deserialize_enum<V>(
186 self,
187 name: &'static str,
188 variants: &'static [&'static str],
189 visitor: V,
190 ) -> Result<V::Value, Error>
191 where
192 V: serde_core::de::Visitor<'de>,
193 {
194 let span = self.input.span();
195 match self.input {
196 crate::Item::Value(crate::Value::String(v)) => {
197 visitor.visit_enum(v.into_value().into_deserializer())
198 }
199 crate::Item::Value(crate::Value::InlineTable(v)) => {
200 if v.is_empty() {
201 Err(Error::custom(
202 "wanted exactly 1 element, found 0 elements",
203 v.span(),
204 ))
205 } else if v.len() != 1 {
206 Err(Error::custom(
207 "wanted exactly 1 element, more than 1 element",
208 v.span(),
209 ))
210 } else {
211 TableDeserializer::new(v.items, v.span)
212 .deserialize_enum(name, variants, visitor)
213 }
214 }
215 crate::Item::Table(v) => {
216 TableDeserializer::new(v.items, v.span).deserialize_enum(name, variants, visitor)
217 }
218 e => Err(Error::custom("wanted string or table", e.span())),
219 }
220 .map_err(|mut e: Self::Error| {
221 if e.span().is_none() {
222 e.set_span(span);
223 }
224 e
225 })
226 }
227
228 serde_core::forward_to_deserialize_any! {
229 bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
230 bytes byte_buf map unit
231 ignored_any unit_struct tuple_struct tuple identifier
232 }
233}
234
235impl serde_core::de::IntoDeserializer<'_, Error> for ValueDeserializer {
236 type Deserializer = Self;
237
238 fn into_deserializer(self) -> Self::Deserializer {
239 self
240 }
241}
242
243impl serde_core::de::IntoDeserializer<'_, Error> for crate::Value {
244 type Deserializer = ValueDeserializer;
245
246 fn into_deserializer(self) -> Self::Deserializer {
247 ValueDeserializer::new(crate::Item::Value(self))
248 }
249}
250
251#[cfg(feature = "parse")]
252impl std::str::FromStr for ValueDeserializer {
253 type Err = Error;
254
255 fn from_str(s: &str) -> Result<Self, Self::Err> {
257 let value = s.parse::<crate::Value>().map_err(Error::from)?;
258 Ok(value.into_deserializer())
259 }
260}
261
262pub(crate) fn validate_struct_keys(
263 table: &crate::table::KeyValuePairs,
264 fields: &'static [&'static str],
265) -> Result<(), Error> {
266 let extra_fields = table
267 .keys()
268 .filter_map(|key| {
269 if !fields.contains(&key.get()) {
270 Some(key.clone())
271 } else {
272 None
273 }
274 })
275 .collect::<Vec<_>>();
276
277 if extra_fields.is_empty() {
278 Ok(())
279 } else {
280 Err(Error::custom(
281 format!(
282 "unexpected keys in table: {}, available keys: {}",
283 extra_fields
284 .iter()
285 .map(|k| k.get())
286 .collect::<Vec<_>>()
287 .join(", "),
288 fields.join(", "),
289 ),
290 extra_fields[0].span(),
291 ))
292 }
293}