1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
mod r#as;
mod writer;

pub use self::{r#as::*, writer::*};

use std::{rc::Rc, sync::Arc};

use bitvec::{order::Msb0, slice::BitSlice, vec::BitVec};
use impl_tools::autoimpl;

use crate::{AsBytes, ResultExt, StringError};

#[autoimpl(for<S: trait + ?Sized> &S, &mut S, Box<S>, Rc<S>, Arc<S>)]
pub trait BitPack {
    fn pack<W>(&self, writer: W) -> Result<(), W::Error>
    where
        W: BitWriter;
}

#[inline]
pub fn pack<T>(value: T) -> Result<BitVec<u8, Msb0>, StringError>
where
    T: BitPack,
{
    let mut writer = BitVec::new();
    writer.pack(value)?;
    Ok(writer)
}

impl BitPack for () {
    #[inline]
    fn pack<W>(&self, _writer: W) -> Result<(), W::Error>
    where
        W: BitWriter,
    {
        Ok(())
    }
}

impl BitPack for bool {
    #[inline]
    fn pack<W>(&self, mut writer: W) -> Result<(), W::Error>
    where
        W: BitWriter,
    {
        writer.write_bit(*self).map_err(Into::into)
    }
}

impl<T> BitPack for [T]
where
    T: BitPack,
{
    #[inline]
    fn pack<W>(&self, mut writer: W) -> Result<(), W::Error>
    where
        W: BitWriter,
    {
        writer.pack_many(self)?;
        Ok(())
    }
}

impl<T, const N: usize> BitPack for [T; N]
where
    T: BitPack,
{
    #[inline]
    fn pack<W>(&self, writer: W) -> Result<(), W::Error>
    where
        W: BitWriter,
    {
        self.as_slice().pack(writer)
    }
}

macro_rules! impl_bit_serialize_for_tuple {
    ($($n:tt:$t:ident),+) => {
        impl<$($t),+> BitPack for ($($t,)+)
        where $(
            $t: BitPack,
        )+
        {
            #[inline]
            fn pack<W>(&self, mut writer: W) -> Result<(), W::Error>
            where
                W: BitWriter,
            {
                $(self.$n.pack(&mut writer).context(concat!(".", stringify!($n)))?;)+
                Ok(())
            }
        }
    };
}
impl_bit_serialize_for_tuple!(0:T0);
impl_bit_serialize_for_tuple!(0:T0,1:T1);
impl_bit_serialize_for_tuple!(0:T0,1:T1,2:T2);
impl_bit_serialize_for_tuple!(0:T0,1:T1,2:T2,3:T3);
impl_bit_serialize_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4);
impl_bit_serialize_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5);
impl_bit_serialize_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5,6:T6);
impl_bit_serialize_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5,6:T6,7:T7);
impl_bit_serialize_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5,6:T6,7:T7,8:T8);
impl_bit_serialize_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5,6:T6,7:T7,8:T8,9:T9);

impl<'a> BitPack for &'a BitSlice<u8, Msb0> {
    #[inline]
    fn pack<W>(&self, mut writer: W) -> Result<(), W::Error>
    where
        W: BitWriter,
    {
        writer.write_bitslice(self)
    }
}

impl BitPack for str {
    #[inline]
    fn pack<W>(&self, mut writer: W) -> Result<(), W::Error>
    where
        W: BitWriter,
    {
        writer.pack_as::<_, AsBytes>(self)?;
        Ok(())
    }
}