Skip to main content

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}