Skip to main content

messagepack_core/extension/
encode.rs

1use super::{ExtensionRef, FixedExtension};
2use super::{U16_MAX, U32_MAX};
3use crate::encode::{self, Encode};
4use crate::formats::Format;
5use crate::io::IoWrite;
6
7impl Encode for ExtensionRef<'_> {
8    fn encode<W: IoWrite>(
9        &self,
10        writer: &mut W,
11    ) -> core::result::Result<usize, encode::Error<W::Error>> {
12        let data_len = self.data.len();
13        let type_byte = self.r#type.to_be_bytes()[0];
14
15        match data_len {
16            1 => {
17                writer.write(&[Format::FixExt1.as_byte(), type_byte])?;
18                writer.write(self.data)?;
19                Ok(2 + data_len)
20            }
21            2 => {
22                writer.write(&[Format::FixExt2.as_byte(), type_byte])?;
23                writer.write(self.data)?;
24                Ok(2 + data_len)
25            }
26            4 => {
27                writer.write(&[Format::FixExt4.as_byte(), type_byte])?;
28                writer.write(self.data)?;
29                Ok(2 + data_len)
30            }
31            8 => {
32                writer.write(&[Format::FixExt8.as_byte(), type_byte])?;
33                writer.write(self.data)?;
34                Ok(2 + data_len)
35            }
36            16 => {
37                writer.write(&[Format::FixExt16.as_byte(), type_byte])?;
38                writer.write(self.data)?;
39                Ok(2 + data_len)
40            }
41            0..=0xff => {
42                let cast = data_len as u8;
43                writer.write(&[Format::Ext8.as_byte(), cast, type_byte])?;
44                writer.write(self.data)?;
45                Ok(3 + data_len)
46            }
47            0x100..=U16_MAX => {
48                let cast = (data_len as u16).to_be_bytes();
49                writer.write(&[Format::Ext16.as_byte(), cast[0], cast[1], type_byte])?;
50                writer.write(self.data)?;
51                Ok(4 + data_len)
52            }
53            0x1_0000..=U32_MAX => {
54                let cast = (data_len as u32).to_be_bytes();
55                writer.write(&[
56                    Format::Ext32.as_byte(),
57                    cast[0],
58                    cast[1],
59                    cast[2],
60                    cast[3],
61                    type_byte,
62                ])?;
63                writer.write(self.data)?;
64                Ok(6 + data_len)
65            }
66            _ => Err(encode::Error::InvalidFormat),
67        }
68    }
69}
70
71impl<const N: usize> Encode for FixedExtension<N> {
72    fn encode<W: IoWrite>(
73        &self,
74        writer: &mut W,
75    ) -> core::result::Result<usize, encode::Error<W::Error>> {
76        self.as_ref().encode(writer)
77    }
78}
79
80#[cfg(feature = "alloc")]
81impl Encode for super::owned::ExtensionOwned {
82    fn encode<W: IoWrite>(
83        &self,
84        writer: &mut W,
85    ) -> core::result::Result<usize, encode::Error<W::Error>> {
86        self.as_ref().encode(writer)
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[rstest::rstest]
95    #[case(0xd4,123,[0x12])]
96    #[case(0xd5,123,[0x12,0x34])]
97    #[case(0xd6,123,[0x12,0x34,0x56,0x78])]
98    #[case(0xd7,123,[0x12;8])]
99    #[case(0xd8,123,[0x12;16])]
100    fn encode_ext_fixed<D: AsRef<[u8]>>(#[case] marker: u8, #[case] ty: i8, #[case] data: D) {
101        let expected = marker
102            .to_be_bytes()
103            .iter()
104            .chain(ty.to_be_bytes().iter())
105            .chain(data.as_ref())
106            .cloned()
107            .collect::<Vec<_>>();
108
109        let encoder = ExtensionRef::new(ty, data.as_ref());
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
118    #[rstest::rstest]
119    #[case(0xc7_u8.to_be_bytes(),123,5u8.to_be_bytes(),[0x12;5])]
120    #[case(0xc8_u8.to_be_bytes(),123,65535_u16.to_be_bytes(),[0x34;65535])]
121    #[case(0xc9_u8.to_be_bytes(),123,65536_u32.to_be_bytes(),[0x56;65536])]
122    fn encode_ext_sized<M: AsRef<[u8]>, S: AsRef<[u8]>, D: AsRef<[u8]>>(
123        #[case] marker: M,
124        #[case] ty: i8,
125        #[case] size: S,
126        #[case] data: D,
127    ) {
128        let expected = marker
129            .as_ref()
130            .iter()
131            .chain(size.as_ref())
132            .chain(ty.to_be_bytes().iter())
133            .chain(data.as_ref())
134            .cloned()
135            .collect::<Vec<_>>();
136
137        let encoder = ExtensionRef::new(ty, data.as_ref());
138
139        let mut buf = vec![];
140        let n = encoder.encode(&mut buf).unwrap();
141
142        assert_eq!(&buf, &expected);
143        assert_eq!(n, expected.len());
144    }
145}