tinycbor/container/
map.rs

1//! Map-like collections.
2
3use crate::{CborLen, Encode, Encoder};
4#[cfg(feature = "alloc")]
5use crate::{Decode, Decoder};
6
7/// Possible errors when decoding a map entry.
8#[derive(#[automatically_derived]
impl<K: ::core::fmt::Debug, V: ::core::fmt::Debug> ::core::fmt::Debug for
    Error<K, V> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Error::Key(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Key",
                    &__self_0),
            Error::Value(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Value",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<K: ::core::clone::Clone, V: ::core::clone::Clone> ::core::clone::Clone
    for Error<K, V> {
    #[inline]
    fn clone(&self) -> Error<K, V> {
        match self {
            Error::Key(__self_0) =>
                Error::Key(::core::clone::Clone::clone(__self_0)),
            Error::Value(__self_0) =>
                Error::Value(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]
impl<K: ::core::marker::Copy, V: ::core::marker::Copy> ::core::marker::Copy
    for Error<K, V> {
}Copy, #[automatically_derived]
impl<K: ::core::cmp::PartialEq, V: ::core::cmp::PartialEq>
    ::core::cmp::PartialEq for Error<K, V> {
    #[inline]
    fn eq(&self, other: &Error<K, V>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Error::Key(__self_0), Error::Key(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Error::Value(__self_0), Error::Value(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl<K: ::core::cmp::Eq, V: ::core::cmp::Eq> ::core::cmp::Eq for Error<K, V> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<K>;
        let _: ::core::cmp::AssertParamIsEq<V>;
    }
}Eq, #[automatically_derived]
impl<K: ::core::cmp::PartialOrd, V: ::core::cmp::PartialOrd>
    ::core::cmp::PartialOrd for Error<K, V> {
    #[inline]
    fn partial_cmp(&self, other: &Error<K, V>)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match (self, other) {
            (Error::Key(__self_0), Error::Key(__arg1_0)) =>
                ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            (Error::Value(__self_0), Error::Value(__arg1_0)) =>
                ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            _ =>
                ::core::cmp::PartialOrd::partial_cmp(&__self_discr,
                    &__arg1_discr),
        }
    }
}PartialOrd, #[automatically_derived]
impl<K: ::core::cmp::Ord, V: ::core::cmp::Ord> ::core::cmp::Ord for
    Error<K, V> {
    #[inline]
    fn cmp(&self, other: &Error<K, V>) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
            ::core::cmp::Ordering::Equal =>
                match (self, other) {
                    (Error::Key(__self_0), Error::Key(__arg1_0)) =>
                        ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    (Error::Value(__self_0), Error::Value(__arg1_0)) =>
                        ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    _ => unsafe { ::core::intrinsics::unreachable() }
                },
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]
impl<K: ::core::hash::Hash, V: ::core::hash::Hash> ::core::hash::Hash for
    Error<K, V> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            Error::Key(__self_0) => ::core::hash::Hash::hash(__self_0, state),
            Error::Value(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash)]
9pub enum Error<K, V> {
10    /// Error decoding the key.
11    Key(K),
12    /// Error decoding the value.
13    Value(V),
14}
15
16impl<K, V> Error<K, V> {
17    /// Map a function on the key and value errors.
18    pub fn map<KO, VO>(self, fk: impl FnOnce(K) -> KO, fv: impl FnOnce(V) -> VO) -> Error<KO, VO> {
19        match self {
20            Error::Key(e) => Error::Key(fk(e)),
21            Error::Value(e) => Error::Value(fv(e)),
22        }
23    }
24}
25
26impl<K: core::fmt::Display, V: core::fmt::Display> core::fmt::Display for Error<K, V> {
27    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
28        match self {
29            Error::Key(_) => f.write_fmt(format_args!("map key error"))write!(f, "map key error"),
30            Error::Value(_) => f.write_fmt(format_args!("map value error"))write!(f, "map value error"),
31        }
32    }
33}
34
35impl<K, V> core::error::Error for Error<K, V>
36where
37    K: core::error::Error + 'static,
38    V: core::error::Error + 'static,
39{
40    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
41        match self {
42            Error::Key(e) => Some(e),
43            Error::Value(e) => Some(e),
44        }
45    }
46}
47
48#[cfg(feature = "std")]
49impl<'b, K, V, S> Decode<'b> for std::collections::HashMap<K, V, S>
50where
51    K: Decode<'b> + Eq + std::hash::Hash,
52    V: Decode<'b>,
53    S: std::hash::BuildHasher + std::default::Default,
54{
55    type Error = super::Error<Error<K::Error, V::Error>>;
56
57    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
58        let mut m = Self::default();
59        let mut visitor = d.map_visitor()?;
60        while let Some(pair) = visitor.visit() {
61            let (k, v) = pair.map_err(super::Error::Content)?;
62            m.insert(k, v);
63        }
64        Ok(m)
65    }
66}
67
68#[cfg(feature = "alloc")]
69impl<'b, K, V> Decode<'b> for alloc::collections::BTreeMap<K, V>
70where
71    K: Decode<'b> + Eq + Ord,
72    V: Decode<'b>,
73{
74    type Error = super::Error<Error<K::Error, V::Error>>;
75
76    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
77        let mut m = Self::new();
78        let mut visitor = d.map_visitor()?;
79        while let Some(pair) = visitor.visit() {
80            let (k, v) = pair.map_err(super::Error::Content)?;
81            m.insert(k, v);
82        }
83        Ok(m)
84    }
85}
86
87#[cfg(feature = "alloc")]
88macro_rules! encode_map {
89    ($($t:ty)*) => {
90        $(
91            impl<K: Encode, V: Encode> Encode for $t {
92                fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
93                    e.map(self.len())?;
94                    for (k, v) in self {
95                        k.encode(e)?;
96                        v.encode(e)?;
97                    }
98                    Ok(())
99                }
100            }
101
102            impl<K: CborLen, V: CborLen> CborLen for $t {
103                fn cbor_len(&self) -> usize {
104                    self.len().cbor_len() + self.iter().map(|(k, v)| k.cbor_len() + v.cbor_len()).sum::<usize>()
105                }
106            }
107        )*
108    }
109}
110
111#[cfg(feature = "alloc")]
112impl<K: Encode, V: Encode> Encode for alloc::collections::BTreeMap<K, V> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>)
        -> Result<(), W::Error> {
        e.map(self.len())?;
        for (k, v) in self { k.encode(e)?; v.encode(e)?; }
        Ok(())
    }
}
impl<K: CborLen, V: CborLen> CborLen for alloc::collections::BTreeMap<K, V> {
    fn cbor_len(&self) -> usize {
        self.len().cbor_len() +
            self.iter().map(|(k, v)|
                        k.cbor_len() + v.cbor_len()).sum::<usize>()
    }
}encode_map! {
113    alloc::collections::BTreeMap<K, V>
114}
115
116#[cfg(feature = "std")]
117impl<K: Encode, V: Encode> Encode for std::collections::HashMap<K, V> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>)
        -> Result<(), W::Error> {
        e.map(self.len())?;
        for (k, v) in self { k.encode(e)?; v.encode(e)?; }
        Ok(())
    }
}
impl<K: CborLen, V: CborLen> CborLen for std::collections::HashMap<K, V> {
    fn cbor_len(&self) -> usize {
        self.len().cbor_len() +
            self.iter().map(|(k, v)|
                        k.cbor_len() + v.cbor_len()).sum::<usize>()
    }
}encode_map! {
118    std::collections::HashMap<K, V>
119}
120
121// Sequential maps
122
123#[cfg(feature = "alloc")]
124impl<'b, K, V> Decode<'b> for alloc::collections::BinaryHeap<(K, V)>
125where
126    K: Decode<'b> + Ord,
127    V: Decode<'b> + Ord,
128{
129    type Error = super::Error<Error<K::Error, V::Error>>;
130
131    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
132        let mut visitor = d.map_visitor()?;
133        let mut v = Self::new();
134        while let Some(elem) = visitor.visit() {
135            v.push(elem.map_err(super::Error::Content)?);
136        }
137
138        Ok(v)
139    }
140}
141
142#[cfg(feature = "std")]
143impl<'b, K, V, S> Decode<'b> for std::collections::HashSet<(K, V), S>
144where
145    K: Decode<'b> + Eq + std::hash::Hash,
146    V: Decode<'b> + Eq + std::hash::Hash,
147    S: std::hash::BuildHasher + std::default::Default,
148{
149    type Error = super::Error<Error<K::Error, V::Error>>;
150
151    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
152        let mut visitor = d.map_visitor()?;
153        let mut v = Self::default();
154        while let Some(elem) = visitor.visit() {
155            v.insert(elem.map_err(super::Error::Content)?);
156        }
157
158        Ok(v)
159    }
160}
161
162#[cfg(feature = "alloc")]
163impl<'b, K, V> Decode<'b> for alloc::collections::BTreeSet<(K, V)>
164where
165    K: Decode<'b> + Ord,
166    V: Decode<'b> + Ord,
167{
168    type Error = super::Error<Error<K::Error, V::Error>>;
169
170    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
171        let mut visitor = d.map_visitor()?;
172        let mut v = Self::new();
173        while let Some(elem) = visitor.visit() {
174            v.insert(elem.map_err(super::Error::Content)?);
175        }
176        Ok(v)
177    }
178}
179
180#[cfg(feature = "alloc")]
181macro_rules! decode_sequential {
182    ($($t:ty, $push:ident)*) => {
183        $(
184            impl<'b, K: Decode<'b>, V: Decode<'b>> Decode<'b> for $t {
185                type Error = super::Error<Error<K::Error, V::Error>>;
186
187                fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
188                    let mut visitor = d.map_visitor()?;
189                    let mut v = Self::new();
190                    while let Some(x) = visitor.visit() {
191                        v.$push(x.map_err(super::Error::Content)?)
192                    }
193                    Ok(v)
194                }
195            }
196        )*
197    }
198}
199
200#[cfg(feature = "alloc")]
201impl<'b, K: Decode<'b>, V: Decode<'b>> Decode<'b> for
    alloc::collections::LinkedList<(K, V)> {
    type Error = super::Error<Error<K::Error, V::Error>>;
    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
        let mut visitor = d.map_visitor()?;
        let mut v = Self::new();
        while let Some(x) = visitor.visit() {
            v.push_back(x.map_err(super::Error::Content)?)
        }
        Ok(v)
    }
}decode_sequential! {
202    alloc::vec::Vec<(K, V)>, push
203    alloc::collections::VecDeque<(K, V)>, push_back
204    alloc::collections::LinkedList<(K, V)>, push_back
205}
206
207macro_rules! encode_sequential {
208    ($($t:ty)*) => {
209        $(
210            impl<K: Encode, V: Encode> Encode for $t {
211                fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
212                    e.map(self.len())?;
213                    for (k, v) in self {
214                        k.encode(e)?;
215                        v.encode(e)?;
216                    }
217                    Ok(())
218                }
219            }
220
221            impl<K: CborLen, V: CborLen> CborLen for $t {
222                fn cbor_len(&self) -> usize {
223                    let n = self.len();
224                    n.cbor_len() + self.iter().map(|(k, v)| k.cbor_len() + v.cbor_len()).sum::<usize>()
225                }
226            }
227        )*
228    }
229}
230
231#[cfg(feature = "alloc")]
232impl<K: Encode, V: Encode> Encode for alloc::collections::BTreeSet<(K, V)> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>)
        -> Result<(), W::Error> {
        e.map(self.len())?;
        for (k, v) in self { k.encode(e)?; v.encode(e)?; }
        Ok(())
    }
}
impl<K: CborLen, V: CborLen> CborLen for alloc::collections::BTreeSet<(K, V)>
    {
    fn cbor_len(&self) -> usize {
        let n = self.len();
        n.cbor_len() +
            self.iter().map(|(k, v)|
                        k.cbor_len() + v.cbor_len()).sum::<usize>()
    }
}encode_sequential! {
233    alloc::vec::Vec<(K, V)>
234    alloc::collections::VecDeque<(K, V)>
235    alloc::collections::LinkedList<(K, V)>
236    alloc::collections::BinaryHeap<(K, V)>
237    alloc::collections::BTreeSet<(K, V)>
238}
239
240#[cfg(feature = "std")]
241impl<K: Encode, V: Encode> Encode for std::collections::HashSet<(K, V)> {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>)
        -> Result<(), W::Error> {
        e.map(self.len())?;
        for (k, v) in self { k.encode(e)?; v.encode(e)?; }
        Ok(())
    }
}
impl<K: CborLen, V: CborLen> CborLen for std::collections::HashSet<(K, V)> {
    fn cbor_len(&self) -> usize {
        let n = self.len();
        n.cbor_len() +
            self.iter().map(|(k, v)|
                        k.cbor_len() + v.cbor_len()).sum::<usize>()
    }
}encode_sequential! {
242    std::collections::HashSet<(K, V)>
243}
244
245impl<K: Encode, V: Encode> Encode for [(K, V)] {
    fn encode<W: embedded_io::Write>(&self, e: &mut Encoder<W>)
        -> Result<(), W::Error> {
        e.map(self.len())?;
        for (k, v) in self { k.encode(e)?; v.encode(e)?; }
        Ok(())
    }
}
impl<K: CborLen, V: CborLen> CborLen for [(K, V)] {
    fn cbor_len(&self) -> usize {
        let n = self.len();
        n.cbor_len() +
            self.iter().map(|(k, v)|
                        k.cbor_len() + v.cbor_len()).sum::<usize>()
    }
}encode_sequential!([(K, V)]);
246
247#[cfg(test)]
248mod tests {
249    #[cfg(feature = "alloc")]
250    use crate::test;
251
252    #[test]
253    #[cfg(feature = "alloc")]
254    fn btreemap() {
255        use alloc::collections::BTreeMap;
256
257        let mut m = BTreeMap::new();
258        assert!(test(m.clone(), &[0xa0]).unwrap());
259
260        m.insert(1u32, 2u32);
261        m.insert(3u32, 4u32);
262        assert!(test(m, &[0xa2, 0x01, 0x02, 0x03, 0x04]).unwrap());
263    }
264
265    #[test]
266    #[cfg(feature = "std")]
267    fn hashmap() {
268        use crate::{Decode, Decoder, Encode, Encoder};
269        use std::collections::HashMap;
270
271        let m: HashMap<&str, u32> = HashMap::new();
272        assert!(test(m, &[0xa0]).unwrap());
273
274        // HashMap doesn't guarantee order, so test roundtrip
275        let mut m = HashMap::new();
276        m.insert("a", 1u32);
277        m.insert("b", 2u32);
278
279        let mut buf = Vec::new();
280        m.encode(&mut Encoder(&mut buf)).unwrap();
281        let decoded = HashMap::<&str, u32>::decode(&mut Decoder(&buf)).unwrap();
282        assert_eq!(decoded, m);
283    }
284
285    #[test]
286    #[cfg(feature = "alloc")]
287    fn vec() {
288        use alloc::vec::Vec;
289
290        let v: Vec<(u32, u32)> = Vec::new();
291        assert!(test(v, &[0xa0]).unwrap());
292
293        let v = vec![(10u32, 20u32), (30u32, 40u32), (50u32, 60u32)];
294
295        assert!(
296            test(
297                v,
298                &[
299                    0xa3, 0x0a, 0x14, 0x18, 0x1e, 0x18, 0x28, 0x18, 0x32, 0x18, 0x3c
300                ]
301            )
302            .unwrap()
303        );
304    }
305
306    #[test]
307    #[cfg(feature = "alloc")]
308    fn vecdeque() {
309        use alloc::collections::VecDeque;
310
311        let v: VecDeque<(u32, u32)> = VecDeque::new();
312        assert!(test(v, &[0xa0]).unwrap());
313
314        let mut v = VecDeque::new();
315        v.push_back((5u32, 10u32));
316        assert!(test(v, &[0xa1, 0x05, 0x0a]).unwrap());
317    }
318
319    #[test]
320    #[cfg(feature = "alloc")]
321    fn linkedlist() {
322        use alloc::collections::LinkedList;
323
324        let v: LinkedList<(u32, u32)> = LinkedList::new();
325        assert!(test(v, &[0xa0]).unwrap());
326
327        let mut v = LinkedList::new();
328        v.push_back((100u32, 200u32));
329        v.push_back((300u32, 400u32));
330        v.push_back((500u32, 600u32));
331        v.push_back((700u32, 800u32));
332
333        assert!(
334            test(
335                v,
336                &[
337                    0xa4, 0x18, 0x64, 0x18, 0xc8, 0x19, 0x01, 0x2c, 0x19, 0x01, 0x90, 0x19, 0x01,
338                    0xf4, 0x19, 0x02, 0x58, 0x19, 0x02, 0xbc, 0x19, 0x03, 0x20
339                ]
340            )
341            .unwrap()
342        );
343    }
344
345    #[test]
346    #[cfg(feature = "alloc")]
347    fn binaryheap() {
348        use crate::{CborLen, Decode, Encode};
349        use alloc::collections::BinaryHeap;
350
351        let cbor = &[0xa4, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
352        let expected = &[(1u32, 2u32), (3u32, 4u32), (5u32, 6u32), (7u32, 8u32)];
353
354        {
355            let heap = BinaryHeap::<(u32, u32)>::decode(&mut crate::Decoder(cbor)).unwrap();
356            let mut buf = Vec::new();
357            heap.encode(&mut crate::Encoder(&mut buf)).unwrap();
358            assert_eq!(heap.cbor_len(), buf.len());
359            assert_eq!(heap.into_sorted_vec(), expected);
360        }
361    }
362
363    #[test]
364    #[cfg(feature = "alloc")]
365    fn btreeset() {
366        use alloc::collections::BTreeSet;
367
368        let v: BTreeSet<(u32, u32)> = BTreeSet::new();
369        assert!(test(v, &[0xa0]).unwrap());
370
371        let mut v = BTreeSet::new();
372        v.insert((7u32, 8u32));
373        v.insert((9u32, 10u32));
374        assert!(test(v, &[0xa2, 0x07, 0x08, 0x09, 0x0a]).unwrap());
375    }
376
377    #[test]
378    #[cfg(feature = "std")]
379    fn hashset() {
380        use crate::{Decode, Decoder, Encode, Encoder};
381        use std::collections::HashSet;
382
383        let v: HashSet<(u32, u32)> = HashSet::new();
384        assert!(test(v, &[0xa0]).unwrap());
385
386        // HashSet doesn't preserve order, so test roundtrip
387        let mut v = HashSet::new();
388        v.insert((15u32, 25u32));
389        v.insert((35u32, 45u32));
390        v.insert((55u32, 65u32));
391
392        let mut buf = Vec::new();
393        v.encode(&mut Encoder(&mut buf)).unwrap();
394        let decoded = HashSet::<(u32, u32)>::decode(&mut Decoder(&buf)).unwrap();
395        assert_eq!(decoded, v);
396    }
397}