use std::ops::Not;
use parking_lot::Mutex;
use super::{
Arc,
StatefulTester,
box_stateful_tester::BoxStatefulTester,
rc_stateful_tester::RcStatefulTester,
};
type ArcStatefulTesterFn = Arc<Mutex<dyn FnMut() -> bool + Send + 'static>>;
pub struct ArcStatefulTester {
pub(super) function: ArcStatefulTesterFn,
}
impl ArcStatefulTester {
#[inline]
pub fn new<F>(f: F) -> Self
where
F: FnMut() -> bool + Send + 'static,
{
ArcStatefulTester {
function: Arc::new(Mutex::new(f)),
}
}
#[inline]
pub fn and<T>(&self, mut next: T) -> ArcStatefulTester
where
T: StatefulTester + Send + 'static,
{
let self_fn = Arc::clone(&self.function);
ArcStatefulTester::new(move || {
let matched = (self_fn.lock())();
matched && next.test()
})
}
#[inline]
pub fn or<T>(&self, mut next: T) -> ArcStatefulTester
where
T: StatefulTester + Send + 'static,
{
let self_fn = Arc::clone(&self.function);
ArcStatefulTester::new(move || {
let matched = (self_fn.lock())();
matched || next.test()
})
}
#[inline]
pub fn nand<T>(&self, mut next: T) -> ArcStatefulTester
where
T: StatefulTester + Send + 'static,
{
let self_fn = Arc::clone(&self.function);
ArcStatefulTester::new(move || {
let matched = (self_fn.lock())();
!(matched && next.test())
})
}
#[inline]
pub fn xor<T>(&self, mut next: T) -> ArcStatefulTester
where
T: StatefulTester + Send + 'static,
{
let self_fn = Arc::clone(&self.function);
ArcStatefulTester::new(move || {
let matched = (self_fn.lock())();
matched ^ next.test()
})
}
#[inline]
pub fn nor<T>(&self, mut next: T) -> ArcStatefulTester
where
T: StatefulTester + Send + 'static,
{
let self_fn = Arc::clone(&self.function);
ArcStatefulTester::new(move || {
let matched = (self_fn.lock())();
!(matched || next.test())
})
}
}
impl Clone for ArcStatefulTester {
#[inline]
fn clone(&self) -> Self {
ArcStatefulTester {
function: Arc::clone(&self.function),
}
}
}
impl Not for ArcStatefulTester {
type Output = ArcStatefulTester;
#[inline]
fn not(self) -> Self::Output {
let function = self.function;
ArcStatefulTester::new(move || !((function.lock())()))
}
}
impl Not for &ArcStatefulTester {
type Output = ArcStatefulTester;
#[inline]
fn not(self) -> Self::Output {
let function = Arc::clone(&self.function);
ArcStatefulTester::new(move || !((function.lock())()))
}
}
impl StatefulTester for ArcStatefulTester {
#[inline]
fn test(&mut self) -> bool {
(self.function.lock())()
}
#[inline]
fn into_box(self) -> BoxStatefulTester {
let function = self.function;
BoxStatefulTester::new(move || (function.lock())())
}
#[inline]
fn into_rc(self) -> RcStatefulTester {
let function = self.function;
RcStatefulTester::new(move || (function.lock())())
}
#[inline]
fn into_arc(self) -> ArcStatefulTester {
self
}
}