#![allow(clippy::must_use_candidate)]
pub trait Bitset {
fn get_bit_msb(self, idx: u32) -> bool;
fn get_bit_range_msb(self, start: u32, len: u32) -> Self;
fn get_bit_range_lsb(self, start: u32, len: u32) -> Self;
fn unset_bit_msb(self, idx: u32) -> Self;
fn set_bit_range_msb(self, start: u32, len: u32) -> Self;
fn unset_bit_range_msb(self, start: u32, len: u32) -> Self;
}
macro_rules! impl_bitset {
($($type:ty),+) => {
$(
impl Bitset for $type {
#[inline]
fn get_bit_msb(self, idx: u32) -> bool {
(self.rotate_left(idx + 1) & 1) == 1
}
#[inline]
fn get_bit_range_msb(self, start: u32, len: u32) -> Self {
self.unbounded_shl(start).unbounded_shr(<$type>::BITS - len)
}
#[inline]
fn get_bit_range_lsb(self, start: u32, len: u32) -> Self {
self.unbounded_shl(<$type>::BITS - (start + len)).unbounded_shr(<$type>::BITS - len)
}
#[inline]
fn unset_bit_msb(self, idx: u32) -> Self {
self & !(((1 << 1) - 1) << Self::BITS - idx - 1)
}
#[inline]
fn set_bit_range_msb(self, start: u32, len: u32) -> Self {
self | (((1 << len) - 1) << Self::BITS - start - len)
}
#[inline]
fn unset_bit_range_msb(self, start: u32, len: u32) -> Self {
self & !(((1 << len) - 1) << Self::BITS - start - len)
}
}
)+
};
}
impl_bitset!(u8, u16, u32, u64);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_bit_msb() {
assert!(0b1010_1111_u8.get_bit_msb(0));
assert!(!0b1010_1111_u8.get_bit_msb(1));
assert!(0b1010_1111_u8.get_bit_msb(2));
assert!(!0b1010_1111_u8.get_bit_msb(3));
assert!(0b1010_1111_u8.get_bit_msb(4));
}
#[test]
fn set_bit_msb() {
assert_eq!(0b1111_1111_u8.unset_bit_msb(0), 0b0111_1111_u8);
assert_eq!(0b1111_1111_u8.unset_bit_msb(7), 0b1111_1110_u8);
}
#[test]
fn get_bit_range_msb() {
assert_eq!(0xAAAA_AAAAu32.get_bit_range_msb(0, 4), 0b1010);
}
#[test]
fn test_msb_set_range() {
let input: u8 = 0b0000_0000;
let result = input.set_bit_range_msb(1, 3);
assert_eq!(result, 0x70, "Failed to set MSB range 1..4 on u8");
let input_32: u32 = 0;
let result_32 = input_32.set_bit_range_msb(0, 4);
assert_eq!(result_32, 0xF000_0000);
}
#[test]
fn test_msb_unset_range() {
let input: u8 = 0b1111_1111;
let result = input.unset_bit_range_msb(4, 4);
assert_eq!(result, 0xF0, "Failed to unset MSB range 4..8 on u8");
let input_16: u16 = 0xFFFF;
let result_16 = input_16.unset_bit_range_msb(4, 8);
assert_eq!(result_16, 0xF00F);
}
}