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}