Skip to main content

tlbits/as/
len.rs

1use std::{
2    borrow::Cow,
3    collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList, VecDeque},
4    hash::Hash,
5    marker::PhantomData,
6};
7
8use bitvec::{boxed::BitBox, order::Msb0, slice::BitSlice, vec::BitVec, view::AsBits};
9
10use crate::{
11    Context,
12    r#as::{BorrowCow, Same},
13    de::{BitReader, BitReaderExt, BitUnpackAs},
14    ser::{BitPackAs, BitWriter, BitWriterExt},
15};
16
17/// **De**/**ser**ialize value from/into exactly `N` bits.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct NBits<const BITS: usize>;
20
21/// **De**/**ser**ialize value by prefixing its length with `BITS`-bit integer.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub struct VarLen<As: ?Sized = Same, const BITS: usize = 32>(PhantomData<As>);
24
25impl<As: ?Sized, const BITS: usize> VarLen<As, BITS> {
26    #[inline]
27    fn pack_len_items<'a, W, T>(
28        source: &'a T,
29        writer: &mut W,
30        args: <<&'a As as IntoIterator>::Item as BitPackAs<<&'a T as IntoIterator>::Item>>::Args,
31    ) -> Result<(), W::Error>
32    where
33        W: BitWriter + ?Sized,
34        T: ?Sized,
35        &'a T: IntoIterator,
36        <&'a T as IntoIterator>::IntoIter: ExactSizeIterator,
37        &'a As: IntoIterator,
38        <&'a As as IntoIterator>::Item: BitPackAs<<&'a T as IntoIterator>::Item>,
39        <<&'a As as IntoIterator>::Item as BitPackAs<<&'a T as IntoIterator>::Item>>::Args: Clone,
40    {
41        let iter = source.into_iter();
42        writer
43            .pack_as::<_, NBits<BITS>>(iter.len(), ())
44            .context("length")?
45            .pack_many_as::<_, <&'a As as IntoIterator>::Item>(iter, args)?;
46        Ok(())
47    }
48
49    #[inline]
50    fn unpack_len_items<'de, R, T>(
51        reader: &mut R,
52        args: <As::Item as BitUnpackAs<'de, <T as IntoIterator>::Item>>::Args,
53    ) -> Result<T, R::Error>
54    where
55        R: BitReader<'de> + ?Sized,
56        T: IntoIterator + FromIterator<<T as IntoIterator>::Item>,
57        As: IntoIterator,
58        As::Item: BitUnpackAs<'de, <T as IntoIterator>::Item>,
59        <As::Item as BitUnpackAs<'de, <T as IntoIterator>::Item>>::Args: Clone,
60    {
61        let len: usize = reader.unpack_as::<_, NBits<BITS>>(()).context("length")?;
62        reader
63            .unpack_iter_as::<_, As::Item>(args)
64            .take(len)
65            .collect()
66    }
67}
68
69impl<const BITS: usize> BitPackAs<BitSlice<u8, Msb0>> for VarLen<Same, BITS> {
70    type Args = ();
71
72    #[inline]
73    fn pack_as<W>(
74        source: &BitSlice<u8, Msb0>,
75        writer: &mut W,
76        (): Self::Args,
77    ) -> Result<(), W::Error>
78    where
79        W: BitWriter + ?Sized,
80    {
81        writer
82            .pack_as::<_, NBits<BITS>>(source.len(), ())
83            .context("length")?
84            .write_bitslice(source)
85    }
86}
87
88impl<'a, const BITS: usize> BitPackAs<Cow<'a, BitSlice<u8, Msb0>>> for VarLen<Same, BITS> {
89    type Args = ();
90
91    #[inline]
92    fn pack_as<W>(
93        source: &Cow<'a, BitSlice<u8, Msb0>>,
94        writer: &mut W,
95        (): Self::Args,
96    ) -> Result<(), W::Error>
97    where
98        W: BitWriter + ?Sized,
99    {
100        writer.pack_as::<_, &Self>(source.as_ref(), ())?;
101        Ok(())
102    }
103}
104
105impl<const BITS: usize> BitPackAs<BitVec<u8, Msb0>> for VarLen<Same, BITS> {
106    type Args = ();
107
108    #[inline]
109    fn pack_as<W>(source: &BitVec<u8, Msb0>, writer: &mut W, (): Self::Args) -> Result<(), W::Error>
110    where
111        W: BitWriter + ?Sized,
112    {
113        Self::pack_as(source.as_bitslice(), writer, ())
114    }
115}
116
117impl<const BITS: usize> BitPackAs<BitBox<u8, Msb0>> for VarLen<Same, BITS> {
118    type Args = ();
119
120    #[inline]
121    fn pack_as<W>(source: &BitBox<u8, Msb0>, writer: &mut W, (): Self::Args) -> Result<(), W::Error>
122    where
123        W: BitWriter + ?Sized,
124    {
125        Self::pack_as(source.as_bitslice(), writer, ())
126    }
127}
128
129impl<'de: 'a, 'a, const BITS: usize> BitUnpackAs<'de, Cow<'a, BitSlice<u8, Msb0>>>
130    for VarLen<Same, BITS>
131{
132    type Args = ();
133
134    #[inline]
135    fn unpack_as<R>(reader: &mut R, (): Self::Args) -> Result<Cow<'a, BitSlice<u8, Msb0>>, R::Error>
136    where
137        R: BitReader<'de> + ?Sized,
138    {
139        let len = reader.unpack_as::<_, NBits<BITS>>(()).context("length")?;
140        reader.unpack_as::<_, BorrowCow>(len)
141    }
142}
143
144impl<'de, const BITS: usize> BitUnpackAs<'de, BitVec<u8, Msb0>> for VarLen<Same, BITS> {
145    type Args = ();
146
147    #[inline]
148    fn unpack_as<R>(reader: &mut R, (): Self::Args) -> Result<BitVec<u8, Msb0>, R::Error>
149    where
150        R: BitReader<'de> + ?Sized,
151    {
152        reader
153            .unpack_as::<Cow<BitSlice<u8, Msb0>>, Self>(())
154            .map(Cow::into_owned)
155    }
156}
157
158impl<'de, const BITS: usize> BitUnpackAs<'de, BitBox<u8, Msb0>> for VarLen<Same, BITS> {
159    type Args = ();
160
161    #[inline]
162    fn unpack_as<R>(reader: &mut R, (): Self::Args) -> Result<BitBox<u8, Msb0>, R::Error>
163    where
164        R: BitReader<'de> + ?Sized,
165    {
166        reader
167            .unpack_as::<BitVec<u8, Msb0>, Self>(())
168            .map(BitVec::into_boxed_bitslice)
169    }
170}
171
172impl<const BITS: usize> BitPackAs<[u8]> for VarLen<Same, BITS> {
173    type Args = ();
174
175    #[inline]
176    fn pack_as<W>(source: &[u8], writer: &mut W, (): Self::Args) -> Result<(), W::Error>
177    where
178        W: BitWriter + ?Sized,
179    {
180        writer
181            .pack_as::<_, NBits<BITS>>(source.len(), ())
182            .context("length")?
183            .write_bitslice(source.as_bits())
184    }
185}
186
187impl<'a, const BITS: usize> BitPackAs<Cow<'a, [u8]>> for VarLen<BorrowCow, BITS> {
188    type Args = ();
189
190    #[inline]
191    fn pack_as<W>(source: &Cow<'a, [u8]>, writer: &mut W, (): Self::Args) -> Result<(), W::Error>
192    where
193        W: BitWriter + ?Sized,
194    {
195        writer.pack_as::<_, &VarLen<Same, BITS>>(source.as_ref(), ())?;
196        Ok(())
197    }
198}
199
200impl<'de: 'a, 'a, const BITS: usize> BitUnpackAs<'de, Cow<'a, [u8]>> for VarLen<BorrowCow, BITS> {
201    type Args = ();
202
203    #[inline]
204    fn unpack_as<R>(reader: &mut R, (): Self::Args) -> Result<Cow<'a, [u8]>, R::Error>
205    where
206        R: BitReader<'de> + ?Sized,
207    {
208        let len: usize = reader.unpack_as::<_, NBits<BITS>>(()).context("length")?;
209        reader.unpack_as::<_, BorrowCow>(len)
210    }
211}
212
213impl<const BITS: usize> BitPackAs<Vec<u8>> for VarLen<Same, BITS> {
214    type Args = ();
215
216    #[inline]
217    fn pack_as<W>(source: &Vec<u8>, writer: &mut W, (): Self::Args) -> Result<(), W::Error>
218    where
219        W: BitWriter + ?Sized,
220    {
221        Self::pack_as(source.as_slice(), writer, ())
222    }
223}
224
225impl<'de, const BITS: usize> BitUnpackAs<'de, Vec<u8>> for VarLen<Same, BITS> {
226    type Args = ();
227
228    #[inline]
229    fn unpack_as<R>(reader: &mut R, (): Self::Args) -> Result<Vec<u8>, R::Error>
230    where
231        R: BitReader<'de> + ?Sized,
232    {
233        reader
234            .unpack_as::<Cow<[u8]>, VarLen<BorrowCow, BITS>>(())
235            .map(Cow::into_owned)
236    }
237}
238
239impl<T, As, const BITS: usize> BitPackAs<[T]> for VarLen<[As], BITS>
240where
241    As: BitPackAs<T>,
242    As::Args: Clone,
243{
244    /// `item_args`
245    type Args = As::Args;
246
247    #[inline]
248    fn pack_as<W>(source: &[T], writer: &mut W, args: Self::Args) -> Result<(), W::Error>
249    where
250        W: BitWriter + ?Sized,
251    {
252        Self::pack_len_items(source, writer, args)
253    }
254}
255
256impl<'a, T, As, const BITS: usize> BitPackAs<Cow<'a, [T]>> for VarLen<Cow<'a, [As]>, BITS>
257where
258    [T]: ToOwned,
259    [As]: ToOwned,
260    As: BitPackAs<T>,
261    As::Args: Clone,
262{
263    /// `item_args`
264    type Args = As::Args;
265
266    #[inline]
267    fn pack_as<W>(source: &Cow<'a, [T]>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
268    where
269        W: BitWriter + ?Sized,
270    {
271        VarLen::<[As], BITS>::pack_len_items(source.as_ref(), writer, args)
272    }
273}
274
275impl<'de: 'a, 'a, T, As, const BITS: usize> BitUnpackAs<'de, Cow<'a, [T]>>
276    for VarLen<Cow<'a, [As]>, BITS>
277where
278    [T]: ToOwned<Owned = Vec<T>>,
279    [As]: ToOwned<Owned = Vec<As>>,
280    As: BitUnpackAs<'de, T>,
281    As::Args: Clone,
282{
283    /// `item_args`
284    type Args = As::Args;
285
286    #[inline]
287    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Cow<'a, [T]>, R::Error>
288    where
289        R: BitReader<'de> + ?Sized,
290    {
291        VarLen::<Vec<As>, BITS>::unpack_len_items(reader, args).map(Cow::Owned)
292    }
293}
294
295impl<T, As, const BITS: usize> BitPackAs<Vec<T>> for VarLen<Vec<As>, BITS>
296where
297    As: BitPackAs<T>,
298    As::Args: Clone,
299{
300    /// `item_args`
301    type Args = As::Args;
302
303    #[inline]
304    fn pack_as<W>(source: &Vec<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
305    where
306        W: BitWriter + ?Sized,
307    {
308        Self::pack_len_items(source, writer, args)
309    }
310}
311
312impl<'de, T, As, const BITS: usize> BitUnpackAs<'de, Vec<T>> for VarLen<Vec<As>, BITS>
313where
314    As: BitUnpackAs<'de, T>,
315    As::Args: Clone,
316{
317    /// `item_args`
318    type Args = As::Args;
319
320    #[inline]
321    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Vec<T>, R::Error>
322    where
323        R: BitReader<'de> + ?Sized,
324    {
325        Self::unpack_len_items(reader, args)
326    }
327}
328
329impl<T, As, const BITS: usize> BitPackAs<Box<[T]>> for VarLen<Box<[As]>, BITS>
330where
331    As: BitPackAs<T>,
332    As::Args: Clone,
333{
334    /// `item_args`
335    type Args = As::Args;
336
337    #[inline]
338    fn pack_as<W>(source: &Box<[T]>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
339    where
340        W: BitWriter + ?Sized,
341    {
342        Self::pack_len_items(source, writer, args)
343    }
344}
345
346impl<'de, T, As, const BITS: usize> BitUnpackAs<'de, Box<[T]>> for VarLen<Box<[As]>, BITS>
347where
348    As: BitUnpackAs<'de, T>,
349    As::Args: Clone,
350{
351    /// `item_args`
352    type Args = As::Args;
353
354    #[inline]
355    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Box<[T]>, R::Error>
356    where
357        R: BitReader<'de> + ?Sized,
358    {
359        Self::unpack_len_items(reader, args)
360    }
361}
362
363impl<T, As, const BITS: usize> BitPackAs<VecDeque<T>> for VarLen<VecDeque<As>, BITS>
364where
365    As: BitPackAs<T>,
366    As::Args: Clone,
367{
368    /// `item_args`
369    type Args = As::Args;
370
371    #[inline]
372    fn pack_as<W>(source: &VecDeque<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
373    where
374        W: BitWriter + ?Sized,
375    {
376        Self::pack_len_items(source, writer, args)
377    }
378}
379
380impl<'de, T, As, const BITS: usize> BitUnpackAs<'de, VecDeque<T>> for VarLen<VecDeque<As>, BITS>
381where
382    As: BitUnpackAs<'de, T>,
383    As::Args: Clone,
384{
385    /// `item_args`
386    type Args = As::Args;
387
388    #[inline]
389    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<VecDeque<T>, R::Error>
390    where
391        R: BitReader<'de> + ?Sized,
392    {
393        Self::unpack_len_items(reader, args)
394    }
395}
396
397impl<T, As, const BITS: usize> BitPackAs<LinkedList<T>> for VarLen<LinkedList<As>, BITS>
398where
399    As: BitPackAs<T>,
400    As::Args: Clone,
401{
402    /// `item_args`
403    type Args = As::Args;
404
405    #[inline]
406    fn pack_as<W>(source: &LinkedList<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
407    where
408        W: BitWriter + ?Sized,
409    {
410        Self::pack_len_items(source, writer, args)
411    }
412}
413
414impl<'de, T, As, const BITS: usize> BitUnpackAs<'de, LinkedList<T>> for VarLen<LinkedList<As>, BITS>
415where
416    As: BitUnpackAs<'de, T>,
417    As::Args: Clone,
418{
419    /// `item_args`
420    type Args = As::Args;
421
422    #[inline]
423    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<LinkedList<T>, R::Error>
424    where
425        R: BitReader<'de> + ?Sized,
426    {
427        Self::unpack_len_items(reader, args)
428    }
429}
430
431impl<T, As, const BITS: usize> BitPackAs<BTreeSet<T>> for VarLen<BTreeSet<As>, BITS>
432where
433    As: BitPackAs<T>,
434    As::Args: Clone,
435{
436    /// `item_args`
437    type Args = As::Args;
438
439    #[inline]
440    fn pack_as<W>(source: &BTreeSet<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
441    where
442        W: BitWriter + ?Sized,
443    {
444        Self::pack_len_items(source, writer, args)
445    }
446}
447
448impl<'de, T, As, const BITS: usize> BitUnpackAs<'de, BTreeSet<T>> for VarLen<BTreeSet<As>, BITS>
449where
450    T: Ord + Eq,
451    As: BitUnpackAs<'de, T>,
452    As::Args: Clone,
453{
454    /// `item_args`
455    type Args = As::Args;
456
457    #[inline]
458    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<BTreeSet<T>, R::Error>
459    where
460        R: BitReader<'de> + ?Sized,
461    {
462        Self::unpack_len_items(reader, args)
463    }
464}
465
466impl<K, V, KAs, VAs, const BITS: usize> BitPackAs<BTreeMap<K, V>>
467    for VarLen<BTreeMap<KAs, VAs>, BITS>
468where
469    KAs: BitPackAs<K>,
470    KAs::Args: Clone,
471    VAs: BitPackAs<V>,
472    VAs::Args: Clone,
473{
474    /// `(key_args, value_args)`
475    type Args = (KAs::Args, VAs::Args);
476
477    #[inline]
478    fn pack_as<W>(source: &BTreeMap<K, V>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
479    where
480        W: BitWriter + ?Sized,
481    {
482        Self::pack_len_items(source, writer, args)
483    }
484}
485
486impl<'de, K, V, KAs, VAs, const BITS: usize> BitUnpackAs<'de, BTreeMap<K, V>>
487    for VarLen<BTreeMap<KAs, VAs>, BITS>
488where
489    K: Ord + Eq,
490    KAs: BitUnpackAs<'de, K>,
491    KAs::Args: Clone,
492    VAs: BitUnpackAs<'de, V>,
493    VAs::Args: Clone,
494{
495    /// `(key_args, value_args)`
496    type Args = (KAs::Args, VAs::Args);
497
498    #[inline]
499    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<BTreeMap<K, V>, R::Error>
500    where
501        R: BitReader<'de> + ?Sized,
502    {
503        Self::unpack_len_items(reader, args)
504    }
505}
506
507impl<T, As, const BITS: usize> BitPackAs<HashSet<T>> for VarLen<HashSet<As>, BITS>
508where
509    As: BitPackAs<T>,
510    As::Args: Clone,
511{
512    /// `item_args`
513    type Args = As::Args;
514
515    #[inline]
516    fn pack_as<W>(source: &HashSet<T>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
517    where
518        W: BitWriter + ?Sized,
519    {
520        Self::pack_len_items(source, writer, args)
521    }
522}
523
524impl<'de, T, As, const BITS: usize> BitUnpackAs<'de, HashSet<T>> for VarLen<HashSet<As>, BITS>
525where
526    T: Hash + Eq,
527    As: BitUnpackAs<'de, T>,
528    As::Args: Clone,
529{
530    /// `item_args`
531    type Args = As::Args;
532
533    #[inline]
534    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<HashSet<T>, R::Error>
535    where
536        R: BitReader<'de> + ?Sized,
537    {
538        Self::unpack_len_items(reader, args)
539    }
540}
541
542impl<K, V, KAs, VAs, const BITS: usize> BitPackAs<HashMap<K, V>> for VarLen<HashMap<KAs, VAs>, BITS>
543where
544    KAs: BitPackAs<K>,
545    KAs::Args: Clone,
546    VAs: BitPackAs<V>,
547    VAs::Args: Clone,
548{
549    /// `(key_args, value_args)`
550    type Args = (KAs::Args, VAs::Args);
551
552    #[inline]
553    fn pack_as<W>(source: &HashMap<K, V>, writer: &mut W, args: Self::Args) -> Result<(), W::Error>
554    where
555        W: BitWriter + ?Sized,
556    {
557        Self::pack_len_items(source, writer, args)
558    }
559}
560
561impl<'de, K, V, KAs, VAs, const BITS: usize> BitUnpackAs<'de, HashMap<K, V>>
562    for VarLen<HashMap<KAs, VAs>, BITS>
563where
564    K: Hash + Eq,
565    KAs: BitUnpackAs<'de, K>,
566    KAs::Args: Clone,
567    VAs: BitUnpackAs<'de, V>,
568    VAs::Args: Clone,
569{
570    /// `(key_args, value_args)`
571    type Args = (KAs::Args, VAs::Args);
572
573    #[inline]
574    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<HashMap<K, V>, R::Error>
575    where
576        R: BitReader<'de> + ?Sized,
577    {
578        Self::unpack_len_items(reader, args)
579    }
580}
581
582impl<const BITS: usize> BitPackAs<str> for VarLen<Same, BITS> {
583    type Args = ();
584
585    #[inline]
586    fn pack_as<W>(source: &str, writer: &mut W, (): Self::Args) -> Result<(), W::Error>
587    where
588        W: BitWriter + ?Sized,
589    {
590        writer.pack_as::<_, &Self>(source.as_bytes(), ())?;
591        Ok(())
592    }
593}
594
595impl<'a, const BITS: usize> BitPackAs<Cow<'a, str>> for VarLen<Same, BITS> {
596    type Args = ();
597
598    #[inline]
599    fn pack_as<W>(source: &Cow<'a, str>, writer: &mut W, (): Self::Args) -> Result<(), W::Error>
600    where
601        W: BitWriter + ?Sized,
602    {
603        writer.pack_as::<_, &Self>(source.as_ref(), ())?;
604        Ok(())
605    }
606}
607
608impl<'de: 'a, 'a, const BITS: usize> BitUnpackAs<'de, Cow<'a, str>> for VarLen<Same, BITS> {
609    type Args = ();
610
611    #[inline]
612    fn unpack_as<R>(reader: &mut R, (): Self::Args) -> Result<Cow<'a, str>, R::Error>
613    where
614        R: BitReader<'de> + ?Sized,
615    {
616        let len: usize = reader.unpack_as::<_, NBits<BITS>>(()).context("length")?;
617        reader.unpack_as::<_, BorrowCow>(len)
618    }
619}
620
621impl<const BITS: usize> BitPackAs<String> for VarLen<Same, BITS> {
622    type Args = ();
623
624    #[inline]
625    fn pack_as<W>(source: &String, writer: &mut W, (): Self::Args) -> Result<(), W::Error>
626    where
627        W: BitWriter + ?Sized,
628    {
629        writer.pack_as::<_, &Self>(source.as_str(), ())?;
630        Ok(())
631    }
632}
633
634impl<'de, const BITS: usize> BitUnpackAs<'de, String> for VarLen<Same, BITS> {
635    type Args = ();
636
637    #[inline]
638    fn unpack_as<R>(reader: &mut R, (): Self::Args) -> Result<String, R::Error>
639    where
640        R: BitReader<'de> + ?Sized,
641    {
642        reader.unpack_as::<Cow<str>, Self>(()).map(Cow::into_owned)
643    }
644}
645
646#[cfg(test)]
647mod tests {
648    use std::fmt::Debug;
649
650    use bitvec::bitvec;
651    use rstest::rstest;
652
653    use crate::{NoArgs, de::BitUnpack, ser::BitPack, tests::assert_pack_unpack_as_eq};
654
655    use super::*;
656
657    #[rstest]
658    #[case(bitvec![u8, Msb0;])]
659    #[case(bitvec![u8, Msb0; 1, 1, 0, 0, 1])]
660    #[case(Vec::<u8>::new())]
661    #[case(vec![1, 2, 3])]
662    fn roundtrip<T>(#[case] value: T)
663    where
664        for<'de> VarLen: BitPackAs<T, Args = ()> + BitUnpackAs<'de, T, Args = ()>,
665        T: PartialEq + Debug,
666    {
667        assert_pack_unpack_as_eq::<_, VarLen>(value, ());
668    }
669
670    #[rstest]
671    #[case(BTreeSet::<u8>::new())]
672    #[case(BTreeSet::from([1, 2, 3]))]
673    fn roundtrip_btreeset<T>(#[case] value: BTreeSet<T>)
674    where
675        T: BitPack<Args = ()> + Ord + Eq + Debug,
676        for<'de> T: BitUnpack<'de, Args = ()>,
677    {
678        assert_pack_unpack_as_eq::<_, VarLen<BTreeSet<Same>>>(value, ());
679    }
680
681    #[rstest]
682    #[case(BTreeMap::<u8, u8>::new())]
683    #[case(BTreeMap::from_iter([(1, 1), (2,2), (3,3)]))]
684    fn roundtrip_btreemap<K, V>(#[case] value: BTreeMap<K, V>)
685    where
686        for<'de> K: BitPack<Args = ()> + BitUnpack<'de, Args = ()> + Ord + Eq + Debug,
687        for<'de> V: BitPack<Args = ()> + BitUnpack<'de, Args = ()> + PartialEq + Debug,
688    {
689        #[allow(clippy::zero_sized_map_values)]
690        assert_pack_unpack_as_eq::<_, VarLen<BTreeMap<Same, Same>>>(value, NoArgs::EMPTY);
691    }
692
693    #[rstest]
694    #[case(HashSet::<u8>::new())]
695    #[case(HashSet::from([1, 2, 3]))]
696    fn roundtrip_hashset<T>(#[case] value: HashSet<T>)
697    where
698        T: BitPack<Args = ()> + Hash + Eq + Debug,
699        for<'de> T: BitUnpack<'de, Args = ()>,
700    {
701        assert_pack_unpack_as_eq::<_, VarLen<HashSet<Same>>>(value, ());
702    }
703
704    #[rstest]
705    #[case(HashMap::<u8, u8>::new())]
706    #[case(HashMap::from_iter([(1, 1), (2,2), (3,3)]))]
707    fn roundtrip_hashmap<K, V>(#[case] value: HashMap<K, V>)
708    where
709        for<'de> K: BitPack<Args = ()> + BitUnpack<'de, Args = ()> + Hash + Eq + Debug,
710        for<'de> V: BitPack<Args = ()> + BitUnpack<'de, Args = ()> + PartialEq + Debug,
711    {
712        #[allow(clippy::zero_sized_map_values)]
713        assert_pack_unpack_as_eq::<_, VarLen<HashMap<Same, Same>>>(value, NoArgs::EMPTY);
714    }
715}