prism3_function/functions/
function_once.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # FunctionOnce Types
10//!
11//! Provides Rust implementations of consuming function traits similar to
12//! Rust's `FnOnce(&T) -> R` trait, for computing output from input references.
13//!
14//! This module provides the `FunctionOnce<T, R>` trait and one-time use
15//! implementations:
16//!
17//! - [`BoxFunctionOnce`]: Single ownership, one-time use
18//!
19//! # Author
20//!
21//! Haixing Hu
22use crate::functions::macros::{
23    impl_box_conditional_function,
24    impl_box_function_methods,
25    impl_conditional_function_debug_display,
26    impl_fn_ops_trait,
27    impl_function_common_methods,
28    impl_function_constant_method,
29    impl_function_debug_display,
30    impl_function_identity_method,
31};
32use crate::macros::{
33    impl_box_once_conversions,
34    impl_closure_once_trait,
35};
36use crate::predicates::predicate::{
37    BoxPredicate,
38    Predicate,
39};
40
41// ============================================================================
42// Core Trait
43// ============================================================================
44
45/// FunctionOnce trait - consuming function that takes ownership
46///
47/// Defines the behavior of a consuming function: computing a value of
48/// type `R` from a reference to type `T` by taking ownership of self.
49/// This trait is analogous to `FnOnce(&T) -> R`.
50///
51/// # Type Parameters
52///
53/// * `T` - The type of the input value (borrowed)
54/// * `R` - The type of the output value
55///
56/// # Author
57///
58/// Haixing Hu
59pub trait FunctionOnce<T, R> {
60    /// Applies the function to the input reference, consuming self
61    ///
62    /// # Parameters
63    ///
64    /// * `t` - Reference to the input value
65    ///
66    /// # Returns
67    ///
68    /// The computed output value
69    fn apply(self, t: &T) -> R;
70
71    /// Converts to BoxFunctionOnce
72    ///
73    /// **⚠️ Consumes `self`**: The original function becomes unavailable
74    /// after calling this method.
75    ///
76    /// # Returns
77    ///
78    /// Returns `BoxFunctionOnce<T, R>`
79    ///
80    /// # Examples
81    ///
82    /// ```rust
83    /// use prism3_function::FunctionOnce;
84    ///
85    /// let double = |x: &i32| x * 2;
86    /// let boxed = double.into_box();
87    /// assert_eq!(boxed.apply(&21), 42);
88    /// ```
89    fn into_box(self) -> BoxFunctionOnce<T, R>
90    where
91        Self: Sized + 'static,
92        T: 'static,
93        R: 'static,
94    {
95        BoxFunctionOnce::new(move |input: &T| self.apply(input))
96    }
97
98    /// Converts function to a closure
99    ///
100    /// **⚠️ Consumes `self`**: The original function becomes unavailable
101    /// after calling this method.
102    ///
103    /// # Returns
104    ///
105    /// Returns a closure that implements `FnOnce(&T) -> R`
106    ///
107    /// # Examples
108    ///
109    /// ```rust
110    /// use prism3_function::FunctionOnce;
111    ///
112    /// let double = |x: &i32| x * 2;
113    /// let func = double.into_fn();
114    /// assert_eq!(func(&21), 42);
115    /// ```
116    fn into_fn(self) -> impl FnOnce(&T) -> R
117    where
118        Self: Sized + 'static,
119        T: 'static,
120        R: 'static,
121    {
122        move |input: &T| self.apply(input)
123    }
124
125    /// Converts to BoxFunctionOnce without consuming self
126    ///
127    /// **📌 Borrows `&self`**: The original function remains usable
128    /// after calling this method.
129    ///
130    /// # Default Implementation
131    ///
132    /// The default implementation creates a new `BoxFunctionOnce` that
133    /// captures a clone. Types implementing `Clone` can override this method
134    /// to provide more efficient conversions.
135    ///
136    /// # Returns
137    ///
138    /// Returns `BoxFunctionOnce<T, R>`
139    ///
140    /// # Examples
141    ///
142    /// ```rust
143    /// use prism3_function::FunctionOnce;
144    ///
145    /// let double = |x: &i32| x * 2;
146    /// let boxed = double.to_box();
147    /// assert_eq!(boxed.apply(&21), 42);
148    /// ```
149    fn to_box(&self) -> BoxFunctionOnce<T, R>
150    where
151        Self: Clone + 'static,
152        T: 'static,
153        R: 'static,
154    {
155        self.clone().into_box()
156    }
157
158    /// Converts function to a closure without consuming self
159    ///
160    /// **📌 Borrows `&self`**: The original function remains usable
161    /// after calling this method.
162    ///
163    /// # Default Implementation
164    ///
165    /// The default implementation creates a closure that captures a
166    /// clone of `self` and calls its `apply` method. Types can
167    /// override this method to provide more efficient conversions.
168    ///
169    /// # Returns
170    ///
171    /// Returns a closure that implements `FnOnce(&T) -> R`
172    ///
173    /// # Examples
174    ///
175    /// ```rust
176    /// use prism3_function::FunctionOnce;
177    ///
178    /// let double = |x: &i32| x * 2;
179    /// let func = double.to_fn();
180    /// assert_eq!(func(&21), 42);
181    /// ```
182    fn to_fn(&self) -> impl FnOnce(&T) -> R
183    where
184        Self: Clone + 'static,
185        T: 'static,
186        R: 'static,
187    {
188        self.clone().into_fn()
189    }
190}
191
192// ============================================================================
193// BoxFunctionOnce - Box<dyn FnOnce(&T) -> R>
194// ============================================================================
195
196/// BoxFunctionOnce - consuming transformer wrapper based on
197/// `Box<dyn FnOnce>`
198///
199/// A transformer wrapper that provides single ownership with one-time use
200/// semantics. Consumes both self and the input value.
201///
202/// # Features
203///
204/// - **Based on**: `Box<dyn FnOnce(&T) -> R>`
205/// - **Ownership**: Single ownership, cannot be cloned
206/// - **Reusability**: Can only be called once (consumes self and input)
207/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
208///
209/// # Author
210///
211/// Haixing Hu
212pub struct BoxFunctionOnce<T, R> {
213    function: Box<dyn FnOnce(&T) -> R>,
214    name: Option<String>,
215}
216
217impl<T, R> BoxFunctionOnce<T, R>
218where
219    T: 'static,
220    R: 'static,
221{
222    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
223    impl_function_common_methods!(
224        BoxFunctionOnce<T, R>,
225        (FnOnce(&T) -> R + 'static),
226        |f| Box::new(f)
227    );
228
229    // Generates: when(), and_then(), compose()
230    impl_box_function_methods!(
231        BoxFunctionOnce<T, R>,
232        BoxConditionalFunctionOnce,
233        FunctionOnce
234    );
235}
236
237impl<T, R> FunctionOnce<T, R> for BoxFunctionOnce<T, R> {
238    fn apply(self, input: &T) -> R {
239        (self.function)(input)
240    }
241
242    impl_box_once_conversions!(
243        BoxFunctionOnce<T, R>,
244        FunctionOnce,
245        FnOnce(&T) -> R
246    );
247}
248
249// Generates: constant() method for BoxFunctionOnce<T, R>
250impl_function_constant_method!(BoxFunctionOnce<T, R>, 'static);
251
252// Generates: identity() method for BoxFunctionOnce<T, T>
253impl_function_identity_method!(BoxFunctionOnce<T, T>);
254
255// Generates: Debug and Display implementations for BoxFunctionOnce<T, R>
256impl_function_debug_display!(BoxFunctionOnce<T, R>);
257
258// ============================================================================
259// Blanket implementation for standard FnOnce trait
260// ============================================================================
261
262// Implement FunctionOnce for all FnOnce(&T) -> R using macro
263impl_closure_once_trait!(
264    FunctionOnce<T, R>,
265    apply,
266    BoxFunctionOnce,
267    FnOnce(input: &T) -> R
268);
269
270// ============================================================================
271// FnFunctionOnceOps - Extension trait for FnOnce transformers
272// ============================================================================
273
274// Generates: FnFunctionOnceOps trait and blanket implementation
275impl_fn_ops_trait!(
276    (FnOnce(&T) -> R),
277    FnFunctionOnceOps,
278    BoxFunctionOnce,
279    FunctionOnce,
280    BoxConditionalFunctionOnce
281);
282
283// ============================================================================
284// BoxConditionalFunctionOnce - Box-based Conditional Function
285// ============================================================================
286
287/// BoxConditionalFunctionOnce struct
288///
289/// A conditional consuming transformer that only executes when a predicate is
290/// satisfied. Uses `BoxFunctionOnce` and `BoxPredicate` for single
291/// ownership semantics.
292///
293/// This type is typically created by calling `BoxFunctionOnce::when()` and
294/// is designed to work with the `or_else()` method to create if-then-else
295/// logic.
296///
297/// # Features
298///
299/// - **Single Ownership**: Not cloneable, consumes `self` on use
300/// - **One-time Use**: Can only be called once
301/// - **Conditional Execution**: Only transforms when predicate returns `true`
302/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
303///
304/// # Examples
305///
306/// ## With or_else Branch
307///
308/// ```rust
309/// use prism3_function::{FunctionOnce, BoxFunctionOnce};
310///
311/// let double = BoxFunctionOnce::new(|x: i32| x * 2);
312/// let negate = BoxFunctionOnce::new(|x: i32| -x);
313/// let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
314/// assert_eq!(conditional.apply(5), 10); // when branch executed
315///
316/// let double2 = BoxFunctionOnce::new(|x: i32| x * 2);
317/// let negate2 = BoxFunctionOnce::new(|x: i32| -x);
318/// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(negate2);
319/// assert_eq!(conditional2.apply(-5), 5); // or_else branch executed
320/// ```
321///
322/// # Author
323///
324/// Haixing Hu
325pub struct BoxConditionalFunctionOnce<T, R> {
326    function: BoxFunctionOnce<T, R>,
327    predicate: BoxPredicate<T>,
328}
329
330// Use macro to generate conditional function implementations
331impl_box_conditional_function!(
332    BoxConditionalFunctionOnce<T, R>,
333    BoxFunctionOnce,
334    FunctionOnce
335);
336
337// Use macro to generate conditional function debug and display implementations
338impl_conditional_function_debug_display!(BoxConditionalFunctionOnce<T, R>);