Skip to main content

messagepack_core/encode/
bin.rs

1//! Binary encoders.
2
3use super::{Encode, Error, Result};
4use crate::{formats::Format, io::IoWrite};
5
6/// Encoder for MessagePack binary values (`bin8/16/32`).
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
8pub struct BinaryEncoder<'blob>(pub &'blob [u8]);
9
10impl<'blob> core::ops::Deref for BinaryEncoder<'blob> {
11    type Target = &'blob [u8];
12    fn deref(&self) -> &Self::Target {
13        &self.0
14    }
15}
16
17impl Encode for BinaryEncoder<'_> {
18    fn encode<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
19        let self_len = self.len();
20        let format_len = match self_len {
21            0x00..=0xff => {
22                let cast = self_len as u8;
23                writer.write(&[Format::Bin8.as_byte(), cast])?;
24                Ok(2)
25            }
26            0x100..=0xffff => {
27                let cast = (self_len as u16).to_be_bytes();
28                writer.write(&[Format::Bin16.as_byte(), cast[0], cast[1]])?;
29                Ok(3)
30            }
31            0x10000..=0xffffffff => {
32                let cast = (self_len as u32).to_be_bytes();
33                writer.write(&[Format::Bin32.as_byte(), cast[0], cast[1], cast[2], cast[3]])?;
34
35                Ok(5)
36            }
37            _ => Err(Error::InvalidFormat),
38        }?;
39
40        writer.write(self.0)?;
41        Ok(format_len + self_len)
42    }
43}
44
45/// Trait for encoding MessagePack binary data.
46pub trait EncodeBytes {
47    /// Encode the value as a MessagePack binary.
48    fn encode_bytes<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error>;
49}
50
51impl EncodeBytes for &[u8] {
52    fn encode_bytes<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
53        BinaryEncoder(self).encode(writer)
54    }
55}
56
57impl<const N: usize> EncodeBytes for [u8; N] {
58    fn encode_bytes<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
59        self.as_slice().encode_bytes(writer)
60    }
61}
62
63impl<T> EncodeBytes for Option<T>
64where
65    T: EncodeBytes,
66{
67    fn encode_bytes<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
68        match self {
69            Some(value) => value.encode_bytes(writer),
70            None => ().encode(writer),
71        }
72    }
73}
74
75#[cfg(feature = "alloc")]
76mod alloc_impl {
77    use super::*;
78
79    impl EncodeBytes for alloc::vec::Vec<u8> {
80        fn encode_bytes<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
81            self.as_slice().encode_bytes(writer)
82        }
83    }
84
85    impl EncodeBytes for alloc::boxed::Box<[u8]> {
86        fn encode_bytes<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
87            self.as_ref().encode_bytes(writer)
88        }
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use rstest::rstest;
96
97    #[rstest]
98    #[case(0xc4, 255_u8.to_be_bytes(),[0x12;255])]
99    #[case(0xc5, 65535_u16.to_be_bytes(),[0x34;65535])]
100    #[case(0xc6, 65536_u32.to_be_bytes(),[0x56;65536])]
101    fn encode_str_sized<S: AsRef<[u8]>, D: AsRef<[u8]>>(
102        #[case] marker: u8,
103        #[case] size: S,
104        #[case] data: D,
105    ) {
106        let expected = marker
107            .to_be_bytes()
108            .iter()
109            .chain(size.as_ref())
110            .chain(data.as_ref())
111            .cloned()
112            .collect::<Vec<u8>>();
113
114        let encoder = BinaryEncoder(data.as_ref());
115
116        let mut buf = vec![];
117        let n = encoder.encode(&mut buf).unwrap();
118
119        assert_eq!(&buf, &expected);
120        assert_eq!(n, expected.len());
121    }
122}