Skip to main content

qubit_function/suppliers/
supplier_once.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # SupplierOnce Types
10//!
11//! Provides one-time supplier implementations that generate and
12//! return values without taking any input parameters, consuming
13//! themselves in the process.
14//!
15//! # Overview
16//!
17//! A **SupplierOnce** is a functional abstraction similar to
18//! `Supplier`, but can only be called once. The `get()` method
19//! consumes `self`, ensuring the supplier cannot be reused.
20//!
21//! # Key Characteristics
22//!
23//! - **Single use**: Can only call `get()` once
24//! - **Consumes self**: The method takes ownership of `self`
25//! - **Holds `FnOnce`**: Can capture and move non-cloneable values
26//! - **Type-system guaranteed**: Prevents multiple calls at compile
27//!   time
28//!
29//! # Use Cases
30//!
31//! 1. **Lazy initialization**: Delay expensive computation until
32//!    needed
33//! 2. **One-time resource consumption**: Generate value by consuming
34//!    a resource
35//! 3. **Move-only closures**: Hold closures that capture moved
36//!    values
37//!
38//! # Examples
39//!
40//! ## Lazy Initialization
41//!
42//! ```rust
43//! use qubit_function::{BoxSupplierOnce, SupplierOnce};
44//!
45//! let once = BoxSupplierOnce::new(|| {
46//!     println!("Expensive initialization");
47//!     42
48//! });
49//!
50//! let value = once.get(); // Only initializes once
51//! assert_eq!(value, 42);
52//! ```
53//!
54//! ## Moving Captured Values
55//!
56//! ```rust
57//! use qubit_function::{BoxSupplierOnce, SupplierOnce};
58//!
59//! let resource = String::from("data");
60//! let once = BoxSupplierOnce::new(move || resource);
61//!
62//! let value = once.get();
63//! assert_eq!(value, "data");
64//! ```
65//!
66//! # Author
67//!
68//! Haixing Hu
69use crate::macros::{
70    impl_box_once_conversions,
71    impl_closure_once_trait,
72};
73use crate::predicates::predicate::Predicate;
74use crate::suppliers::macros::{
75    impl_box_supplier_methods,
76    impl_supplier_common_methods,
77    impl_supplier_debug_display,
78};
79use crate::transformers::transformer::Transformer;
80
81// ==========================================================================
82// SupplierOnce Trait
83// ==========================================================================
84
85/// One-time supplier trait: generates a value consuming self.
86///
87/// Similar to `Supplier`, but can only be called once. The `get()`
88/// method consumes `self`, ensuring the supplier cannot be reused.
89///
90/// # Key Characteristics
91///
92/// - **Single use**: Can only call `get()` once
93/// - **Consumes self**: The method takes ownership of `self`
94/// - **Holds `FnOnce`**: Can capture and move non-cloneable values
95/// - **Type-system guaranteed**: Prevents multiple calls at compile
96///   time
97///
98/// # Use Cases
99///
100/// 1. **Lazy initialization**: Delay expensive computation until
101///    needed
102/// 2. **One-time resource consumption**: Generate value by consuming
103///    a resource
104/// 3. **Move-only closures**: Hold closures that capture moved
105///    values
106///
107/// # Examples
108///
109/// ## Lazy Initialization
110///
111/// ```rust
112/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
113///
114/// let once = BoxSupplierOnce::new(|| {
115///     println!("Expensive computation");
116///     42
117/// });
118///
119/// let value = once.get(); // Prints: Expensive computation
120/// assert_eq!(value, 42);
121/// // once is now consumed and cannot be used again
122/// ```
123///
124/// ## Resource Consumption
125///
126/// ```rust
127/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
128///
129/// let resource = String::from("data");
130/// let once = BoxSupplierOnce::new(move || {
131///     resource // Move the resource
132/// });
133///
134/// let value = once.get();
135/// assert_eq!(value, "data");
136/// ```
137///
138/// # Author
139///
140/// Haixing Hu
141pub trait SupplierOnce<T> {
142    /// Generates and returns the value, consuming self.
143    ///
144    /// This method can only be called once because it consumes
145    /// `self`. This ensures type-system level guarantee that the
146    /// supplier won't be called multiple times.
147    ///
148    /// # Returns
149    ///
150    /// The generated value of type `T`
151    ///
152    /// # Examples
153    ///
154    /// ```rust
155    /// use qubit_function::{BoxSupplierOnce, SupplierOnce};
156    ///
157    /// let once = BoxSupplierOnce::new(|| 42);
158    /// assert_eq!(once.get(), 42);
159    /// // once is consumed here
160    /// ```
161    fn get(self) -> T;
162
163    /// Converts to `BoxSupplierOnce`.
164    ///
165    /// # Returns
166    ///
167    /// A new `BoxSupplierOnce<T>` instance
168    ///
169    /// # Examples
170    ///
171    /// ```rust
172    /// use qubit_function::SupplierOnce;
173    ///
174    /// let closure = || 42;
175    /// let boxed = closure.into_box();
176    /// assert_eq!(boxed.get(), 42);
177    /// ```
178    fn into_box(self) -> BoxSupplierOnce<T>
179    where
180        Self: Sized + 'static,
181        T: 'static,
182    {
183        BoxSupplierOnce::new(move || self.get())
184    }
185
186    /// Converts the supplier to a `Box<dyn FnOnce() -> T>`.
187    ///
188    /// This method consumes the current supplier and wraps it in a `Box` as a
189    /// trait object, allowing it to be used where a dynamically dispatched
190    /// `FnOnce` is needed.
191    ///
192    /// # Returns
193    ///
194    /// A `Box<dyn FnOnce() -> T>` that executes the supplier when called.
195    ///
196    /// # Examples
197    ///
198    /// ```rust
199    /// use qubit_function::SupplierOnce;
200    ///
201    /// let closure = || 42;
202    /// let fn_once = closure.into_fn();
203    /// assert_eq!(fn_once(), 42);
204    /// ```
205    fn into_fn(self) -> impl FnOnce() -> T
206    where
207        Self: Sized + 'static,
208        T: 'static,
209    {
210        move || self.get()
211    }
212
213    /// Converts the supplier to a `BoxSupplierOnce`.
214    ///
215    /// This is a convenience method that clones the current supplier and
216    /// wraps it in a `BoxSupplierOnce`. This is useful for type erasure and
217    /// creating homogenous collections of suppliers.
218    ///
219    /// # Returns
220    ///
221    /// A new `BoxSupplierOnce<T>` instance.
222    ///
223    /// # Note
224    ///
225    /// This requires the `SupplierOnce` to be `Clone` because it only
226    /// borrows `&self` but must create a new owned `BoxSupplierOnce`. The
227    /// clone provides the owned value needed for the new instance.
228    fn to_box(&self) -> BoxSupplierOnce<T>
229    where
230        Self: Clone + Sized + 'static,
231        T: 'static,
232    {
233        self.clone().into_box()
234    }
235
236    /// Converts the supplier to a `Box<dyn FnOnce() -> T>`.
237    ///
238    /// This method clones the current supplier and wraps it in a `Box` as a
239    /// trait object, allowing it to be used where a dynamically dispatched
240    /// `FnOnce` is needed.
241    ///
242    /// # Returns
243    ///
244    /// A `Box<dyn FnOnce() -> T>` that executes the supplier when called.
245    ///
246    /// # Note
247    ///
248    /// This requires the `SupplierOnce` to be `Clone` since `to_fn` only
249    /// borrows `&self` but needs to produce a `FnOnce` which will be
250    /// consumed. The underlying supplier is cloned to provide an owned value
251    /// that the returned closure can consume.
252    fn to_fn(&self) -> impl FnOnce() -> T
253    where
254        Self: Clone + Sized + 'static,
255        T: 'static,
256    {
257        self.clone().into_fn()
258    }
259}
260
261// ==========================================================================
262// BoxSupplierOnce - One-time Supplier Implementation
263// ==========================================================================
264
265/// Box-based one-time supplier.
266///
267/// Uses `Box<dyn FnOnce() -> T>` for one-time value generation.
268/// Can only call `get()` once, consuming the supplier.
269///
270/// # Examples
271///
272/// ## Lazy Initialization
273///
274/// ```rust
275/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
276///
277/// let once = BoxSupplierOnce::new(|| {
278///     println!("Expensive initialization");
279///     42
280/// });
281///
282/// let value = once.get(); // Prints: Expensive initialization
283/// assert_eq!(value, 42);
284/// ```
285///
286/// ## Moving Captured Values
287///
288/// ```rust
289/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
290///
291/// let resource = String::from("data");
292/// let once = BoxSupplierOnce::new(move || resource);
293///
294/// let value = once.get();
295/// assert_eq!(value, "data");
296/// ```
297///
298/// # Author
299///
300/// Haixing Hu
301pub struct BoxSupplierOnce<T> {
302    function: Box<dyn FnOnce() -> T>,
303    name: Option<String>,
304}
305
306impl<T> BoxSupplierOnce<T>
307where
308    T: 'static,
309{
310    // Generates: new(), new_with_name(), name(), set_name(), constant()
311    impl_supplier_common_methods!(BoxSupplierOnce<T>, (FnOnce() -> T + 'static), |f| Box::new(
312        f
313    ));
314
315    // Generates: map(), filter(), zip()
316    impl_box_supplier_methods!(BoxSupplierOnce<T>, SupplierOnce);
317}
318
319// Generates: implement SupplierOnce for BoxSupplierOnce<T>
320impl<T> SupplierOnce<T> for BoxSupplierOnce<T> {
321    fn get(self) -> T {
322        (self.function)()
323    }
324
325    impl_box_once_conversions!(
326        BoxSupplierOnce<T>,
327        SupplierOnce,
328        FnOnce() -> T
329    );
330}
331
332// Generates: Debug and Display implementations for BoxSupplierOnce<T>
333impl_supplier_debug_display!(BoxSupplierOnce<T>);
334
335// ==========================================================================
336// Implement SupplierOnce for Closures
337// ==========================================================================
338
339// Implement SupplierOnce for all FnOnce() -> T using macro
340impl_closure_once_trait!(
341    SupplierOnce<T>,
342    get,
343    BoxSupplierOnce,
344    FnOnce() -> T
345);