bin_proto/impls/
list.rs

1#[allow(unused)]
2macro_rules! impl_read_list {
3    (
4        $ty:ident<T $(: $tbound0:ident $(+ $tbound1:ident)?)?
5        $(, $h:ident: $hbound0:ident + $hbound1:ident)?>,
6        $new:expr,
7        $push:ident
8    ) => {
9        impl<Tag, Ctx, T, $($h)?> $crate::BitDecode<Ctx, $crate::Tag<Tag>> for $ty<T, $($h)?>
10        where
11            T: $crate::BitDecode<Ctx> $(+ $tbound0 $(+ $tbound1)?)?,
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.$push($crate::BitDecode::<_, _>::decode::<_, E>(read, ctx, ())?);
29                }
30                ::core::result::Result::Ok(this)
31            }
32        }
33
34        impl<Ctx, T, $($h)?> $crate::BitDecode<Ctx, $crate::Untagged> for $ty<T, $($h)?>
35        where
36            T: $crate::BitDecode<Ctx> $(+ $tbound0 $(+ $tbound1)?)?,
37            $($h: $hbound0 + $hbound1)?
38        {
39            fn decode<R, E>(
40                read: &mut R,
41                ctx: &mut Ctx,
42                _: $crate::Untagged,
43            ) -> $crate::Result<Self>
44            where
45                R: ::bitstream_io::BitRead,
46                E: ::bitstream_io::Endianness,
47            {
48                $crate::util::decode_items_to_eof::<_, E, _, _>(read, ctx).collect()
49            }
50        }
51
52        #[cfg(feature = "prepend-tags")]
53        impl<Ctx, T, $($h)?> $crate::BitDecode<Ctx> for $ty<T, $($h)?>
54        where
55            T: $crate::BitDecode<Ctx> $(+ $tbound0 $(+ $tbound1)?)?,
56            $($h: $hbound0 + $hbound1)?
57        {
58            fn decode<R, E>(
59                read: &mut R,
60                ctx: &mut Ctx,
61                (): (),
62            ) -> $crate::Result<Self>
63            where
64                R: ::bitstream_io::BitRead,
65                E: ::bitstream_io::Endianness,
66            {
67                let tag: usize = $crate::BitDecode::decode::<_, E>(read, ctx, ())?;
68                $crate::BitDecode::decode::<_, E>(read, ctx, $crate::Tag(tag))
69            }
70        }
71    }
72}
73
74#[allow(unused)]
75macro_rules! impl_write_list {
76    ($ty:ident<T $(: $tbound0:ident $(+ $tbound1:ident)?)? $(, $h:ident)?> ) => {
77        impl<Ctx, T, $($h)?> $crate::BitEncode<Ctx, $crate::Untagged> for $ty<T, $($h)?>
78        where
79            T: $crate::BitEncode<Ctx> $(+ $tbound0 $(+ $tbound1)?)?
80        {
81            fn encode<W, E>(&self,
82                write: &mut W,
83                ctx: &mut Ctx,
84                _: $crate::Untagged,
85            ) -> $crate::Result<()>
86            where
87                W: ::bitstream_io::BitWrite,
88                E: ::bitstream_io::Endianness,
89            {
90                $crate::util::encode_items::<_, E, _, _>(self.iter(), write,  ctx)
91            }
92        }
93
94        #[cfg(feature = "prepend-tags")]
95        impl<Ctx, T, $($h)?> $crate::BitEncode<Ctx> for $ty<T, $($h)?>
96        where
97            T: $crate::BitEncode<Ctx> $(+ $tbound0 $(+ $tbound1)?)?
98        {
99            fn encode<W, E>(&self,
100                write: &mut W,
101                ctx: &mut Ctx,
102                (): (),
103            ) -> $crate::Result<()>
104            where
105                W: ::bitstream_io::BitWrite,
106                E: ::bitstream_io::Endianness,
107            {
108                $crate::BitEncode::encode::<_, E>(&self.len(), write, ctx, ())?;
109                $crate::BitEncode::encode::<_, E>(self, write, ctx, $crate::Untagged)
110            }
111        }
112    }
113}
114
115#[cfg(feature = "alloc")]
116mod vec {
117    use alloc::vec::Vec;
118
119    impl_read_list!(Vec<T>, |n| Self::with_capacity(n), push);
120    impl_write_list!(Vec<T>);
121
122    #[cfg(test)]
123    mod tests {
124        use crate::{Tag, Untagged};
125
126        use super::*;
127
128        test_untagged_and_codec!(
129            Vec<u8>| Untagged, Tag(3); alloc::vec![1, 2, 3] => [0x01, 0x02, 0x03]
130        );
131
132        #[cfg(feature = "prepend-tags")]
133        test_roundtrip!(Vec::<i32>);
134    }
135}
136
137#[cfg(feature = "alloc")]
138mod linked_list {
139    use alloc::collections::linked_list::LinkedList;
140
141    impl_read_list!(LinkedList<T>, |_| Self::new(), push_back);
142    impl_write_list!(LinkedList<T>);
143
144    #[cfg(test)]
145    mod tests {
146        use crate::{Tag, Untagged};
147
148        use super::*;
149
150        test_untagged_and_codec!(
151            LinkedList<u8>| Untagged, Tag(3); [1, 2, 3].into() => [0x01, 0x02, 0x03]
152        );
153
154        #[cfg(feature = "prepend-tags")]
155        test_roundtrip!(LinkedList::<i32>);
156    }
157}
158
159#[cfg(feature = "alloc")]
160mod vec_deque {
161    use alloc::collections::vec_deque::VecDeque;
162
163    impl_read_list!(VecDeque<T>, |n| Self::with_capacity(n), push_back);
164    impl_write_list!(VecDeque<T>);
165
166    #[cfg(test)]
167    mod tests {
168        use crate::{Tag, Untagged};
169
170        use super::*;
171
172        test_untagged_and_codec!(
173            VecDeque<u8>| Untagged, Tag(3); [1, 2, 3].into() => [0x01, 0x02, 0x03]
174        );
175
176        #[cfg(feature = "prepend-tags")]
177        test_roundtrip!(VecDeque::<i32>);
178    }
179}
180
181#[cfg(feature = "alloc")]
182mod b_tree_set {
183    use alloc::collections::btree_set::BTreeSet;
184
185    impl_read_list!(BTreeSet<T: Ord>, |_| Self::new(), insert);
186    impl_write_list!(BTreeSet<T: Ord>);
187
188    #[cfg(test)]
189    mod tests {
190        use crate::{Tag, Untagged};
191
192        use super::*;
193
194        test_untagged_and_codec!(
195            BTreeSet<u8>| Untagged, Tag(3); [1, 2, 3].into() => [0x01, 0x02, 0x03]
196        );
197
198        #[cfg(feature = "prepend-tags")]
199        test_roundtrip!(BTreeSet::<i32>);
200    }
201}
202
203#[cfg(feature = "alloc")]
204mod binary_heap {
205    use alloc::collections::binary_heap::BinaryHeap;
206
207    impl_read_list!(BinaryHeap<T: Ord>, |n| Self::with_capacity(n), push);
208    impl_write_list!(BinaryHeap<T: Ord>);
209
210    #[cfg(test)]
211    mod tests {
212        use alloc::vec::Vec;
213
214        use bitstream_io::{BigEndian, BitReader};
215
216        use crate::{BitDecode, Tag, Untagged};
217
218        use super::*;
219
220        #[test]
221        fn decode() {
222            let bytes: &[u8] = &[0x01];
223            let exp: BinaryHeap<u8> = [1].into();
224            let read: BinaryHeap<u8> = BitDecode::decode::<_, BigEndian>(
225                &mut BitReader::endian(bytes, BigEndian),
226                &mut (),
227                Tag(1),
228            )
229            .unwrap();
230            assert_eq!(
231                exp.into_iter().collect::<Vec<_>>(),
232                read.into_iter().collect::<Vec<_>>()
233            );
234        }
235
236        test_encode!(BinaryHeap<u8>| Untagged; [1].into() => [0x01]);
237    }
238}
239
240#[cfg(feature = "std")]
241mod hash_set {
242    use core::hash::{BuildHasher, Hash};
243    use std::collections::HashSet;
244
245    impl_read_list!(HashSet<T: Hash + Eq, H: BuildHasher + Default>, |n| Self::with_capacity_and_hasher(n, H::default()), insert);
246    impl_write_list!(HashSet<T: Hash + Eq, H>);
247
248    #[cfg(test)]
249    mod tests {
250        use crate::{Tag, Untagged};
251
252        use super::*;
253
254        test_untagged_and_codec!(HashSet<u8>| Untagged, Tag(1); [1].into() => [0x01]);
255
256        #[cfg(feature = "prepend-tags")]
257        test_roundtrip!(HashSet::<i32>);
258    }
259}