use std::ops::Not;
use super::{
ALWAYS_FALSE_NAME,
ALWAYS_TRUE_NAME,
Arc,
BoxStatefulPredicate,
Mutex,
RcStatefulPredicate,
StatefulPredicate,
impl_arc_conversions,
impl_predicate_clone,
impl_predicate_common_methods,
impl_predicate_debug_display,
};
type ArcStatefulPredicateFn<T> = Arc<Mutex<dyn FnMut(&T) -> bool + Send + 'static>>;
pub struct ArcStatefulPredicate<T> {
pub(super) function: ArcStatefulPredicateFn<T>,
pub(super) name: Option<String>,
}
impl<T> ArcStatefulPredicate<T> {
impl_predicate_common_methods!(
ArcStatefulPredicate<T>,
(FnMut(&T) -> bool + Send + 'static),
|f| Arc::new(Mutex::new(f))
);
#[inline]
pub fn and<P>(&self, mut other: P) -> ArcStatefulPredicate<T>
where
P: StatefulPredicate<T> + Send + 'static,
T: 'static,
{
let self_fn = self.function.clone();
ArcStatefulPredicate::new(move |value| {
let matched = (self_fn.lock())(value);
matched && other.test(value)
})
}
#[inline]
pub fn or<P>(&self, mut other: P) -> ArcStatefulPredicate<T>
where
P: StatefulPredicate<T> + Send + 'static,
T: 'static,
{
let self_fn = self.function.clone();
ArcStatefulPredicate::new(move |value| {
let matched = (self_fn.lock())(value);
matched || other.test(value)
})
}
#[inline]
pub fn nand<P>(&self, mut other: P) -> ArcStatefulPredicate<T>
where
P: StatefulPredicate<T> + Send + 'static,
T: 'static,
{
let self_fn = self.function.clone();
ArcStatefulPredicate::new(move |value| {
let matched = (self_fn.lock())(value);
!(matched && other.test(value))
})
}
#[inline]
pub fn xor<P>(&self, mut other: P) -> ArcStatefulPredicate<T>
where
P: StatefulPredicate<T> + Send + 'static,
T: 'static,
{
let self_fn = self.function.clone();
ArcStatefulPredicate::new(move |value| {
let matched = (self_fn.lock())(value);
matched ^ other.test(value)
})
}
#[inline]
pub fn nor<P>(&self, mut other: P) -> ArcStatefulPredicate<T>
where
P: StatefulPredicate<T> + Send + 'static,
T: 'static,
{
let self_fn = self.function.clone();
ArcStatefulPredicate::new(move |value| {
let matched = (self_fn.lock())(value);
!(matched || other.test(value))
})
}
}
impl<T> Not for ArcStatefulPredicate<T>
where
T: 'static,
{
type Output = ArcStatefulPredicate<T>;
fn not(self) -> Self::Output {
let function = self.function;
ArcStatefulPredicate::new(move |value| !((function.lock())(value)))
}
}
impl<T> Not for &ArcStatefulPredicate<T>
where
T: 'static,
{
type Output = ArcStatefulPredicate<T>;
fn not(self) -> Self::Output {
let function = self.function.clone();
ArcStatefulPredicate::new(move |value| !((function.lock())(value)))
}
}
impl_predicate_clone!(ArcStatefulPredicate<T>);
impl_predicate_debug_display!(ArcStatefulPredicate<T>);
impl<T> StatefulPredicate<T> for ArcStatefulPredicate<T> {
fn test(&mut self, value: &T) -> bool {
(self.function.lock())(value)
}
impl_arc_conversions!(
ArcStatefulPredicate<T>,
BoxStatefulPredicate,
RcStatefulPredicate,
FnMut(t: &T) -> bool
);
}
impl<F, T> StatefulPredicate<T> for F
where
F: FnMut(&T) -> bool,
{
fn test(&mut self, value: &T) -> bool {
self(value)
}
}