modular_bitfield/private/
push_pop.rs
1use crate::private::{
2 checks::private::Sealed,
3 PopBits,
4 PushBits,
5};
6
7pub struct PopBuffer<T> {
9 bytes: T,
10}
11
12impl<T> PopBuffer<T> {
13 #[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
58pub struct PushBuffer<T> {
60 bytes: T,
61}
62
63impl<T> PushBuffer<T> {
64 #[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);