bin_proto/impls/
map.rs

1#[allow(unused)]
2macro_rules! impl_read_map {
3    (
4        $ty:ident<K: $kbound0:ident $(+ $kbound1:ident)?, V
5        $(, $h:ident : $hbound0:ident + $hbound1:ident)?>,
6        $new:expr
7    ) => {
8        impl<Tag, Ctx, K, V, $($h)?> $crate::BitDecode<Ctx, $crate::Tag<Tag>> for $ty<K, V, $($h)?>
9        where
10            K: $crate::BitDecode<Ctx> + $kbound0 + $($kbound1)?,
11            V: $crate::BitDecode<Ctx>,
12            Tag: ::core::convert::TryInto<usize>,
13            $($h: $hbound0 + $hbound1)?
14        {
15            fn decode<R, E>(
16                read: &mut R,
17                ctx: &mut Ctx,
18                tag: $crate::Tag<Tag>,
19            ) -> $crate::Result<Self>
20            where
21                R: ::bitstream_io::BitRead,
22                E: ::bitstream_io::Endianness,
23            {
24                let item_count = ::core::convert::TryInto::try_into(tag.0)
25                    .map_err(|_| $crate::Error::TagConvert)?;
26                let mut this = ($new)(item_count);
27                for _ in 0..item_count {
28                    this.insert(
29                        $crate::BitDecode::<_, _>::decode::<_, E>(read, ctx, ())?,
30                        $crate::BitDecode::<_, _>::decode::<_, E>(read, ctx, ())?
31                    );
32                }
33                ::core::result::Result::Ok(this)
34            }
35        }
36
37        impl<Ctx, K, V, $($h)?> $crate::BitDecode<Ctx, $crate::Untagged> for $ty<K, V, $($h)?>
38        where
39            K: $crate::BitDecode<Ctx> + $kbound0 $(+ $kbound1)?,
40            V: $crate::BitDecode<Ctx>,
41            $($h: $hbound0 + $hbound1)?
42        {
43            fn decode<R, E>(
44                read: &mut R,
45                ctx: &mut Ctx,
46                _: $crate::Untagged,
47            ) -> $crate::Result<Self>
48            where
49                R: ::bitstream_io::BitRead,
50                E: ::bitstream_io::Endianness,
51            {
52                $crate::util::decode_items_to_eof::<_, E, _, _>(read,  ctx).collect()
53            }
54        }
55
56        #[cfg(feature = "prepend-tags")]
57        impl<Ctx, K, V, $($h)?> $crate::BitDecode<Ctx> for $ty<K, V, $($h)?>
58        where
59            K: $crate::BitDecode<Ctx> + $kbound0 $(+ $kbound1)?,
60            V: $crate::BitDecode<Ctx>,
61            $($h: $hbound0 + $hbound1)?
62        {
63            fn decode<R, E>(
64                read: &mut R,
65                ctx: &mut Ctx,
66                (): (),
67            ) -> $crate::Result<Self>
68            where
69                R: ::bitstream_io::BitRead,
70                E: ::bitstream_io::Endianness,
71            {
72                let tag: usize = $crate::BitDecode::decode::<_, E>(read, ctx, ())?;
73                $crate::BitDecode::decode::<_, E>(read, ctx, $crate::Tag(tag))
74            }
75        }
76    };
77}
78
79#[allow(unused)]
80macro_rules! impl_write_map {
81    ( $ty:ident<K: $kbound0:ident $(+ $kbound1:ident)?, V $(, $h:ident)?> ) => {
82        impl<Ctx, K, V, $($h)?> $crate::BitEncode<Ctx, $crate::Untagged> for $ty<K, V, $($h)?>
83        where
84            K: $crate::BitEncode<Ctx> + $kbound0 $(+ $kbound1)?,
85            V: $crate::BitEncode<Ctx>
86        {
87            fn encode<W, E>(
88                &self,
89                write: &mut W,
90                ctx: &mut Ctx,
91                _: $crate::Untagged,
92            ) -> $crate::Result<()>
93            where
94                W: ::bitstream_io::BitWrite,
95                E: ::bitstream_io::Endianness,
96            {
97                for (key, value) in self.iter() {
98                    $crate::BitEncode::encode::<_, E>(key, write,  ctx, ())?;
99                    $crate::BitEncode::encode::<_, E>(value, write,  ctx, ())?;
100                }
101
102                Ok(())
103            }
104        }
105
106        #[cfg(feature = "prepend-tags")]
107        impl<Ctx, K, V, $($h)?> $crate::BitEncode<Ctx> for $ty<K, V, $($h)?>
108        where
109            K: $crate::BitEncode<Ctx> + $kbound0 $(+ $kbound1)?,
110            V: $crate::BitEncode<Ctx>
111        {
112            fn encode<W, E>(
113                &self,
114                write: &mut W,
115                ctx: &mut Ctx,
116                (): (),
117            ) -> $crate::Result<()>
118            where
119                W: ::bitstream_io::BitWrite,
120                E: ::bitstream_io::Endianness,
121            {
122                $crate::BitEncode::encode::<_, E>(&self.len(), write, ctx, ())?;
123                $crate::BitEncode::encode::<_, E>(self, write, ctx, $crate::Untagged)
124            }
125        }
126    }
127}
128
129#[cfg(feature = "std")]
130mod hash_map {
131    use core::hash::{BuildHasher, Hash};
132    use std::collections::HashMap;
133
134    impl_write_map!(HashMap<K: Eq + Hash, V, H>);
135    impl_read_map!(HashMap<K: Eq + Hash, V, H: BuildHasher + Default>, |n| Self::with_capacity_and_hasher(n, H::default()));
136
137    #[cfg(test)]
138    mod tests {
139        use crate::{Tag, Untagged};
140
141        use super::*;
142
143        test_untagged_and_codec!(
144            HashMap<u8, u8>| Untagged, Tag(1); [(1, 2)].into() => [0x01, 0x02]
145        );
146
147        #[cfg(feature = "prepend-tags")]
148        test_roundtrip!(HashMap::<i32, i64>);
149    }
150}
151
152#[cfg(feature = "alloc")]
153mod b_tree_map {
154    use alloc::collections::btree_map::BTreeMap;
155
156    impl_write_map!(BTreeMap<K: Ord, V>);
157    impl_read_map!(BTreeMap<K: Ord, V>, |_| Self::new());
158
159    #[cfg(test)]
160    mod tests {
161        use crate::{Tag, Untagged};
162
163        use super::*;
164
165        test_untagged_and_codec!(
166            BTreeMap<u8, u8>| Untagged, Tag(3);
167            [(1, 2), (3, 4), (5, 6)].into() => [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]
168        );
169
170        #[cfg(feature = "prepend-tags")]
171        test_roundtrip!(BTreeMap::<i32, i64>);
172    }
173}