#![allow(unused)]
use core::fmt;
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Index};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BitSet128(u64, u64);
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct BitSet128Iter {
bits: (u64, u64),
current_bit: u8,
}
impl Default for BitSet128 {
fn default() -> Self {
Self::new()
}
}
impl BitSet128 {
pub const fn new() -> Self {
Self(0, 0)
}
pub fn reset_all(&mut self) {
self.0 = 0;
self.1 = 0;
}
pub fn reset(&mut self, index: u8) -> bool {
if index < 64 {
self.0 &= !(1 << index);
true
} else if index < 128 {
self.1 &= !(1 << (index - 64));
true
} else {
false
}
}
pub fn set(&mut self, index: u8) -> bool {
if index < 64 {
self.0 |= 1 << index;
true
} else if index < 128 {
self.1 |= 1 << (index - 64);
true
} else {
false
}
}
pub fn test(&self, index: u8) -> bool {
if index < 64 {
(self.0 & (1 << index)) != 0
} else if index < 128 {
(self.1 & (1 << (index - 64))) != 0
} else {
false
}
}
}
impl BitOr for BitSet128 {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0, self.1 | rhs.1)
}
}
impl BitAnd for BitSet128 {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0, self.1 & rhs.1)
}
}
impl BitXor for BitSet128 {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
Self(self.0 ^ rhs.0, self.1 ^ rhs.1)
}
}
impl BitOrAssign for BitSet128 {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
self.1 |= rhs.1;
}
}
impl BitAndAssign for BitSet128 {
fn bitand_assign(&mut self, rhs: Self) {
self.0 &= rhs.0;
self.1 &= rhs.1;
}
}
impl BitXorAssign for BitSet128 {
fn bitxor_assign(&mut self, rhs: Self) {
self.0 ^= rhs.0;
self.1 ^= rhs.1;
}
}
impl Index<u8> for BitSet128 {
type Output = bool;
fn index(&self, index: u8) -> &Self::Output {
if self.test(index) { &true } else { &false }
}
}
impl Index<usize> for BitSet128 {
type Output = bool;
#[allow(clippy::cast_possible_truncation)]
fn index(&self, index: usize) -> &Self::Output {
if self.test(index as u8) { &true } else { &false }
}
}
impl From<u32> for BitSet128 {
#[inline(always)]
fn from(a: u32) -> Self {
Self(u64::from(a), 0)
}
}
impl From<(u32, u32)> for BitSet128 {
#[inline(always)]
fn from((a, b): (u32, u32)) -> Self {
Self(u64::from(a) << 32 | u64::from(b), 0)
}
}
impl fmt::Binary for BitSet128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
f.write_str("0b")?;
}
for i in (0..64).rev() {
let val = (self.1 >> i) & 1;
write!(f, "{val}")?;
}
for i in (0..64).rev() {
let val = (self.0 >> i) & 1;
write!(f, "{val}")?;
}
Ok(())
}
}
impl fmt::UpperHex for BitSet128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
f.write_str("0x")?;
}
write!(f, "{:016X}{:016X}", self.1, self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn is_normal<T: Sized + Send + Sync + Unpin>() {}
fn is_full<T: Sized + Send + Sync + Unpin + Copy + Clone + Default + PartialEq>() {}
#[test]
fn normal_types() {
is_full::<BitSet128>();
is_normal::<BitSet128Iter>();
}
#[test]
fn new() {
let mut bits = BitSet128::new();
_ = bits.set(42);
assert!(bits[42u8]);
assert!(bits.test(42));
}
#[test]
fn assign() {
let mut bits = BitSet128::new();
_ = bits.set(42);
assert!(bits[42u8]);
assert!(bits.test(42));
let mask = bits;
assert!(mask.test(42));
}
#[test]
fn exercise() {
let mut system_flags = BitSet128::new();
let error_mask = BitSet128::new();
system_flags |= error_mask;
system_flags ^= error_mask;
let mut set_a = BitSet128::new();
_ = set_a.set(10);
_ = set_a.set(20);
let mut set_b = BitSet128::new();
_ = set_b.set(20);
_ = set_b.set(30);
let common = set_a & set_b;
assert!(!common.test(10));
assert!(common.test(20));
assert!(!common.test(30));
let all = set_a | set_b;
assert!(all.test(10));
assert!(all.test(20));
assert!(all.test(30));
let diff = set_a ^ set_b;
assert!(diff.test(10));
assert!(!diff.test(20));
assert!(diff.test(30));
}
}