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}