use core::ops::{Bound, Range}; pub const trait Bits { const BITS: usize; fn get_bit(&self, index: usize) -> bool; fn set_bit(&mut self, index: usize, value: bool) -> &mut Self; fn get_bits(&self, range: Range) -> Self; fn set_bits(&mut self, range: Range, value: Self) -> &mut Self; } const fn range_to_bounds>( range: &R, max: usize, ) -> (usize, usize) { let start = match range.start_bound() { Bound::Included(&start) => start, Bound::Excluded(&start) => start + 1, Bound::Unbounded => 0, }; let end = match range.end_bound() { Bound::Included(&end) => end + 1, Bound::Excluded(&end) => end, Bound::Unbounded => max, }; assert!( start <= end, "Start of range must be less than or equal to end" ); assert!(end <= max, "End of range must be less than or equal to max"); (start, end) } macro_rules! impl_bits_for { ($($t:ty),*) => { $( const impl Bits for $t { const BITS: usize = <$t>::BITS as usize; fn get_bit(&self, index: usize) -> bool { assert!(index < ::BITS, "Index out of bounds"); (*self & (1 << index)) != 0 } fn set_bit(&mut self, index: usize, value: bool) -> &mut Self{ assert!(index < ::BITS, "Index out of bounds"); if value { *self |= 1 << index; } else { *self &= !(1 << index); } self } fn get_bits(&self, range: Range) -> Self { let (start, end) = range_to_bounds(&range, ::BITS); let leading = ::BITS - end; let bits = (*self << leading) >> (end + start); bits } fn set_bits(&mut self, range: Range, value: Self) -> &mut Self{ let (start, end) = range_to_bounds(&range, ::BITS); let mask = ((1 << (end - start)) - 1); let value = (value & mask) << start; *self &= !(mask << start); *self |= value; self } } )* }; } impl_bits_for!(u8, u16, u32, u64, u128);