messagepack_core/decode/
array.rs

1//! Array decoding helpers.
2
3use core::marker::PhantomData;
4
5use super::{DecodeBorrowed, Error, NbyteReader};
6use crate::{formats::Format, io::IoRead};
7
8/// Decode a MessagePack array of `V` into `Array` collecting iterator.
9pub struct ArrayDecoder<Array, V>(PhantomData<(Array, V)>);
10
11impl<'de, Array, V> DecodeBorrowed<'de> for ArrayDecoder<Array, V>
12where
13    V: DecodeBorrowed<'de>,
14    Array: FromIterator<V::Value>,
15{
16    type Value = Array;
17
18    fn decode_borrowed_with_format<R>(
19        format: Format,
20        reader: &mut R,
21    ) -> core::result::Result<Self::Value, Error<R::Error>>
22    where
23        R: IoRead<'de>,
24    {
25        let len = match format {
26            Format::FixArray(len) => len.into(),
27            Format::Array16 => NbyteReader::<2>::read(reader)?,
28            Format::Array32 => NbyteReader::<4>::read(reader)?,
29            _ => return Err(Error::UnexpectedFormat),
30        };
31
32        let out = (0..len)
33            .map(|_| V::decode_borrowed(reader))
34            .collect::<core::result::Result<Array, Error<R::Error>>>()?;
35        Ok(out)
36    }
37}
38
39impl<'de, const N: usize, V> DecodeBorrowed<'de> for [V; N]
40where
41    V: DecodeBorrowed<'de>,
42{
43    type Value = [V::Value; N];
44
45    fn decode_borrowed_with_format<R>(
46        format: Format,
47        reader: &mut R,
48    ) -> core::result::Result<Self::Value, Error<R::Error>>
49    where
50        R: IoRead<'de>,
51    {
52        let len = match format {
53            Format::FixArray(len) => len.into(),
54            Format::Array16 => NbyteReader::<2>::read(reader)?,
55            Format::Array32 => NbyteReader::<4>::read(reader)?,
56            _ => return Err(Error::UnexpectedFormat),
57        };
58        if len != N {
59            return Err(Error::InvalidData);
60        };
61
62        let mut tmp: [Option<V::Value>; N] = core::array::from_fn(|_| None);
63        for item in tmp.iter_mut() {
64            *item = Some(V::decode_borrowed(reader)?);
65        }
66        // NOTE: This `expect` cannot fire given the invariant established above.
67        // - We allocate a temporary `[Option<V::Value>; N]` initialized to `None`.
68        // - The loop assigns `Some(..)` to every element or returns early on error.
69        // - Therefore, reaching here implies all entries are `Some`, making the
70        //   unwrap logically safe.
71        //
72        // Why not avoid `expect` entirely?
73        // - On stable Rust, there is no fully-ergonomic way to construct
74        //   `[T; N]` from a fallible producer without either allocation or
75        //   `unsafe`.
76        // - `core::array::try_from_fn` would be a perfect fit but is not yet
77        //   stabilized at the time of writing.
78        // - Collecting into `Vec<T>` and converting with `try_into::<[T; N]>()`
79        //   requires the `alloc` feature, while this crate targets `no_std` by
80        //   default.
81        //
82        // If/when `try_from_fn` is stabilized, or if an `alloc`-enabled fast
83        // path is desired, this code can be revisited to remove `expect`.
84        let out = core::array::from_fn(|i| tmp[i].take().expect("initialized"));
85        Ok(out)
86    }
87}
88
89macro_rules! tuple_decode_impls {
90    ($($len:expr => ($($name:ident)+))+ $(,)?) => {
91        $(
92            impl<'de, $($name),+> DecodeBorrowed<'de> for ($($name,)+)
93            where
94                $($name: DecodeBorrowed<'de>,)+
95            {
96                type Value = ($(<$name as DecodeBorrowed<'de>>::Value,)+);
97
98                fn decode_borrowed_with_format<R>(format: Format, reader: &mut R) -> core::result::Result<Self::Value, Error<R::Error>>
99                where
100                    R: IoRead<'de>,
101                {
102                    let len = match format {
103                        Format::FixArray(len) => len.into(),
104                        Format::Array16 => NbyteReader::<2>::read(reader)?,
105                        Format::Array32 => NbyteReader::<4>::read(reader)?,
106                        _ => return Err(Error::UnexpectedFormat),
107                    };
108                    if len != $len {
109                        return Err(Error::InvalidData);
110                    }
111
112                    let value = (
113                        $({
114                            let v = <$name as DecodeBorrowed<'de>>::decode_borrowed(reader)?;
115                            v
116                        },)+
117                    );
118                    Ok(value)
119                }
120            }
121        )+
122    };
123}
124
125tuple_decode_impls! {
126    1  => (V0)
127    2  => (V0 V1)
128    3  => (V0 V1 V2)
129    4  => (V0 V1 V2 V3)
130    5  => (V0 V1 V2 V3 V4)
131    6  => (V0 V1 V2 V3 V4 V5)
132    7  => (V0 V1 V2 V3 V4 V5 V6)
133    8  => (V0 V1 V2 V3 V4 V5 V6 V7)
134    9  => (V0 V1 V2 V3 V4 V5 V6 V7 V8)
135    10 => (V0 V1 V2 V3 V4 V5 V6 V7 V8 V9)
136    11 => (V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10)
137    12 => (V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11)
138    13 => (V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12)
139    14 => (V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13)
140    15 => (V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14)
141    16 => (V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15)
142}
143
144#[cfg(feature = "alloc")]
145impl<'de, V> DecodeBorrowed<'de> for alloc::vec::Vec<V>
146where
147    V: DecodeBorrowed<'de>,
148{
149    type Value = alloc::vec::Vec<V::Value>;
150
151    fn decode_borrowed_with_format<R>(
152        format: Format,
153        reader: &mut R,
154    ) -> core::result::Result<Self::Value, Error<R::Error>>
155    where
156        R: IoRead<'de>,
157    {
158        let len = match format {
159            Format::FixArray(len) => len.into(),
160            Format::Array16 => NbyteReader::<2>::read(reader)?,
161            Format::Array32 => NbyteReader::<4>::read(reader)?,
162            _ => return Err(Error::UnexpectedFormat),
163        };
164
165        let mut out: alloc::vec::Vec<<V as DecodeBorrowed<'de>>::Value> =
166            alloc::vec::Vec::with_capacity(len);
167        for _ in 0..len {
168            out.push(V::decode_borrowed(reader)?);
169        }
170        Ok(out)
171    }
172}
173
174#[cfg(test)]
175mod tests {
176    use super::*;
177    use crate::decode::Decode;
178    use rstest::rstest;
179
180    #[rstest]
181    #[case(&[0x92, 0x01, 0x02, 0x01], vec![1u8, 2], &[0x01])]
182    #[case(&[0xdc, 0x00, 0x02, 0x2a, 0x2b], vec![42u8, 43], &[])]
183    fn array_decode_success(
184        #[case] buf: &[u8],
185        #[case] expect: Vec<u8>,
186        #[case] rest_expect: &[u8],
187    ) {
188        let mut r = crate::io::SliceReader::new(buf);
189        let decoded = ArrayDecoder::<Vec<u8>, u8>::decode(&mut r).unwrap();
190        assert_eq!(decoded, expect);
191        assert_eq!(r.rest(), rest_expect);
192    }
193
194    #[rstest]
195    fn array_decoder_unexpected_format() {
196        let buf = &[0x81, 0x01, 0x02]; // map(1)
197        let mut r = crate::io::SliceReader::new(buf);
198        let err = ArrayDecoder::<Vec<u8>, u8>::decode(&mut r).unwrap_err();
199        assert!(matches!(err, Error::UnexpectedFormat));
200    }
201
202    #[rstest]
203    fn fixed_array_len0_success() {
204        let buf = &[0x90]; // array(0)
205        let mut r = crate::io::SliceReader::new(buf);
206        let arr = <[u8; 0] as Decode>::decode(&mut r).unwrap();
207        assert_eq!(arr, []);
208        assert!(r.rest().is_empty());
209    }
210
211    #[rstest]
212    fn fixed_array_len3_success() {
213        let buf = &[0x93, 0x0a, 0x0b, 0x0c];
214        let mut r = crate::io::SliceReader::new(buf);
215        let arr = <[u8; 3] as Decode>::decode(&mut r).unwrap();
216        assert_eq!(arr, [10u8, 11, 12]);
217        assert!(r.rest().is_empty());
218    }
219
220    #[rstest]
221    #[case(&[0x92, 0x01, 0x02])] // len=2
222    #[case(&[0x94, 0x01, 0x02, 0x03, 0x04])] // len=4 
223    fn fixed_array_len_mismatch(#[case] buf: &[u8]) {
224        let mut r = crate::io::SliceReader::new(buf);
225        let err = <[u8; 3] as Decode>::decode(&mut r).unwrap_err();
226        assert!(matches!(err, Error::InvalidData));
227    }
228
229    #[rstest]
230    fn tuple1_success() {
231        let buf = &[0x91, 0x2a]; // [42]
232        let mut r = crate::io::SliceReader::new(buf);
233        let (v0,) = <(u8,) as Decode>::decode(&mut r).unwrap();
234        assert_eq!(v0, 42);
235        assert!(r.rest().is_empty());
236    }
237
238    #[rstest]
239    #[case(&[0x92, 0x2a, 0x2b])] // fixarray
240    #[case(&[0xdc, 0x00, 0x02, 0x2a, 0x2b])] // array16(2)
241    fn tuple2_success(#[case] buf: &[u8]) {
242        let mut r = crate::io::SliceReader::new(buf);
243        let (a, b) = <(u8, u8) as Decode>::decode(&mut r).unwrap();
244        assert_eq!((a, b), (42, 43));
245        assert!(r.rest().is_empty());
246    }
247
248    #[rstest]
249    fn tuple3_success() {
250        let buf = &[0x93, 0x01, 0x02, 0x03];
251        let mut r = crate::io::SliceReader::new(buf);
252        let (a, b, c) = <(u8, u8, u8) as Decode>::decode(&mut r).unwrap();
253        assert_eq!((a, b, c), (1, 2, 3));
254        assert!(r.rest().is_empty());
255    }
256
257    #[rstest]
258    #[case(&[0x92, 0x01, 0x02])] // len 2
259    #[case(&[0xdc, 0x00, 0x04, 1, 2, 3, 4])] // len 4
260    fn tuple_len_mismatch(#[case] buf: &[u8]) {
261        let mut r = crate::io::SliceReader::new(buf);
262        let err = <(u8, u8, u8) as Decode>::decode(&mut r).unwrap_err();
263        assert!(matches!(err, Error::InvalidData));
264    }
265
266    #[rstest]
267    fn tuple_unexpected_format() {
268        let buf = &[0x81, 0x01, 0x02]; // map(1)
269        let mut r = crate::io::SliceReader::new(buf);
270        let err = <(u8,) as Decode>::decode(&mut r).unwrap_err();
271        assert!(matches!(err, Error::UnexpectedFormat));
272    }
273
274    #[cfg(feature = "alloc")]
275    #[test]
276    fn vec_of_u8_success() {
277        let buf = &[0x92, 0x2a, 0x2b]; // [42,43]
278        let mut r = crate::io::SliceReader::new(buf);
279        let v = <alloc::vec::Vec<u8> as Decode>::decode(&mut r).unwrap();
280        assert_eq!(v, alloc::vec![42u8, 43]);
281        assert!(r.rest().is_empty());
282    }
283}