curiOS/kernel/src/bits.rs
2026-07-23 01:53:10 +02:00

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);