Skip to main content

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 Encode for ArrayFormatEncoder {
10    fn encode<W: IoWrite>(&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<V: Encode> Encode for &[V] {
41    fn encode<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
42        let format_len = ArrayFormatEncoder(self.len()).encode(writer)?;
43        let array_len = self
44            .iter()
45            .map(|v| v.encode(writer))
46            .try_fold(0, |acc, v| v.map(|n| acc + n))?;
47        Ok(format_len + array_len)
48    }
49}
50
51impl<const N: usize, V: Encode> Encode for [V; N] {
52    fn encode<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
53        self.as_slice().encode(writer)
54    }
55}
56
57macro_rules! tuple_impls {
58    ($($len:expr => ($($n:tt $name:ident)+))+ $(,)?) => {
59        $(
60            tuple_impls!(@impl $len; $($n $name)+);
61        )+
62    };
63    (@impl $len:expr; $($n:tt $name:ident)+) => {
64        impl<$($name: Encode),+> Encode for ($($name,)+) {
65            fn encode<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
66                let format_len = ArrayFormatEncoder($len).encode(writer)?;
67                let mut array_len = 0;
68                $(
69                    array_len += self.$n.encode(writer)?;
70                )+
71                Ok(format_len + array_len)
72            }
73        }
74    };
75}
76
77tuple_impls! {
78    1  => (0 V0)
79    2  => (0 V0 1 V1)
80    3  => (0 V0 1 V1 2 V2)
81    4  => (0 V0 1 V1 2 V2 3 V3)
82    5  => (0 V0 1 V1 2 V2 3 V3 4 V4)
83    6  => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5)
84    7  => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6)
85    8  => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7)
86    9  => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8)
87    10 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9)
88    11 => (0 V0 1 V1 2 V2 3 V3 4 V4 5 V5 6 V6 7 V7 8 V8 9 V9 10 V10)
89    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)
90    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)
91    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)
92    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)
93    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)
94}
95
96#[cfg(feature = "alloc")]
97impl<V: Encode> Encode for alloc::vec::Vec<V> {
98    fn encode<W: IoWrite>(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
99        self.as_slice().encode(writer)
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106    use rstest::rstest;
107
108    #[rstest]
109    #[case([1u8, 2u8, 3u8],[0x93, 0x01, 0x02, 0x03])]
110    fn encode_fix_array<V: Encode, Array: AsRef<[V]>, E: AsRef<[u8]> + Sized>(
111        #[case] value: Array,
112        #[case] expected: E,
113    ) {
114        let expected = expected.as_ref();
115
116        let mut buf = vec![];
117        let n = value.as_ref().encode(&mut buf).unwrap();
118        assert_eq!(buf, expected);
119        assert_eq!(n, expected.len());
120    }
121
122    #[rstest]
123    #[case(0xdc, 65535_u16.to_be_bytes(),[0x34;65535])]
124    #[case(0xdd, 65536_u32.to_be_bytes(),[0x56;65536])]
125    fn encode_array_sized<S: AsRef<[u8]>, D: AsRef<[u8]>>(
126        #[case] marker: u8,
127        #[case] size: S,
128        #[case] data: D,
129    ) {
130        let expected = marker
131            .to_be_bytes()
132            .iter()
133            .chain(size.as_ref())
134            .chain(data.as_ref())
135            .cloned()
136            .collect::<Vec<u8>>();
137
138        let mut buf = vec![];
139        let n = data.as_ref().encode(&mut buf).unwrap();
140
141        assert_eq!(&buf, &expected);
142        assert_eq!(n, expected.len());
143    }
144
145    #[rstest]
146    #[case((1u8,), &[0x91,0x01])]
147    #[case((1u8,2u8), &[0x92,0x01,0x02])]
148    #[case((1u8,2u8,3u8), &[0x93,0x01,0x02,0x03])]
149    fn encode_tuple<V: Encode>(#[case] v: V, #[case] expected: &[u8]) {
150        let mut buf = Vec::new();
151        let _ = v.encode(&mut buf).unwrap();
152        assert_eq!(buf, expected);
153    }
154
155    #[cfg(feature = "alloc")]
156    #[test]
157    fn encode_vec_via_slice() {
158        let v = alloc::vec![1u8, 2, 3];
159        let mut buf = alloc::vec::Vec::new();
160        let _ = v.encode(&mut buf).unwrap();
161        assert_eq!(buf, alloc::vec![0x93, 0x01, 0x02, 0x03]);
162    }
163}