Coverage Report

Created: 2025-07-14 07:05

/rust/registry/src/index.crates.io-6f17d22bba15001f/bit_field-0.10.2/src/lib.rs
Line
Count
Source (jump to first uncovered line)
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)]
7
mod tests;
8
9
use core::ops::{Bound, Range, RangeBounds};
10
11
/// A generic trait which provides methods for extracting and setting specific bits or ranges of
12
/// bits.
13
pub 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
111
pub 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.
209
macro_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
0
            fn get_bit(&self, bit: usize) -> bool {
217
0
                assert!(bit < Self::BIT_LENGTH);
218
219
0
                (*self & (1 << bit)) != 0
220
0
            }
Unexecuted instantiation: <u32 as bit_field::BitField>::get_bit
Unexecuted instantiation: <u64 as bit_field::BitField>::get_bit
221
222
            #[track_caller]
223
            #[inline]
224
0
            fn get_bits<T: RangeBounds<usize>>(&self, range: T) -> Self {
225
0
                let range = to_regular_range(&range, Self::BIT_LENGTH);
226
0
227
0
                assert!(range.start < Self::BIT_LENGTH);
228
0
                assert!(range.end <= Self::BIT_LENGTH);
229
0
                assert!(range.start < range.end);
230
231
                // shift away high bits
232
0
                let bits = *self << (Self::BIT_LENGTH - range.end) >> (Self::BIT_LENGTH - range.end);
233
0
234
0
                // shift away low bits
235
0
                bits >> range.start
236
0
            }
Unexecuted instantiation: <u32 as bit_field::BitField>::get_bits::<core::ops::range::RangeInclusive<usize>>
Unexecuted instantiation: <u32 as bit_field::BitField>::get_bits::<core::ops::range::Range<usize>>
Unexecuted instantiation: <u16 as bit_field::BitField>::get_bits::<core::ops::range::Range<usize>>
Unexecuted instantiation: <u32 as bit_field::BitField>::get_bits::<core::ops::range::RangeInclusive<usize>>
Unexecuted instantiation: <u64 as bit_field::BitField>::get_bits::<core::ops::range::Range<usize>>
Unexecuted instantiation: <u64 as bit_field::BitField>::get_bits::<core::ops::range::RangeFrom<usize>>
237
238
            #[track_caller]
239
            #[inline]
240
0
            fn set_bit(&mut self, bit: usize, value: bool) -> &mut Self {
241
0
                assert!(bit < Self::BIT_LENGTH);
242
243
0
                if value {
244
0
                    *self |= 1 << bit;
245
0
                } else {
246
0
                    *self &= !(1 << bit);
247
0
                }
248
249
0
                self
250
0
            }
Unexecuted instantiation: <u32 as bit_field::BitField>::set_bit
Unexecuted instantiation: <u64 as bit_field::BitField>::set_bit
Unexecuted instantiation: <usize as bit_field::BitField>::set_bit
251
252
            #[track_caller]
253
            #[inline]
254
0
            fn set_bits<T: RangeBounds<usize>>(&mut self, range: T, value: Self) -> &mut Self {
255
0
                let range = to_regular_range(&range, Self::BIT_LENGTH);
256
0
257
0
                assert!(range.start < Self::BIT_LENGTH);
258
0
                assert!(range.end <= Self::BIT_LENGTH);
259
0
                assert!(range.start < range.end);
260
0
                assert!(value << (Self::BIT_LENGTH - (range.end - range.start)) >>
261
0
                        (Self::BIT_LENGTH - (range.end - range.start)) == value,
262
0
                        "value does not fit into bit range");
263
264
0
                let bitmask: Self = !(!0 << (Self::BIT_LENGTH - range.end) >>
265
0
                                    (Self::BIT_LENGTH - range.end) >>
266
0
                                    range.start << range.start);
267
0
268
0
                // set bits
269
0
                *self = (*self & bitmask) | (value << range.start);
270
0
271
0
                self
272
0
            }
Unexecuted instantiation: <usize as bit_field::BitField>::set_bits::<core::ops::range::RangeInclusive<usize>>
Unexecuted instantiation: <u64 as bit_field::BitField>::set_bits::<core::ops::range::Range<usize>>
Unexecuted instantiation: <u64 as bit_field::BitField>::set_bits::<core::ops::range::RangeFrom<usize>>
273
        }
274
    )*)
275
}
276
277
bitfield_numeric_impl! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
278
279
impl<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
361
0
fn to_regular_range<T: RangeBounds<usize>>(generic_rage: &T, bit_length: usize) -> Range<usize> {
362
0
    let start = match generic_rage.start_bound() {
363
0
        Bound::Excluded(&value) => value + 1,
364
0
        Bound::Included(&value) => value,
365
0
        Bound::Unbounded => 0,
366
    };
367
0
    let end = match generic_rage.end_bound() {
368
0
        Bound::Excluded(&value) => value,
369
0
        Bound::Included(&value) => value + 1,
370
0
        Bound::Unbounded => bit_length,
371
    };
372
373
0
    start..end
374
0
}
Unexecuted instantiation: bit_field::to_regular_range::<core::ops::range::RangeInclusive<usize>>
Unexecuted instantiation: bit_field::to_regular_range::<core::ops::range::Range<usize>>
Unexecuted instantiation: bit_field::to_regular_range::<core::ops::range::RangeInclusive<usize>>
Unexecuted instantiation: bit_field::to_regular_range::<core::ops::range::Range<usize>>
Unexecuted instantiation: bit_field::to_regular_range::<core::ops::range::RangeFrom<usize>>