use std::ops::Not;
use super::{
ALWAYS_FALSE_NAME,
ALWAYS_TRUE_NAME,
RcStatefulBiPredicate,
StatefulBiPredicate,
impl_box_conversions,
impl_predicate_common_methods,
impl_predicate_debug_display,
};
type BoxStatefulBiPredicateFn<T, U> = dyn FnMut(&T, &U) -> bool;
pub struct BoxStatefulBiPredicate<T, U> {
pub(super) function: Box<BoxStatefulBiPredicateFn<T, U>>,
pub(super) name: Option<String>,
}
impl<T, U> BoxStatefulBiPredicate<T, U> {
impl_predicate_common_methods!(
BoxStatefulBiPredicate<T, U>,
(FnMut(&T, &U) -> bool + 'static),
|f| Box::new(f)
);
#[inline]
pub fn and<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + 'static,
T: 'static,
U: 'static,
{
BoxStatefulBiPredicate::new(move |first, second| {
self.test(first, second) && other.test(first, second)
})
}
#[inline]
pub fn or<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + 'static,
T: 'static,
U: 'static,
{
BoxStatefulBiPredicate::new(move |first, second| {
self.test(first, second) || other.test(first, second)
})
}
#[inline]
pub fn nand<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + 'static,
T: 'static,
U: 'static,
{
BoxStatefulBiPredicate::new(move |first, second| {
!(self.test(first, second) && other.test(first, second))
})
}
#[inline]
pub fn xor<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + 'static,
T: 'static,
U: 'static,
{
BoxStatefulBiPredicate::new(move |first, second| {
self.test(first, second) ^ other.test(first, second)
})
}
#[inline]
pub fn nor<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
where
P: StatefulBiPredicate<T, U> + 'static,
T: 'static,
U: 'static,
{
BoxStatefulBiPredicate::new(move |first, second| {
!(self.test(first, second) || other.test(first, second))
})
}
}
impl<T, U> Not for BoxStatefulBiPredicate<T, U>
where
T: 'static,
U: 'static,
{
type Output = BoxStatefulBiPredicate<T, U>;
fn not(mut self) -> Self::Output {
BoxStatefulBiPredicate::new(move |first, second| !self.test(first, second))
}
}
impl_predicate_debug_display!(BoxStatefulBiPredicate<T, U>);
impl<T, U> StatefulBiPredicate<T, U> for BoxStatefulBiPredicate<T, U> {
fn test(&mut self, first: &T, second: &U) -> bool {
(self.function)(first, second)
}
impl_box_conversions!(
BoxStatefulBiPredicate<T, U>,
RcStatefulBiPredicate,
FnMut(&T, &U) -> bool
);
}