bit_field/
lib.rs

1//! Provides the abstraction of a bit field, which allows for bit-level update and retrieval
2//! operations.
3
4#![no_std]
5
6#[cfg(test)]
7mod tests;
8
9use core::ops::{Bound, Range, RangeBounds};
10
11/// A generic trait which provides methods for extracting and setting specific bits or ranges of
12/// bits.
13pub trait BitField {
14    /// The number of bits in this bit field.
15    ///
16    /// ```rust
17    /// use bit_field::BitField;
18    ///
19    /// assert_eq!(u32::BIT_LENGTH, 32);
20    /// assert_eq!(u64::BIT_LENGTH, 64);
21    /// ```
22    const BIT_LENGTH: usize;
23
24    /// Obtains the bit at the index `bit`; note that index 0 is the least significant bit, while
25    /// index `length() - 1` is the most significant bit.
26    ///
27    /// ```rust
28    /// use bit_field::BitField;
29    ///
30    /// let value: u32 = 0b110101;
31    ///
32    /// assert_eq!(value.get_bit(1), false);
33    /// assert_eq!(value.get_bit(2), true);
34    /// ```
35    ///
36    /// ## Panics
37    ///
38    /// This method will panic if the bit index is out of bounds of the bit field.
39    fn get_bit(&self, bit: usize) -> bool;
40
41    /// Obtains the range of bits specified by `range`; note that index 0 is the least significant
42    /// bit, while index `length() - 1` is the most significant bit.
43    ///
44    /// ```rust
45    /// use bit_field::BitField;
46    ///
47    /// let value: u32 = 0b110101;
48    ///
49    /// assert_eq!(value.get_bits(0..3), 0b101);
50    /// assert_eq!(value.get_bits(2..6), 0b1101);
51    /// assert_eq!(value.get_bits(..), 0b110101);
52    /// assert_eq!(value.get_bits(3..=3), value.get_bit(3) as u32);
53    /// ```
54    ///
55    /// ## Panics
56    ///
57    /// This method will panic if the start or end indexes of the range are out of bounds of the
58    /// bit field.
59    fn get_bits<T: RangeBounds<usize>>(&self, range: T) -> Self;
60
61    /// Sets the bit at the index `bit` to the value `value` (where true means a value of '1' and
62    /// false means a value of '0'); note that index 0 is the least significant bit, while index
63    /// `length() - 1` is the most significant bit.
64    ///
65    /// ```rust
66    /// use bit_field::BitField;
67    ///
68    /// let mut value = 0u32;
69    ///
70    /// value.set_bit(1, true);
71    /// assert_eq!(value, 2u32);
72    ///
73    /// value.set_bit(3, true);
74    /// assert_eq!(value, 10u32);
75    ///
76    /// value.set_bit(1, false);
77    /// assert_eq!(value, 8u32);
78    /// ```
79    ///
80    /// ## Panics
81    ///
82    /// This method will panic if the bit index is out of the bounds of the bit field.
83    fn set_bit(&mut self, bit: usize, value: bool) -> &mut Self;
84
85    /// Sets the range of bits defined by the range `range` to the lower bits of `value`; to be
86    /// specific, if the range is N bits long, the N lower bits of `value` will be used; if any of
87    /// the other bits in `value` are set to 1, this function will panic.
88    ///
89    /// ```rust
90    /// use bit_field::BitField;
91    ///
92    /// let mut value = 0u32;
93    ///
94    /// value.set_bits(0..2, 0b11);
95    /// assert_eq!(value, 0b11);
96    ///
97    /// value.set_bits(2..=3, 0b11);
98    /// assert_eq!(value, 0b1111);
99    ///
100    /// value.set_bits(..4, 0b1010);
101    /// assert_eq!(value, 0b1010);
102    /// ```
103    ///
104    /// ## Panics
105    ///
106    /// This method will panic if the range is out of bounds of the bit field, or if there are `1`s
107    /// not in the lower N bits of `value`.
108    fn set_bits<T: RangeBounds<usize>>(&mut self, range: T, value: Self) -> &mut Self;
109}
110
111pub trait BitArray<T: BitField> {
112    /// Returns the length, eg number of bits, in this bit array.
113    ///
114    /// ```rust
115    /// use bit_field::BitArray;
116    ///
117    /// assert_eq!([0u8, 4u8, 8u8].bit_length(), 24);
118    /// assert_eq!([0u32, 5u32].bit_length(), 64);
119    /// ```
120    fn bit_length(&self) -> usize;
121
122    /// Obtains the bit at the index `bit`; note that index 0 is the least significant bit, while
123    /// index `length() - 1` is the most significant bit.
124    ///
125    /// ```rust
126    /// use bit_field::BitArray;
127    ///
128    /// let value: [u32; 1] = [0b110101];
129    ///
130    /// assert_eq!(value.get_bit(1), false);
131    /// assert_eq!(value.get_bit(2), true);
132    /// ```
133    ///
134    /// ## Panics
135    ///
136    /// This method will panic if the bit index is out of bounds of the bit array.
137    fn get_bit(&self, bit: usize) -> bool;
138
139    /// Obtains the range of bits specified by `range`; note that index 0 is the least significant
140    /// bit, while index `length() - 1` is the most significant bit.
141    ///
142    /// ```rust
143    /// use bit_field::BitArray;
144    ///
145    /// let value: [u32; 2] = [0b110101, 0b11];
146    ///
147    /// assert_eq!(value.get_bits(0..3), 0b101);
148    /// assert_eq!(value.get_bits(..6), 0b110101);
149    /// assert_eq!(value.get_bits(31..33), 0b10);
150    /// assert_eq!(value.get_bits(5..=32), 0b1_0000_0000_0000_0000_0000_0000_001);
151    /// assert_eq!(value.get_bits(34..), 0);
152    /// ```
153    ///
154    /// ## Panics
155    ///
156    /// This method will panic if the start or end indexes of the range are out of bounds of the
157    /// bit array, or if the range can't be contained by the bit field T.
158    fn get_bits<U: RangeBounds<usize>>(&self, range: U) -> T;
159
160    /// Sets the bit at the index `bit` to the value `value` (where true means a value of '1' and
161    /// false means a value of '0'); note that index 0 is the least significant bit, while index
162    /// `length() - 1` is the most significant bit.
163    ///
164    /// ```rust
165    /// use bit_field::BitArray;
166    ///
167    /// let mut value = [0u32];
168    ///
169    /// value.set_bit(1, true);
170    /// assert_eq!(value, [2u32]);
171    ///
172    /// value.set_bit(3, true);
173    /// assert_eq!(value, [10u32]);
174    ///
175    /// value.set_bit(1, false);
176    /// assert_eq!(value, [8u32]);
177    /// ```
178    ///
179    /// ## Panics
180    ///
181    /// This method will panic if the bit index is out of the bounds of the bit array.
182    fn set_bit(&mut self, bit: usize, value: bool);
183
184    /// Sets the range of bits defined by the range `range` to the lower bits of `value`; to be
185    /// specific, if the range is N bits long, the N lower bits of `value` will be used; if any of
186    /// the other bits in `value` are set to 1, this function will panic.
187    ///
188    /// ```rust
189    /// use bit_field::BitArray;
190    ///
191    /// let mut value = [0u32, 0u32];
192    ///
193    /// value.set_bits(0..2, 0b11);
194    /// assert_eq!(value, [0b11, 0u32]);
195    ///
196    /// value.set_bits(31..35, 0b1010);
197    /// assert_eq!(value, [0x0003, 0b101]);
198    /// ```
199    ///
200    /// ## Panics
201    ///
202    /// This method will panic if the range is out of bounds of the bit array,
203    /// if the range can't be contained by the bit field T, or if there are `1`s
204    /// not in the lower N bits of `value`.
205    fn set_bits<U: RangeBounds<usize>>(&mut self, range: U, value: T);
206}
207
208/// An internal macro used for implementing BitField on the standard integral types.
209macro_rules! bitfield_numeric_impl {
210    ($($t:ty)*) => ($(
211        impl BitField for $t {
212            const BIT_LENGTH: usize = ::core::mem::size_of::<Self>() as usize * 8;
213
214            #[track_caller]
215            #[inline]
216            fn get_bit(&self, bit: usize) -> bool {
217                assert!(bit < Self::BIT_LENGTH);
218
219                (*self & (1 << bit)) != 0
220            }
221
222            #[track_caller]
223            #[inline]
224            fn get_bits<T: RangeBounds<usize>>(&self, range: T) -> Self {
225                let range = to_regular_range(&range, Self::BIT_LENGTH);
226
227                assert!(range.start < Self::BIT_LENGTH);
228                assert!(range.end <= Self::BIT_LENGTH);
229                assert!(range.start < range.end);
230
231                // shift away high bits
232                let bits = *self << (Self::BIT_LENGTH - range.end) >> (Self::BIT_LENGTH - range.end);
233
234                // shift away low bits
235                bits >> range.start
236            }
237
238            #[track_caller]
239            #[inline]
240            fn set_bit(&mut self, bit: usize, value: bool) -> &mut Self {
241                assert!(bit < Self::BIT_LENGTH);
242
243                if value {
244                    *self |= 1 << bit;
245                } else {
246                    *self &= !(1 << bit);
247                }
248
249                self
250            }
251
252            #[track_caller]
253            #[inline]
254            fn set_bits<T: RangeBounds<usize>>(&mut self, range: T, value: Self) -> &mut Self {
255                let range = to_regular_range(&range, Self::BIT_LENGTH);
256
257                assert!(range.start < Self::BIT_LENGTH);
258                assert!(range.end <= Self::BIT_LENGTH);
259                assert!(range.start < range.end);
260                assert!(value << (Self::BIT_LENGTH - (range.end - range.start)) >>
261                        (Self::BIT_LENGTH - (range.end - range.start)) == value,
262                        "value does not fit into bit range");
263
264                let bitmask: Self = !(!0 << (Self::BIT_LENGTH - range.end) >>
265                                    (Self::BIT_LENGTH - range.end) >>
266                                    range.start << range.start);
267
268                // set bits
269                *self = (*self & bitmask) | (value << range.start);
270
271                self
272            }
273        }
274    )*)
275}
276
277bitfield_numeric_impl! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
278
279impl<T: BitField> BitArray<T> for [T] {
280    #[inline]
281    fn bit_length(&self) -> usize {
282        self.len() * T::BIT_LENGTH
283    }
284
285    #[track_caller]
286    #[inline]
287    fn get_bit(&self, bit: usize) -> bool {
288        let slice_index = bit / T::BIT_LENGTH;
289        let bit_index = bit % T::BIT_LENGTH;
290        self[slice_index].get_bit(bit_index)
291    }
292
293    #[track_caller]
294    #[inline]
295    fn get_bits<U: RangeBounds<usize>>(&self, range: U) -> T {
296        let range = to_regular_range(&range, self.bit_length());
297
298        assert!(range.len() <= T::BIT_LENGTH);
299
300        let slice_start = range.start / T::BIT_LENGTH;
301        let slice_end = range.end / T::BIT_LENGTH;
302        let bit_start = range.start % T::BIT_LENGTH;
303        let bit_end = range.end % T::BIT_LENGTH;
304        let len = range.len();
305
306        assert!(slice_end - slice_start <= 1);
307
308        if slice_start == slice_end {
309            self[slice_start].get_bits(bit_start..bit_end)
310        } else if bit_end == 0 {
311            self[slice_start].get_bits(bit_start..T::BIT_LENGTH)
312        } else {
313            let mut ret = self[slice_start].get_bits(bit_start..T::BIT_LENGTH);
314            ret.set_bits(
315                (T::BIT_LENGTH - bit_start)..len,
316                self[slice_end].get_bits(0..bit_end),
317            );
318            ret
319        }
320    }
321
322    #[track_caller]
323    #[inline]
324    fn set_bit(&mut self, bit: usize, value: bool) {
325        let slice_index = bit / T::BIT_LENGTH;
326        let bit_index = bit % T::BIT_LENGTH;
327        self[slice_index].set_bit(bit_index, value);
328    }
329
330    #[track_caller]
331    #[inline]
332    fn set_bits<U: RangeBounds<usize>>(&mut self, range: U, value: T) {
333        let range = to_regular_range(&range, self.bit_length());
334
335        assert!(range.len() <= T::BIT_LENGTH);
336
337        let slice_start = range.start / T::BIT_LENGTH;
338        let slice_end = range.end / T::BIT_LENGTH;
339        let bit_start = range.start % T::BIT_LENGTH;
340        let bit_end = range.end % T::BIT_LENGTH;
341
342        assert!(slice_end - slice_start <= 1);
343
344        if slice_start == slice_end {
345            self[slice_start].set_bits(bit_start..bit_end, value);
346        } else if bit_end == 0 {
347            self[slice_start].set_bits(bit_start..T::BIT_LENGTH, value);
348        } else {
349            self[slice_start].set_bits(
350                bit_start..T::BIT_LENGTH,
351                value.get_bits(0..T::BIT_LENGTH - bit_start),
352            );
353            self[slice_end].set_bits(
354                0..bit_end,
355                value.get_bits(T::BIT_LENGTH - bit_start..T::BIT_LENGTH),
356            );
357        }
358    }
359}
360
361fn to_regular_range<T: RangeBounds<usize>>(generic_rage: &T, bit_length: usize) -> Range<usize> {
362    let start = match generic_rage.start_bound() {
363        Bound::Excluded(&value) => value + 1,
364        Bound::Included(&value) => value,
365        Bound::Unbounded => 0,
366    };
367    let end = match generic_rage.end_bound() {
368        Bound::Excluded(&value) => value,
369        Bound::Included(&value) => value + 1,
370        Bound::Unbounded => bit_length,
371    };
372
373    start..end
374}