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| self.test(first, second) && other.test(first, second))
65    }
66
67    /// Returns a bi-predicate representing logical OR with another predicate.
68    ///
69    /// This method consumes `self` and evaluates `other` only when this
70    /// predicate returns `false`.
71    ///
72    /// # Parameters
73    ///
74    /// * `other` - The other bi-predicate to combine with.
75    ///
76    /// # Returns
77    ///
78    /// A new `BoxStatefulBiPredicate` representing logical OR.
79    #[inline]
80    pub fn or<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
81    where
82        P: StatefulBiPredicate<T, U> + 'static,
83        T: 'static,
84        U: 'static,
85    {
86        BoxStatefulBiPredicate::new(move |first, second| self.test(first, second) || other.test(first, second))
87    }
88
89    /// Returns a bi-predicate representing logical NAND with another predicate.
90    ///
91    /// NAND returns `true` unless both predicates return `true`.
92    ///
93    /// # Parameters
94    ///
95    /// * `other` - The other bi-predicate to combine with.
96    ///
97    /// # Returns
98    ///
99    /// A new `BoxStatefulBiPredicate` representing logical NAND.
100    #[inline]
101    pub fn nand<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
102    where
103        P: StatefulBiPredicate<T, U> + 'static,
104        T: 'static,
105        U: 'static,
106    {
107        BoxStatefulBiPredicate::new(move |first, second| !(self.test(first, second) && other.test(first, second)))
108    }
109
110    /// Returns a bi-predicate representing logical XOR with another predicate.
111    ///
112    /// XOR evaluates both predicates and returns `true` when exactly one
113    /// predicate returns `true`.
114    ///
115    /// # Parameters
116    ///
117    /// * `other` - The other bi-predicate to combine with.
118    ///
119    /// # Returns
120    ///
121    /// A new `BoxStatefulBiPredicate` representing logical XOR.
122    #[inline]
123    pub fn xor<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
124    where
125        P: StatefulBiPredicate<T, U> + 'static,
126        T: 'static,
127        U: 'static,
128    {
129        BoxStatefulBiPredicate::new(move |first, second| self.test(first, second) ^ other.test(first, second))
130    }
131
132    /// Returns a bi-predicate representing logical NOR with another predicate.
133    ///
134    /// NOR returns `true` only when both predicates return `false`.
135    ///
136    /// # Parameters
137    ///
138    /// * `other` - The other bi-predicate to combine with.
139    ///
140    /// # Returns
141    ///
142    /// A new `BoxStatefulBiPredicate` representing logical NOR.
143    #[inline]
144    pub fn nor<P>(mut self, mut other: P) -> BoxStatefulBiPredicate<T, U>
145    where
146        P: StatefulBiPredicate<T, U> + 'static,
147        T: 'static,
148        U: 'static,
149    {
150        BoxStatefulBiPredicate::new(move |first, second| !(self.test(first, second) || other.test(first, second)))
151    }
152}
153
154impl<T, U> Not for BoxStatefulBiPredicate<T, U>
155where
156    T: 'static,
157    U: 'static,
158{
159    type Output = BoxStatefulBiPredicate<T, U>;
160
161    fn not(mut self) -> Self::Output {
162        BoxStatefulBiPredicate::new(move |first, second| !self.test(first, second))
163    }
164}
165
166// Generates: impl Debug for BoxStatefulBiPredicate<T, U> and impl Display for BoxStatefulBiPredicate<T, U>
167impl_predicate_debug_display!(BoxStatefulBiPredicate<T, U>);
168
169impl<T, U> StatefulBiPredicate<T, U> for BoxStatefulBiPredicate<T, U> {
170    fn test(&mut self, first: &T, second: &U) -> bool {
171        (self.function)(first, second)
172    }
173
174    // Generates: into_box(), into_rc(), into_fn()
175    impl_box_conversions!(
176        BoxStatefulBiPredicate<T, U>,
177        RcStatefulBiPredicate,
178        FnMut(&T, &U) -> bool
179    );
180}