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!(BoxStatefulPredicate<T>, (FnMut(&T) -> bool + 'static), |f| Box::new(f));
38
39 /// Returns a predicate representing logical AND with another predicate.
40 ///
41 /// This method consumes `self` and evaluates `other` only when this
42 /// predicate returns `true`.
43 ///
44 /// # Parameters
45 ///
46 /// * `other` - The other predicate to combine with.
47 ///
48 /// # Returns
49 ///
50 /// A new `BoxStatefulPredicate` representing logical AND.
51 #[inline]
52 pub fn and<P>(mut self, mut other: P) -> BoxStatefulPredicate<T>
53 where
54 P: StatefulPredicate<T> + 'static,
55 T: 'static,
56 {
57 BoxStatefulPredicate::new(move |value| self.test(value) && other.test(value))
58 }
59
60 /// Returns a predicate representing logical OR with another predicate.
61 ///
62 /// This method consumes `self` and evaluates `other` only when this
63 /// predicate returns `false`.
64 ///
65 /// # Parameters
66 ///
67 /// * `other` - The other predicate to combine with.
68 ///
69 /// # Returns
70 ///
71 /// A new `BoxStatefulPredicate` representing logical OR.
72 #[inline]
73 pub fn or<P>(mut self, mut other: P) -> BoxStatefulPredicate<T>
74 where
75 P: StatefulPredicate<T> + 'static,
76 T: 'static,
77 {
78 BoxStatefulPredicate::new(move |value| self.test(value) || other.test(value))
79 }
80
81 /// Returns a predicate representing logical NAND with another predicate.
82 ///
83 /// NAND returns `true` unless both predicates return `true`.
84 ///
85 /// # Parameters
86 ///
87 /// * `other` - The other predicate to combine with.
88 ///
89 /// # Returns
90 ///
91 /// A new `BoxStatefulPredicate` representing logical NAND.
92 #[inline]
93 pub fn nand<P>(mut self, mut other: P) -> BoxStatefulPredicate<T>
94 where
95 P: StatefulPredicate<T> + 'static,
96 T: 'static,
97 {
98 BoxStatefulPredicate::new(move |value| !(self.test(value) && other.test(value)))
99 }
100
101 /// Returns a predicate representing logical XOR with another predicate.
102 ///
103 /// XOR evaluates both predicates and returns `true` when exactly one
104 /// predicate returns `true`.
105 ///
106 /// # Parameters
107 ///
108 /// * `other` - The other predicate to combine with.
109 ///
110 /// # Returns
111 ///
112 /// A new `BoxStatefulPredicate` representing logical XOR.
113 #[inline]
114 pub fn xor<P>(mut self, mut other: P) -> BoxStatefulPredicate<T>
115 where
116 P: StatefulPredicate<T> + 'static,
117 T: 'static,
118 {
119 BoxStatefulPredicate::new(move |value| self.test(value) ^ other.test(value))
120 }
121
122 /// Returns a predicate representing logical NOR with another predicate.
123 ///
124 /// NOR returns `true` only when both predicates return `false`.
125 ///
126 /// # Parameters
127 ///
128 /// * `other` - The other predicate to combine with.
129 ///
130 /// # Returns
131 ///
132 /// A new `BoxStatefulPredicate` representing logical NOR.
133 #[inline]
134 pub fn nor<P>(mut self, mut other: P) -> BoxStatefulPredicate<T>
135 where
136 P: StatefulPredicate<T> + 'static,
137 T: 'static,
138 {
139 BoxStatefulPredicate::new(move |value| !(self.test(value) || other.test(value)))
140 }
141}
142
143impl<T> Not for BoxStatefulPredicate<T>
144where
145 T: 'static,
146{
147 type Output = BoxStatefulPredicate<T>;
148
149 fn not(mut self) -> Self::Output {
150 BoxStatefulPredicate::new(move |value| !self.test(value))
151 }
152}
153
154// Generates: impl Debug for BoxStatefulPredicate<T> and impl Display for BoxStatefulPredicate<T>
155impl_predicate_debug_display!(BoxStatefulPredicate<T>);
156
157// Implements StatefulPredicate trait for BoxStatefulPredicate<T>
158impl<T> StatefulPredicate<T> for BoxStatefulPredicate<T> {
159 fn test(&mut self, value: &T) -> bool {
160 (self.function)(value)
161 }
162
163 // Generates: into_box(), into_rc(), into_fn()
164 impl_box_conversions!(
165 BoxStatefulPredicate<T>,
166 RcStatefulPredicate,
167 FnMut(&T) -> bool
168 );
169}