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!(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}