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