Skip to main content

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