Skip to main content

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