collectd_plugin/de/
mod.rs

1mod deconfig;
2mod errors;
3mod level;
4pub use self::errors::*;
5
6use self::deconfig::*;
7use crate::api::ConfigItem;
8use serde::de::{self, Deserialize, DeserializeSeed, MapAccess, SeqAccess, Visitor};
9use serde::forward_to_deserialize_any;
10
11/// Serde documentation shadows the std's Result type which can be really confusing for Rust
12/// newcomers, so we compromise by creating an alias but prefixing with "De" to make it standout.
13pub type DeResult<T> = Result<T, Error>;
14
15/// Keeps track of the current state of deserialization.
16#[derive(Debug, Clone)]
17enum DeType<'a> {
18    /// The values that had the associated key
19    Item(&'a str, Vec<DeConfig<'a>>),
20
21    /// Vector of key, values tuples and the index that we are at in deserializing them
22    Struct(Vec<(&'a str, Vec<DeConfig<'a>>)>, usize),
23
24    /// The index of the current object we're deserializing and associated vector of objects
25    Seq(Vec<DeConfig<'a>>, usize),
26}
27
28pub struct Deserializer<'a> {
29    depth: Vec<DeType<'a>>,
30}
31
32impl<'a> Deserializer<'a> {
33    fn from_collectd(input: Vec<(&'a str, Vec<DeConfig<'a>>)>) -> Self {
34        Deserializer {
35            depth: vec![DeType::Struct(input, 0)],
36        }
37    }
38
39    fn current(&self) -> DeResult<&DeType<'a>> {
40        if self.depth.is_empty() {
41            return Err(Error(DeError::NoMoreValuesLeft));
42        }
43
44        Ok(&self.depth[self.depth.len() - 1])
45    }
46
47    fn grab_val(&self) -> DeResult<&DeConfig<'a>> {
48        match *self.current()? {
49            DeType::Item(_, ref values) => {
50                if values.len() != 1 {
51                    return Err(Error(DeError::ExpectSingleValue));
52                }
53
54                Ok(&values[0])
55            }
56            DeType::Seq(ref items, ind) => Ok(&items[ind]),
57            _ => Err(Error(DeError::ExpectSingleValue)),
58        }
59    }
60
61    fn grab_string(&self) -> DeResult<&'a str> {
62        if let DeConfig::String(x) = *self.grab_val()? {
63            Ok(x)
64        } else {
65            Err(Error(DeError::ExpectString))
66        }
67    }
68
69    fn grab_bool(&self) -> DeResult<bool> {
70        if let DeConfig::Boolean(x) = *self.grab_val()? {
71            Ok(x)
72        } else {
73            Err(Error(DeError::ExpectBoolean))
74        }
75    }
76
77    fn grab_number(&self) -> DeResult<f64> {
78        if let DeConfig::Number(x) = *self.grab_val()? {
79            Ok(x)
80        } else {
81            Err(Error(DeError::ExpectNumber))
82        }
83    }
84
85    fn pop(&mut self) {
86        self.depth.pop();
87    }
88
89    fn push(&mut self, pos: usize) {
90        // Find the parent -- it's either the tail element of depth or penultimate.
91        let cur = if pos == 0 { 1 } else { 2 };
92        let end = self.depth.len() - cur;
93
94        let mut t = None;
95        if let DeType::Struct(ref values, _ind) = self.depth[end] {
96            t = Some(values[pos].clone());
97        }
98
99        if let Some((key, vs)) = t {
100            if pos == 0 {
101                self.depth.push(DeType::Item(key, vs));
102            } else {
103                let end = self.depth.len() - 1;
104                self.depth[end] = DeType::Item(key, vs);
105            }
106        }
107    }
108
109    fn push_seq(&mut self, pos: usize) {
110        // Find the parent -- it's either the tail element of depth or penultimate.
111        let cur = if pos == 0 { 1 } else { 2 };
112        let end = self.depth.len() - cur;
113
114        let mut t = None;
115        if let DeType::Item(_key, ref values) = self.depth[end] {
116            t = Some(values.clone());
117        }
118
119        if let Some(vs) = t {
120            if pos == 0 {
121                self.depth.push(DeType::Seq(vs, pos));
122            } else {
123                let end = self.depth.len() - 1;
124                self.depth[end] = DeType::Seq(vs, pos);
125            }
126        }
127    }
128}
129
130pub fn from_collectd<'a, T>(s: &'a [ConfigItem<'a>]) -> DeResult<T>
131where
132    T: Deserialize<'a>,
133{
134    let props = from_config(s);
135    let mut deserializer = Deserializer::from_collectd(props);
136    T::deserialize(&mut deserializer)
137}
138
139impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> {
140    type Error = Error;
141
142    fn deserialize_bool<V>(self, visitor: V) -> DeResult<V::Value>
143    where
144        V: Visitor<'de>,
145    {
146        self.grab_bool().and_then(|x| visitor.visit_bool(x))
147    }
148
149    fn deserialize_string<V>(self, visitor: V) -> DeResult<V::Value>
150    where
151        V: Visitor<'de>,
152    {
153        self.grab_string()
154            .and_then(|x| visitor.visit_string(String::from(x)))
155    }
156
157    fn deserialize_str<V>(self, visitor: V) -> DeResult<V::Value>
158    where
159        V: Visitor<'de>,
160    {
161        self.grab_string()
162            .and_then(|x| visitor.visit_borrowed_str(x))
163    }
164
165    fn deserialize_i8<V>(self, visitor: V) -> DeResult<V::Value>
166    where
167        V: Visitor<'de>,
168    {
169        self.grab_number().and_then(|x| visitor.visit_i8(x as i8))
170    }
171
172    fn deserialize_i16<V>(self, visitor: V) -> DeResult<V::Value>
173    where
174        V: Visitor<'de>,
175    {
176        self.grab_number().and_then(|x| visitor.visit_i16(x as i16))
177    }
178
179    fn deserialize_i32<V>(self, visitor: V) -> DeResult<V::Value>
180    where
181        V: Visitor<'de>,
182    {
183        self.grab_number().and_then(|x| visitor.visit_i32(x as i32))
184    }
185
186    fn deserialize_i64<V>(self, visitor: V) -> DeResult<V::Value>
187    where
188        V: Visitor<'de>,
189    {
190        self.grab_number().and_then(|x| visitor.visit_i64(x as i64))
191    }
192
193    fn deserialize_u8<V>(self, visitor: V) -> DeResult<V::Value>
194    where
195        V: Visitor<'de>,
196    {
197        self.grab_number().and_then(|x| visitor.visit_u8(x as u8))
198    }
199
200    fn deserialize_u16<V>(self, visitor: V) -> DeResult<V::Value>
201    where
202        V: Visitor<'de>,
203    {
204        self.grab_number().and_then(|x| visitor.visit_u16(x as u16))
205    }
206
207    fn deserialize_u32<V>(self, visitor: V) -> DeResult<V::Value>
208    where
209        V: Visitor<'de>,
210    {
211        self.grab_number().and_then(|x| visitor.visit_u32(x as u32))
212    }
213
214    fn deserialize_u64<V>(self, visitor: V) -> DeResult<V::Value>
215    where
216        V: Visitor<'de>,
217    {
218        self.grab_number().and_then(|x| visitor.visit_u64(x as u64))
219    }
220
221    fn deserialize_f32<V>(self, visitor: V) -> DeResult<V::Value>
222    where
223        V: Visitor<'de>,
224    {
225        self.grab_number().and_then(|x| visitor.visit_f32(x as f32))
226    }
227
228    fn deserialize_f64<V>(self, visitor: V) -> DeResult<V::Value>
229    where
230        V: Visitor<'de>,
231    {
232        self.grab_number().and_then(|x| visitor.visit_f64(x))
233    }
234
235    fn deserialize_option<V>(self, visitor: V) -> DeResult<V::Value>
236    where
237        V: Visitor<'de>,
238    {
239        visitor.visit_some(self)
240    }
241
242    fn deserialize_char<V>(self, visitor: V) -> DeResult<V::Value>
243    where
244        V: Visitor<'de>,
245    {
246        self.grab_string().and_then(|x| {
247            if x.len() != 1 {
248                Err(Error(DeError::ExpectChar(String::from(x))))
249            } else {
250                visitor.visit_char(x.chars().next().unwrap())
251            }
252        })
253    }
254
255    fn deserialize_identifier<V>(self, visitor: V) -> DeResult<V::Value>
256    where
257        V: Visitor<'de>,
258    {
259        let v = &self.depth[self.depth.len() - 1];
260        match *v {
261            DeType::Item(key, _) => visitor.visit_borrowed_str(key),
262            DeType::Seq(ref x, pos) if pos == 0 => {
263                if let DeConfig::String(ss) = x[pos] {
264                    visitor.visit_borrowed_str(ss)
265                } else {
266                    Err(de::Error::custom("expected the first element, when deserializing for an identifier, to be a string"))
267                }
268            }
269            _ => Err(de::Error::custom(
270                "expected an item when deserializing identifier",
271            )),
272        }
273    }
274
275    fn deserialize_seq<V>(self, visitor: V) -> DeResult<V::Value>
276    where
277        V: Visitor<'de>,
278    {
279        let len = if let DeType::Item(_key, ref v) = *self.current()? {
280            v.len()
281        } else {
282            return Err(de::Error::custom("expected an item when deserializing seq"));
283        };
284
285        visitor.visit_seq(SeqSeparated::new(self, len))
286    }
287
288    fn deserialize_struct<V>(
289        self,
290        _name: &'static str,
291        _fields: &'static [&'static str],
292        visitor: V,
293    ) -> DeResult<V::Value>
294    where
295        V: Visitor<'de>,
296    {
297        // A small hack to remember if we dive into a sequence's children. Since we're going down
298        // two levels, we need to remember to pop back up when were down the children.
299        let mut to_pop = false;
300
301        let t = match self.current()?.clone() {
302            DeType::Struct(ref values, _ind) => Some(values.len()),
303            DeType::Seq(ref values, ind) => {
304                if let DeConfig::Object(ref obj) = values[ind] {
305                    // Push the children onto the stack
306                    let s = DeType::Struct(obj.clone(), 0);
307                    self.depth.push(s);
308                    to_pop = true;
309                    Some(obj.len())
310                } else {
311                    return Err(Error(DeError::ExpectObject));
312                }
313            }
314            _ => None,
315        };
316
317        let res = visitor.visit_map(FieldSeparated::new(self, t.unwrap_or(0)))?;
318        if to_pop {
319            self.pop();
320        }
321        Ok(res)
322    }
323
324    fn deserialize_ignored_any<V>(self, visitor: V) -> DeResult<V::Value>
325    where
326        V: Visitor<'de>,
327    {
328        visitor.visit_none()
329    }
330
331    fn deserialize_any<V>(self, _visitor: V) -> DeResult<V::Value>
332    where
333        V: Visitor<'de>,
334    {
335        Err(Error(DeError::DataTypeNotSupported))
336    }
337
338    fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> DeResult<V::Value>
339    where
340        V: Visitor<'de>,
341    {
342        visitor.visit_newtype_struct(self)
343    }
344
345    fn deserialize_enum<V>(
346        self,
347        _name: &str,
348        _variants: &'static [&'static str],
349        visitor: V,
350    ) -> DeResult<V::Value>
351    where
352        V: Visitor<'de>,
353    {
354        if let DeType::Item(_key, ref v) = self.current()?.clone() {
355            if v.len() != 1 {
356                return Err(de::Error::custom(
357                    "expected enum item to have a single item list",
358                ));
359            }
360
361            // With a unit variant enum, it needs to take a look at the identifier, so in the case
362            // deserializing JSON {"level": "INFO"} serde will attempt to deserialize two identifiers
363            // in a row (first "level" and then "INFO"). Since we don't want to re-read the "level"
364            // identifier we simulate sequence. Not the most elegant solution, but it works.
365            self.push_seq(0);
366            let res = visitor.visit_enum(UnitVariantAccess::new(self))?;
367            self.pop();
368            Ok(res)
369        } else {
370            Err(Error(DeError::ExpectStruct))
371        }
372    }
373
374    forward_to_deserialize_any! {
375        bytes
376        byte_buf unit unit_struct tuple
377        tuple_struct map
378    }
379}
380
381struct UnitVariantAccess<'a, 'de: 'a> {
382    de: &'a mut Deserializer<'de>,
383}
384
385impl<'a, 'de: 'a> UnitVariantAccess<'a, 'de> {
386    fn new(de: &'a mut Deserializer<'de>) -> Self {
387        UnitVariantAccess { de }
388    }
389}
390
391impl<'de> de::EnumAccess<'de> for UnitVariantAccess<'_, 'de> {
392    type Error = Error;
393    type Variant = Self;
394
395    fn variant_seed<V>(self, seed: V) -> DeResult<(V::Value, Self)>
396    where
397        V: de::DeserializeSeed<'de>,
398    {
399        let variant = seed.deserialize(&mut *self.de)?;
400        Ok((variant, self))
401    }
402}
403
404impl<'de> de::VariantAccess<'de> for UnitVariantAccess<'_, 'de> {
405    type Error = Error;
406
407    fn unit_variant(self) -> DeResult<()> {
408        Ok(())
409    }
410
411    fn newtype_variant_seed<T>(self, _seed: T) -> DeResult<T::Value>
412    where
413        T: de::DeserializeSeed<'de>,
414    {
415        Err(de::Error::custom("newtype variant"))
416    }
417
418    fn tuple_variant<V>(self, _len: usize, _visitor: V) -> DeResult<V::Value>
419    where
420        V: de::Visitor<'de>,
421    {
422        Err(de::Error::custom("tuple variant"))
423    }
424
425    fn struct_variant<V>(self, _fields: &'static [&'static str], _visitor: V) -> DeResult<V::Value>
426    where
427        V: de::Visitor<'de>,
428    {
429        Err(de::Error::custom("struct variant"))
430    }
431}
432
433struct FieldSeparated<'a, 'de: 'a> {
434    de: &'a mut Deserializer<'de>,
435    item_count: usize,
436    item_pos: usize,
437}
438
439impl<'a, 'de> FieldSeparated<'a, 'de> {
440    fn new(de: &'a mut Deserializer<'de>, item_count: usize) -> Self {
441        FieldSeparated {
442            de,
443            item_pos: 0,
444            item_count,
445        }
446    }
447}
448
449impl<'de> MapAccess<'de> for FieldSeparated<'_, 'de> {
450    type Error = Error;
451
452    fn next_key_seed<K>(&mut self, seed: K) -> DeResult<Option<K::Value>>
453    where
454        K: DeserializeSeed<'de>,
455    {
456        // Check if there are no more entries.
457        if self.item_pos == self.item_count {
458            if self.item_count != 0 {
459                self.de.pop();
460            }
461            return Ok(None);
462        }
463
464        self.de.push(self.item_pos);
465        self.item_pos += 1;
466        seed.deserialize(&mut *self.de).map(Some)
467    }
468
469    fn next_value_seed<V>(&mut self, seed: V) -> DeResult<V::Value>
470    where
471        V: DeserializeSeed<'de>,
472    {
473        seed.deserialize(&mut *self.de)
474    }
475}
476
477struct SeqSeparated<'a, 'de: 'a> {
478    de: &'a mut Deserializer<'de>,
479    item_count: usize,
480    item_pos: usize,
481}
482
483impl<'a, 'de> SeqSeparated<'a, 'de> {
484    fn new(de: &'a mut Deserializer<'de>, item_count: usize) -> Self {
485        SeqSeparated {
486            de,
487            item_count,
488            item_pos: 0,
489        }
490    }
491}
492
493impl<'de> SeqAccess<'de> for SeqSeparated<'_, 'de> {
494    type Error = Error;
495
496    fn next_element_seed<T>(&mut self, seed: T) -> DeResult<Option<T::Value>>
497    where
498        T: DeserializeSeed<'de>,
499    {
500        if self.item_pos == self.item_count {
501            if self.item_count != 0 {
502                self.de.pop();
503            }
504            return Ok(None);
505        }
506
507        self.de.push_seq(self.item_pos);
508        self.item_pos += 1;
509        seed.deserialize(&mut *self.de).map(Some)
510    }
511}
512
513#[cfg(test)]
514mod tests {
515    use super::super::ConfigValue;
516    use super::*;
517    use crate::api::LogLevel;
518    use serde::Deserialize;
519
520    #[test]
521    fn test_serde_simple_bool() {
522        #[derive(Deserialize, PartialEq, Eq, Debug)]
523        struct MyStruct {
524            my_bool: bool,
525        }
526
527        let items = vec![ConfigItem {
528            key: "my_bool",
529            values: vec![ConfigValue::Boolean(true)],
530            children: vec![],
531        }];
532
533        let actual = from_collectd(&items).unwrap();
534        assert_eq!(MyStruct { my_bool: true }, actual);
535    }
536
537    #[test]
538    fn test_serde_empty_bool() {
539        #[derive(Deserialize, PartialEq, Eq, Debug)]
540        struct MyStruct {
541            my_bool: Option<bool>,
542        }
543
544        let actual = from_collectd(Default::default()).unwrap();
545        assert_eq!(MyStruct { my_bool: None }, actual);
546    }
547
548    #[test]
549    fn test_serde_simple_number() {
550        #[derive(Deserialize, PartialEq, Eq, Debug)]
551        struct MyStruct {
552            my_int: i8,
553        }
554
555        let items = vec![ConfigItem {
556            key: "my_int",
557            values: vec![ConfigValue::Number(1.0)],
558            children: vec![],
559        }];
560
561        let actual = from_collectd(&items).unwrap();
562        assert_eq!(MyStruct { my_int: 1 }, actual);
563    }
564
565    #[test]
566    fn test_serde_simple_string() {
567        #[derive(Deserialize, PartialEq, Eq, Debug)]
568        struct MyStruct {
569            my_string: String,
570        }
571
572        let items = vec![ConfigItem {
573            key: "my_string",
574            values: vec![ConfigValue::String("HEY")],
575            children: vec![],
576        }];
577
578        let actual = from_collectd(&items).unwrap();
579        assert_eq!(
580            MyStruct {
581                my_string: String::from("HEY"),
582            },
583            actual
584        );
585    }
586
587    #[test]
588    fn test_serde_simple_str() {
589        #[derive(Deserialize, PartialEq, Eq, Debug)]
590        struct MyStruct<'a> {
591            my_string: &'a str,
592        }
593
594        let items = vec![ConfigItem {
595            key: "my_string",
596            values: vec![ConfigValue::String("HEY")],
597            children: vec![],
598        }];
599
600        let actual = from_collectd(&items).unwrap();
601        assert_eq!(MyStruct { my_string: "HEY" }, actual);
602    }
603
604    #[test]
605    fn test_serde_multiple() {
606        #[derive(Deserialize, PartialEq, Eq, Debug)]
607        struct MyStruct {
608            my_bool: bool,
609            my_string: String,
610        }
611
612        let items = vec![
613            ConfigItem {
614                key: "my_bool",
615                values: vec![ConfigValue::Boolean(true)],
616                children: vec![],
617            },
618            ConfigItem {
619                key: "my_string",
620                values: vec![ConfigValue::String("/")],
621                children: vec![],
622            },
623        ];
624
625        let actual = from_collectd(&items).unwrap();
626        assert_eq!(
627            MyStruct {
628                my_bool: true,
629                my_string: String::from("/"),
630            },
631            actual
632        );
633    }
634
635    #[test]
636    fn test_serde_bool_vec() {
637        #[derive(Deserialize, PartialEq, Eq, Debug)]
638        struct MyStruct {
639            my_bool: Vec<bool>,
640        }
641
642        let items = vec![ConfigItem {
643            key: "my_bool",
644            values: vec![ConfigValue::Boolean(true), ConfigValue::Boolean(false)],
645            children: vec![],
646        }];
647
648        let actual = from_collectd(&items).unwrap();
649        assert_eq!(
650            MyStruct {
651                my_bool: vec![true, false],
652            },
653            actual
654        );
655    }
656
657    #[test]
658    fn test_serde_bool_vec_sep() {
659        #[derive(Deserialize, PartialEq, Eq, Debug)]
660        struct MyStruct {
661            my_bool: Vec<bool>,
662        }
663
664        let items = vec![
665            ConfigItem {
666                key: "my_bool",
667                values: vec![ConfigValue::Boolean(true)],
668                children: vec![],
669            },
670            ConfigItem {
671                key: "my_bool",
672                values: vec![ConfigValue::Boolean(false)],
673                children: vec![],
674            },
675        ];
676
677        let actual = from_collectd(&items).unwrap();
678        assert_eq!(
679            MyStruct {
680                my_bool: vec![true, false],
681            },
682            actual
683        );
684    }
685
686    #[test]
687    fn test_serde_multiple_vec() {
688        #[derive(Deserialize, PartialEq, Debug)]
689        struct MyStruct {
690            my_bool: Vec<bool>,
691            my_num: Vec<f64>,
692        }
693
694        let items = vec![
695            ConfigItem {
696                key: "my_bool",
697                values: vec![ConfigValue::Boolean(true)],
698                children: vec![],
699            },
700            ConfigItem {
701                key: "my_bool",
702                values: vec![ConfigValue::Boolean(false)],
703                children: vec![],
704            },
705            ConfigItem {
706                key: "my_num",
707                values: vec![ConfigValue::Number(10.0), ConfigValue::Number(12.0)],
708                children: vec![],
709            },
710        ];
711
712        let actual = from_collectd(&items).unwrap();
713        assert_eq!(
714            MyStruct {
715                my_bool: vec![true, false],
716                my_num: vec![10.0, 12.0],
717            },
718            actual
719        );
720    }
721
722    #[test]
723    fn test_serde_options() {
724        #[derive(Deserialize, PartialEq, Eq, Debug)]
725        struct MyStruct {
726            my_bool: Option<bool>,
727            my_string: Option<String>,
728        }
729
730        let items = vec![ConfigItem {
731            key: "my_bool",
732            values: vec![ConfigValue::Boolean(true)],
733            children: vec![],
734        }];
735
736        let actual = from_collectd(&items).unwrap();
737        assert_eq!(
738            MyStruct {
739                my_bool: Some(true),
740                my_string: None,
741            },
742            actual
743        );
744    }
745
746    #[test]
747    fn test_serde_log_level() {
748        #[derive(Deserialize, PartialEq, Eq, Debug)]
749        struct MyStruct {
750            warn: LogLevel,
751            warning: LogLevel,
752            err: LogLevel,
753            error: LogLevel,
754            debug: LogLevel,
755            info: LogLevel,
756            notice: LogLevel,
757        }
758
759        let items = vec![
760            ConfigItem {
761                key: "warn",
762                values: vec![ConfigValue::String("warn")],
763                children: vec![],
764            },
765            ConfigItem {
766                key: "warning",
767                values: vec![ConfigValue::String("Warning")],
768                children: vec![],
769            },
770            ConfigItem {
771                key: "err",
772                values: vec![ConfigValue::String("ErR")],
773                children: vec![],
774            },
775            ConfigItem {
776                key: "error",
777                values: vec![ConfigValue::String("Error")],
778                children: vec![],
779            },
780            ConfigItem {
781                key: "debug",
782                values: vec![ConfigValue::String("debug")],
783                children: vec![],
784            },
785            ConfigItem {
786                key: "info",
787                values: vec![ConfigValue::String("INFO")],
788                children: vec![],
789            },
790            ConfigItem {
791                key: "notice",
792                values: vec![ConfigValue::String("notice")],
793                children: vec![],
794            },
795        ];
796
797        let actual = from_collectd(&items).unwrap();
798        assert_eq!(
799            MyStruct {
800                warn: LogLevel::Warning,
801                warning: LogLevel::Warning,
802                err: LogLevel::Error,
803                error: LogLevel::Error,
804                debug: LogLevel::Debug,
805                info: LogLevel::Info,
806                notice: LogLevel::Notice,
807            },
808            actual
809        );
810    }
811
812    #[test]
813    fn test_serde_char() {
814        #[derive(Deserialize, PartialEq, Eq, Debug)]
815        struct MyStruct {
816            my_char: char,
817        }
818
819        let items = vec![ConfigItem {
820            key: "my_char",
821            values: vec![ConfigValue::String("/")],
822            children: vec![],
823        }];
824
825        let actual = from_collectd(&items).unwrap();
826        assert_eq!(MyStruct { my_char: '/' }, actual);
827    }
828
829    #[test]
830    fn test_serde_ignore() {
831        #[derive(Deserialize, PartialEq, Eq, Debug)]
832        struct MyStruct {
833            my_char: char,
834        }
835
836        let items = vec![
837            ConfigItem {
838                key: "my_char",
839                values: vec![ConfigValue::String("/")],
840                children: vec![],
841            },
842            ConfigItem {
843                key: "my_boat",
844                values: vec![ConfigValue::String("/")],
845                children: vec![],
846            },
847        ];
848
849        let actual = from_collectd(&items).unwrap();
850        assert_eq!(MyStruct { my_char: '/' }, actual);
851    }
852
853    #[test]
854    fn test_serde_nested() {
855        #[derive(Deserialize, PartialEq, Eq, Debug)]
856        struct MyPort {
857            port: i32,
858        }
859
860        #[derive(Deserialize, PartialEq, Eq, Debug)]
861        struct MyStruct {
862            ports: Vec<MyPort>,
863        }
864
865        let items = vec![
866            ConfigItem {
867                key: "ports",
868                values: vec![],
869                children: vec![ConfigItem {
870                    key: "port",
871                    values: vec![ConfigValue::Number(2003.0)],
872                    children: vec![],
873                }],
874            },
875            ConfigItem {
876                key: "ports",
877                values: vec![],
878                children: vec![ConfigItem {
879                    key: "port",
880                    values: vec![ConfigValue::Number(2004.0)],
881                    children: vec![],
882                }],
883            },
884        ];
885
886        let actual = from_collectd(&items).unwrap();
887        assert_eq!(
888            MyStruct {
889                ports: vec![MyPort { port: 2003 }, MyPort { port: 2004 }],
890            },
891            actual
892        );
893    }
894
895    #[test]
896    fn test_serde_nested_multiple() {
897        #[derive(Deserialize, PartialEq, Eq, Debug)]
898        struct MyAddress {
899            port: i32,
900            host: String,
901        }
902
903        #[derive(Deserialize, PartialEq, Eq, Debug)]
904        struct MyStruct {
905            address: Vec<MyAddress>,
906        }
907
908        let items = vec![
909            ConfigItem {
910                key: "address",
911                values: vec![],
912                children: vec![
913                    ConfigItem {
914                        key: "port",
915                        values: vec![ConfigValue::Number(2003.0)],
916                        children: vec![],
917                    },
918                    ConfigItem {
919                        key: "host",
920                        values: vec![ConfigValue::String("localhost")],
921                        children: vec![],
922                    },
923                ],
924            },
925            ConfigItem {
926                key: "address",
927                values: vec![],
928                children: vec![
929                    ConfigItem {
930                        key: "host",
931                        values: vec![ConfigValue::String("127.0.0.1")],
932                        children: vec![],
933                    },
934                    ConfigItem {
935                        key: "port",
936                        values: vec![ConfigValue::Number(2004.0)],
937                        children: vec![],
938                    },
939                ],
940            },
941        ];
942
943        let actual = from_collectd(&items).unwrap();
944        assert_eq!(
945            MyStruct {
946                address: vec![
947                    MyAddress {
948                        host: String::from("localhost"),
949                        port: 2003,
950                    },
951                    MyAddress {
952                        host: String::from("127.0.0.1"),
953                        port: 2004,
954                    },
955                ],
956            },
957            actual
958        );
959    }
960
961    #[test]
962    fn test_serde_new_type() {
963        #[derive(Deserialize, PartialEq, Eq, Debug)]
964        struct MyNew(String);
965
966        #[derive(Deserialize, PartialEq, Eq, Debug)]
967        struct MyStruct {
968            it: MyNew,
969        }
970
971        let items = vec![ConfigItem {
972            key: "it",
973            values: vec![ConfigValue::String("INFO")],
974            children: vec![],
975        }];
976
977        let actual = from_collectd(&items).unwrap();
978        assert_eq!(
979            MyStruct {
980                it: MyNew(String::from("INFO"))
981            },
982            actual
983        );
984    }
985
986    #[test]
987    fn test_log_serde_enum() {
988        use log::Level;
989
990        #[derive(Deserialize, PartialEq, Eq, Debug)]
991        #[serde(deny_unknown_fields)]
992        struct MyStruct {
993            it: Level,
994            sentinel: i32,
995        }
996
997        let items = vec![
998            ConfigItem {
999                key: "it",
1000                values: vec![ConfigValue::String("INFO")],
1001                children: vec![],
1002            },
1003            ConfigItem {
1004                key: "sentinel",
1005                values: vec![ConfigValue::Number(2003.0)],
1006                children: vec![],
1007            },
1008        ];
1009
1010        let actual = from_collectd(&items).unwrap();
1011        assert_eq!(
1012            MyStruct {
1013                it: Level::Info,
1014                sentinel: 2003
1015            },
1016            actual
1017        );
1018    }
1019
1020    #[test]
1021    fn test_serde_enum() {
1022        #[derive(PartialEq, Eq, Debug)]
1023        enum MyEnum {
1024            Foo,
1025        }
1026
1027        use serde::de::{self, Deserializer};
1028
1029        impl<'de> Deserialize<'de> for MyEnum {
1030            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1031            where
1032                D: Deserializer<'de>,
1033            {
1034                let s = String::deserialize(deserializer)?;
1035                match s.as_str() {
1036                    "Foo" => Ok(MyEnum::Foo),
1037                    _ => Err(de::Error::custom(format!("bad type: {}", s))),
1038                }
1039            }
1040        }
1041
1042        #[derive(Deserialize, PartialEq, Eq, Debug)]
1043        #[serde(deny_unknown_fields)]
1044        struct MyStruct {
1045            it: MyEnum,
1046            sentinel: i32,
1047        }
1048
1049        let items = vec![
1050            ConfigItem {
1051                key: "it",
1052                values: vec![ConfigValue::String("Foo")],
1053                children: vec![],
1054            },
1055            ConfigItem {
1056                key: "sentinel",
1057                values: vec![ConfigValue::Number(2003.0)],
1058                children: vec![],
1059            },
1060        ];
1061
1062        let actual = from_collectd(&items).unwrap();
1063        assert_eq!(
1064            MyStruct {
1065                it: MyEnum::Foo,
1066                sentinel: 2003
1067            },
1068            actual
1069        );
1070    }
1071}