lazy_bytes_cast/
bits.rs

1use core::{mem, fmt, ops, hash};
2
3#[repr(transparent)]
4#[derive(Clone, Copy, Default)]
5///Wrapper to provide access to bit fields
6///
7///```
8///use lazy_bytes_cast::Bits;
9///
10///let mut bits = Bits(u32::max_value());
11///assert!(!bits.empty());
12///
13///assert!(bits.get(1));
14///
15///bits = bits.set(1);
16///assert!(bits.get(1));
17///
18///bits = bits.toggle(1);
19///assert!(!bits.get(1));
20///
21///bits = bits.unset(1);
22///assert!(!bits.get(1));
23///
24///bits = bits.toggle(1);
25///assert!(bits.get(1));
26///
27///bits = bits.reset();
28///assert_eq!(bits, 0);
29///assert!(bits.empty());
30///
31///assert!(!bits.get(1));
32///
33///assert_eq!(bits.len(), core::mem::size_of_val(&bits) * 8);
34///
35///bits = Bits(u32::min_value());
36///assert!(bits.empty());
37///assert!(!bits.get(1));
38///
39///bits = bits.set(1);
40///assert!(bits.get(1));
41///
42///bits = bits.unset(1);
43///assert!(!bits.get(1));
44///
45///bits = bits.set(26);
46///assert!(bits.get(26));
47///assert!(bits.get(90)); //90 % 32 == 26
48///bits = bits.set(91);
49///assert!(bits.get(26));
50///
51///bits = bits.flip();
52///assert!(!bits.get(26));
53///assert!(bits.get(5));
54///```
55pub struct Bits<T>(pub T);
56
57macro_rules! impl_bits {
58    ($($ty:ident),*) => {$(
59        impl Bits<$ty> {
60            #[inline(always)]
61            ///Get bit by index.
62            pub const fn get(&self, idx: u32) -> bool {
63                self.0.wrapping_shr(idx) & 1 != 0
64            }
65
66            #[inline(always)]
67            ///Set bit by index and return updated value.
68            pub const fn set(self, idx: u32) -> Self {
69                const ONE: $ty = 1;
70
71                Self(self.0 | ONE.wrapping_shl(idx))
72            }
73
74            #[inline(always)]
75            ///Unset bit by index and return updated value.
76            pub const fn unset(self, idx: u32) -> Self {
77                Self(self.0 & !(1 << idx))
78            }
79
80            #[inline(always)]
81            ///Unset bit by index and return updated value.
82            pub const fn toggle(self, idx: u32) -> Self {
83                Self(self.0 ^ (1 << idx))
84            }
85
86            #[inline(always)]
87            ///Returns whether all bits are unset
88            pub const fn empty(&self) -> bool {
89                self.0 == 0
90            }
91
92            #[inline(always)]
93            ///Unset all bits and returns updated value
94            pub const fn reset(&self) -> Self {
95                Self(0)
96            }
97
98            #[inline(always)]
99            ///Flip all bits and returns updated value
100            pub const fn flip(&self) -> Self {
101                Self(self.0.reverse_bits())
102            }
103
104            #[inline(always)]
105            ///Returns number of bits inside.
106            pub const fn len(&self) -> usize {
107                Self::size()
108            }
109
110            #[inline(always)]
111            ///Returns number of bits inside.
112            pub const fn size() -> usize {
113                mem::size_of::<$ty>() * 8
114            }
115        }
116
117        impl PartialEq<Bits<$ty>> for $ty {
118            #[inline(always)]
119            fn eq(&self, other: &Bits<$ty>) -> bool {
120                PartialEq::eq(self, &other.0)
121            }
122        }
123
124        impl fmt::Debug for Bits<$ty> {
125            #[inline(always)]
126            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
127                fmt::Debug::fmt(&self.0, fmt)
128            }
129        }
130
131        impl fmt::Display for Bits<$ty> {
132            #[inline(always)]
133            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
134                fmt::Display::fmt(&self.0, fmt)
135            }
136        }
137
138        impl fmt::Binary for Bits<$ty> {
139            #[inline(always)]
140            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
141                fmt::Binary::fmt(&self.0, fmt)
142            }
143        }
144
145        impl PartialEq<$ty> for Bits<$ty> {
146            #[inline(always)]
147            fn eq(&self, other: &$ty) -> bool {
148                PartialEq::eq(&self.0, other)
149            }
150        }
151
152        impl ops::Deref for Bits<$ty> {
153            type Target = $ty;
154            #[inline(always)]
155            fn deref(&self) -> &Self::Target {
156                &self.0
157            }
158        }
159
160        impl ops::DerefMut for Bits<$ty> {
161            #[inline(always)]
162            fn deref_mut(&mut self) -> &mut Self::Target {
163                &mut self.0
164            }
165        }
166
167        impl hash::Hash for Bits<$ty> {
168            #[inline(always)]
169            fn hash<H: hash::Hasher>(&self, state: &mut H) {
170                hash::Hash::hash(&self.0, state)
171            }
172        }
173
174        impl From<$ty> for Bits<$ty> {
175            #[inline(always)]
176            fn from(val: $ty) -> Self {
177                Self(val)
178            }
179        }
180
181        impl Into<$ty> for Bits<$ty> {
182            #[inline(always)]
183            fn into(self) -> $ty {
184                self.0
185            }
186        }
187    )*};
188}
189
190impl_bits!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);