76 lines
2.5 KiB
Rust
76 lines
2.5 KiB
Rust
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<usize>) -> Self;
|
|
fn set_bits(&mut self, range: Range<usize>, value: Self) -> &mut Self;
|
|
}
|
|
|
|
const fn range_to_bounds<R: [const] core::ops::RangeBounds<usize>>(
|
|
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 < <Self as Bits>::BITS, "Index out of bounds");
|
|
|
|
(*self & (1 << index)) != 0
|
|
}
|
|
|
|
fn set_bit(&mut self, index: usize, value: bool) -> &mut Self{
|
|
assert!(index < <Self as Bits>::BITS, "Index out of bounds");
|
|
|
|
if value {
|
|
*self |= 1 << index;
|
|
} else {
|
|
*self &= !(1 << index);
|
|
}
|
|
self
|
|
}
|
|
fn get_bits(&self, range: Range<usize>) -> Self {
|
|
let (start, end) = range_to_bounds(&range, <Self as Bits>::BITS);
|
|
let leading = <Self as Bits>::BITS - end;
|
|
let bits = (*self << leading) >> (end + start);
|
|
bits
|
|
}
|
|
|
|
fn set_bits(&mut self, range: Range<usize>, value: Self) -> &mut Self{
|
|
let (start, end) = range_to_bounds(&range, <Self as Bits>::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);
|