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