Skip to main content

qubit_function/suppliers/
supplier_once.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//! # SupplierOnce Types
11//!
12//! Provides one-time supplier implementations that generate and
13//! return values without taking any input parameters, consuming
14//! themselves in the process.
15//!
16//! # Overview
17//!
18//! A **SupplierOnce** is a functional abstraction similar to
19//! `Supplier`, but can only be called once. The `get()` method
20//! consumes `self`, ensuring the supplier cannot be reused.
21//!
22//! # Key Characteristics
23//!
24//! - **Single use**: Can only call `get()` once
25//! - **Consumes self**: The method takes ownership of `self`
26//! - **Holds `FnOnce`**: Can capture and move non-cloneable values
27//! - **Type-system guaranteed**: Prevents multiple calls at compile
28//!   time
29//!
30//! # Use Cases
31//!
32//! 1. **Lazy initialization**: Delay expensive computation until
33//!    needed
34//! 2. **One-time resource consumption**: Generate value by consuming
35//!    a resource
36//! 3. **Move-only closures**: Hold closures that capture moved
37//!    values
38//!
39//! # Examples
40//!
41//! ## Lazy Initialization
42//!
43//! ```rust
44//! use qubit_function::{BoxSupplierOnce, SupplierOnce};
45//!
46//! let once = BoxSupplierOnce::new(|| {
47//!     println!("Expensive initialization");
48//!     42
49//! });
50//!
51//! let value = once.get(); // Only initializes once
52//! assert_eq!(value, 42);
53//! ```
54//!
55//! ## Moving Captured Values
56//!
57//! ```rust
58//! use qubit_function::{BoxSupplierOnce, SupplierOnce};
59//!
60//! let resource = String::from("data");
61//! let once = BoxSupplierOnce::new(move || resource);
62//!
63//! let value = once.get();
64//! assert_eq!(value, "data");
65//! ```
66//!
67use crate::macros::{
68    impl_box_once_conversions,
69    impl_closure_once_trait,
70};
71use crate::predicates::predicate::Predicate;
72use crate::suppliers::macros::{
73    impl_box_supplier_methods,
74    impl_supplier_common_methods,
75    impl_supplier_debug_display,
76};
77use crate::transformers::transformer::Transformer;
78
79mod box_supplier_once;
80pub use box_supplier_once::BoxSupplierOnce;
81
82// ==========================================================================
83// SupplierOnce Trait
84// ==========================================================================
85
86/// One-time supplier trait: generates a value consuming self.
87///
88/// Similar to `Supplier`, but can only be called once. The `get()`
89/// method consumes `self`, ensuring the supplier cannot be reused.
90///
91/// # Key Characteristics
92///
93/// - **Single use**: Can only call `get()` once
94/// - **Consumes self**: The method takes ownership of `self`
95/// - **Holds `FnOnce`**: Can capture and move non-cloneable values
96/// - **Type-system guaranteed**: Prevents multiple calls at compile
97///   time
98///
99/// # Use Cases
100///
101/// 1. **Lazy initialization**: Delay expensive computation until
102///    needed
103/// 2. **One-time resource consumption**: Generate value by consuming
104///    a resource
105/// 3. **Move-only closures**: Hold closures that capture moved
106///    values
107///
108/// # Examples
109///
110/// ## Lazy Initialization
111///
112/// ```rust
113/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
114///
115/// let once = BoxSupplierOnce::new(|| {
116///     println!("Expensive computation");
117///     42
118/// });
119///
120/// let value = once.get(); // Prints: Expensive computation
121/// assert_eq!(value, 42);
122/// // once is now consumed and cannot be used again
123/// ```
124///
125/// ## Resource Consumption
126///
127/// ```rust
128/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
129///
130/// let resource = String::from("data");
131/// let once = BoxSupplierOnce::new(move || {
132///     resource // Move the resource
133/// });
134///
135/// let value = once.get();
136/// assert_eq!(value, "data");
137/// ```
138///
139pub trait SupplierOnce<T> {
140    /// Generates and returns the value, consuming self.
141    ///
142    /// This method can only be called once because it consumes
143    /// `self`. This ensures type-system level guarantee that the
144    /// supplier won't be called multiple times.
145    ///
146    /// # Returns
147    ///
148    /// The generated value of type `T`
149    ///
150    /// # Examples
151    ///
152    /// ```rust
153    /// use qubit_function::{BoxSupplierOnce, SupplierOnce};
154    ///
155    /// let once = BoxSupplierOnce::new(|| 42);
156    /// assert_eq!(once.get(), 42);
157    /// // once is consumed here
158    /// ```
159    fn get(self) -> T;
160
161    /// Converts to `BoxSupplierOnce`.
162    ///
163    /// # Returns
164    ///
165    /// A new `BoxSupplierOnce<T>` instance
166    ///
167    /// # Examples
168    ///
169    /// ```rust
170    /// use qubit_function::SupplierOnce;
171    ///
172    /// let closure = || 42;
173    /// let boxed = closure.into_box();
174    /// assert_eq!(boxed.get(), 42);
175    /// ```
176    fn into_box(self) -> BoxSupplierOnce<T>
177    where
178        Self: Sized + 'static,
179    {
180        BoxSupplierOnce::new(move || self.get())
181    }
182
183    /// Converts the supplier to a `Box<dyn FnOnce() -> T>`.
184    ///
185    /// This method consumes the current supplier and wraps it in a `Box` as a
186    /// trait object, allowing it to be used where a dynamically dispatched
187    /// `FnOnce` is needed.
188    ///
189    /// # Returns
190    ///
191    /// A `Box<dyn FnOnce() -> T>` that executes the supplier when called.
192    ///
193    /// # Examples
194    ///
195    /// ```rust
196    /// use qubit_function::SupplierOnce;
197    ///
198    /// let closure = || 42;
199    /// let fn_once = closure.into_fn();
200    /// assert_eq!(fn_once(), 42);
201    /// ```
202    fn into_fn(self) -> impl FnOnce() -> T
203    where
204        Self: Sized + 'static,
205    {
206        move || self.get()
207    }
208
209    /// Converts the supplier to a `BoxSupplierOnce`.
210    ///
211    /// This is a convenience method that clones the current supplier and
212    /// wraps it in a `BoxSupplierOnce`. This is useful for type erasure and
213    /// creating homogenous collections of suppliers.
214    ///
215    /// # Returns
216    ///
217    /// A new `BoxSupplierOnce<T>` instance.
218    ///
219    /// # Note
220    ///
221    /// This requires the `SupplierOnce` to be `Clone` because it only
222    /// borrows `&self` but must create a new owned `BoxSupplierOnce`. The
223    /// clone provides the owned value needed for the new instance.
224    fn to_box(&self) -> BoxSupplierOnce<T>
225    where
226        Self: Clone + Sized + 'static,
227    {
228        self.clone().into_box()
229    }
230
231    /// Converts the supplier to a `Box<dyn FnOnce() -> T>`.
232    ///
233    /// This method clones the current supplier and wraps it in a `Box` as a
234    /// trait object, allowing it to be used where a dynamically dispatched
235    /// `FnOnce` is needed.
236    ///
237    /// # Returns
238    ///
239    /// A `Box<dyn FnOnce() -> T>` that executes the supplier when called.
240    ///
241    /// # Note
242    ///
243    /// This requires the `SupplierOnce` to be `Clone` since `to_fn` only
244    /// borrows `&self` but needs to produce a `FnOnce` which will be
245    /// consumed. The underlying supplier is cloned to provide an owned value
246    /// that the returned closure can consume.
247    fn to_fn(&self) -> impl FnOnce() -> T
248    where
249        Self: Clone + Sized + 'static,
250    {
251        self.clone().into_fn()
252    }
253}