1use std::collections::hash_map::IntoIter;
19use std::collections::HashMap;
20use std::iter::empty;
21
22use serde::de::value::MapDeserializer;
23use serde::de::value::SeqDeserializer;
24use serde::de::Deserializer;
25use serde::de::IntoDeserializer;
26use serde::de::Visitor;
27use serde::de::{self};
28
29use crate::*;
30
31pub fn new_xml_serialize_error(e: quick_xml::SeError) -> Error {
33 Error::new(ErrorKind::Unexpected, "serialize xml").set_source(e)
34}
35
36pub fn new_xml_deserialize_error(e: quick_xml::DeError) -> Error {
38 Error::new(ErrorKind::Unexpected, "deserialize xml").set_source(e)
39}
40
41pub fn new_json_serialize_error(e: serde_json::Error) -> Error {
43 Error::new(ErrorKind::Unexpected, "serialize json").set_source(e)
44}
45
46pub fn new_json_deserialize_error(e: serde_json::Error) -> Error {
48 Error::new(ErrorKind::Unexpected, "deserialize json").set_source(e)
49}
50
51pub struct ConfigDeserializer(MapDeserializer<'static, Pairs, de::value::Error>);
55
56impl ConfigDeserializer {
57 pub fn new(map: HashMap<String, String>) -> Self {
59 let pairs = Pairs(map.into_iter());
60 Self(MapDeserializer::new(pairs))
61 }
62}
63
64impl<'de> Deserializer<'de> for ConfigDeserializer {
65 type Error = de::value::Error;
66
67 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
68 where
69 V: Visitor<'de>,
70 {
71 self.deserialize_map(visitor)
72 }
73
74 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
75 where
76 V: Visitor<'de>,
77 {
78 visitor.visit_map(self.0)
79 }
80
81 serde::forward_to_deserialize_any! {
82 bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
83 bytes byte_buf unit_struct tuple_struct
84 identifier tuple ignored_any option newtype_struct enum
85 struct
86 }
87}
88
89struct Pairs(IntoIter<String, String>);
91
92impl Iterator for Pairs {
93 type Item = (String, Pair);
94
95 fn next(&mut self) -> Option<Self::Item> {
96 self.0.next().map(|(k, v)| (k.to_lowercase(), Pair(k, v)))
97 }
98}
99
100struct Pair(String, String);
102
103impl IntoDeserializer<'_, de::value::Error> for Pair {
104 type Deserializer = Self;
105
106 fn into_deserializer(self) -> Self::Deserializer {
107 self
108 }
109}
110
111impl<'de> Deserializer<'de> for Pair {
112 type Error = de::value::Error;
113
114 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
115 where
116 V: Visitor<'de>,
117 {
118 self.1.into_deserializer().deserialize_any(visitor)
119 }
120
121 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
122 where
123 V: Visitor<'de>,
124 {
125 match self.1.to_lowercase().as_str() {
126 "true" | "on" => true.into_deserializer().deserialize_bool(visitor),
127 "false" | "off" => false.into_deserializer().deserialize_bool(visitor),
128 _ => Err(de::Error::custom(format_args!(
129 "parse config '{}' with value '{}' failed for {:?}",
130 self.0, self.1, "invalid bool value"
131 ))),
132 }
133 }
134
135 fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
136 where
137 V: Visitor<'de>,
138 {
139 match self.1.parse::<i8>() {
140 Ok(val) => val.into_deserializer().deserialize_i8(visitor),
141 Err(e) => Err(de::Error::custom(format_args!(
142 "parse config '{}' with value '{}' failed for {:?}",
143 self.0, self.1, e
144 ))),
145 }
146 }
147
148 fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
149 where
150 V: Visitor<'de>,
151 {
152 match self.1.parse::<i16>() {
153 Ok(val) => val.into_deserializer().deserialize_i16(visitor),
154 Err(e) => Err(de::Error::custom(format_args!(
155 "parse config '{}' with value '{}' failed for {:?}",
156 self.0, self.1, e
157 ))),
158 }
159 }
160
161 fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
162 where
163 V: Visitor<'de>,
164 {
165 match self.1.parse::<i32>() {
166 Ok(val) => val.into_deserializer().deserialize_i32(visitor),
167 Err(e) => Err(de::Error::custom(format_args!(
168 "parse config '{}' with value '{}' failed for {:?}",
169 self.0, self.1, e
170 ))),
171 }
172 }
173
174 fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
175 where
176 V: Visitor<'de>,
177 {
178 match self.1.parse::<i64>() {
179 Ok(val) => val.into_deserializer().deserialize_i64(visitor),
180 Err(e) => Err(de::Error::custom(format_args!(
181 "parse config '{}' with value '{}' failed for {:?}",
182 self.0, self.1, e
183 ))),
184 }
185 }
186
187 fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
188 where
189 V: Visitor<'de>,
190 {
191 match self.1.parse::<u8>() {
192 Ok(val) => val.into_deserializer().deserialize_u8(visitor),
193 Err(e) => Err(de::Error::custom(format_args!(
194 "parse config '{}' with value '{}' failed for {:?}",
195 self.0, self.1, e
196 ))),
197 }
198 }
199
200 fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
201 where
202 V: Visitor<'de>,
203 {
204 match self.1.parse::<u16>() {
205 Ok(val) => val.into_deserializer().deserialize_u16(visitor),
206 Err(e) => Err(de::Error::custom(format_args!(
207 "parse config '{}' with value '{}' failed for {:?}",
208 self.0, self.1, e
209 ))),
210 }
211 }
212
213 fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
214 where
215 V: Visitor<'de>,
216 {
217 match self.1.parse::<u32>() {
218 Ok(val) => val.into_deserializer().deserialize_u32(visitor),
219 Err(e) => Err(de::Error::custom(format_args!(
220 "parse config '{}' with value '{}' failed for {:?}",
221 self.0, self.1, e
222 ))),
223 }
224 }
225
226 fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
227 where
228 V: Visitor<'de>,
229 {
230 match self.1.parse::<u64>() {
231 Ok(val) => val.into_deserializer().deserialize_u64(visitor),
232 Err(e) => Err(de::Error::custom(format_args!(
233 "parse config '{}' with value '{}' failed for {:?}",
234 self.0, self.1, e
235 ))),
236 }
237 }
238
239 fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
240 where
241 V: Visitor<'de>,
242 {
243 match self.1.parse::<f32>() {
244 Ok(val) => val.into_deserializer().deserialize_f32(visitor),
245 Err(e) => Err(de::Error::custom(format_args!(
246 "parse config '{}' with value '{}' failed for {:?}",
247 self.0, self.1, e
248 ))),
249 }
250 }
251
252 fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
253 where
254 V: Visitor<'de>,
255 {
256 match self.1.parse::<f64>() {
257 Ok(val) => val.into_deserializer().deserialize_f64(visitor),
258 Err(e) => Err(de::Error::custom(format_args!(
259 "parse config '{}' with value '{}' failed for {:?}",
260 self.0, self.1, e
261 ))),
262 }
263 }
264
265 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
266 where
267 V: Visitor<'de>,
268 {
269 if self.1.is_empty() {
270 visitor.visit_none()
271 } else {
272 visitor.visit_some(self)
273 }
274 }
275
276 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
277 where
278 V: Visitor<'de>,
279 {
280 if self.1.is_empty() {
282 SeqDeserializer::new(empty::<Pair>())
283 .deserialize_seq(visitor)
284 .map_err(|e| {
285 de::Error::custom(format_args!(
286 "parse config '{}' with value '{}' failed for {:?}",
287 self.0, self.1, e
288 ))
289 })
290 } else {
291 let values = self
292 .1
293 .split(',')
294 .map(|v| Pair(self.0.clone(), v.trim().to_owned()));
295 SeqDeserializer::new(values)
296 .deserialize_seq(visitor)
297 .map_err(|e| {
298 de::Error::custom(format_args!(
299 "parse config '{}' with value '{}' failed for {:?}",
300 self.0, self.1, e
301 ))
302 })
303 }
304 }
305
306 serde::forward_to_deserialize_any! {
307 char str string unit newtype_struct enum
308 bytes byte_buf map unit_struct tuple_struct
309 identifier tuple ignored_any
310 struct
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use serde::Deserialize;
317
318 use super::*;
319
320 #[derive(Debug, Default, Deserialize, Eq, PartialEq)]
321 #[serde(default)]
322 #[non_exhaustive]
323 pub struct TestConfig {
324 bool_value: bool,
325 bool_option_value_none: Option<bool>,
326 bool_option_value_some: Option<bool>,
327 bool_value_with_on: bool,
328 bool_value_with_off: bool,
329
330 string_value: String,
331 string_option_value_none: Option<String>,
332 string_option_value_some: Option<String>,
333
334 u8_value: u8,
335 u16_value: u16,
336 u32_value: u32,
337 u64_value: u64,
338 i8_value: i8,
339 i16_value: i16,
340 i32_value: i32,
341 i64_value: i64,
342
343 vec_value: Vec<String>,
344 vec_value_two: Vec<String>,
345 vec_none: Option<Vec<String>>,
346 vec_empty: Vec<String>,
347 }
348
349 #[test]
350 fn test_config_deserializer() {
351 let mut map = HashMap::new();
352 map.insert("bool_value", "true");
353 map.insert("bool_option_value_none", "");
354 map.insert("bool_option_value_some", "false");
355 map.insert("bool_value_with_on", "on");
356 map.insert("bool_value_with_off", "off");
357 map.insert("string_value", "hello");
358 map.insert("string_option_value_none", "");
359 map.insert("string_option_value_some", "hello");
360 map.insert("u8_value", "8");
361 map.insert("u16_value", "16");
362 map.insert("u32_value", "32");
363 map.insert("u64_value", "64");
364 map.insert("i8_value", "-8");
365 map.insert("i16_value", "16");
366 map.insert("i32_value", "-32");
367 map.insert("i64_value", "64");
368 map.insert("vec_value", "hello");
369 map.insert("vec_value_two", "hello,world");
370 map.insert("vec_none", "");
371 map.insert("vec_empty", "");
372 let map = map
373 .into_iter()
374 .map(|(k, v)| (k.to_string(), v.to_string()))
375 .collect();
376
377 let output = TestConfig::deserialize(ConfigDeserializer::new(map)).unwrap();
378 assert_eq!(
379 output,
380 TestConfig {
381 bool_value: true,
382 bool_option_value_none: None,
383 bool_option_value_some: Some(false),
384 bool_value_with_on: true,
385 bool_value_with_off: false,
386 string_value: "hello".to_string(),
387 string_option_value_none: None,
388 string_option_value_some: Some("hello".to_string()),
389 u8_value: 8,
390 u16_value: 16,
391 u32_value: 32,
392 u64_value: 64,
393 i8_value: -8,
394 i16_value: 16,
395 i32_value: -32,
396 i64_value: 64,
397 vec_value: vec!["hello".to_string()],
398 vec_value_two: vec!["hello".to_string(), "world".to_string()],
399 vec_none: None,
400 vec_empty: vec![],
401 }
402 );
403 }
404
405 #[test]
406 fn test_part_config_deserializer() {
407 let mut map = HashMap::new();
408 map.insert("bool_value", "true");
409 let map = map
410 .into_iter()
411 .map(|(k, v)| (k.to_string(), v.to_string()))
412 .collect();
413
414 let output = TestConfig::deserialize(ConfigDeserializer::new(map)).unwrap();
415 assert_eq!(
416 output,
417 TestConfig {
418 bool_value: true,
419 ..TestConfig::default()
420 }
421 );
422 }
423}