qubit_function/testers/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 `StatefulTester` public trait.
11
12use super::{
13 Arc,
14 Rc,
15};
16
17use self::{
18 arc_stateful_tester::ArcStatefulTester,
19 box_stateful_tester::BoxStatefulTester,
20 rc_stateful_tester::RcStatefulTester,
21};
22
23pub mod arc_stateful_tester;
24pub mod box_stateful_tester;
25pub mod fn_stateful_tester_ops;
26pub mod rc_stateful_tester;
27
28/// Tests whether a zero-argument condition holds while allowing state mutation.
29///
30/// `StatefulTester` is the stateful counterpart of
31/// [`Tester`](super::tester::Tester).
32/// It is equivalent to `FnMut() -> bool`: callers execute it through
33/// `&mut self`, so the implementation may update captured or internal state
34/// between calls.
35///
36/// # Examples
37///
38/// ```rust
39/// use qubit_function::StatefulTester;
40///
41/// let mut count = 0;
42/// let mut tester = move || {
43/// count += 1;
44/// count >= 2
45/// };
46///
47/// assert!(!tester.test());
48/// assert!(tester.test());
49/// ```
50pub trait StatefulTester {
51 /// Executes the stateful test and returns the test result.
52 ///
53 /// This method uses `&mut self` to match `FnMut() -> bool`, allowing each
54 /// call to update internal state before producing the boolean result.
55 ///
56 /// # Return Value
57 ///
58 /// Returns `true` if the condition holds, otherwise returns `false`.
59 fn test(&mut self) -> bool;
60
61 /// Converts this tester to `BoxStatefulTester`.
62 #[inline]
63 fn into_box(mut self) -> BoxStatefulTester
64 where
65 Self: Sized + 'static,
66 {
67 BoxStatefulTester::new(move || self.test())
68 }
69
70 /// Converts this tester to `RcStatefulTester`.
71 #[inline]
72 fn into_rc(mut self) -> RcStatefulTester
73 where
74 Self: Sized + 'static,
75 {
76 RcStatefulTester::new(move || self.test())
77 }
78
79 /// Converts this tester to `ArcStatefulTester`.
80 #[inline]
81 fn into_arc(mut self) -> ArcStatefulTester
82 where
83 Self: Sized + Send + 'static,
84 {
85 ArcStatefulTester::new(move || self.test())
86 }
87
88 /// Converts this tester to a mutable closure.
89 ///
90 /// # Return Value
91 ///
92 /// A closure implementing `FnMut() -> bool` that owns this tester and
93 /// delegates each call to [`StatefulTester::test`].
94 fn into_fn(mut self) -> impl FnMut() -> bool
95 where
96 Self: Sized + 'static,
97 {
98 move || self.test()
99 }
100
101 /// Converts this tester to a mutable closure with an explicit method name.
102 ///
103 /// This is a naming alias of [`StatefulTester::into_fn`] for call sites
104 /// that want the returned `FnMut` shape to be obvious.
105 fn into_mut_fn(self) -> impl FnMut() -> bool
106 where
107 Self: Sized + 'static,
108 {
109 self.into_fn()
110 }
111
112 /// Converts a clone of this tester to `BoxStatefulTester`.
113 #[inline]
114 fn to_box(&self) -> BoxStatefulTester
115 where
116 Self: Clone + Sized + 'static,
117 {
118 self.clone().into_box()
119 }
120
121 /// Converts a clone of this tester to `RcStatefulTester`.
122 #[inline]
123 fn to_rc(&self) -> RcStatefulTester
124 where
125 Self: Clone + Sized + 'static,
126 {
127 self.clone().into_rc()
128 }
129
130 /// Converts a clone of this tester to `ArcStatefulTester`.
131 #[inline]
132 fn to_arc(&self) -> ArcStatefulTester
133 where
134 Self: Clone + Sized + Send + 'static,
135 {
136 self.clone().into_arc()
137 }
138
139 /// Creates a mutable closure from a cloned tester.
140 ///
141 /// The original tester remains available. The returned closure owns a clone
142 /// and mutates that clone on each call.
143 fn to_fn(&self) -> impl FnMut() -> bool
144 where
145 Self: Clone + Sized + 'static,
146 {
147 self.clone().into_fn()
148 }
149
150 /// Creates a mutable closure from a cloned tester with an explicit method
151 /// name.
152 ///
153 /// This is a naming alias of [`StatefulTester::to_fn`] and preserves the
154 /// same clone-based behavior.
155 fn to_mut_fn(&self) -> impl FnMut() -> bool
156 where
157 Self: Clone + Sized + 'static,
158 {
159 self.to_fn()
160 }
161}
162
163impl<F> StatefulTester for F
164where
165 F: FnMut() -> bool,
166{
167 #[inline]
168 fn test(&mut self) -> bool {
169 self()
170 }
171}