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}