Skip to main content

qubit_function/predicates/stateful_bi_predicate/
rc_stateful_bi_predicate.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10// qubit-style: allow explicit-imports
11//! Defines the `RcStatefulBiPredicate` public type.
12
13use std::ops::Not;
14
15use super::{
16    ALWAYS_FALSE_NAME,
17    ALWAYS_TRUE_NAME,
18    BoxStatefulBiPredicate,
19    Rc,
20    RefCell,
21    StatefulBiPredicate,
22    impl_predicate_clone,
23    impl_predicate_common_methods,
24    impl_predicate_debug_display,
25    impl_rc_conversions,
26};
27
28type RcStatefulBiPredicateFn<T, U> = Rc<RefCell<dyn FnMut(&T, &U) -> bool>>;
29
30/// An Rc-based stateful bi-predicate with single-threaded shared ownership.
31///
32/// This type stores the predicate closure inside `Rc<RefCell<_>>`, allowing
33/// cheap clones that share the same mutable predicate state on one thread.
34pub struct RcStatefulBiPredicate<T, U> {
35    pub(super) function: RcStatefulBiPredicateFn<T, U>,
36    pub(super) name: Option<String>,
37}
38
39impl<T, U> RcStatefulBiPredicate<T, U> {
40    // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
41    impl_predicate_common_methods!(
42        RcStatefulBiPredicate<T, U>,
43        (FnMut(&T, &U) -> bool + 'static),
44        |f| Rc::new(RefCell::new(f))
45    );
46
47    /// Returns a bi-predicate representing logical AND with another predicate.
48    ///
49    /// This method borrows `self`; the returned predicate shares this
50    /// predicate's mutable state through the same `Rc<RefCell<_>>`.
51    ///
52    /// # Parameters
53    ///
54    /// * `other` - The other bi-predicate to combine with.
55    ///
56    /// # Returns
57    ///
58    /// A new `RcStatefulBiPredicate` representing logical AND.
59    #[inline]
60    pub fn and<P>(&self, mut other: P) -> RcStatefulBiPredicate<T, U>
61    where
62        P: StatefulBiPredicate<T, U> + 'static,
63        T: 'static,
64        U: 'static,
65    {
66        let self_fn = self.function.clone();
67        RcStatefulBiPredicate::new(move |first, second| {
68            let matched = (self_fn.borrow_mut())(first, second);
69            matched && other.test(first, second)
70        })
71    }
72
73    /// Returns a bi-predicate representing logical OR with another predicate.
74    ///
75    /// This method borrows `self`; the returned predicate shares this
76    /// predicate's mutable state through the same `Rc<RefCell<_>>`.
77    ///
78    /// # Parameters
79    ///
80    /// * `other` - The other bi-predicate to combine with.
81    ///
82    /// # Returns
83    ///
84    /// A new `RcStatefulBiPredicate` representing logical OR.
85    #[inline]
86    pub fn or<P>(&self, mut other: P) -> RcStatefulBiPredicate<T, U>
87    where
88        P: StatefulBiPredicate<T, U> + 'static,
89        T: 'static,
90        U: 'static,
91    {
92        let self_fn = self.function.clone();
93        RcStatefulBiPredicate::new(move |first, second| {
94            let matched = (self_fn.borrow_mut())(first, second);
95            matched || other.test(first, second)
96        })
97    }
98
99    /// Returns a bi-predicate representing logical NAND with another predicate.
100    ///
101    /// NAND returns `true` unless both predicates return `true`.
102    ///
103    /// # Parameters
104    ///
105    /// * `other` - The other bi-predicate to combine with.
106    ///
107    /// # Returns
108    ///
109    /// A new `RcStatefulBiPredicate` representing logical NAND.
110    #[inline]
111    pub fn nand<P>(&self, mut other: P) -> RcStatefulBiPredicate<T, U>
112    where
113        P: StatefulBiPredicate<T, U> + 'static,
114        T: 'static,
115        U: 'static,
116    {
117        let self_fn = self.function.clone();
118        RcStatefulBiPredicate::new(move |first, second| {
119            let matched = (self_fn.borrow_mut())(first, second);
120            !(matched && other.test(first, second))
121        })
122    }
123
124    /// Returns a bi-predicate representing logical XOR with another predicate.
125    ///
126    /// XOR evaluates both predicates and returns `true` when exactly one
127    /// predicate returns `true`.
128    ///
129    /// # Parameters
130    ///
131    /// * `other` - The other bi-predicate to combine with.
132    ///
133    /// # Returns
134    ///
135    /// A new `RcStatefulBiPredicate` representing logical XOR.
136    #[inline]
137    pub fn xor<P>(&self, mut other: P) -> RcStatefulBiPredicate<T, U>
138    where
139        P: StatefulBiPredicate<T, U> + 'static,
140        T: 'static,
141        U: 'static,
142    {
143        let self_fn = self.function.clone();
144        RcStatefulBiPredicate::new(move |first, second| {
145            let matched = (self_fn.borrow_mut())(first, second);
146            matched ^ other.test(first, second)
147        })
148    }
149
150    /// Returns a bi-predicate representing logical NOR with another predicate.
151    ///
152    /// NOR returns `true` only when both predicates return `false`.
153    ///
154    /// # Parameters
155    ///
156    /// * `other` - The other bi-predicate to combine with.
157    ///
158    /// # Returns
159    ///
160    /// A new `RcStatefulBiPredicate` representing logical NOR.
161    #[inline]
162    pub fn nor<P>(&self, mut other: P) -> RcStatefulBiPredicate<T, U>
163    where
164        P: StatefulBiPredicate<T, U> + 'static,
165        T: 'static,
166        U: 'static,
167    {
168        let self_fn = self.function.clone();
169        RcStatefulBiPredicate::new(move |first, second| {
170            let matched = (self_fn.borrow_mut())(first, second);
171            !(matched || other.test(first, second))
172        })
173    }
174}
175
176impl<T, U> Not for RcStatefulBiPredicate<T, U>
177where
178    T: 'static,
179    U: 'static,
180{
181    type Output = RcStatefulBiPredicate<T, U>;
182
183    fn not(self) -> Self::Output {
184        let function = self.function;
185        RcStatefulBiPredicate::new(move |first, second| !((function.borrow_mut())(first, second)))
186    }
187}
188
189impl<T, U> Not for &RcStatefulBiPredicate<T, U>
190where
191    T: 'static,
192    U: 'static,
193{
194    type Output = RcStatefulBiPredicate<T, U>;
195
196    fn not(self) -> Self::Output {
197        let function = self.function.clone();
198        RcStatefulBiPredicate::new(move |first, second| !((function.borrow_mut())(first, second)))
199    }
200}
201
202// Generates: impl Clone for RcStatefulBiPredicate<T, U>
203impl_predicate_clone!(RcStatefulBiPredicate<T, U>);
204
205// Generates: impl Debug for RcStatefulBiPredicate<T, U> and impl Display for RcStatefulBiPredicate<T, U>
206impl_predicate_debug_display!(RcStatefulBiPredicate<T, U>);
207
208impl<T, U> StatefulBiPredicate<T, U> for RcStatefulBiPredicate<T, U> {
209    fn test(&mut self, first: &T, second: &U) -> bool {
210        (self.function.borrow_mut())(first, second)
211    }
212
213    // Generates: into_box(), into_rc(), into_fn(), to_box(), to_rc(), to_fn()
214    impl_rc_conversions!(
215        RcStatefulBiPredicate<T, U>,
216        BoxStatefulBiPredicate,
217        FnMut(first: &T, second: &U) -> bool
218    );
219}