messagepack_core/encode/
array.rs

1//! Array format encoder.
2
3use super::{Encode, Error, Result};
4use crate::{formats::Format, io::IoWrite};
5
6/// Encode only the array header for an array of a given length.
7pub struct ArrayFormatEncoder(pub usize);
8
9impl<W: IoWrite> Encode<W> for ArrayFormatEncoder {
10    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
11        match self.0 {
12            0x00..=0b1111 => {
13                let cast = self.0 as u8;
14                writer.write(&[Format::FixArray(cast).as_byte()])?;
15                Ok(1)
16            }
17            0x10..=0xffff => {
18                let cast = (self.0 as u16).to_be_bytes();
19                writer.write(&[Format::Array16.as_byte(), cast[0], cast[1]])?;
20
21                Ok(3)
22            }
23            0x10000..=0xffffffff => {
24                let cast = (self.0 as u32).to_be_bytes();
25                writer.write(&[
26                    Format::Array32.as_byte(),
27                    cast[0],
28                    cast[1],
29                    cast[2],
30                    cast[3],
31                ])?;
32
33                Ok(5)
34            }
35            _ => Err(Error::InvalidFormat),
36        }
37    }
38}
39
40impl<W, V> Encode<W> for &[V]
41where
42    W: IoWrite,
43    V: Encode<W>,
44{
45    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
46        let format_len = ArrayFormatEncoder(self.len()).encode(writer)?;
47        let array_len = self
48            .iter()
49            .map(|v| v.encode(writer))
50            .try_fold(0, |acc, v| v.map(|n| acc + n))?;
51        Ok(format_len + array_len)
52    }
53}
54
55impl<const N: usize, W, V> Encode<W> for [V; N]
56where
57    W: IoWrite,
58    V: Encode<W>,
59{
60    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
61        self.as_slice().encode(writer)
62    }
63}
64
65macro_rules! tuple_impls {
66    ($($len:expr => ($($n:tt $name:ident)+))+ $(,)?) => {
67        $(
68            tuple_impls!(@impl $len; $($n $name)+);
69        )+
70    };
71    (@impl $len:expr; $($n:tt $name:ident)+) => {
72        impl<W, $($name),+> Encode<W> for ($($name,)+)
73        where
74            W: IoWrite,
75            $($name: Encode<W>,)+
76        {
77            fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
78                let format_len = ArrayFormatEncoder($len).encode(writer)?;
79                let mut array_len = 0;
80                $(
81                    array_len += self.$n.encode(writer)?;
82                )+
83                Ok(format_len + array_len)
84            }
85        }
86    };
87}
88
89tuple_impls! {
90    1  => (0 V0)
91    2  => (0 V0 1 V1)
92    3  => (0 V0 1 V1 2 V2)
93    4  => (0 V0 1 V1 2 V2 3 V3)
94    5  => (0 V0 1 V1 2 V2 3 V3 4 V4)
95    6  => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5)
96    7  => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6)
97    8  => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7)
98    9  => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8)
99    10 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9)
100    11 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9 10 V10)
101    12 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9 10 V10 11 V11)
102    13 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9 10 V10 11 V11 12 V12)
103    14 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9 10 V10 11 V11 12 V12 13 V13)
104    15 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9 10 V10 11 V11 12 V12 13 V13 14 V14)
105    16 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9 10 V10 11 V11 12 V12 13 V13 14 V14 15 V15)
106}
107
108#[cfg(feature = "alloc")]
109impl<W, V> Encode<W> for alloc::vec::Vec<V>
110where
111    W: IoWrite,
112    V: Encode<W>,
113{
114    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
115        self.as_slice().encode(writer)
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122    use rstest::rstest;
123
124    #[rstest]
125    #[case([1u8, 2u8, 3u8],[0x93, 0x01, 0x02, 0x03])]
126    fn encode_fix_array<V: Encode<Vec<u8>>, Array: AsRef<[V]>, E: AsRef<[u8]> + Sized>(
127        #[case] value: Array,
128        #[case] expected: E,
129    ) {
130        let expected = expected.as_ref();
131
132        let mut buf = vec![];
133        let n = value.as_ref().encode(&mut buf).unwrap();
134        assert_eq!(buf, expected);
135        assert_eq!(n, expected.len());
136    }
137
138    #[rstest]
139    #[case(0xdc, 65535_u16.to_be_bytes(),[0x34;65535])]
140    #[case(0xdd, 65536_u32.to_be_bytes(),[0x56;65536])]
141    fn encode_array_sized<S: AsRef<[u8]>, D: AsRef<[u8]>>(
142        #[case] marker: u8,
143        #[case] size: S,
144        #[case] data: D,
145    ) {
146        let expected = marker
147            .to_be_bytes()
148            .iter()
149            .chain(size.as_ref())
150            .chain(data.as_ref())
151            .cloned()
152            .collect::<Vec<u8>>();
153
154        let mut buf = vec![];
155        let n = data.as_ref().encode(&mut buf).unwrap();
156
157        assert_eq!(&buf, &expected);
158        assert_eq!(n, expected.len());
159    }
160
161    #[rstest]
162    #[case((1u8,), &[0x91,0x01])]
163    #[case((1u8,2u8), &[0x92,0x01,0x02])]
164    #[case((1u8,2u8,3u8), &[0x93,0x01,0x02,0x03])]
165    fn encode_tuple<V: Encode<Vec<u8>>>(#[case] v: V, #[case] expected: &[u8]) {
166        let mut buf = Vec::new();
167        let _ = v.encode(&mut buf).unwrap();
168        assert_eq!(buf, expected);
169    }
170
171    #[cfg(feature = "alloc")]
172    #[test]
173    fn encode_vec_via_slice() {
174        let v = alloc::vec![1u8, 2, 3];
175        let mut buf = alloc::vec::Vec::new();
176        let _ = v.encode(&mut buf).unwrap();
177        assert_eq!(buf, alloc::vec![0x93, 0x01, 0x02, 0x03]);
178    }
179}