prism3_function/supplier_once.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025.
4 * 3-Prism 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 prism3_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 prism3_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
69
70// ==========================================================================
71// SupplierOnce Trait
72// ==========================================================================
73
74/// One-time supplier trait: generates a value consuming self.
75///
76/// Similar to `Supplier`, but can only be called once. The `get()`
77/// method consumes `self`, ensuring the supplier cannot be reused.
78///
79/// # Key Characteristics
80///
81/// - **Single use**: Can only call `get()` once
82/// - **Consumes self**: The method takes ownership of `self`
83/// - **Holds `FnOnce`**: Can capture and move non-cloneable values
84/// - **Type-system guaranteed**: Prevents multiple calls at compile
85/// time
86///
87/// # Use Cases
88///
89/// 1. **Lazy initialization**: Delay expensive computation until
90/// needed
91/// 2. **One-time resource consumption**: Generate value by consuming
92/// a resource
93/// 3. **Move-only closures**: Hold closures that capture moved
94/// values
95///
96/// # Examples
97///
98/// ## Lazy Initialization
99///
100/// ```rust
101/// use prism3_function::{BoxSupplierOnce, SupplierOnce};
102///
103/// let once = BoxSupplierOnce::new(|| {
104/// println!("Expensive computation");
105/// 42
106/// });
107///
108/// let value = once.get(); // Prints: Expensive computation
109/// assert_eq!(value, 42);
110/// // once is now consumed and cannot be used again
111/// ```
112///
113/// ## Resource Consumption
114///
115/// ```rust
116/// use prism3_function::{BoxSupplierOnce, SupplierOnce};
117///
118/// let resource = String::from("data");
119/// let once = BoxSupplierOnce::new(move || {
120/// resource // Move the resource
121/// });
122///
123/// let value = once.get();
124/// assert_eq!(value, "data");
125/// ```
126///
127/// # Author
128///
129/// Haixing Hu
130pub trait SupplierOnce<T> {
131 /// Generates and returns the value, consuming self.
132 ///
133 /// This method can only be called once because it consumes
134 /// `self`. This ensures type-system level guarantee that the
135 /// supplier won't be called multiple times.
136 ///
137 /// # Returns
138 ///
139 /// The generated value of type `T`
140 ///
141 /// # Examples
142 ///
143 /// ```rust
144 /// use prism3_function::{BoxSupplierOnce, SupplierOnce};
145 ///
146 /// let once = BoxSupplierOnce::new(|| 42);
147 /// assert_eq!(once.get(), 42);
148 /// // once is consumed here
149 /// ```
150 fn get(self) -> T;
151
152 /// Converts to `BoxSupplierOnce`.
153 ///
154 /// # Returns
155 ///
156 /// A new `BoxSupplierOnce<T>` instance
157 ///
158 /// # Examples
159 ///
160 /// ```rust
161 /// use prism3_function::SupplierOnce;
162 ///
163 /// let closure = || 42;
164 /// let boxed = closure.into_box_once();
165 /// assert_eq!(boxed.get(), 42);
166 /// ```
167 fn into_box_once(self) -> BoxSupplierOnce<T>
168 where
169 Self: Sized + 'static,
170 T: 'static;
171}
172
173// ==========================================================================
174// Implement SupplierOnce for Closures
175// ==========================================================================
176
177impl<T, F> SupplierOnce<T> for F
178where
179 F: FnOnce() -> T,
180{
181 fn get(self) -> T {
182 self()
183 }
184
185 fn into_box_once(self) -> BoxSupplierOnce<T>
186 where
187 Self: Sized + 'static,
188 T: 'static,
189 {
190 BoxSupplierOnce::new(self)
191 }
192}
193
194// ==========================================================================
195// BoxSupplierOnce - One-time Supplier Implementation
196// ==========================================================================
197
198/// Box-based one-time supplier.
199///
200/// Uses `Box<dyn FnOnce() -> T>` for one-time value generation.
201/// Can only call `get()` once, consuming the supplier.
202///
203/// # Examples
204///
205/// ## Lazy Initialization
206///
207/// ```rust
208/// use prism3_function::{BoxSupplierOnce, SupplierOnce};
209///
210/// let once = BoxSupplierOnce::new(|| {
211/// println!("Expensive initialization");
212/// 42
213/// });
214///
215/// let value = once.get(); // Prints: Expensive initialization
216/// assert_eq!(value, 42);
217/// ```
218///
219/// ## Moving Captured Values
220///
221/// ```rust
222/// use prism3_function::{BoxSupplierOnce, SupplierOnce};
223///
224/// let resource = String::from("data");
225/// let once = BoxSupplierOnce::new(move || resource);
226///
227/// let value = once.get();
228/// assert_eq!(value, "data");
229/// ```
230///
231/// # Author
232///
233/// Haixing Hu
234pub struct BoxSupplierOnce<T> {
235 func: Option<Box<dyn FnOnce() -> T>>,
236}
237
238impl<T> BoxSupplierOnce<T> {
239 /// Creates a new `BoxSupplierOnce`.
240 ///
241 /// # Parameters
242 ///
243 /// * `f` - The closure to wrap
244 ///
245 /// # Returns
246 ///
247 /// A new `BoxSupplierOnce<T>` instance
248 ///
249 /// # Examples
250 ///
251 /// ```rust
252 /// use prism3_function::{BoxSupplierOnce, SupplierOnce};
253 ///
254 /// let once = BoxSupplierOnce::new(|| 42);
255 /// assert_eq!(once.get(), 42);
256 /// ```
257 pub fn new<F>(f: F) -> Self
258 where
259 F: FnOnce() -> T + 'static,
260 {
261 BoxSupplierOnce {
262 func: Some(Box::new(f)),
263 }
264 }
265}
266
267impl<T> SupplierOnce<T> for BoxSupplierOnce<T> {
268 fn get(mut self) -> T {
269 (self.func.take().expect("Supplier already consumed"))()
270 }
271
272 fn into_box_once(self) -> BoxSupplierOnce<T>
273 where
274 T: 'static,
275 {
276 self
277 }
278}