messagepack_core/decode/
array.rs

1use core::marker::PhantomData;
2
3use super::{Decode, Error, NbyteReader, Result};
4use crate::formats::Format;
5
6pub struct ArrayDecoder<Array, V>(PhantomData<(Array, V)>);
7
8impl<'a, Array, V> Decode<'a> for ArrayDecoder<Array, V>
9where
10    V: Decode<'a>,
11    Array: FromIterator<V::Value>,
12{
13    type Value = Array;
14
15    fn decode(buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
16        let (format, buf) = Format::decode(buf)?;
17        match format {
18            Format::FixArray(_) | Format::Array16 | Format::Array32 => {
19                Self::decode_with_format(format, buf)
20            }
21            _ => Err(Error::UnexpectedFormat),
22        }
23    }
24
25    fn decode_with_format(format: Format, buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
26        let (len, buf) = match format {
27            Format::FixArray(len) => (len.into(), buf),
28            Format::Array16 => NbyteReader::<2>::read(buf)?,
29            Format::Array32 => NbyteReader::<4>::read(buf)?,
30            _ => return Err(Error::UnexpectedFormat),
31        };
32
33        let mut has_err = None;
34        let mut buf_ptr = buf;
35        let collector = core::iter::repeat_n((), len).map_while(|_| match V::decode(buf_ptr) {
36            Ok((v, b)) => {
37                buf_ptr = b;
38                Some(v)
39            }
40            Err(e) => {
41                has_err = Some(e);
42                None
43            }
44        });
45        let res = Array::from_iter(collector);
46
47        if let Some(e) = has_err {
48            Err(e)
49        } else {
50            Ok((res, buf_ptr))
51        }
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn decode_int_array() {
61        let buf: &[u8] = &[0x95, 0x01, 0x02, 0x03, 0x04, 0x05];
62        let (decoded, rest) = ArrayDecoder::<Vec<u8>, u8>::decode(buf).unwrap();
63
64        let expect: &[u8] = &[1, 2, 3, 4, 5];
65        assert_eq!(decoded, expect);
66        assert_eq!(rest.len(), 0);
67    }
68}