/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>> |