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!(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}