serde_vici/
de.rs

1//! Deserialize VICI data to a Rust data structure.
2
3use std::{io, str};
4
5use serde::de::{self, IntoDeserializer};
6
7use crate::{
8    error::{Error, ErrorCode, Result},
9    read::{IoRead, Read, Reference, SliceRead},
10    value::ListElement,
11    ElementType,
12};
13
14#[derive(Clone, Debug, Eq, PartialEq)]
15pub(crate) enum State {
16    None,
17    Key,
18    Value,
19    SectionKey,
20    ListName,
21    ListItem(ListElement),
22}
23
24/// A structure for deserializing into Rust values using the VICI protocol.
25///
26/// # Example
27///
28/// ```
29/// use anyhow::Result;
30/// use serde::Deserialize;
31/// use std::collections::BTreeMap;
32///
33/// fn main() -> Result<()> {
34///     let input = vec![
35///         3, 4, b'k', b'e', b'y', b'1', 0, 6, b'v', b'a', b'l', b'u', b'e', b'1',
36///         3, 4, b'k', b'e', b'y', b'2', 0, 6, b'v', b'a', b'l', b'u', b'e', b'2',
37///     ];
38///     let mut de = serde_vici::Deserializer::from_slice(&input);
39///     let value = BTreeMap::deserialize(&mut de)?;
40///
41///     assert_eq!(
42///         value,
43///         {
44///             let mut object = BTreeMap::new();
45///             object.insert("key1", "value1");
46///             object.insert("key2", "value2");
47///             object
48///         }
49///     );
50///     Ok(())
51/// }
52/// ```
53pub struct Deserializer<R> {
54    read: R,
55    level: Option<usize>,
56    state: State,
57    scratch: Vec<u8>,
58}
59
60/// Deserialize an instance of type `T` from an IO stream of the VICI protocol.
61///
62/// The content of the IO Stream is deserialized directly from the stream while being buffered in memory by serde_vici.
63///
64/// # Errors
65/// Deserialization can fail if the structure of the input does not match the structure expected by `T`, for example if `T` is a struct type
66/// but the input contains something other than a VICI section. It can also fail if the structure is correct but `T`'s implementation of
67/// `Deserialize` decides that something is wrong with the data, for example required struct fields are missing from a VICI section.
68pub fn from_reader<R, T>(reader: R) -> Result<T>
69where
70    R: io::Read,
71    T: de::DeserializeOwned,
72{
73    let mut deserializer = Deserializer::new(IoRead::new(reader));
74    let value = de::Deserialize::deserialize(&mut deserializer)?;
75    Ok(value)
76}
77
78/// Deserialize an instance of type `T` from bytes of the VICI protocol.
79///
80/// # Errors
81/// Deserialization can fail if the structure of the input does not match the structure expected by `T`, for example if `T` is a struct type
82/// but the input contains something other than a VICI section. It can also fail if the structure is correct but `T`'s implementation of
83/// `Deserialize` decides that something is wrong with the data, for example required struct fields are missing from a VICI section.
84pub fn from_slice<'a, T>(slice: &'a [u8]) -> Result<T>
85where
86    T: de::Deserialize<'a>,
87{
88    let mut deserializer = Deserializer::new(SliceRead::new(slice));
89    let value = de::Deserialize::deserialize(&mut deserializer)?;
90    Ok(value)
91}
92
93impl<'de, R> Deserializer<R>
94where
95    R: Read<'de>,
96{
97    /// Creates a VICI deserializer from one of the possible serde_vici input sources.
98    ///
99    /// Typically it is more convenient to use either of the following methods instead:
100    ///
101    /// - Deserializer::from_reader
102    /// - Deserializer::from_slice
103    pub fn new(read: R) -> Self {
104        let level = None;
105        let state = State::None;
106        let scratch = vec![];
107        Self {
108            read,
109            level,
110            state,
111            scratch,
112        }
113    }
114
115    #[inline]
116    fn parse_element_type(&mut self) -> Result<ElementType> {
117        self.read.parse_element_type()
118    }
119
120    #[inline]
121    fn parse_str(&mut self) -> Result<Reference<'de, '_, str>> {
122        match &self.state {
123            State::Key | State::SectionKey | State::ListName => {
124                self.scratch.clear();
125                self.read.parse_key(&mut self.scratch)
126            },
127            State::Value | State::ListItem(_) => {
128                self.scratch.clear();
129                self.read.parse_value(&mut self.scratch)
130            },
131            State::None => Err(Error::io(io::Error::from(io::ErrorKind::InvalidData), Some(self.read.position()))),
132        }
133    }
134
135    #[inline]
136    fn parse_raw_value(&mut self) -> Result<Reference<'de, '_, [u8]>> {
137        match &self.state {
138            State::Value | State::ListItem(_) => {
139                self.scratch.clear();
140                self.read.parse_value_raw(&mut self.scratch)
141            },
142            _ => Err(Error::io(io::Error::from(io::ErrorKind::InvalidData), Some(self.read.position()))),
143        }
144    }
145
146    #[inline]
147    fn peek(&mut self) -> Result<usize> {
148        match &self.state {
149            State::Key | State::SectionKey | State::ListName => self.read.peek_key(),
150            State::Value | State::ListItem(_) => self.read.peek_value(),
151            State::None => Err(Error::io(io::Error::from(io::ErrorKind::InvalidData), Some(self.read.position()))),
152        }
153    }
154}
155
156impl<R> Deserializer<IoRead<R>>
157where
158    R: io::Read,
159{
160    /// Creates a VICI deserializer from an `io::Read`.
161    pub fn from_reader(reader: R) -> Self {
162        Deserializer::new(IoRead::new(reader))
163    }
164}
165
166impl<'a> Deserializer<SliceRead<'a>> {
167    /// Creates a VICI deserializer from a `&[u8]`.
168    pub fn from_slice(slice: &'a [u8]) -> Self {
169        Deserializer::new(SliceRead::new(slice))
170    }
171}
172
173macro_rules! deserialize_number {
174    ($method:ident => $visit:ident) => {
175        #[inline]
176        fn $method<V>(self, visitor: V) -> Result<V::Value>
177        where
178            V: de::Visitor<'de>,
179        {
180            let result = self.parse_str()?;
181            let value = result.parse().map_err::<Self::Error, _>(de::Error::custom)?;
182            visitor.$visit(value)
183        }
184    };
185}
186
187impl<'de, R> de::Deserializer<'de> for &mut Deserializer<R>
188where
189    R: Read<'de>,
190{
191    type Error = Error;
192
193    #[inline]
194    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
195    where
196        V: de::Visitor<'de>,
197    {
198        match &self.state {
199            State::Key | State::SectionKey | State::ListName => self.deserialize_str(visitor),
200            State::Value => self.deserialize_byte_buf(visitor),
201            State::ListItem(ListElement::String) => self.deserialize_seq(visitor),
202            State::ListItem(ListElement::Section) | State::None => self.deserialize_map(visitor),
203        }
204    }
205
206    #[inline]
207    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
208    where
209        V: de::Visitor<'de>,
210    {
211        let input = self.parse_str()?;
212        match &*input {
213            "yes" => visitor.visit_bool(true),
214            "no" => visitor.visit_bool(false),
215            _ => Err(Error::io(io::Error::from(io::ErrorKind::InvalidData), Some(self.read.position()))),
216        }
217    }
218
219    deserialize_number!(deserialize_i8 => visit_i8);
220    deserialize_number!(deserialize_i16 => visit_i16);
221    deserialize_number!(deserialize_i32 => visit_i32);
222    deserialize_number!(deserialize_i64 => visit_i64);
223    deserialize_number!(deserialize_u8 => visit_u8);
224    deserialize_number!(deserialize_u16 => visit_u16);
225    deserialize_number!(deserialize_u32 => visit_u32);
226    deserialize_number!(deserialize_u64 => visit_u64);
227    deserialize_number!(deserialize_f32 => visit_f32);
228    deserialize_number!(deserialize_f64 => visit_f64);
229    deserialize_number!(deserialize_char => visit_char);
230
231    #[inline]
232    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
233    where
234        V: de::Visitor<'de>,
235    {
236        match self.parse_str()? {
237            Reference::Borrowed(s) => visitor.visit_borrowed_str(s),
238            Reference::Copied(s) => visitor.visit_str(s),
239        }
240    }
241
242    #[inline]
243    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
244    where
245        V: de::Visitor<'de>,
246    {
247        self.deserialize_str(visitor)
248    }
249
250    #[inline]
251    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
252    where
253        V: de::Visitor<'de>,
254    {
255        match self.parse_raw_value()? {
256            Reference::Borrowed(s) => visitor.visit_borrowed_bytes(s),
257            Reference::Copied(s) => visitor.visit_bytes(s),
258        }
259    }
260
261    #[inline]
262    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
263    where
264        V: de::Visitor<'de>,
265    {
266        self.deserialize_bytes(visitor)
267    }
268
269    #[inline]
270    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
271    where
272        V: de::Visitor<'de>,
273    {
274        if self.state == State::None {
275            return visitor.visit_some(self);
276        }
277
278        match self.peek()? {
279            0 => {
280                self.parse_str()?;
281                visitor.visit_none()
282            },
283            _ => visitor.visit_some(self),
284        }
285    }
286
287    #[inline]
288    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
289    where
290        V: de::Visitor<'de>,
291    {
292        visitor.visit_unit()
293    }
294
295    #[inline]
296    fn deserialize_unit_struct<V>(self, _: &'static str, visitor: V) -> Result<V::Value>
297    where
298        V: de::Visitor<'de>,
299    {
300        self.deserialize_unit(visitor)
301    }
302
303    #[inline]
304    fn deserialize_newtype_struct<V>(self, _: &'static str, visitor: V) -> Result<V::Value>
305    where
306        V: de::Visitor<'de>,
307    {
308        visitor.visit_newtype_struct(self)
309    }
310
311    #[inline]
312    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
313    where
314        V: de::Visitor<'de>,
315    {
316        visitor.visit_seq(self)
317    }
318
319    #[inline]
320    fn deserialize_tuple<V>(self, _: usize, visitor: V) -> Result<V::Value>
321    where
322        V: de::Visitor<'de>,
323    {
324        visitor.visit_seq(self)
325    }
326
327    #[inline]
328    fn deserialize_tuple_struct<V>(self, _: &'static str, _: usize, visitor: V) -> Result<V::Value>
329    where
330        V: de::Visitor<'de>,
331    {
332        visitor.visit_seq(self)
333    }
334
335    #[inline]
336    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
337    where
338        V: de::Visitor<'de>,
339    {
340        visitor.visit_map(self)
341    }
342
343    #[inline]
344    fn deserialize_struct<V>(self, _: &'static str, _: &'static [&'static str], visitor: V) -> Result<V::Value>
345    where
346        V: de::Visitor<'de>,
347    {
348        visitor.visit_map(self)
349    }
350
351    #[inline]
352    fn deserialize_enum<V>(self, _: &'static str, _: &'static [&'static str], visitor: V) -> Result<V::Value>
353    where
354        V: de::Visitor<'de>,
355    {
356        let input = self.parse_str()?;
357        visitor.visit_enum(input.into_deserializer())
358    }
359
360    #[inline]
361    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
362    where
363        V: de::Visitor<'de>,
364    {
365        self.deserialize_str(visitor)
366    }
367
368    #[inline]
369    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
370    where
371        V: de::Visitor<'de>,
372    {
373        self.deserialize_any(visitor)
374    }
375
376    #[inline]
377    fn is_human_readable(&self) -> bool {
378        false
379    }
380}
381
382#[doc(hidden)]
383impl<'de, R> de::SeqAccess<'de> for &mut Deserializer<R>
384where
385    R: Read<'de>,
386{
387    type Error = Error;
388
389    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
390    where
391        T: de::DeserializeSeed<'de>,
392    {
393        match self.parse_element_type()? {
394            ElementType::ListItem if matches!(self.state, State::ListItem(ListElement::String)) => {
395                self.state = State::Value;
396                let value = seed.deserialize(&mut **self).map(Some)?;
397
398                self.state = State::ListItem(ListElement::String);
399                Ok(value)
400            },
401            ElementType::ListEnd if matches!(self.state, State::ListItem(ListElement::String)) => {
402                self.level = self.level.map(|l| l - 1).filter(|&l| l > 0);
403                self.state = State::None;
404                Ok(None)
405            },
406            ElementType::SectionEnd if matches!(self.state, State::ListItem(ListElement::Section)) => {
407                self.level = self.level.map(|l| l - 1).filter(|&l| l > 0);
408                self.state = State::None;
409                Ok(None)
410            },
411            ElementType::SectionStart => {
412                self.level = Some(self.level.map_or(1, |l| l + 1));
413
414                self.state = State::SectionKey;
415                let _index = self.parse_str()?;
416
417                self.state = State::ListItem(ListElement::Section);
418                let value = seed.deserialize(&mut **self).map(Some)?;
419
420                self.state = State::ListItem(ListElement::Section);
421                Ok(value)
422            },
423            v => Err(Error::data(
424                ErrorCode::Message("unexpected element type".into()),
425                Some(v as u8),
426                Some(self.read.position()),
427            )),
428        }
429    }
430}
431
432#[doc(hidden)]
433impl<'de, R> de::MapAccess<'de> for &mut Deserializer<R>
434where
435    R: Read<'de>,
436{
437    type Error = Error;
438
439    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
440    where
441        K: de::DeserializeSeed<'de>,
442    {
443        match self.parse_element_type() {
444            Ok(ElementType::SectionStart) => {
445                self.level = Some(self.level.map_or(1, |l| l + 1));
446                self.state = State::SectionKey;
447                seed.deserialize(&mut **self).map(Some)
448            },
449            Ok(ElementType::ListStart) => {
450                self.level = Some(self.level.map_or(1, |l| l + 1));
451                self.state = State::ListName;
452                seed.deserialize(&mut **self).map(Some)
453            },
454            Ok(ElementType::KeyValue) => {
455                self.state = State::Key;
456                seed.deserialize(&mut **self).map(Some)
457            },
458            Ok(ElementType::SectionEnd) if self.level.is_some() => {
459                self.level = self.level.map(|l| l - 1).filter(|&l| l > 0);
460                self.state = State::None;
461                Ok(None)
462            },
463            Ok(v) => Err(Error::data(
464                ErrorCode::Message("unexpected element type".into()),
465                Some(v as u8),
466                Some(self.read.position()),
467            )),
468            Err(e) if e.is_eof() && self.level.is_none() => Ok(None),
469            Err(e) => Err(e),
470        }
471    }
472
473    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
474    where
475        V: de::DeserializeSeed<'de>,
476    {
477        match &self.state {
478            State::ListName => {
479                self.state = State::ListItem(ListElement::String);
480                seed.deserialize(&mut **self)
481            },
482            State::Key => {
483                self.state = State::Value;
484                seed.deserialize(&mut **self)
485            },
486            _ => {
487                self.state = State::None;
488                seed.deserialize(&mut **self)
489            },
490        }
491    }
492}
493
494#[cfg(test)]
495mod tests {
496    use indexmap::{indexmap, IndexMap};
497    use pretty_assertions::assert_eq;
498    use serde_derive::Deserialize;
499
500    use super::*;
501
502    #[test]
503    fn deserialize_reader_example() {
504        #[derive(Debug, Deserialize, Eq, PartialEq)]
505        struct RootSection {
506            key1: String,
507            section1: MainSection,
508        }
509
510        #[derive(Debug, Deserialize, Eq, PartialEq)]
511        struct MainSection {
512            #[serde(rename = "sub-section")]
513            sub_section: Option<SubSection>,
514            list1: Vec<String>,
515        }
516
517        #[derive(Debug, Deserialize, Eq, PartialEq)]
518        struct SubSection {
519            key2: String,
520        }
521
522        #[rustfmt::skip]
523        let data: &[_] = &[
524            // key1 = value1
525            3, 4, b'k', b'e', b'y', b'1', 0, 6, b'v', b'a', b'l', b'u', b'e', b'1',
526            // section1
527            1, 8, b's', b'e', b'c', b't', b'i', b'o', b'n', b'1',
528            // sub-section
529            1, 11, b's', b'u', b'b', b'-', b's', b'e', b'c', b't', b'i', b'o', b'n',
530            // key2 = value2
531            3, 4, b'k', b'e', b'y', b'2', 0, 6, b'v', b'a', b'l', b'u', b'e', b'2',
532            // sub-section end
533            2,
534            // list1
535            4, 5, b'l', b'i', b's', b't', b'1',
536            // item1
537            5, 0, 5, b'i', b't', b'e', b'm', b'1',
538            // item2
539            5, 0, 5, b'i', b't', b'e', b'm', b'2',
540            // list1 end
541            6,
542            // section1 end
543            2,
544        ];
545
546        let actual: RootSection = from_reader(data).unwrap();
547        assert_eq!(
548            actual,
549            RootSection {
550                key1: "value1".to_string(),
551                section1: MainSection {
552                    sub_section: Some(SubSection {
553                        key2: "value2".to_string(),
554                    }),
555                    list1: vec!["item1".to_string(), "item2".to_string()],
556                },
557            }
558        );
559    }
560
561    #[test]
562    fn deserialize_reader_none() {
563        #[derive(Debug, Deserialize, Eq, PartialEq)]
564        struct RootSection {
565            key1: String,
566            section1: MainSection,
567        }
568
569        #[derive(Debug, Deserialize, Eq, PartialEq)]
570        struct MainSection {
571            #[serde(rename = "sub-section")]
572            sub_section: Option<SubSection>,
573            list1: Vec<String>,
574        }
575
576        #[derive(Debug, Deserialize, Eq, PartialEq)]
577        struct SubSection {
578            key2: String,
579        }
580
581        #[rustfmt::skip]
582        let data: &[_] = &[
583            // key1 = value1
584            3, 4, b'k', b'e', b'y', b'1', 0, 6, b'v', b'a', b'l', b'u', b'e', b'1',
585            // section1
586            1, 8, b's', b'e', b'c', b't', b'i', b'o', b'n', b'1',
587            // list1
588            4, 5, b'l', b'i', b's', b't', b'1',
589            // item1
590            5, 0, 5, b'i', b't', b'e', b'm', b'1',
591            // item2
592            5, 0, 5, b'i', b't', b'e', b'm', b'2',
593            // list1 end
594            6,
595            // section1 end
596            2,
597        ];
598
599        let actual: RootSection = from_reader(data).unwrap();
600        assert_eq!(
601            actual,
602            RootSection {
603                key1: "value1".to_string(),
604                section1: MainSection {
605                    sub_section: None,
606                    list1: vec!["item1".to_string(), "item2".to_string()],
607                },
608            }
609        );
610    }
611
612    #[test]
613    fn deserialize_reader_pools() {
614        #[derive(Debug, Deserialize, Eq, PartialEq)]
615        struct Pool {
616            base: String,
617            size: u32,
618            online: u32,
619            offline: u32,
620            leases: Vec<Lease>,
621        }
622
623        #[derive(Debug, Deserialize, Eq, PartialEq)]
624        struct Lease {
625            address: String,
626            identity: Option<String>,
627            status: Status,
628        }
629
630        #[derive(Debug, Deserialize, Eq, PartialEq)]
631        enum Status {
632            #[serde(rename = "online")]
633            Online,
634            #[serde(rename = "offline")]
635            Offline,
636        }
637
638        #[rustfmt::skip]
639        let data: &[_] = &[
640            // pool-01
641            1, 7, b'p', b'o', b'o', b'l', b'-', b'0', b'1',
642            // base = 192.0.2.1
643            3, 4, b'b', b'a', b's', b'e', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'1',
644            // size = 4
645            3, 4, b's', b'i', b'z', b'e', 0, 1, b'4',
646            // online = 3,
647            3, 6, b'o', b'n', b'l', b'i', b'n', b'e', 0, 1, b'3',
648            // offline = 1,
649            3, 7, b'o', b'f', b'f', b'l', b'i', b'n', b'e', 0, 1, b'1',
650            // leases
651            1, 6, b'l', b'e', b'a', b's', b'e', b's',
652            // 0
653            1, 1, b'0',
654            // address = 192.0.2.2
655            3, 7, b'a', b'd', b'd', b'r', b'e', b's', b's', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'2',
656            // identity = identity-01
657            3, 8, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', 0, 11, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', b'-', b'0', b'1',
658            // status = online
659            3, 6, b's', b't', b'a', b't', b'u', b's', 0, 6, b'o', b'n', b'l', b'i', b'n', b'e',
660            // 0 end
661            2,
662            // 1
663            1, 1, b'1',
664            // address = 192.0.2.3
665            3, 7, b'a', b'd', b'd', b'r', b'e', b's', b's', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'3',
666            // identity = identity-02
667            3, 8, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', 0, 11, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', b'-', b'0', b'2',
668            // status = online
669            3, 6, b's', b't', b'a', b't', b'u', b's', 0, 6, b'o', b'n', b'l', b'i', b'n', b'e',
670            // 1 end
671            2,
672            // 2
673            1, 1, b'2',
674            // address = 192.0.2.4
675            3, 7, b'a', b'd', b'd', b'r', b'e', b's', b's', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'4',
676            // identity = identity-03
677            3, 8, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', 0, 11, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', b'-', b'0', b'3',
678            // status = online
679            3, 6, b's', b't', b'a', b't', b'u', b's', 0, 6, b'o', b'n', b'l', b'i', b'n', b'e',
680            // 2 end
681            2,
682            // 3
683            1, 1, b'3',
684            // address = 192.0.2.5
685            3, 7, b'a', b'd', b'd', b'r', b'e', b's', b's', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'5',
686            // identity =
687            3, 8, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', 0, 0,
688            // status = offline
689            3, 6, b's', b't', b'a', b't', b'u', b's', 0, 7, b'o', b'f', b'f', b'l', b'i', b'n', b'e',
690            // 3 end
691            2,
692            // leases end
693            2,
694            // pool-01 end
695            2,
696        ];
697
698        let actual: IndexMap<String, Pool> = from_reader(data).unwrap();
699        assert_eq!(
700            actual,
701            indexmap! {
702                "pool-01".to_string() => Pool {
703                    base: "192.0.2.1".to_string(),
704                    size: 4,
705                    online: 3,
706                    offline: 1,
707                    leases: vec![
708                        Lease {
709                            address: "192.0.2.2".to_string(),
710                            identity: Some("identity-01".to_string()),
711                            status: Status::Online,
712                        },
713                        Lease {
714                            address: "192.0.2.3".to_string(),
715                            identity: Some("identity-02".to_string()),
716                            status: Status::Online,
717                        },
718                        Lease {
719                            address: "192.0.2.4".to_string(),
720                            identity: Some("identity-03".to_string()),
721                            status: Status::Online,
722                        },
723                        Lease {
724                            address: "192.0.2.5".to_string(),
725                            identity: None,
726                            status: Status::Offline,
727                        },
728                    ],
729                },
730            }
731        );
732    }
733
734    #[test]
735    fn deserialize_reader_certs() {
736        #[derive(Debug, Deserialize, Eq, PartialEq)]
737        enum Type {
738            X509,
739            #[serde(rename = "X509_AC")]
740            X509Ac,
741            #[serde(rename = "X509_CRL")]
742            X509Crl,
743            #[serde(rename = "OCSP_RESPONSE")]
744            OcspResponse,
745            #[serde(rename = "PUBKEY")]
746            Pubkey,
747        }
748
749        #[derive(Debug, Deserialize, Eq, PartialEq)]
750        enum Flag {
751            #[serde(rename = "NONE")]
752            None,
753            CA,
754            AA,
755            #[serde(rename = "OCSP")]
756            Ocsp,
757        }
758
759        #[derive(Debug, Deserialize, Eq, PartialEq)]
760        struct CertResponse {
761            r#type: Type,
762            flag: Flag,
763            #[serde(with = "serde_bytes")]
764            data: Vec<u8>,
765        }
766
767        #[rustfmt::skip]
768        let data: &[_] = &[
769            // type = X509
770            3, 4, b't', b'y', b'p', b'e', 0, 4, b'X', b'5', b'0', b'9',
771            // flag = CA
772            3, 4, b'f', b'l', b'a', b'g', 0, 2, b'C', b'A',
773            // data = 0x00 0x01 0x02 0x03
774            3, 4, b'd', b'a', b't', b'a', 0, 4, 0x00, 0x01, 0x02, 0x03,
775        ];
776
777        let actual: CertResponse = from_reader(data).unwrap();
778        assert_eq!(
779            actual,
780            CertResponse {
781                r#type: Type::X509,
782                flag: Flag::CA,
783                data: vec![0x00, 0x01, 0x02, 0x03],
784            }
785        );
786    }
787
788    #[test]
789    fn deserialize_slice_example() {
790        #[derive(Debug, Deserialize, Eq, PartialEq)]
791        struct RootSection<'a> {
792            key1: &'a str,
793            section1: MainSection<'a>,
794        }
795
796        #[derive(Debug, Deserialize, Eq, PartialEq)]
797        struct MainSection<'a> {
798            #[serde(borrow, rename = "sub-section")]
799            sub_section: Option<SubSection<'a>>,
800            list1: Vec<&'a str>,
801        }
802
803        #[derive(Debug, Deserialize, Eq, PartialEq)]
804        struct SubSection<'a> {
805            key2: &'a str,
806        }
807
808        #[rustfmt::skip]
809        let data = &[
810            // key1 = value1
811            3, 4, b'k', b'e', b'y', b'1', 0, 6, b'v', b'a', b'l', b'u', b'e', b'1',
812            // section1
813            1, 8, b's', b'e', b'c', b't', b'i', b'o', b'n', b'1',
814            // sub-section
815            1, 11, b's', b'u', b'b', b'-', b's', b'e', b'c', b't', b'i', b'o', b'n',
816            // key2 = value2
817            3, 4, b'k', b'e', b'y', b'2', 0, 6, b'v', b'a', b'l', b'u', b'e', b'2',
818            // sub-section end
819            2,
820            // list1
821            4, 5, b'l', b'i', b's', b't', b'1',
822            // item1
823            5, 0, 5, b'i', b't', b'e', b'm', b'1',
824            // item2
825            5, 0, 5, b'i', b't', b'e', b'm', b'2',
826            // list1 end
827            6,
828            // section1 end
829            2,
830        ];
831
832        let actual: RootSection = from_slice(data).unwrap();
833        assert_eq!(
834            actual,
835            RootSection {
836                key1: "value1",
837                section1: MainSection {
838                    sub_section: Some(SubSection { key2: "value2" }),
839                    list1: vec!["item1", "item2",],
840                },
841            }
842        );
843    }
844
845    #[test]
846    fn deserialize_slice_none() {
847        #[derive(Debug, Deserialize, Eq, PartialEq)]
848        struct RootSection<'a> {
849            key1: &'a str,
850            section1: MainSection<'a>,
851        }
852
853        #[derive(Debug, Deserialize, Eq, PartialEq)]
854        struct MainSection<'a> {
855            #[serde(borrow, rename = "sub-section")]
856            sub_section: Option<SubSection<'a>>,
857            list1: Vec<&'a str>,
858        }
859
860        #[derive(Debug, Deserialize, Eq, PartialEq)]
861        struct SubSection<'a> {
862            key2: &'a str,
863        }
864
865        #[rustfmt::skip]
866        let data = &[
867            // key1 = value1
868            3, 4, b'k', b'e', b'y', b'1', 0, 6, b'v', b'a', b'l', b'u', b'e', b'1',
869            // section1
870            1, 8, b's', b'e', b'c', b't', b'i', b'o', b'n', b'1',
871            // list1
872            4, 5, b'l', b'i', b's', b't', b'1',
873            // item1
874            5, 0, 5, b'i', b't', b'e', b'm', b'1',
875            // item2
876            5, 0, 5, b'i', b't', b'e', b'm', b'2',
877            // list1 end
878            6,
879            // section1 end
880            2,
881        ];
882
883        let actual: RootSection = from_slice(data).unwrap();
884        assert_eq!(
885            actual,
886            RootSection {
887                key1: "value1",
888                section1: MainSection {
889                    sub_section: None,
890                    list1: vec!["item1", "item2",],
891                },
892            }
893        );
894    }
895
896    #[test]
897    fn deserialize_slice_pools() {
898        #[derive(Debug, Deserialize, Eq, PartialEq)]
899        struct Pool<'a> {
900            base: &'a str,
901            size: u32,
902            online: u32,
903            offline: u32,
904            #[serde(borrow)]
905            leases: Vec<Lease<'a>>,
906        }
907
908        #[derive(Debug, Deserialize, Eq, PartialEq)]
909        struct Lease<'a> {
910            address: &'a str,
911            identity: Option<&'a str>,
912            status: Status,
913        }
914
915        #[derive(Debug, Deserialize, Eq, PartialEq)]
916        enum Status {
917            #[serde(rename = "online")]
918            Online,
919            #[serde(rename = "offline")]
920            Offline,
921        }
922
923        #[rustfmt::skip]
924        let data = &[
925            // pool-01
926            1, 7, b'p', b'o', b'o', b'l', b'-', b'0', b'1',
927            // base = 192.0.2.1
928            3, 4, b'b', b'a', b's', b'e', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'1',
929            // size = 4
930            3, 4, b's', b'i', b'z', b'e', 0, 1, b'4',
931            // online = 3,
932            3, 6, b'o', b'n', b'l', b'i', b'n', b'e', 0, 1, b'3',
933            // offline = 1,
934            3, 7, b'o', b'f', b'f', b'l', b'i', b'n', b'e', 0, 1, b'1',
935            // leases
936            1, 6, b'l', b'e', b'a', b's', b'e', b's',
937            // 0
938            1, 1, b'0',
939            // address = 192.0.2.2
940            3, 7, b'a', b'd', b'd', b'r', b'e', b's', b's', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'2',
941            // identity = identity-01
942            3, 8, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', 0, 11, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', b'-', b'0', b'1',
943            // status = online
944            3, 6, b's', b't', b'a', b't', b'u', b's', 0, 6, b'o', b'n', b'l', b'i', b'n', b'e',
945            // 0 end
946            2,
947            // 1
948            1, 1, b'1',
949            // address = 192.0.2.3
950            3, 7, b'a', b'd', b'd', b'r', b'e', b's', b's', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'3',
951            // identity = identity-02
952            3, 8, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', 0, 11, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', b'-', b'0', b'2',
953            // status = online
954            3, 6, b's', b't', b'a', b't', b'u', b's', 0, 6, b'o', b'n', b'l', b'i', b'n', b'e',
955            // 1 end
956            2,
957            // 2
958            1, 1, b'2',
959            // address = 192.0.2.4
960            3, 7, b'a', b'd', b'd', b'r', b'e', b's', b's', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'4',
961            // identity = identity-03
962            3, 8, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', 0, 11, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', b'-', b'0', b'3',
963            // status = online
964            3, 6, b's', b't', b'a', b't', b'u', b's', 0, 6, b'o', b'n', b'l', b'i', b'n', b'e',
965            // 2 end
966            2,
967            // 3
968            1, 1, b'3',
969            // address = 192.0.2.5
970            3, 7, b'a', b'd', b'd', b'r', b'e', b's', b's', 0, 9, b'1', b'9', b'2', b'.', b'0', b'.', b'2', b'.', b'5',
971            // identity =
972            3, 8, b'i', b'd', b'e', b'n', b't', b'i', b't', b'y', 0, 0,
973            // status = offline
974            3, 6, b's', b't', b'a', b't', b'u', b's', 0, 7, b'o', b'f', b'f', b'l', b'i', b'n', b'e',
975            // 3 end
976            2,
977            // leases end
978            2,
979            // pool-01 end
980            2,
981        ];
982
983        let actual: IndexMap<&str, Pool> = from_slice(data).unwrap();
984        assert_eq!(
985            actual,
986            indexmap! {
987                "pool-01" => Pool {
988                    base: "192.0.2.1",
989                    size: 4,
990                    online: 3,
991                    offline: 1,
992                    leases: vec![
993                        Lease {
994                            address: "192.0.2.2",
995                            identity: Some("identity-01"),
996                            status: Status::Online,
997                        },
998                        Lease {
999                            address: "192.0.2.3",
1000                            identity: Some("identity-02"),
1001                            status: Status::Online,
1002                        },
1003                        Lease {
1004                            address: "192.0.2.4",
1005                            identity: Some("identity-03"),
1006                            status: Status::Online,
1007                        },
1008                        Lease {
1009                            address: "192.0.2.5",
1010                            identity: None,
1011                            status: Status::Offline,
1012                        },
1013                    ],
1014                },
1015            }
1016        );
1017    }
1018
1019    #[test]
1020    fn deserialize_slice_certs() {
1021        #[derive(Debug, Deserialize, Eq, PartialEq)]
1022        enum Type {
1023            X509,
1024            #[serde(rename = "X509_AC")]
1025            X509Ac,
1026            #[serde(rename = "X509_CRL")]
1027            X509Crl,
1028            #[serde(rename = "OCSP_RESPONSE")]
1029            OcspResponse,
1030            #[serde(rename = "PUBKEY")]
1031            Pubkey,
1032        }
1033
1034        #[derive(Debug, Deserialize, Eq, PartialEq)]
1035        enum Flag {
1036            #[serde(rename = "NONE")]
1037            None,
1038            CA,
1039            AA,
1040            #[serde(rename = "OCSP")]
1041            Ocsp,
1042        }
1043
1044        #[derive(Debug, Deserialize, Eq, PartialEq)]
1045        struct CertResponse {
1046            r#type: Type,
1047            flag: Flag,
1048            #[serde(with = "serde_bytes")]
1049            data: Vec<u8>,
1050        }
1051
1052        #[rustfmt::skip]
1053        let data = &[
1054            // type = X509
1055            3, 4, b't', b'y', b'p', b'e', 0, 4, b'X', b'5', b'0', b'9',
1056            // flag = CA
1057            3, 4, b'f', b'l', b'a', b'g', 0, 2, b'C', b'A',
1058            // data = 0x00 0x01 0x02 0x03
1059            3, 4, b'd', b'a', b't', b'a', 0, 4, 0x00, 0x01, 0x02, 0x03,
1060        ];
1061
1062        let actual: CertResponse = from_slice(data).unwrap();
1063        assert_eq!(
1064            actual,
1065            CertResponse {
1066                r#type: Type::X509,
1067                flag: Flag::CA,
1068                data: vec![0x00, 0x01, 0x02, 0x03],
1069            }
1070        );
1071    }
1072}