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