lilliput_core/encoder/
bytes.rs

1use crate::{
2    config::PackingMode, error::Result, header::BytesHeader, io::Write,
3    num::WithPackedBeBytes as _, value::BytesValue,
4};
5
6use super::Encoder;
7
8impl<W> Encoder<W>
9where
10    W: Write,
11{
12    // MARK: - Value
13
14    /// Encodes a byte array value, from a slice reference.
15    pub fn encode_bytes(&mut self, value: &[u8]) -> Result<()> {
16        self.encode_bytes_header(&BytesHeader::for_len(value.len()))?;
17
18        // Push the value's actual bytes:
19        self.push_bytes(value)?;
20
21        Ok(())
22    }
23
24    /// Encodes a byte array value, from a `BytesValue`.
25    pub fn encode_bytes_value(&mut self, value: &BytesValue) -> Result<()> {
26        self.encode_bytes(&value.0)
27    }
28
29    // MARK: - Header
30
31    /// Encodes a byte array value's header.
32    pub fn encode_bytes_header(&mut self, header: &BytesHeader) -> Result<()> {
33        let len = header.len();
34
35        // The bytes header only supports native packing:
36        let packing_mode = self.config.lengths.packing.min(PackingMode::Native);
37
38        len.with_packed_be_bytes(packing_mode, |bytes| {
39            let width = bytes.len();
40
41            debug_assert!(width.count_ones() == 1, "must be a power of two");
42
43            let mut byte = BytesHeader::TYPE_BITS;
44
45            const EXPONENT: [u8; 8] = [0, 1, 2, 2, 3, 3, 3, 3];
46            let exponent = EXPONENT[width - 1];
47
48            byte |= exponent & BytesHeader::LEN_WIDTH_EXPONENT_BITS;
49
50            #[cfg(feature = "tracing")]
51            tracing::debug!(
52                byte = crate::binary::fmt_byte(byte),
53                bytes = format!("{:b}", crate::binary::BytesSlice(bytes)),
54                len = len
55            );
56
57            // Push the value's header:
58            self.push_byte(byte)?;
59
60            // Push the value's length:
61            self.push_bytes(bytes)
62        })
63    }
64
65    /// Creates a header for a byte array value, from its length.
66    pub fn header_for_bytes_len(&self, len: usize) -> BytesHeader {
67        BytesHeader::for_len(len)
68    }
69}