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}