Skip to main content

messagepack_core/encode/
str.rs

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