Skip to main content

qubit_function/predicates/
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//! # StatefulBiPredicate Abstraction
11//!
12//! Provides bi-predicate wrappers for closures that implement
13//! `FnMut(&T, &U) -> bool`. A stateful bi-predicate can update its own
14//! internal state while testing two borrowed input values.
15//!
16//! Use [`BiPredicate`](crate::BiPredicate) for immutable
17//! `Fn(&T, &U) -> bool` predicates and `StatefulBiPredicate` when the
18//! predicate needs native `FnMut` semantics, such as counters, rolling
19//! windows, sampling, or stateful filters over pairs of values.
20//!
21use std::cell::RefCell;
22use std::rc::Rc;
23use std::sync::Arc;
24
25use parking_lot::Mutex;
26
27use crate::macros::{
28    impl_arc_conversions,
29    impl_box_conversions,
30    impl_closure_trait,
31    impl_rc_conversions,
32};
33use crate::predicates::macros::{
34    constants::{
35        ALWAYS_FALSE_NAME,
36        ALWAYS_TRUE_NAME,
37    },
38    impl_predicate_clone,
39    impl_predicate_common_methods,
40    impl_predicate_debug_display,
41};
42
43mod arc_stateful_bi_predicate;
44pub use arc_stateful_bi_predicate::ArcStatefulBiPredicate;
45mod box_stateful_bi_predicate;
46pub use box_stateful_bi_predicate::BoxStatefulBiPredicate;
47mod fn_stateful_bi_predicate_ops;
48pub use fn_stateful_bi_predicate_ops::FnStatefulBiPredicateOps;
49mod rc_stateful_bi_predicate;
50pub use rc_stateful_bi_predicate::RcStatefulBiPredicate;
51
52/// A stateful bi-predicate trait for testing pairs with mutable internal state.
53///
54/// This trait represents closures and wrapper types equivalent to
55/// `FnMut(&T, &U) -> bool`: each call borrows the predicate mutably so the
56/// predicate can update counters, caches, rolling state, or other internal
57/// data while leaving both tested values borrowed immutably.
58///
59/// # Type Parameters
60///
61/// * `T` - The type of the first value being tested.
62/// * `U` - The type of the second value being tested.
63pub trait StatefulBiPredicate<T, U> {
64    /// Tests whether the given values satisfy this bi-predicate.
65    ///
66    /// The method takes `&mut self` because evaluating the predicate may
67    /// update internal state. The tested values themselves are only borrowed
68    /// immutably and are not modified by this API.
69    ///
70    /// # Parameters
71    ///
72    /// * `first` - The first value to test.
73    /// * `second` - The second value to test.
74    ///
75    /// # Returns
76    ///
77    /// `true` if the values satisfy this bi-predicate, `false` otherwise.
78    fn test(&mut self, first: &T, second: &U) -> bool;
79
80    /// Converts this bi-predicate into a `BoxStatefulBiPredicate`.
81    ///
82    /// This consumes `self` and wraps it in a single-owner stateful
83    /// bi-predicate. The returned wrapper forwards each call to this
84    /// predicate's [`test`](StatefulBiPredicate::test) method.
85    ///
86    /// # Returns
87    ///
88    /// A `BoxStatefulBiPredicate` wrapping this predicate.
89    fn into_box(mut self) -> BoxStatefulBiPredicate<T, U>
90    where
91        Self: Sized + 'static,
92    {
93        BoxStatefulBiPredicate::new(move |first: &T, second: &U| self.test(first, second))
94    }
95
96    /// Converts this bi-predicate into an `RcStatefulBiPredicate`.
97    ///
98    /// This consumes `self` and wraps it in a single-threaded shared
99    /// stateful bi-predicate using `Rc<RefCell<_>>`.
100    ///
101    /// # Returns
102    ///
103    /// An `RcStatefulBiPredicate` wrapping this predicate.
104    fn into_rc(mut self) -> RcStatefulBiPredicate<T, U>
105    where
106        Self: Sized + 'static,
107    {
108        RcStatefulBiPredicate::new(move |first: &T, second: &U| self.test(first, second))
109    }
110
111    /// Converts this bi-predicate into an `ArcStatefulBiPredicate`.
112    ///
113    /// This consumes `self` and wraps it in a thread-safe shared stateful
114    /// bi-predicate using `Arc<Mutex<_>>`. The wrapped predicate must be
115    /// `Send` so it can be stored behind the thread-safe wrapper.
116    ///
117    /// # Returns
118    ///
119    /// An `ArcStatefulBiPredicate` wrapping this predicate.
120    fn into_arc(mut self) -> ArcStatefulBiPredicate<T, U>
121    where
122        Self: Sized + Send + 'static,
123    {
124        ArcStatefulBiPredicate::new(move |first: &T, second: &U| self.test(first, second))
125    }
126
127    /// Converts this bi-predicate into a closure implementing
128    /// `FnMut(&T, &U) -> bool`.
129    ///
130    /// This consumes `self` and returns a mutable closure that forwards each
131    /// call to [`test`](StatefulBiPredicate::test).
132    ///
133    /// # Returns
134    ///
135    /// A closure implementing `FnMut(&T, &U) -> bool`.
136    fn into_fn(mut self) -> impl FnMut(&T, &U) -> bool
137    where
138        Self: Sized + 'static,
139    {
140        move |first: &T, second: &U| self.test(first, second)
141    }
142
143    /// Converts a clone of this bi-predicate into a `BoxStatefulBiPredicate`.
144    ///
145    /// The original predicate remains available after this call. The cloned
146    /// predicate owns independent state unless its clone implementation shares
147    /// state internally.
148    ///
149    /// # Returns
150    ///
151    /// A `BoxStatefulBiPredicate` wrapping a clone of this predicate.
152    fn to_box(&self) -> BoxStatefulBiPredicate<T, U>
153    where
154        Self: Clone + Sized + 'static,
155    {
156        self.clone().into_box()
157    }
158
159    /// Converts a clone of this bi-predicate into an `RcStatefulBiPredicate`.
160    ///
161    /// The original predicate remains available after this call. The cloned
162    /// predicate owns independent state unless its clone implementation shares
163    /// state internally.
164    ///
165    /// # Returns
166    ///
167    /// An `RcStatefulBiPredicate` wrapping a clone of this predicate.
168    fn to_rc(&self) -> RcStatefulBiPredicate<T, U>
169    where
170        Self: Clone + Sized + 'static,
171    {
172        self.clone().into_rc()
173    }
174
175    /// Converts a clone of this bi-predicate into an `ArcStatefulBiPredicate`.
176    ///
177    /// The original predicate remains available after this call. The cloned
178    /// predicate must be `Send` so it can be stored behind the thread-safe
179    /// wrapper.
180    ///
181    /// # Returns
182    ///
183    /// An `ArcStatefulBiPredicate` wrapping a clone of this predicate.
184    fn to_arc(&self) -> ArcStatefulBiPredicate<T, U>
185    where
186        Self: Clone + Sized + Send + 'static,
187    {
188        self.clone().into_arc()
189    }
190
191    /// Converts a clone of this bi-predicate into a mutable closure.
192    ///
193    /// The original predicate remains available after this call. The cloned
194    /// predicate owns independent state unless its clone implementation shares
195    /// state internally.
196    ///
197    /// # Returns
198    ///
199    /// A closure implementing `FnMut(&T, &U) -> bool`.
200    fn to_fn(&self) -> impl FnMut(&T, &U) -> bool
201    where
202        Self: Clone + Sized + 'static,
203    {
204        let mut predicate = self.clone();
205        move |first: &T, second: &U| predicate.test(first, second)
206    }
207}