qubit_function/functions/function_once.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit 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 qubit_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 qubit_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 {
120 move |input: &T| self.apply(input)
121 }
122
123 /// Converts to BoxFunctionOnce without consuming self
124 ///
125 /// **📌 Borrows `&self`**: The original function remains usable
126 /// after calling this method.
127 ///
128 /// # Default Implementation
129 ///
130 /// The default implementation creates a new `BoxFunctionOnce` that
131 /// captures a clone. Types implementing `Clone` can override this method
132 /// to provide more efficient conversions.
133 ///
134 /// # Returns
135 ///
136 /// Returns `BoxFunctionOnce<T, R>`
137 ///
138 /// # Examples
139 ///
140 /// ```rust
141 /// use qubit_function::FunctionOnce;
142 ///
143 /// let double = |x: &i32| x * 2;
144 /// let boxed = double.to_box();
145 /// assert_eq!(boxed.apply(&21), 42);
146 /// ```
147 fn to_box(&self) -> BoxFunctionOnce<T, R>
148 where
149 Self: Clone + 'static,
150 T: 'static,
151 R: 'static,
152 {
153 self.clone().into_box()
154 }
155
156 /// Converts function to a closure without consuming self
157 ///
158 /// **📌 Borrows `&self`**: The original function remains usable
159 /// after calling this method.
160 ///
161 /// # Default Implementation
162 ///
163 /// The default implementation creates a closure that captures a
164 /// clone of `self` and calls its `apply` method. Types can
165 /// override this method to provide more efficient conversions.
166 ///
167 /// # Returns
168 ///
169 /// Returns a closure that implements `FnOnce(&T) -> R`
170 ///
171 /// # Examples
172 ///
173 /// ```rust
174 /// use qubit_function::FunctionOnce;
175 ///
176 /// let double = |x: &i32| x * 2;
177 /// let func = double.to_fn();
178 /// assert_eq!(func(&21), 42);
179 /// ```
180 fn to_fn(&self) -> impl FnOnce(&T) -> R
181 where
182 Self: Clone + 'static,
183 {
184 self.clone().into_fn()
185 }
186}
187
188// ============================================================================
189// BoxFunctionOnce - Box<dyn FnOnce(&T) -> R>
190// ============================================================================
191
192/// BoxFunctionOnce - consuming transformer wrapper based on
193/// `Box<dyn FnOnce>`
194///
195/// A transformer wrapper that provides single ownership with one-time use
196/// semantics. Consumes both self and the input value.
197///
198/// # Features
199///
200/// - **Based on**: `Box<dyn FnOnce(&T) -> R>`
201/// - **Ownership**: Single ownership, cannot be cloned
202/// - **Reusability**: Can only be called once (consumes self and input)
203/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
204///
205/// # Author
206///
207/// Haixing Hu
208pub struct BoxFunctionOnce<T, R> {
209 function: Box<dyn FnOnce(&T) -> R>,
210 name: Option<String>,
211}
212
213impl<T, R> BoxFunctionOnce<T, R> {
214 // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
215 impl_function_common_methods!(
216 BoxFunctionOnce<T, R>,
217 (FnOnce(&T) -> R + 'static),
218 |f| Box::new(f)
219 );
220
221 // Generates: when(), and_then(), compose()
222 impl_box_function_methods!(
223 BoxFunctionOnce<T, R>,
224 BoxConditionalFunctionOnce,
225 FunctionOnce
226 );
227}
228
229impl<T, R> FunctionOnce<T, R> for BoxFunctionOnce<T, R> {
230 fn apply(self, input: &T) -> R {
231 (self.function)(input)
232 }
233
234 impl_box_once_conversions!(
235 BoxFunctionOnce<T, R>,
236 FunctionOnce,
237 FnOnce(&T) -> R
238 );
239}
240
241// Generates: constant() method for BoxFunctionOnce<T, R>
242impl_function_constant_method!(BoxFunctionOnce<T, R>, 'static);
243
244// Generates: identity() method for BoxFunctionOnce<T, T>
245impl_function_identity_method!(BoxFunctionOnce<T, T>);
246
247// Generates: Debug and Display implementations for BoxFunctionOnce<T, R>
248impl_function_debug_display!(BoxFunctionOnce<T, R>);
249
250// ============================================================================
251// Blanket implementation for standard FnOnce trait
252// ============================================================================
253
254// Implement FunctionOnce for all FnOnce(&T) -> R using macro
255impl_closure_once_trait!(
256 FunctionOnce<T, R>,
257 apply,
258 BoxFunctionOnce,
259 FnOnce(input: &T) -> R
260);
261
262// ============================================================================
263// FnFunctionOnceOps - Extension trait for FnOnce transformers
264// ============================================================================
265
266// Generates: FnFunctionOnceOps trait and blanket implementation
267impl_fn_ops_trait!(
268 (FnOnce(&T) -> R),
269 FnFunctionOnceOps,
270 BoxFunctionOnce,
271 FunctionOnce,
272 BoxConditionalFunctionOnce
273);
274
275// ============================================================================
276// BoxConditionalFunctionOnce - Box-based Conditional Function
277// ============================================================================
278
279/// BoxConditionalFunctionOnce struct
280///
281/// A conditional consuming transformer that only executes when a predicate is
282/// satisfied. Uses `BoxFunctionOnce` and `BoxPredicate` for single
283/// ownership semantics.
284///
285/// This type is typically created by calling `BoxFunctionOnce::when()` and
286/// is designed to work with the `or_else()` method to create if-then-else
287/// logic.
288///
289/// # Features
290///
291/// - **Single Ownership**: Not cloneable, consumes `self` on use
292/// - **One-time Use**: Can only be called once
293/// - **Conditional Execution**: Only transforms when predicate returns `true`
294/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
295///
296/// # Examples
297///
298/// ## With or_else Branch
299///
300/// ```rust
301/// use qubit_function::{FunctionOnce, BoxFunctionOnce};
302///
303/// let double = BoxFunctionOnce::new(|x: i32| x * 2);
304/// let negate = BoxFunctionOnce::new(|x: i32| -x);
305/// let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
306/// assert_eq!(conditional.apply(5), 10); // when branch executed
307///
308/// let double2 = BoxFunctionOnce::new(|x: i32| x * 2);
309/// let negate2 = BoxFunctionOnce::new(|x: i32| -x);
310/// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(negate2);
311/// assert_eq!(conditional2.apply(-5), 5); // or_else branch executed
312/// ```
313///
314/// # Author
315///
316/// Haixing Hu
317pub struct BoxConditionalFunctionOnce<T, R> {
318 function: BoxFunctionOnce<T, R>,
319 predicate: BoxPredicate<T>,
320}
321
322// Use macro to generate conditional function implementations
323impl_box_conditional_function!(
324 BoxConditionalFunctionOnce<T, R>,
325 BoxFunctionOnce,
326 FunctionOnce
327);
328
329// Use macro to generate conditional function debug and display implementations
330impl_conditional_function_debug_display!(BoxConditionalFunctionOnce<T, R>);