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 { function: Box::new(f) }
36    }
37
38    /// Combines this tester with another stateful tester using logical AND.
39    ///
40    /// The second tester is evaluated only when the first tester returns
41    /// `true`.
42    #[inline]
43    pub fn and<T>(mut self, mut next: T) -> BoxStatefulTester
44    where
45        T: StatefulTester + 'static,
46    {
47        BoxStatefulTester::new(move || self.test() && next.test())
48    }
49
50    /// Combines this tester with another stateful tester using logical OR.
51    ///
52    /// The second tester is evaluated only when the first tester returns
53    /// `false`.
54    #[inline]
55    pub fn or<T>(mut self, mut next: T) -> BoxStatefulTester
56    where
57        T: StatefulTester + 'static,
58    {
59        BoxStatefulTester::new(move || self.test() || next.test())
60    }
61
62    /// Combines this tester with another stateful tester using logical NAND.
63    #[inline]
64    pub fn nand<T>(mut self, mut next: T) -> BoxStatefulTester
65    where
66        T: StatefulTester + 'static,
67    {
68        BoxStatefulTester::new(move || !(self.test() && next.test()))
69    }
70
71    /// Combines this tester with another stateful tester using logical XOR.
72    #[inline]
73    pub fn xor<T>(mut self, mut next: T) -> BoxStatefulTester
74    where
75        T: StatefulTester + 'static,
76    {
77        BoxStatefulTester::new(move || self.test() ^ next.test())
78    }
79
80    /// Combines this tester with another stateful tester using logical NOR.
81    #[inline]
82    pub fn nor<T>(mut self, mut next: T) -> BoxStatefulTester
83    where
84        T: StatefulTester + 'static,
85    {
86        BoxStatefulTester::new(move || !(self.test() || next.test()))
87    }
88}
89
90impl Not for BoxStatefulTester {
91    type Output = BoxStatefulTester;
92
93    #[inline]
94    fn not(mut self) -> Self::Output {
95        BoxStatefulTester::new(move || !self.test())
96    }
97}
98
99impl StatefulTester for BoxStatefulTester {
100    #[inline]
101    fn test(&mut self) -> bool {
102        (self.function)()
103    }
104
105    #[inline]
106    fn into_box(self) -> BoxStatefulTester {
107        self
108    }
109
110    #[inline]
111    fn into_rc(self) -> RcStatefulTester {
112        let function = self.function;
113        RcStatefulTester::new(function)
114    }
115}