use std::ops::Not;
use {
super::ALWAYS_FALSE_NAME,
super::ALWAYS_TRUE_NAME,
crate::StatefulBiPredicate,
crate::predicates::macros::impl_predicate_clone,
crate::predicates::macros::impl_predicate_common_methods,
crate::predicates::macros::impl_predicate_debug_display,
parking_lot::Mutex,
std::sync::Arc,
};
type ArcStatefulBiPredicateFn<T, U> =
Arc<Mutex<dyn FnMut(&T, &U) -> bool + Send + 'static>>;
#[must_use = "callback wrappers do nothing unless stored or invoked"]
pub struct ArcStatefulBiPredicate<T, U> {
pub(super) function: ArcStatefulBiPredicateFn<T, U>,
pub(super) metadata: crate::internal::CallbackMetadata,
}
impl<T, U> ArcStatefulBiPredicate<T, U> {
impl_predicate_common_methods!(
ArcStatefulBiPredicate<T, U>,
(FnMut(&T, &U) -> bool + Send + 'static),
|f| Arc::new(Mutex::new(f))
);
#[inline]
pub fn and<P>(&self, mut other: P) -> ArcStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + Send + 'static,
T: 'static,
U: 'static,
{
let self_fn = self.function.clone();
ArcStatefulBiPredicate::new(move |first: &T, second: &U| {
let matched = {
let mut function = self_fn.lock();
function(first, second)
};
matched && other.test(first, second)
})
}
#[inline]
pub fn or<P>(&self, mut other: P) -> ArcStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + Send + 'static,
T: 'static,
U: 'static,
{
let self_fn = self.function.clone();
ArcStatefulBiPredicate::new(move |first: &T, second: &U| {
let matched = {
let mut function = self_fn.lock();
function(first, second)
};
matched || other.test(first, second)
})
}
#[inline]
pub fn nand<P>(&self, mut other: P) -> ArcStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + Send + 'static,
T: 'static,
U: 'static,
{
let self_fn = self.function.clone();
ArcStatefulBiPredicate::new(move |first: &T, second: &U| {
let matched = {
let mut function = self_fn.lock();
function(first, second)
};
!(matched && other.test(first, second))
})
}
#[inline]
pub fn xor<P>(&self, mut other: P) -> ArcStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + Send + 'static,
T: 'static,
U: 'static,
{
let self_fn = self.function.clone();
ArcStatefulBiPredicate::new(move |first: &T, second: &U| {
let matched = {
let mut function = self_fn.lock();
function(first, second)
};
matched ^ other.test(first, second)
})
}
#[inline]
pub fn nor<P>(&self, mut other: P) -> ArcStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + Send + 'static,
T: 'static,
U: 'static,
{
let self_fn = self.function.clone();
ArcStatefulBiPredicate::new(move |first: &T, second: &U| {
let matched = {
let mut function = self_fn.lock();
function(first, second)
};
!(matched || other.test(first, second))
})
}
}
impl<T, U> Not for ArcStatefulBiPredicate<T, U>
where
T: 'static,
U: 'static,
{
type Output = ArcStatefulBiPredicate<T, U>;
fn not(self) -> Self::Output {
let metadata = self.metadata;
let function = self.function;
ArcStatefulBiPredicate::new_with_metadata(
move |first: &T, second: &U| {
let mut function = function.lock();
!function(first, second)
},
metadata,
)
}
}
impl<T, U> Not for &ArcStatefulBiPredicate<T, U>
where
T: 'static,
U: 'static,
{
type Output = ArcStatefulBiPredicate<T, U>;
fn not(self) -> Self::Output {
let function = self.function.clone();
ArcStatefulBiPredicate::new_with_metadata(
move |first: &T, second: &U| {
let mut function = function.lock();
!function(first, second)
},
self.metadata.clone(),
)
}
}
impl_predicate_clone!(ArcStatefulBiPredicate<T, U>);
impl_predicate_debug_display!(ArcStatefulBiPredicate<T, U>);
impl<T, U> StatefulBiPredicate<T, U> for ArcStatefulBiPredicate<T, U> {
#[inline]
fn test(&mut self, first: &T, second: &U) -> bool {
let mut function = self.function.lock();
function(first, second)
}
}