Skip to main content

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}