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 {
209 move || self.get()
210 }
211
212 /// Converts the supplier to a `BoxSupplierOnce`.
213 ///
214 /// This is a convenience method that clones the current supplier and
215 /// wraps it in a `BoxSupplierOnce`. This is useful for type erasure and
216 /// creating homogenous collections of suppliers.
217 ///
218 /// # Returns
219 ///
220 /// A new `BoxSupplierOnce<T>` instance.
221 ///
222 /// # Note
223 ///
224 /// This requires the `SupplierOnce` to be `Clone` because it only
225 /// borrows `&self` but must create a new owned `BoxSupplierOnce`. The
226 /// clone provides the owned value needed for the new instance.
227 fn to_box(&self) -> BoxSupplierOnce<T>
228 where
229 Self: Clone + Sized + 'static,
230 T: 'static,
231 {
232 self.clone().into_box()
233 }
234
235 /// Converts the supplier to a `Box<dyn FnOnce() -> T>`.
236 ///
237 /// This method clones the current supplier and wraps it in a `Box` as a
238 /// trait object, allowing it to be used where a dynamically dispatched
239 /// `FnOnce` is needed.
240 ///
241 /// # Returns
242 ///
243 /// A `Box<dyn FnOnce() -> T>` that executes the supplier when called.
244 ///
245 /// # Note
246 ///
247 /// This requires the `SupplierOnce` to be `Clone` since `to_fn` only
248 /// borrows `&self` but needs to produce a `FnOnce` which will be
249 /// consumed. The underlying supplier is cloned to provide an owned value
250 /// that the returned closure can consume.
251 fn to_fn(&self) -> impl FnOnce() -> T
252 where
253 Self: Clone + Sized + 'static,
254 {
255 self.clone().into_fn()
256 }
257}
258
259// ==========================================================================
260// BoxSupplierOnce - One-time Supplier Implementation
261// ==========================================================================
262
263/// Box-based one-time supplier.
264///
265/// Uses `Box<dyn FnOnce() -> T>` for one-time value generation.
266/// Can only call `get()` once, consuming the supplier.
267///
268/// # Examples
269///
270/// ## Lazy Initialization
271///
272/// ```rust
273/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
274///
275/// let once = BoxSupplierOnce::new(|| {
276/// println!("Expensive initialization");
277/// 42
278/// });
279///
280/// let value = once.get(); // Prints: Expensive initialization
281/// assert_eq!(value, 42);
282/// ```
283///
284/// ## Moving Captured Values
285///
286/// ```rust
287/// use qubit_function::{BoxSupplierOnce, SupplierOnce};
288///
289/// let resource = String::from("data");
290/// let once = BoxSupplierOnce::new(move || resource);
291///
292/// let value = once.get();
293/// assert_eq!(value, "data");
294/// ```
295///
296/// # Author
297///
298/// Haixing Hu
299pub struct BoxSupplierOnce<T> {
300 function: Box<dyn FnOnce() -> T>,
301 name: Option<String>,
302}
303
304impl<T> BoxSupplierOnce<T> {
305 // Generates: new(), new_with_name(), name(), set_name(), constant()
306 impl_supplier_common_methods!(BoxSupplierOnce<T>, (FnOnce() -> T + 'static), |f| Box::new(
307 f
308 ));
309
310 // Generates: map(), filter(), zip()
311 impl_box_supplier_methods!(BoxSupplierOnce<T>, SupplierOnce);
312}
313
314// Generates: implement SupplierOnce for BoxSupplierOnce<T>
315impl<T> SupplierOnce<T> for BoxSupplierOnce<T> {
316 fn get(self) -> T {
317 (self.function)()
318 }
319
320 impl_box_once_conversions!(
321 BoxSupplierOnce<T>,
322 SupplierOnce,
323 FnOnce() -> T
324 );
325}
326
327// Generates: Debug and Display implementations for BoxSupplierOnce<T>
328impl_supplier_debug_display!(BoxSupplierOnce<T>);
329
330// ==========================================================================
331// Implement SupplierOnce for Closures
332// ==========================================================================
333
334// Implement SupplierOnce for all FnOnce() -> T using macro
335impl_closure_once_trait!(
336 SupplierOnce<T>,
337 get,
338 BoxSupplierOnce,
339 FnOnce() -> T
340);