1use serde::de::IntoDeserializer as _;
2
3use crate::de::DatetimeDeserializer;
4use 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/// ```
37pub struct ValueDeserializer {
38 input: crate::Item,
39 validate_struct_keys: bool,
40}
41
42impl 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
58impl<'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
226impl serde::de::IntoDeserializer<'_, Error> for ValueDeserializer {
227 type Deserializer = Self;
228
229 fn into_deserializer(self) -> Self::Deserializer {
230 self
231 }
232}
233
234impl 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
242impl crate::Item {
243 pub(crate) fn into_deserializer(self) -> ValueDeserializer {
244 ValueDeserializer::new(self)
245 }
246}
247
248#[cfg(feature = "parse")]
249impl 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