Skip to main content

qubit_function/suppliers/stateful_supplier/
box_stateful_supplier.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! Defines the `BoxStatefulSupplier` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// ==========================================================================
16// BoxStatefulSupplier - Single Ownership Implementation
17// ==========================================================================
18
19/// Box-based single ownership supplier.
20///
21/// Uses `Box<dyn FnMut() -> T>` for single ownership scenarios.
22/// This is the most lightweight supplier with zero reference
23/// counting overhead.
24///
25/// # Ownership Model
26///
27/// Methods consume `self` (move semantics). When you call a method
28/// like `map()`, the original supplier is consumed and you get a new
29/// one:
30///
31/// ```rust
32/// use qubit_function::{BoxStatefulSupplier, StatefulSupplier};
33///
34/// let supplier = BoxStatefulSupplier::new(|| 10);
35/// let mapped = supplier.map(|x| x * 2);
36/// // supplier is no longer usable here
37/// ```
38///
39/// # Examples
40///
41/// ## Counter
42///
43/// ```rust
44/// use qubit_function::{BoxStatefulSupplier, StatefulSupplier};
45///
46/// let mut counter = 0;
47/// let mut supplier = BoxStatefulSupplier::new(move || {
48///     counter += 1;
49///     counter
50/// });
51///
52/// assert_eq!(supplier.get(), 1);
53/// assert_eq!(supplier.get(), 2);
54/// ```
55///
56/// ## Method Chaining
57///
58/// ```rust
59/// use qubit_function::{BoxStatefulSupplier, StatefulSupplier};
60///
61/// let mut pipeline = BoxStatefulSupplier::new(|| 10)
62///     .map(|x| x * 2)
63///     .map(|x| x + 5);
64///
65/// assert_eq!(pipeline.get(), 25);
66/// ```
67///
68/// # Author
69///
70/// Haixing Hu
71pub struct BoxStatefulSupplier<T> {
72    pub(super) function: Box<dyn FnMut() -> T>,
73    pub(super) name: Option<String>,
74}
75
76impl<T> BoxStatefulSupplier<T> {
77    // Generates: new(), new_with_name(), name(), set_name(), constant()
78    impl_supplier_common_methods!(BoxStatefulSupplier<T>, (FnMut() -> T + 'static), |f| {
79        Box::new(f)
80    });
81
82    // Generates: map(), filter(), zip()
83    impl_box_supplier_methods!(BoxStatefulSupplier<T>, StatefulSupplier);
84
85    /// Creates a memoizing supplier.
86    ///
87    /// Returns a new supplier that caches the first value it
88    /// produces. All subsequent calls return the cached value.
89    ///
90    /// # Returns
91    ///
92    /// A new memoized `BoxStatefulSupplier<T>`
93    ///
94    /// # Examples
95    ///
96    /// ```rust
97    /// use qubit_function::{BoxStatefulSupplier, StatefulSupplier};
98    ///
99    /// let mut call_count = 0;
100    /// let mut memoized = BoxStatefulSupplier::new(move || {
101    ///     call_count += 1;
102    ///     42
103    /// }).memoize();
104    ///
105    /// assert_eq!(memoized.get(), 42); // Calls underlying function
106    /// assert_eq!(memoized.get(), 42); // Returns cached value
107    /// ```
108    pub fn memoize(mut self) -> BoxStatefulSupplier<T>
109    where
110        T: Clone + 'static,
111    {
112        let mut cache: Option<T> = None;
113        BoxStatefulSupplier::new(move || {
114            if let Some(ref cached) = cache {
115                cached.clone()
116            } else {
117                let value = StatefulSupplier::get(&mut self);
118                cache = Some(value.clone());
119                value
120            }
121        })
122    }
123}
124
125// Generates: Debug and Display implementations for BoxStatefulSupplier<T>
126impl_supplier_debug_display!(BoxStatefulSupplier<T>);
127
128impl<T> StatefulSupplier<T> for BoxStatefulSupplier<T> {
129    fn get(&mut self) -> T {
130        (self.function)()
131    }
132
133    // Generates: into_box(), into_rc(), into_fn(), into_once()
134    impl_box_conversions!(
135        BoxStatefulSupplier<T>,
136        RcStatefulSupplier,
137        FnMut() -> T,
138        BoxSupplierOnce
139    );
140}