use crate::{
backend::{Backend, WordRef},
word::{CompositeWord, Word, WordLike},
};
use core::ops::{BitAnd, BitOr, BitXor, Not};
#[derive(Debug)]
#[repr(transparent)]
pub struct BooleanWordRef<B: Backend> {
inner: WordRef<B, u8, 1>,
}
impl<B: Backend> BooleanWordRef<B> {
pub(super) fn new(inner: WordRef<B, u8, 1>) -> Self {
return Self { inner };
}
pub fn into_true(self) -> Self {
return Self {
inner: self
.inner
.into_const_same_width(CompositeWord::<u8, 1>::ONE),
};
}
pub fn into_false(self) -> Self {
return Self {
inner: self.inner.into_zero(),
};
}
pub fn into(self) -> WordRef<B, u8, 1> {
return self.inner;
}
pub fn into_lsb(self) -> WordRef<B, u8, 1> {
return self.inner & 1u8;
}
pub fn select<W: Word, const N: usize>(
self,
then: WordRef<B, W, N>,
else_: WordRef<B, W, N>,
) -> WordRef<B, W, N> {
let cond = WordRef::mask(self);
return (cond.clone() & then) ^ ((!cond) & else_);
}
pub fn select_var_const<W: Word, const N: usize, C: WordLike<W, N>>(
self,
then: WordRef<B, W, N>,
else_: C,
) -> WordRef<B, W, N> {
let cond = WordRef::mask(self);
return (cond.clone() & then) ^ ((!cond) & else_);
}
pub fn select_const_var<W: Word, const N: usize, C: WordLike<W, N>>(
self,
then: C,
else_: WordRef<B, W, N>,
) -> WordRef<B, W, N> {
let cond = WordRef::<B, W, N>::mask(self);
return (cond.clone() & then) ^ ((!cond) & else_);
}
pub fn select_const_const<W: Word, const N: usize, C: WordLike<W, N>>(
self,
then: C,
else_: C,
) -> WordRef<B, W, N> {
let cond = WordRef::<B, W, N>::mask(self);
return (cond.clone() & then) ^ ((!cond) & else_);
}
pub fn boolean_select(
self,
then: BooleanWordRef<B>,
else_: BooleanWordRef<B>,
) -> BooleanWordRef<B> {
return Self::new(self.select(then.into(), else_.into()));
}
pub fn boolean_select_var_const(
self,
then: BooleanWordRef<B>,
else_: bool,
) -> BooleanWordRef<B> {
return Self::new(self.select_var_const(then.into(), else_ as u8));
}
pub fn boolean_select_const_var(
self,
then: bool,
else_: BooleanWordRef<B>,
) -> BooleanWordRef<B> {
return Self::new(self.select_const_var(then as u8, else_.into()));
}
pub fn boolean_select_const_const(self, then: bool, else_: bool) -> BooleanWordRef<B> {
return Self::new(self.select_const_const(then as u8, else_ as u8));
}
}
impl<B: Backend> Not for BooleanWordRef<B> {
type Output = Self;
fn not(self) -> Self::Output {
return BooleanWordRef {
inner: self.inner ^ 1u8,
};
}
}
impl<B: Backend> BitAnd<BooleanWordRef<B>> for BooleanWordRef<B> {
type Output = Self;
fn bitand(self, rhs: BooleanWordRef<B>) -> Self::Output {
return BooleanWordRef {
inner: self.inner & rhs.inner,
};
}
}
impl<B: Backend> BitAnd<bool> for BooleanWordRef<B> {
type Output = Self;
fn bitand(self, rhs: bool) -> Self::Output {
return BooleanWordRef {
inner: self.inner & rhs as u8,
};
}
}
impl<B: Backend> BitOr<BooleanWordRef<B>> for BooleanWordRef<B> {
type Output = Self;
fn bitor(self, rhs: BooleanWordRef<B>) -> Self::Output {
return BooleanWordRef {
inner: self.inner | rhs.inner,
};
}
}
impl<B: Backend> BitOr<bool> for BooleanWordRef<B> {
type Output = Self;
fn bitor(self, rhs: bool) -> Self::Output {
return BooleanWordRef {
inner: self.inner | rhs as u8,
};
}
}
impl<B: Backend> BitXor<BooleanWordRef<B>> for BooleanWordRef<B> {
type Output = Self;
fn bitxor(self, rhs: BooleanWordRef<B>) -> Self::Output {
return BooleanWordRef {
inner: self.inner ^ rhs.inner,
};
}
}
impl<B: Backend> BitXor<bool> for BooleanWordRef<B> {
type Output = Self;
fn bitxor(self, rhs: bool) -> Self::Output {
return BooleanWordRef {
inner: self.inner ^ rhs as u8,
};
}
}
impl<B: Backend> Clone for BooleanWordRef<B> {
fn clone(&self) -> Self {
return BooleanWordRef {
inner: self.inner.clone(),
};
}
}