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