use std::{
fmt,
ops::Not,
};
use {
super::StatefulTester,
crate::{
internal::CallbackMetadata,
macros::{
impl_common_name_methods,
impl_common_new_methods,
},
},
};
#[must_use = "callback wrappers do nothing unless stored or invoked"]
pub struct BoxStatefulTester {
pub(super) function: Box<dyn FnMut() -> bool>,
pub(super) metadata: CallbackMetadata,
}
impl BoxStatefulTester {
impl_common_new_methods!(
semantic_mut(StatefulTester + 'static),
|source| move || source.test(),
|function| Box::new(function),
"stateful tester"
);
impl_common_name_methods!("stateful tester");
#[inline]
pub fn and<T>(mut self, mut next: T) -> BoxStatefulTester
where
T: StatefulTester + 'static,
{
BoxStatefulTester::new(move || self.test() && next.test())
}
#[inline]
pub fn or<T>(mut self, mut next: T) -> BoxStatefulTester
where
T: StatefulTester + 'static,
{
BoxStatefulTester::new(move || self.test() || next.test())
}
#[inline]
pub fn nand<T>(mut self, mut next: T) -> BoxStatefulTester
where
T: StatefulTester + 'static,
{
BoxStatefulTester::new(move || !(self.test() && next.test()))
}
#[inline]
pub fn xor<T>(mut self, mut next: T) -> BoxStatefulTester
where
T: StatefulTester + 'static,
{
BoxStatefulTester::new(move || self.test() ^ next.test())
}
#[inline]
pub fn nor<T>(mut self, mut next: T) -> BoxStatefulTester
where
T: StatefulTester + 'static,
{
BoxStatefulTester::new(move || !(self.test() || next.test()))
}
}
impl Not for BoxStatefulTester {
type Output = BoxStatefulTester;
#[inline]
fn not(self) -> Self::Output {
let metadata = self.metadata;
let mut function = self.function;
BoxStatefulTester::new_with_metadata(move || !function(), metadata)
}
}
impl StatefulTester for BoxStatefulTester {
#[inline(always)]
fn test(&mut self) -> bool {
(self.function)()
}
}
impl fmt::Debug for BoxStatefulTester {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("BoxStatefulTester")
.field("name", &self.metadata.name())
.finish()
}
}
impl fmt::Display for BoxStatefulTester {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.metadata.name() {
Some(name) => write!(formatter, "BoxStatefulTester({name})"),
None => formatter.write_str("BoxStatefulTester"),
}
}
}