Skip to main content

qubit_function/testers/stateful_tester/
box_stateful_tester.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//! Defines the `BoxStatefulTester` public type.
11
12use std::ops::Not;
13
14use super::{
15    StatefulTester,
16    rc_stateful_tester::RcStatefulTester,
17};
18
19/// A single-ownership stateful tester backed by `Box<dyn FnMut() -> bool>`.
20///
21/// `BoxStatefulTester` is the owned wrapper for zero-argument tests that need
22/// native `FnMut() -> bool` semantics. Calling [`StatefulTester::test`] may
23/// mutate state captured by the wrapped closure.
24pub struct BoxStatefulTester {
25    pub(super) function: Box<dyn FnMut() -> bool>,
26}
27
28impl BoxStatefulTester {
29    /// Creates a new boxed stateful tester.
30    #[inline]
31    pub fn new<F>(f: F) -> Self
32    where
33        F: FnMut() -> bool + 'static,
34    {
35        BoxStatefulTester {
36            function: Box::new(f),
37        }
38    }
39
40    /// Combines this tester with another stateful tester using logical AND.
41    ///
42    /// The second tester is evaluated only when the first tester returns
43    /// `true`.
44    #[inline]
45    pub fn and<T>(mut self, mut next: T) -> BoxStatefulTester
46    where
47        T: StatefulTester + 'static,
48    {
49        BoxStatefulTester::new(move || self.test() && next.test())
50    }
51
52    /// Combines this tester with another stateful tester using logical OR.
53    ///
54    /// The second tester is evaluated only when the first tester returns
55    /// `false`.
56    #[inline]
57    pub fn or<T>(mut self, mut next: T) -> BoxStatefulTester
58    where
59        T: StatefulTester + 'static,
60    {
61        BoxStatefulTester::new(move || self.test() || next.test())
62    }
63
64    /// Combines this tester with another stateful tester using logical NAND.
65    #[inline]
66    pub fn nand<T>(mut self, mut next: T) -> BoxStatefulTester
67    where
68        T: StatefulTester + 'static,
69    {
70        BoxStatefulTester::new(move || !(self.test() && next.test()))
71    }
72
73    /// Combines this tester with another stateful tester using logical XOR.
74    #[inline]
75    pub fn xor<T>(mut self, mut next: T) -> BoxStatefulTester
76    where
77        T: StatefulTester + 'static,
78    {
79        BoxStatefulTester::new(move || self.test() ^ next.test())
80    }
81
82    /// Combines this tester with another stateful tester using logical NOR.
83    #[inline]
84    pub fn nor<T>(mut self, mut next: T) -> BoxStatefulTester
85    where
86        T: StatefulTester + 'static,
87    {
88        BoxStatefulTester::new(move || !(self.test() || next.test()))
89    }
90}
91
92impl Not for BoxStatefulTester {
93    type Output = BoxStatefulTester;
94
95    #[inline]
96    fn not(mut self) -> Self::Output {
97        BoxStatefulTester::new(move || !self.test())
98    }
99}
100
101impl StatefulTester for BoxStatefulTester {
102    #[inline]
103    fn test(&mut self) -> bool {
104        (self.function)()
105    }
106
107    #[inline]
108    fn into_box(self) -> BoxStatefulTester {
109        self
110    }
111
112    #[inline]
113    fn into_rc(self) -> RcStatefulTester {
114        let function = self.function;
115        RcStatefulTester::new(function)
116    }
117}