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