modular_bitfield/private/
push_pop.rs

1use crate::private::{
2    checks::private::Sealed,
3    PopBits,
4    PushBits,
5};
6
7/// A bit buffer that allows to pop bits from it.
8pub struct PopBuffer<T> {
9    bytes: T,
10}
11
12impl<T> PopBuffer<T> {
13    /// Creates a new pop buffer from the given bytes.
14    #[inline]
15    pub(super) fn from_bytes(bytes: T) -> Self {
16        Self { bytes }
17    }
18}
19
20impl Sealed for PopBuffer<u8> {}
21
22impl PopBits for PopBuffer<u8> {
23    #[inline]
24    fn pop_bits(&mut self, amount: u32) -> u8 {
25        let Self { bytes } = self;
26        let orig_ones = bytes.count_ones();
27        debug_assert!(1 <= amount && amount <= 8);
28        let res = *bytes & ((0x01_u16.wrapping_shl(amount)).wrapping_sub(1) as u8);
29        *bytes = bytes.checked_shr(amount).unwrap_or(0);
30        debug_assert_eq!(res.count_ones() + bytes.count_ones(), orig_ones);
31        res
32    }
33}
34
35macro_rules! impl_pop_bits {
36    ( $($type:ty),+ ) => {
37        $(
38            impl Sealed for PopBuffer<$type> {}
39
40            impl PopBits for PopBuffer<$type> {
41                #[inline]
42                fn pop_bits(&mut self, amount: u32) -> u8 {
43                    let Self { bytes } = self;
44                    let orig_ones = bytes.count_ones();
45                    debug_assert!(1 <= amount && amount <= 8);
46                    let bitmask = 0xFF >> (8 - amount);
47                    let res = (*bytes & bitmask) as u8;
48                    *bytes = bytes.checked_shr(amount).unwrap_or(0);
49                    debug_assert_eq!(res.count_ones() + bytes.count_ones(), orig_ones);
50                    res
51                }
52            }
53        )+
54    };
55}
56impl_pop_bits!(u16, u32, u64, u128);
57
58/// A bit buffer that allows to push bits onto it.
59pub struct PushBuffer<T> {
60    bytes: T,
61}
62
63impl<T> PushBuffer<T> {
64    /// Returns the underlying bytes of the push buffer.
65    #[inline]
66    pub(super) fn into_bytes(self) -> T {
67        self.bytes
68    }
69}
70
71macro_rules! impl_push_bits {
72    ( $($type:ty),+ ) => {
73        $(
74            impl Sealed for PushBuffer<$type> {}
75
76            impl Default for PushBuffer<$type> {
77                #[inline]
78                fn default() -> Self {
79                    Self { bytes: <$type as Default>::default() }
80                }
81            }
82
83            impl PushBits for PushBuffer<$type> {
84                #[inline]
85                fn push_bits(&mut self, amount: u32, bits: u8) {
86                    let Self { bytes } = self;
87                    let orig_ones = bytes.count_ones();
88                    debug_assert!(1 <= amount && amount <= 8);
89                    let bitmask = 0xFF >> (8 - amount as u8);
90                    *bytes = bytes.wrapping_shl(amount) | ((bits & bitmask) as $type);
91                    debug_assert_eq!((bits & bitmask).count_ones() + orig_ones, bytes.count_ones());
92                }
93            }
94        )+
95    }
96}
97impl_push_bits!(u8, u16, u32, u64, u128);