Skip to main content

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