| 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 | 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 | |
| 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 | fn to_regular_range<T: RangeBounds<usize>>(generic_rage: &T, bit_length: usize) -> Range<usize> { |
| 362 | let start: usize = match generic_rage.start_bound() { |
| 363 | Bound::Excluded(&value: usize) => value + 1, |
| 364 | Bound::Included(&value: usize) => value, |
| 365 | Bound::Unbounded => 0, |
| 366 | }; |
| 367 | let end: usize = match generic_rage.end_bound() { |
| 368 | Bound::Excluded(&value: usize) => value, |
| 369 | Bound::Included(&value: usize) => value + 1, |
| 370 | Bound::Unbounded => bit_length, |
| 371 | }; |
| 372 | |
| 373 | start..end |
| 374 | } |
| 375 | |