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}