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