use super::{mask_commons::has_bit, sbi_ret::SbiRegister};
#[repr(C)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct CounterMask<T = usize> {
counter_idx_mask: T,
counter_idx_base: T,
}
impl<T: SbiRegister> CounterMask<T> {
pub const IGNORE_MASK: T = T::FULL_MASK;
#[inline]
pub const fn from_mask_base(counter_idx_mask: T, counter_idx_base: T) -> Self {
Self {
counter_idx_mask,
counter_idx_base,
}
}
#[inline]
pub const fn ignore_mask(&self) -> T {
Self::IGNORE_MASK
}
#[inline]
pub const fn into_inner(self) -> (T, T) {
(self.counter_idx_mask, self.counter_idx_base)
}
}
impl CounterMask<usize> {
#[inline]
pub const fn has_bit(self, counter: usize) -> bool {
has_bit(
self.counter_idx_mask,
self.counter_idx_base,
Self::IGNORE_MASK,
counter,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rustsbi_counter_index_mask() {
let mask = CounterMask::from_mask_base(0b1, 400);
assert!(!mask.has_bit(0));
assert!(mask.has_bit(400));
assert!(!mask.has_bit(401));
let mask = CounterMask::from_mask_base(0b110, 500);
assert!(!mask.has_bit(0));
assert!(!mask.has_bit(500));
assert!(mask.has_bit(501));
assert!(mask.has_bit(502));
assert!(!mask.has_bit(500 + (usize::BITS as usize)));
let max_bit = 1 << (usize::BITS - 1);
let mask = CounterMask::from_mask_base(max_bit, 600);
assert!(mask.has_bit(600 + (usize::BITS as usize) - 1));
assert!(!mask.has_bit(600 + (usize::BITS as usize)));
let mask = CounterMask::from_mask_base(0b11, usize::MAX - 1);
assert!(!mask.has_bit(usize::MAX - 2));
assert!(mask.has_bit(usize::MAX - 1));
assert!(mask.has_bit(usize::MAX));
assert!(!mask.has_bit(0));
let mask = CounterMask::from_mask_base(0, usize::MAX);
let null_mask = CounterMask::from_mask_base(0, 0);
(0..=usize::BITS as usize).for_each(|i| {
assert!(mask.has_bit(i));
assert!(!null_mask.has_bit(i));
});
assert!(mask.has_bit(usize::MAX));
}
#[test]
fn rustsbi_counter_mask_non_usize() {
assert_eq!(CounterMask::<i32>::IGNORE_MASK, -1);
assert_eq!(CounterMask::<i64>::IGNORE_MASK, -1);
assert_eq!(CounterMask::<i128>::IGNORE_MASK, -1);
assert_eq!(CounterMask::<u32>::IGNORE_MASK, u32::MAX);
assert_eq!(CounterMask::<u64>::IGNORE_MASK, u64::MAX);
assert_eq!(CounterMask::<u128>::IGNORE_MASK, u128::MAX);
}
}