lilliput_core/encoder/
string.rs

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