messagepack_core/decode/
map.rs

1//! Map decoding helpers.
2
3use core::marker::PhantomData;
4
5use super::{DecodeBorrowed, Error, NbyteReader};
6use crate::{formats::Format, io::IoRead};
7
8/// Decode a MessagePack map of `K -> V` into `Map` collecting iterator.
9pub struct MapDecoder<Map, K, V>(PhantomData<(Map, K, V)>);
10
11#[allow(clippy::type_complexity)]
12fn decode_kv<'de, R, K, V>(reader: &mut R) -> Result<(K::Value, V::Value), Error<R::Error>>
13where
14    R: IoRead<'de>,
15    K: DecodeBorrowed<'de>,
16    V: DecodeBorrowed<'de>,
17{
18    let k = K::decode_borrowed(reader)?;
19    let v = V::decode_borrowed(reader)?;
20    Ok((k, v))
21}
22
23impl<'de, Map, K, V> DecodeBorrowed<'de> for MapDecoder<Map, K, V>
24where
25    K: DecodeBorrowed<'de>,
26    V: DecodeBorrowed<'de>,
27    Map: FromIterator<(K::Value, V::Value)>,
28{
29    type Value = Map;
30
31    fn decode_borrowed_with_format<R>(
32        format: Format,
33        reader: &mut R,
34    ) -> Result<Self::Value, Error<R::Error>>
35    where
36        R: IoRead<'de>,
37    {
38        let len = match format {
39            Format::FixMap(len) => len.into(),
40            Format::Map16 => NbyteReader::<2>::read(reader)?,
41            Format::Map32 => NbyteReader::<4>::read(reader)?,
42            _ => return Err(Error::UnexpectedFormat),
43        };
44
45        let mut err: Option<Error<R::Error>> = None;
46        let iter = (0..len).map_while(|_| match decode_kv::<R, K, V>(reader) {
47            Ok((k, v)) => Some((k, v)),
48            Err(e) => {
49                err = Some(e);
50                None
51            }
52        });
53        let res = Map::from_iter(iter);
54        match err {
55            Some(e) => Err(e),
56            None => Ok(res),
57        }
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64    use crate::decode::Decode;
65    use rstest::rstest;
66
67    #[rstest]
68    #[case(&[0x82, 0x01, 0x0a, 0x02, 0x14], vec![(1u8, 10u8), (2, 20)], &[])]
69    #[case(&[0xde, 0x00, 0x02, 0x01, 0x0a, 0x02, 0x14], vec![(1u8, 10u8), (2, 20)], &[])]
70    fn map_decode_success(
71        #[case] buf: &[u8],
72        #[case] expect: Vec<(u8, u8)>,
73        #[case] rest_expect: &[u8],
74    ) {
75        let mut r = crate::io::SliceReader::new(buf);
76        let decoded = MapDecoder::<Vec<(u8, u8)>, u8, u8>::decode(&mut r).unwrap();
77        assert_eq!(decoded, expect);
78        assert_eq!(r.rest(), rest_expect);
79    }
80
81    #[test]
82    fn map_decoder_unexpected_format() {
83        // array(1) where a map is expected
84        let buf = &[0x91, 0x00];
85        let mut r = crate::io::SliceReader::new(buf);
86        let err = MapDecoder::<Vec<(u8, u8)>, u8, u8>::decode(&mut r).unwrap_err();
87        assert!(matches!(err, Error::UnexpectedFormat));
88    }
89
90    #[test]
91    fn map_decode_eof_on_key() {
92        // map(1) but missing key/value bytes
93        let buf = &[0x81];
94        let mut r = crate::io::SliceReader::new(buf);
95        let err = MapDecoder::<Vec<(u8, u8)>, u8, u8>::decode(&mut r).unwrap_err();
96        assert!(matches!(err, Error::Io(_)));
97    }
98
99    #[test]
100    fn map_decode_key_unexpected_format() {
101        // map(1) with a string key (invalid for u8 key)
102        let buf = &[0x81, 0xa1, b'a', 0x02];
103        let mut r = crate::io::SliceReader::new(buf);
104        let err = MapDecoder::<Vec<(u8, u8)>, u8, u8>::decode(&mut r).unwrap_err();
105        assert!(matches!(err, Error::UnexpectedFormat));
106    }
107
108    #[test]
109    fn map_decode_value_error_after_first_pair() {
110        // map(2): first pair ok (1->1), second pair truncated (key present, value missing)
111        let buf = &[0x82, 0x01, 0x01, 0x02];
112        let mut r = crate::io::SliceReader::new(buf);
113        let err = MapDecoder::<Vec<(u8, u8)>, u8, u8>::decode(&mut r).unwrap_err();
114        // read_slice should fail while decoding second value
115        assert!(matches!(err, Error::Io(_)));
116    }
117}