lilliput_core/decoder/
seq.rs

1use crate::{
2    error::Result,
3    header::SeqHeader,
4    io::Read,
5    marker::Marker,
6    value::{Seq, SeqValue},
7};
8
9use super::Decoder;
10
11impl<'de, R> Decoder<R>
12where
13    R: Read<'de>,
14{
15    // MARK: - Value
16
17    /// Decodes a sequence value.
18    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
19    pub fn decode_seq(&mut self) -> Result<Seq> {
20        let header = self.decode_seq_header()?;
21
22        self.decode_seq_of(header)
23    }
24
25    /// Decodes a sequence value, as a `SeqValue`.
26    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
27    pub fn decode_seq_value(&mut self) -> Result<SeqValue> {
28        let header = self.decode_seq_header()?;
29
30        self.decode_seq_value_of(header)
31    }
32
33    // MARK: - Header
34
35    /// Decodes a sequence value's header.
36    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
37    pub fn decode_seq_header(&mut self) -> Result<SeqHeader> {
38        let byte = self.pull_byte_expecting(Marker::Seq)?;
39
40        let is_compact = (byte & SeqHeader::COMPACT_VARIANT_BIT) != 0b0;
41
42        if is_compact {
43            let len = byte & SeqHeader::COMPACT_LEN_BITS;
44
45            #[cfg(feature = "tracing")]
46            tracing::debug!(
47                byte = crate::binary::fmt_byte(byte),
48                is_compact = true,
49                len = len
50            );
51
52            Ok(SeqHeader::compact(len))
53        } else {
54            let len_width = 1 + (byte & SeqHeader::EXTENDED_LEN_WIDTH_BITS);
55            let len = self.pull_len_bytes(len_width)?;
56
57            #[cfg(feature = "tracing")]
58            tracing::debug!(
59                byte = crate::binary::fmt_byte(byte),
60                is_compact = false,
61                len = len
62            );
63
64            Ok(SeqHeader::extended(len))
65        }
66    }
67
68    // MARK: - Skip
69
70    /// Skips the sequence value for a given `header`.
71    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
72    pub fn skip_seq_value_of(&mut self, header: SeqHeader) -> Result<()> {
73        let len: usize = match header {
74            SeqHeader::Compact(header) => header.len().into(),
75            SeqHeader::Extended(header) => header.len(),
76        };
77
78        for _ in 0..len {
79            self.skip_value()?; // item
80        }
81
82        Ok(())
83    }
84
85    // MARK: - Body
86
87    /// Decodes sequence value for a given `header`, as a `SeqValue`.
88    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
89    pub fn decode_seq_value_of(&mut self, header: SeqHeader) -> Result<SeqValue> {
90        self.decode_seq_of(header).map(From::from)
91    }
92
93    // MARK: - Private
94
95    /// Decodes sequence value for a given `header`.
96    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
97    fn decode_seq_of(&mut self, header: SeqHeader) -> Result<Seq> {
98        let mut seq = Seq::default();
99
100        for _ in 0..header.len() {
101            let value = self.decode_value()?;
102            seq.push(value);
103        }
104
105        Ok(seq)
106    }
107}