messagepack_core/encode/
str.rs

1//! String encoders.
2
3use core::ops::Deref;
4
5use super::{Encode, Error, Result};
6use crate::{formats::Format, io::IoWrite};
7
8/// Encode only the string header for a string of a given byte length.
9pub struct StrFormatEncoder(pub usize);
10impl<W: IoWrite> Encode<W> for StrFormatEncoder {
11    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
12        match self.0 {
13            0x00..=31 => {
14                let cast = self.0 as u8;
15                writer.write(&Format::FixStr(cast).as_slice())?;
16                Ok(1)
17            }
18            32..=0xff => {
19                let cast = self.0 as u8;
20                writer.write(&Format::Str8.as_slice())?;
21                writer.write(&cast.to_be_bytes())?;
22                Ok(2)
23            }
24            0x100..=0xffff => {
25                let cast = self.0 as u16;
26                writer.write(&Format::Str16.as_slice())?;
27                writer.write(&cast.to_be_bytes())?;
28                Ok(3)
29            }
30            0x10000..=0xffffffff => {
31                let cast = self.0 as u32;
32                writer.write(&Format::Str32.as_slice())?;
33                writer.write(&cast.to_be_bytes())?;
34                Ok(5)
35            }
36            _ => Err(Error::InvalidFormat),
37        }
38    }
39}
40
41/// Encode only the string bytes without a header.
42pub struct StrDataEncoder<'a>(pub &'a str);
43impl<W: IoWrite> Encode<W> for StrDataEncoder<'_> {
44    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
45        let data = self.0.as_bytes();
46        writer.write(data)?;
47        Ok(self.0.len())
48    }
49}
50/// Encode a `&str` including its appropriate header.
51pub struct StrEncoder<'s>(pub &'s str);
52
53impl<'s> Deref for StrEncoder<'s> {
54    type Target = &'s str;
55
56    fn deref(&self) -> &Self::Target {
57        &self.0
58    }
59}
60
61impl<W: IoWrite> Encode<W> for StrEncoder<'_> {
62    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
63        let self_len = self.len();
64        let format_len = StrFormatEncoder(self_len).encode(writer)?;
65        let data_len = StrDataEncoder(self.0).encode(writer)?;
66
67        Ok(format_len + data_len)
68    }
69}
70
71impl<W: IoWrite> Encode<W> for &str {
72    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
73        StrEncoder(self).encode(writer)
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80    use rstest::rstest;
81
82    #[rstest]
83    #[case("Today",[0xa5, 0x54, 0x6f, 0x64, 0x61, 0x79])]
84    #[case("MessagePack",[0xab,0x4d,0x65,0x73,0x73,0x61,0x67,0x65,0x50,0x61,0x63,0x6b])]
85    fn encode_fixed_str<E: AsRef<[u8]> + Sized>(#[case] value: &str, #[case] expected: E) {
86        let expected = expected.as_ref();
87        let encoder = StrEncoder(value);
88
89        let mut buf = vec![];
90        let n = encoder.encode(&mut buf).unwrap();
91        assert_eq!(buf, expected);
92        assert_eq!(n, expected.len());
93    }
94
95    #[rstest]
96    #[case(0xd9, 255_u8.to_be_bytes(),255)]
97    #[case(0xda, 65535_u16.to_be_bytes(),65535)]
98    #[case(0xdb, 65536_u32.to_be_bytes(),65536)]
99    fn encode_str_sized<L: AsRef<[u8]>>(#[case] marker: u8, #[case] size: L, #[case] len: usize) {
100        let value = core::iter::repeat_n("a", len).collect::<String>();
101        let expected = marker
102            .to_be_bytes()
103            .iter()
104            .chain(size.as_ref())
105            .cloned()
106            .chain(value.chars().map(|c| c as u8))
107            .collect::<Vec<u8>>();
108
109        let encoder = StrEncoder(&value);
110
111        let mut buf = vec![];
112        let n = encoder.encode(&mut buf).unwrap();
113
114        assert_eq!(&buf, &expected);
115        assert_eq!(n, expected.len());
116    }
117}