Skip to main content

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}