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