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
81mod box_supplier_once;
82pub use box_supplier_once::BoxSupplierOnce;
83
84// ==========================================================================
85// SupplierOnce Trait
86// ==========================================================================
87
88/// One-time supplier trait: generates a value consuming self.
89///
90/// Similar to `Supplier`, but can only be called once. The `get()`
91/// method consumes `self`, ensuring the supplier cannot be reused.
92///
93/// # Key Characteristics
94///
95/// - **Single use**: Can only call `get()` once
96/// - **Consumes self**: The method takes ownership of `self`
97/// - **Holds `FnOnce`**: Can capture and move non-cloneable values
98/// - **Type-system guaranteed**: Prevents multiple calls at compile
99///   time
100///
101/// # Use Cases
102///
103/// 1. **Lazy initialization**: Delay expensive computation until
104///    needed
105/// 2. **One-time resource consumption**: Generate value by consuming
106///    a resource
107/// 3. **Move-only closures**: Hold closures that capture moved
108///    values
109///
110/// # Examples
111///
112/// ## Lazy Initialization
113///
114/// ```rust
115/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
116///
117/// let once = BoxSupplierOnce::new(|| {
118///     println!("Expensive computation");
119///     42
120/// });
121///
122/// let value = once.get(); // Prints: Expensive computation
123/// assert_eq!(value, 42);
124/// // once is now consumed and cannot be used again
125/// ```
126///
127/// ## Resource Consumption
128///
129/// ```rust
130/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
131///
132/// let resource = String::from("data");
133/// let once = BoxSupplierOnce::new(move || {
134///     resource // Move the resource
135/// });
136///
137/// let value = once.get();
138/// assert_eq!(value, "data");
139/// ```
140///
141/// # Author
142///
143/// Haixing Hu
144pub trait SupplierOnce<T> {
145    /// Generates and returns the value, consuming self.
146    ///
147    /// This method can only be called once because it consumes
148    /// `self`. This ensures type-system level guarantee that the
149    /// supplier won't be called multiple times.
150    ///
151    /// # Returns
152    ///
153    /// The generated value of type `T`
154    ///
155    /// # Examples
156    ///
157    /// ```rust
158    /// use qubit_function::{BoxSupplierOnce, SupplierOnce};
159    ///
160    /// let once = BoxSupplierOnce::new(|| 42);
161    /// assert_eq!(once.get(), 42);
162    /// // once is consumed here
163    /// ```
164    fn get(self) -> T;
165
166    /// Converts to `BoxSupplierOnce`.
167    ///
168    /// # Returns
169    ///
170    /// A new `BoxSupplierOnce<T>` instance
171    ///
172    /// # Examples
173    ///
174    /// ```rust
175    /// use qubit_function::SupplierOnce;
176    ///
177    /// let closure = || 42;
178    /// let boxed = closure.into_box();
179    /// assert_eq!(boxed.get(), 42);
180    /// ```
181    fn into_box(self) -> BoxSupplierOnce<T>
182    where
183        Self: Sized + 'static,
184    {
185        BoxSupplierOnce::new(move || self.get())
186    }
187
188    /// Converts the supplier to a `Box<dyn FnOnce() -> T>`.
189    ///
190    /// This method consumes the current supplier and wraps it in a `Box` as a
191    /// trait object, allowing it to be used where a dynamically dispatched
192    /// `FnOnce` is needed.
193    ///
194    /// # Returns
195    ///
196    /// A `Box<dyn FnOnce() -> T>` that executes the supplier when called.
197    ///
198    /// # Examples
199    ///
200    /// ```rust
201    /// use qubit_function::SupplierOnce;
202    ///
203    /// let closure = || 42;
204    /// let fn_once = closure.into_fn();
205    /// assert_eq!(fn_once(), 42);
206    /// ```
207    fn into_fn(self) -> impl FnOnce() -> T
208    where
209        Self: Sized + 'static,
210    {
211        move || self.get()
212    }
213
214    /// Converts the supplier to a `BoxSupplierOnce`.
215    ///
216    /// This is a convenience method that clones the current supplier and
217    /// wraps it in a `BoxSupplierOnce`. This is useful for type erasure and
218    /// creating homogenous collections of suppliers.
219    ///
220    /// # Returns
221    ///
222    /// A new `BoxSupplierOnce<T>` instance.
223    ///
224    /// # Note
225    ///
226    /// This requires the `SupplierOnce` to be `Clone` because it only
227    /// borrows `&self` but must create a new owned `BoxSupplierOnce`. The
228    /// clone provides the owned value needed for the new instance.
229    fn to_box(&self) -> BoxSupplierOnce<T>
230    where
231        Self: Clone + Sized + '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    {
256        self.clone().into_fn()
257    }
258}