use std::error::Error;
#[rustfmt::skip]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(u8)]
enum TestInput {
A = 0b00000001,
B = 0b00000010,
C = 0b00000100,
D = 0b00010000,
E = 0b10000000,
F = 0b01000000,
G = 0b00001000,
H = 0b00100000,
}
mod test_input_varflags {
use varflags::error::ReprToFlagError;
use bitworks::index::Index;
use bitworks::prelude::Bitset8 as Inner;
type Repr = u8;
use super::TestInput as E;
pub type TestInputVarflags = varflags::Varflags<E, Inner>;
impl From<E> for Repr {
fn from(value: E) -> Self {
value as Repr
}
}
impl core::ops::Not for E {
type Output = TestInputVarflags;
fn not(self) -> Self::Output {
TestInputVarflags::_from_inner(!Inner::new(self as Repr))
}
}
impl core::ops::BitAnd for E {
type Output = TestInputVarflags;
fn bitand(self, rhs: Self) -> Self::Output {
TestInputVarflags::_from_inner(Inner::new(self as Repr) & Inner::new(rhs as Repr))
}
}
impl core::ops::BitOr for E {
type Output = TestInputVarflags;
fn bitor(self, rhs: Self) -> Self::Output {
TestInputVarflags::_from_inner(Inner::new(self as Repr) | Inner::new(rhs as Repr))
}
}
impl core::ops::BitXor for E {
type Output = TestInputVarflags;
fn bitxor(self, rhs: Self) -> Self::Output {
TestInputVarflags::_from_inner(Inner::new(self as Repr) ^ Inner::new(rhs as Repr))
}
}
impl TryFrom<Index<Inner>> for E {
type Error = ReprToFlagError<Repr>;
fn try_from(value: Index<Inner>) -> Result<Self, Self::Error> {
let n: Repr = 1 << value.into_inner();
match n {
0b00000001 => Ok(E::A),
0b00000010 => Ok(E::B),
0b00000100 => Ok(E::C),
0b00010000 => Ok(E::D),
0b10000000 => Ok(E::E),
0b01000000 => Ok(E::F),
0b00001000 => Ok(E::G),
0b00100000 => Ok(E::H),
_ => Err(Self::Error::new(n)),
}
}
}
impl core::fmt::Display for E {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match *self {
E::A => "A",
E::B => "B",
E::C => "C",
E::D => "D",
E::E => "E",
E::F => "F",
E::G => "G",
E::H => "H",
}
)
}
}
}
use test_input_varflags::TestInputVarflags;
#[test]
fn example() -> Result<(), Box<dyn Error>> {
use bitworks::prelude::*;
let a = TestInput::A;
let b = TestInput::B;
assert_eq!(u8::from(TestInput::D), 0b00010000);
assert_eq!(u8::from(TestInput::E), 0b10000000);
assert_eq!(u8::from(TestInput::F), 0b01000000);
let c = a | b | TestInput::D;
assert_eq!(c, TestInputVarflags::_from_inner(Bitset8::new(0b00010011)));
assert!(c.contains(&TestInput::A));
assert!(!c.contains(&TestInput::H));
let d = TestInput::A | TestInput::B;
let e = TestInput::A | TestInput::C;
assert!(c.includes(&d));
assert!(!c.includes(&e));
let f = TestInput::F | TestInput::H;
assert!(c.intersects(&e));
assert!(!c.intersects(&f));
let x = TestInputVarflags::ALL;
let mut iter = x.variants();
assert_eq!(iter.next(), Some(TestInput::A));
assert_eq!(iter.next(), Some(TestInput::B));
assert_eq!(iter.next(), Some(TestInput::C));
assert_eq!(iter.next(), Some(TestInput::G));
assert_eq!(iter.next(), Some(TestInput::D));
assert_eq!(iter.next(), Some(TestInput::H));
assert_eq!(iter.next(), Some(TestInput::F));
assert_eq!(iter.next(), Some(TestInput::E));
assert_eq!(iter.next(), None);
let iter = c.variants();
let c: TestInputVarflags = iter.collect();
assert_eq!(c, TestInputVarflags::_from_inner(Bitset8::new(0b00010011)));
println!("{c}");
println!("{c:?}");
Ok(())
}