lilliput_core/encoder/
seq.rs

1use crate::{
2    error::Result,
3    header::{CompactSeqHeader, ExtendedSeqHeader, SeqHeader},
4    io::Write,
5    num::WithPackedBeBytes as _,
6    value::{SeqValue, Value},
7};
8
9use super::Encoder;
10
11impl<W> Encoder<W>
12where
13    W: Write,
14{
15    // MARK: - Value
16
17    /// Encodes a sequence value.
18    pub fn encode_seq(&mut self, value: &[Value]) -> Result<()> {
19        self.encode_seq_header(&self.header_for_seq_len(value.len()))?;
20
21        for value in value {
22            self.encode_value(value)?;
23        }
24
25        Ok(())
26    }
27
28    /// Encodes a sequence value, from a `SeqValue`.
29    pub fn encode_seq_value(&mut self, value: &SeqValue) -> Result<()> {
30        self.encode_seq(&value.0)
31    }
32
33    // MARK: - Header
34
35    /// Encodes a sequence value's header.
36    pub fn encode_seq_header(&mut self, header: &SeqHeader) -> Result<()> {
37        let mut byte = SeqHeader::TYPE_BITS;
38
39        match *header {
40            SeqHeader::Compact(CompactSeqHeader { len }) => {
41                byte |= SeqHeader::COMPACT_VARIANT_BIT;
42                byte |= len & SeqHeader::COMPACT_LEN_BITS;
43
44                // Push the value's header:
45                self.push_byte(byte)
46            }
47            SeqHeader::Extended(ExtendedSeqHeader { len }) => {
48                len.with_packed_be_bytes(self.config.lengths.packing, |bytes| {
49                    let width = bytes.len() as u8;
50
51                    byte |= (width - 1) & SeqHeader::EXTENDED_LEN_WIDTH_BITS;
52
53                    #[cfg(feature = "tracing")]
54                    tracing::debug!(
55                        byte = crate::binary::fmt_byte(byte),
56                        bytes = format!("{:b}", crate::binary::BytesSlice(bytes)),
57                        len = len
58                    );
59
60                    // Push the value's header:
61                    self.push_byte(byte)?;
62
63                    // Push the value's length:
64                    self.push_bytes(bytes)
65                })
66            }
67        }
68    }
69
70    /// Creates a header for a sequence value, from its length.
71    pub fn header_for_seq_len(&self, len: usize) -> SeqHeader {
72        SeqHeader::for_len(len, self.config.lengths.packing)
73    }
74}