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