use std::ops::{ BitAnd, BitOr, Not };
pub trait BitField: BitAnd<Output = Self> + BitOr<Output = Self> + Not<Output = Self> + Sized + Copy {
fn empty() -> Self;
fn set_bit(&mut self, n: usize, state: bool);
fn get_bit(&self, n: usize) -> bool;
fn n_bits() -> usize;
}
macro_rules! impl_bitfield {
($t:ty, $bits:expr) => {
impl BitField for $t {
fn empty() -> Self { 0 }
fn set_bit(&mut self, n: usize, state: bool) {
if state {
*self |= (1 << n);
}else{
*self &= !(1 << n);
}
}
fn get_bit(&self, n: usize) -> bool {
*self & (1 << n) > 0
}
#[inline(always)]
fn n_bits() -> usize { $bits }
}
}
}
impl_bitfield!(u8, 8);
impl_bitfield!(u16, 16);
impl_bitfield!(u32, 32);
impl_bitfield!(u64, 64);
impl_bitfield!(u128, 128);
#[cfg(test)]
mod test {
use super::*;
#[test]
fn get_bits() {
assert_eq!(0b00101u32.get_bit(0), true);
assert_eq!(0b00101u32.get_bit(1), false);
assert_eq!(0b00101u32.get_bit(2), true);
assert_eq!(0b00101u32.get_bit(3), false);
}
#[test]
fn set_bits() {
let mut bits = 0b00000u32;
bits.set_bit(5, true);
assert_eq!(bits.get_bit(5), true);
bits.set_bit(5, false);
assert_eq!(bits.get_bit(5), false);
}
}