Skip to main content

qubit_function/predicates/stateful_bi_predicate/
box_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 `BoxStatefulBiPredicate` public type.
12
13use std::ops::Not;
14
15use super::{
16    ALWAYS_FALSE_NAME,
17    ALWAYS_TRUE_NAME,
18    RcStatefulBiPredicate,
19    StatefulBiPredicate,
20    impl_box_conversions,
21    impl_predicate_common_methods,
22    impl_predicate_debug_display,
23};
24
25type BoxStatefulBiPredicateFn<T, U> = dyn FnMut(&T, &U) -> bool;
26
27/// A Box-based stateful bi-predicate with single ownership.
28///
29/// This type stores a `Box<dyn FnMut(&T, &U) -> bool>`, so each call may
30/// update the predicate's internal state. Composition methods consume `self`,
31/// matching the single-ownership model.
32pub struct BoxStatefulBiPredicate<T, U> {
33    pub(super) function: Box<BoxStatefulBiPredicateFn<T, U>>,
34    pub(super) name: Option<String>,
35}
36
37impl<T, U> BoxStatefulBiPredicate<T, U> {
38    // Generates: new(), new_with_name(), name(), set_name(), always_true(), always_false()
39    impl_predicate_common_methods!(
40        BoxStatefulBiPredicate<T, U>,
41        (FnMut(&T, &U) -> bool + 'static),
42        |f| Box::new(f)
43    );
44
45    /// Returns a bi-predicate representing logical AND with another predicate.
46    ///
47    /// This method consumes `self` and evaluates `other` only when this
48    /// predicate returns `true`.
49    ///
50    /// # Parameters
51    ///
52    /// * `other` - The other bi-predicate to combine with.
53    ///
54    /// # Returns
55    ///
56    /// A new `BoxStatefulBiPredicate` representing logical AND.
57    #[inline]
58    pub fn and<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
59    where
60        P: StatefulBiPredicate<T, U> + 'static,
61        T: 'static,
62        U: 'static,
63    {
64        BoxStatefulBiPredicate::new(move |first, second| {
65            self.test(first, second) && other.test(first, second)
66        })
67    }
68
69    /// Returns a bi-predicate representing logical OR with another predicate.
70    ///
71    /// This method consumes `self` and evaluates `other` only when this
72    /// predicate returns `false`.
73    ///
74    /// # Parameters
75    ///
76    /// * `other` - The other bi-predicate to combine with.
77    ///
78    /// # Returns
79    ///
80    /// A new `BoxStatefulBiPredicate` representing logical OR.
81    #[inline]
82    pub fn or<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
83    where
84        P: StatefulBiPredicate<T, U> + 'static,
85        T: 'static,
86        U: 'static,
87    {
88        BoxStatefulBiPredicate::new(move |first, second| {
89            self.test(first, second) || other.test(first, second)
90        })
91    }
92
93    /// Returns a bi-predicate representing logical NAND with another predicate.
94    ///
95    /// NAND returns `true` unless both predicates return `true`.
96    ///
97    /// # Parameters
98    ///
99    /// * `other` - The other bi-predicate to combine with.
100    ///
101    /// # Returns
102    ///
103    /// A new `BoxStatefulBiPredicate` representing logical NAND.
104    #[inline]
105    pub fn nand<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
106    where
107        P: StatefulBiPredicate<T, U> + 'static,
108        T: 'static,
109        U: 'static,
110    {
111        BoxStatefulBiPredicate::new(move |first, second| {
112            !(self.test(first, second) && other.test(first, second))
113        })
114    }
115
116    /// Returns a bi-predicate representing logical XOR with another predicate.
117    ///
118    /// XOR evaluates both predicates and returns `true` when exactly one
119    /// predicate returns `true`.
120    ///
121    /// # Parameters
122    ///
123    /// * `other` - The other bi-predicate to combine with.
124    ///
125    /// # Returns
126    ///
127    /// A new `BoxStatefulBiPredicate` representing logical XOR.
128    #[inline]
129    pub fn xor<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
130    where
131        P: StatefulBiPredicate<T, U> + 'static,
132        T: 'static,
133        U: 'static,
134    {
135        BoxStatefulBiPredicate::new(move |first, second| {
136            self.test(first, second) ^ other.test(first, second)
137        })
138    }
139
140    /// Returns a bi-predicate representing logical NOR with another predicate.
141    ///
142    /// NOR returns `true` only when both predicates return `false`.
143    ///
144    /// # Parameters
145    ///
146    /// * `other` - The other bi-predicate to combine with.
147    ///
148    /// # Returns
149    ///
150    /// A new `BoxStatefulBiPredicate` representing logical NOR.
151    #[inline]
152    pub fn nor<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
153    where
154        P: StatefulBiPredicate<T, U> + 'static,
155        T: 'static,
156        U: 'static,
157    {
158        BoxStatefulBiPredicate::new(move |first, second| {
159            !(self.test(first, second) || other.test(first, second))
160        })
161    }
162}
163
164impl<T, U> Not for BoxStatefulBiPredicate<T, U>
165where
166    T: 'static,
167    U: 'static,
168{
169    type Output = BoxStatefulBiPredicate<T, U>;
170
171    fn not(mut self) -> Self::Output {
172        BoxStatefulBiPredicate::new(move |first, second| !self.test(first, second))
173    }
174}
175
176// Generates: impl Debug for BoxStatefulBiPredicate<T, U> and impl Display for BoxStatefulBiPredicate<T, U>
177impl_predicate_debug_display!(BoxStatefulBiPredicate<T, U>);
178
179impl<T, U> StatefulBiPredicate<T, U> for BoxStatefulBiPredicate<T, U> {
180    fn test(&mut self, first: &T, second: &U) -> bool {
181        (self.function)(first, second)
182    }
183
184    // Generates: into_box(), into_rc(), into_fn()
185    impl_box_conversions!(
186        BoxStatefulBiPredicate<T, U>,
187        RcStatefulBiPredicate,
188        FnMut(&T, &U) -> bool
189    );
190}