Skip to main content

qubit_function/transformers/
transformer_once.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # TransformerOnce Types
10//!
11//! Provides Rust implementations of consuming transformer traits similar to
12//! Rust's `FnOnce` trait, but with value-oriented semantics for functional
13//! programming patterns.
14//!
15//! This module provides the `TransformerOnce<T, R>` trait and one-time use
16//! implementations:
17//!
18//! - [`BoxTransformerOnce`]: Single ownership, one-time use
19//!
20//! # Author
21//!
22//! Haixing Hu
23
24use crate::macros::{
25    impl_box_once_conversions,
26    impl_closure_once_trait,
27};
28use crate::predicates::predicate::{
29    BoxPredicate,
30    Predicate,
31};
32use crate::transformers::macros::{
33    impl_box_conditional_transformer,
34    impl_box_transformer_methods,
35    impl_conditional_transformer_debug_display,
36    impl_transformer_common_methods,
37    impl_transformer_constant_method,
38    impl_transformer_debug_display,
39};
40
41// ============================================================================
42// Core Trait
43// ============================================================================
44
45/// TransformerOnce trait - consuming transformation that takes ownership
46///
47/// Defines the behavior of a consuming transformer: converting a value of
48/// type `T` to a value of type `R` by taking ownership of both self and the
49/// input. This trait is analogous to `FnOnce(T) -> R`.
50///
51/// # Type Parameters
52///
53/// * `T` - The type of the input value (consumed)
54/// * `R` - The type of the output value
55///
56/// # Author
57///
58/// Haixing Hu
59pub trait TransformerOnce<T, R> {
60    /// Transforms the input value, consuming both self and input
61    ///
62    /// # Parameters
63    ///
64    /// * `input` - The input value (consumed)
65    ///
66    /// # Returns
67    ///
68    /// The transformed output value
69    fn apply(self, input: T) -> R;
70
71    /// Converts to BoxTransformerOnce
72    ///
73    /// **⚠️ Consumes `self`**: The original transformer becomes unavailable
74    /// after calling this method.
75    ///
76    /// # Returns
77    ///
78    /// Returns `BoxTransformerOnce<T, R>`
79    ///
80    /// # Examples
81    ///
82    /// ```rust
83    /// use qubit_function::TransformerOnce;
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) -> BoxTransformerOnce<T, R>
90    where
91        Self: Sized + 'static,
92    {
93        BoxTransformerOnce::new(move |input: T| self.apply(input))
94    }
95
96    /// Converts transformer to a closure
97    ///
98    /// **⚠️ Consumes `self`**: The original transformer becomes unavailable
99    /// after calling this method.
100    ///
101    /// # Returns
102    ///
103    /// Returns a closure that implements `FnOnce(T) -> R`
104    ///
105    /// # Examples
106    ///
107    /// ```rust
108    /// use qubit_function::TransformerOnce;
109    ///
110    /// let double = |x: i32| x * 2;
111    /// let func = double.into_fn();
112    /// assert_eq!(func(21), 42);
113    /// ```
114    fn into_fn(self) -> impl FnOnce(T) -> R
115    where
116        Self: Sized + 'static,
117    {
118        move |input: T| self.apply(input)
119    }
120
121    /// Converts to BoxTransformerOnce without consuming self
122    ///
123    /// **📌 Borrows `&self`**: The original transformer remains usable
124    /// after calling this method.
125    ///
126    /// # Default Implementation
127    ///
128    /// The default implementation creates a new `BoxTransformerOnce` that
129    /// captures a clone. Types implementing `Clone` can override this method
130    /// to provide more efficient conversions.
131    ///
132    /// # Returns
133    ///
134    /// Returns `BoxTransformerOnce<T, R>`
135    ///
136    /// # Examples
137    ///
138    /// ```rust
139    /// use qubit_function::TransformerOnce;
140    ///
141    /// let double = |x: i32| x * 2;
142    /// let boxed = double.to_box();
143    /// assert_eq!(boxed.apply(21), 42);
144    /// ```
145    fn to_box(&self) -> BoxTransformerOnce<T, R>
146    where
147        Self: Clone + 'static,
148    {
149        self.clone().into_box()
150    }
151
152    /// Converts transformer to a closure without consuming self
153    ///
154    /// **📌 Borrows `&self`**: The original transformer remains usable
155    /// after calling this method.
156    ///
157    /// # Default Implementation
158    ///
159    /// The default implementation creates a closure that captures a
160    /// clone of `self` and calls its `transform` method. Types can
161    /// override this method to provide more efficient conversions.
162    ///
163    /// # Returns
164    ///
165    /// Returns a closure that implements `FnOnce(T) -> R`
166    ///
167    /// # Examples
168    ///
169    /// ```rust
170    /// use qubit_function::TransformerOnce;
171    ///
172    /// let double = |x: i32| x * 2;
173    /// let func = double.to_fn();
174    /// assert_eq!(func(21), 42);
175    /// ```
176    fn to_fn(&self) -> impl FnOnce(T) -> R
177    where
178        Self: Clone + 'static,
179    {
180        self.clone().into_fn()
181    }
182}
183
184// ============================================================================
185// BoxTransformerOnce - Box<dyn FnOnce(T) -> R>
186// ============================================================================
187
188/// BoxTransformerOnce - consuming transformer wrapper based on
189/// `Box<dyn FnOnce>`
190///
191/// A transformer wrapper that provides single ownership with one-time use
192/// semantics. Consumes both self and the input value.
193///
194/// # Features
195///
196/// - **Based on**: `Box<dyn FnOnce(T) -> R>`
197/// - **Ownership**: Single ownership, cannot be cloned
198/// - **Reusability**: Can only be called once (consumes self and input)
199/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
200///
201/// # Author
202///
203/// Haixing Hu
204pub struct BoxTransformerOnce<T, R> {
205    function: Box<dyn FnOnce(T) -> R>,
206    name: Option<String>,
207}
208
209// Implement BoxTransformerOnce
210impl<T, R> BoxTransformerOnce<T, R> {
211    impl_transformer_common_methods!(
212        BoxTransformerOnce<T, R>,
213        (FnOnce(T) -> R + 'static),
214        |f| Box::new(f)
215    );
216
217    impl_box_transformer_methods!(
218        BoxTransformerOnce<T, R>,
219        BoxConditionalTransformerOnce,
220        TransformerOnce
221    );
222}
223
224// Implement TransformerOnce trait for BoxTransformerOnce
225impl<T, R> TransformerOnce<T, R> for BoxTransformerOnce<T, R> {
226    fn apply(self, input: T) -> R {
227        (self.function)(input)
228    }
229
230    impl_box_once_conversions!(
231        BoxTransformerOnce<T, R>,
232        TransformerOnce,
233        FnOnce(T) -> R
234    );
235}
236
237// Implement constant method for BoxTransformerOnce
238impl_transformer_constant_method!(BoxTransformerOnce<T, R>);
239
240// Use macro to generate Debug and Display implementations
241impl_transformer_debug_display!(BoxTransformerOnce<T, R>);
242
243// ============================================================================
244// Blanket implementation for standard FnOnce trait
245// ============================================================================
246
247// Implement TransformerOnce for all FnOnce(T) -> R using macro
248impl_closure_once_trait!(
249    TransformerOnce<T, R>,
250    apply,
251    BoxTransformerOnce,
252    FnOnce(input: T) -> R
253);
254
255// ============================================================================
256// FnTransformerOnceOps - Extension trait for FnOnce transformers
257// ============================================================================
258
259/// Extension trait for closures implementing `FnOnce(T) -> R`
260///
261/// Provides composition methods (`and_then`, `compose`, `when`) for one-time
262/// use closures and function pointers without requiring explicit wrapping in
263/// `BoxTransformerOnce`.
264///
265/// This trait is automatically implemented for all closures and function
266/// pointers that implement `FnOnce(T) -> R`.
267///
268/// # Design Rationale
269///
270/// While closures automatically implement `TransformerOnce<T, R>` through
271/// blanket implementation, they don't have access to instance methods like
272/// `and_then`, `compose`, and `when`. This extension trait provides those
273/// methods, returning `BoxTransformerOnce` for maximum flexibility.
274///
275/// # Examples
276///
277/// ## Chain composition with and_then
278///
279/// ```rust
280/// use qubit_function::{TransformerOnce, FnTransformerOnceOps};
281///
282/// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
283/// let double = |x: i32| x * 2;
284///
285/// let composed = parse.and_then(double);
286/// assert_eq!(composed.apply("21".to_string()), 42);
287/// ```
288///
289/// ## Forward composition with and_then
290///
291/// ```rust
292/// use qubit_function::{TransformerOnce, FnTransformerOnceOps};
293///
294/// let double = |x: i32| x * 2;
295/// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
296///
297/// let composed = parse.and_then(double);
298/// assert_eq!(composed.apply("21".to_string()), 42);
299/// ```
300///
301/// ## Conditional transformation with when
302///
303/// ```rust
304/// use qubit_function::{TransformerOnce, FnTransformerOnceOps};
305///
306/// let double = |x: i32| x * 2;
307/// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
308///
309/// assert_eq!(conditional.apply(5), 10);
310/// ```
311///
312/// # Author
313///
314/// Haixing Hu
315pub trait FnTransformerOnceOps<T, R>: FnOnce(T) -> R + Sized {
316    /// Chain composition - applies self first, then after
317    ///
318    /// Creates a new transformer that applies this transformer first, then
319    /// applies the after transformer to the result. Consumes self and returns
320    /// a `BoxTransformerOnce`.
321    ///
322    /// # Type Parameters
323    ///
324    /// * `S` - The output type of the after transformer
325    /// * `G` - The type of the after transformer (must implement
326    ///   TransformerOnce<R, S>)
327    ///
328    /// # Parameters
329    ///
330    /// * `after` - The transformer to apply after self. **Note: This parameter
331    ///   is passed by value and will transfer ownership.** Since this is a
332    ///   `FnOnce` transformer, the parameter will be consumed. Can be:
333    ///   - A closure: `|x: R| -> S`
334    ///   - A function pointer: `fn(R) -> S`
335    ///   - A `BoxTransformerOnce<R, S>`
336    ///   - Any type implementing `TransformerOnce<R, S>`
337    ///
338    /// # Returns
339    ///
340    /// A new `BoxTransformerOnce<T, S>` representing the composition
341    ///
342    /// # Examples
343    ///
344    /// ```rust
345    /// use qubit_function::{TransformerOnce, FnTransformerOnceOps,
346    ///     BoxTransformerOnce};
347    ///
348    /// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
349    /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
350    ///
351    /// // double is moved and consumed
352    /// let composed = parse.and_then(double);
353    /// assert_eq!(composed.apply("21".to_string()), 42);
354    /// // double.apply(5); // Would not compile - moved
355    /// ```
356    fn and_then<S, G>(self, after: G) -> BoxTransformerOnce<T, S>
357    where
358        Self: 'static,
359        S: 'static,
360        G: TransformerOnce<R, S> + 'static,
361        T: 'static,
362        R: 'static,
363    {
364        BoxTransformerOnce::new(move |x: T| {
365            let intermediate = self(x);
366            after.apply(intermediate)
367        })
368    }
369
370    /// Creates a conditional transformer
371    ///
372    /// Returns a transformer that only executes when a predicate is satisfied.
373    /// You must call `or_else()` to provide an alternative transformer for when
374    /// the condition is not satisfied.
375    ///
376    /// # Parameters
377    ///
378    /// * `predicate` - The condition to check. **Note: This parameter is passed
379    ///   by value and will transfer ownership.** If you need to preserve the
380    ///   original predicate, clone it first (if it implements `Clone`). Can be:
381    ///   - A closure: `|x: &T| -> bool`
382    ///   - A function pointer: `fn(&T) -> bool`
383    ///   - A `BoxPredicate<T>`
384    ///   - An `RcPredicate<T>`
385    ///   - An `ArcPredicate<T>`
386    ///   - Any type implementing `Predicate<T>`
387    ///
388    /// # Returns
389    ///
390    /// Returns `BoxConditionalTransformerOnce<T, R>`
391    ///
392    /// # Examples
393    ///
394    /// ## Basic usage with or_else
395    ///
396    /// ```rust
397    /// use qubit_function::{TransformerOnce, FnTransformerOnceOps};
398    ///
399    /// let double = |x: i32| x * 2;
400    /// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
401    ///
402    /// assert_eq!(conditional.apply(5), 10);
403    /// ```
404    ///
405    /// ## Preserving predicate with a second closure
406    ///
407    /// ```rust
408    /// use qubit_function::{Predicate, TransformerOnce, FnTransformerOnceOps};
409    ///
410    /// let double = |x: i32| x * 2;
411    /// let is_positive = |x: &i32| *x > 0;
412    /// let is_positive_for_validation = |x: &i32| *x > 0;
413    /// let conditional = double.when(is_positive)
414    ///     .or_else(|x: i32| -x);
415    ///
416    /// assert_eq!(conditional.apply(5), 10);
417    ///
418    /// // Original predicate still usable
419    /// assert!(is_positive_for_validation(&3));
420    /// ```
421    fn when<P>(self, predicate: P) -> BoxConditionalTransformerOnce<T, R>
422    where
423        Self: 'static,
424        P: Predicate<T> + 'static,
425        T: 'static,
426        R: 'static,
427    {
428        BoxTransformerOnce::new(self).when(predicate)
429    }
430}
431
432/// Blanket implementation of FnTransformerOnceOps for all FnOnce closures
433///
434/// Automatically implements `FnTransformerOnceOps<T, R>` for any type that
435/// implements `FnOnce(T) -> R`.
436///
437/// # Author
438///
439/// Haixing Hu
440impl<T, R, F> FnTransformerOnceOps<T, R> for F where F: FnOnce(T) -> R {}
441
442// ============================================================================
443// UnaryOperatorOnce Trait - Marker trait for TransformerOnce<T, T>
444// ============================================================================
445
446/// UnaryOperatorOnce trait - marker trait for one-time use unary operators
447///
448/// A one-time use unary operator transforms a value of type `T` to another
449/// value of the same type `T`, consuming self in the process. This trait
450/// extends `TransformerOnce<T, T>` to provide semantic clarity for same-type
451/// transformations with consuming semantics. Equivalent to Java's
452/// `UnaryOperator<T>` but with FnOnce semantics.
453///
454/// # Automatic Implementation
455///
456/// This trait is automatically implemented for all types that implement
457/// `TransformerOnce<T, T>`, so you don't need to implement it manually.
458///
459/// # Type Parameters
460///
461/// * `T` - The type of both input and output values
462///
463/// # Examples
464///
465/// ## Using in generic constraints
466///
467/// ```rust
468/// use qubit_function::{UnaryOperatorOnce, TransformerOnce};
469///
470/// fn apply<T, O>(value: T, op: O) -> T
471/// where
472///     O: UnaryOperatorOnce<T>,
473/// {
474///     op.apply(value)
475/// }
476///
477/// let double = |x: i32| x * 2;
478/// assert_eq!(apply(21, double), 42);
479/// ```
480///
481/// # Author
482///
483/// Haixing Hu
484pub trait UnaryOperatorOnce<T>: TransformerOnce<T, T> {}
485
486/// Blanket implementation of UnaryOperatorOnce for all TransformerOnce<T, T>
487///
488/// This automatically implements `UnaryOperatorOnce<T>` for any type that
489/// implements `TransformerOnce<T, T>`.
490///
491/// # Author
492///
493/// Haixing Hu
494impl<F, T> UnaryOperatorOnce<T> for F
495where
496    F: TransformerOnce<T, T>,
497{
498    // empty
499}
500
501// ============================================================================
502// Type Aliases for UnaryOperatorOnce (TransformerOnce<T, T>)
503// ============================================================================
504
505/// Type alias for `BoxTransformerOnce<T, T>`
506///
507/// Represents a one-time use unary operator that transforms a value of type `T`
508/// to another value of the same type `T`. Equivalent to Java's `UnaryOperator<T>`
509/// with consuming semantics (FnOnce).
510///
511/// # Examples
512///
513/// ```rust
514/// use qubit_function::{BoxUnaryOperatorOnce, TransformerOnce};
515///
516/// let increment: BoxUnaryOperatorOnce<i32> = BoxUnaryOperatorOnce::new(|x| x + 1);
517/// assert_eq!(increment.apply(41), 42);
518/// ```
519///
520/// # Author
521///
522/// Haixing Hu
523pub type BoxUnaryOperatorOnce<T> = BoxTransformerOnce<T, T>;
524
525// ============================================================================
526// BoxConditionalTransformerOnce - Box-based Conditional Transformer
527// ============================================================================
528
529/// BoxConditionalTransformerOnce struct
530///
531/// A conditional consuming transformer that only executes when a predicate is
532/// satisfied. Uses `BoxTransformerOnce` and `BoxPredicate` for single
533/// ownership semantics.
534///
535/// This type is typically created by calling `BoxTransformerOnce::when()` and
536/// is designed to work with the `or_else()` method to create if-then-else
537/// logic.
538///
539/// # Features
540///
541/// - **Single Ownership**: Not cloneable, consumes `self` on use
542/// - **One-time Use**: Can only be called once
543/// - **Conditional Execution**: Only transforms when predicate returns `true`
544/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
545///
546/// # Examples
547///
548/// ## With or_else Branch
549///
550/// ```rust
551/// use qubit_function::{TransformerOnce, BoxTransformerOnce};
552///
553/// let double = BoxTransformerOnce::new(|x: i32| x * 2);
554/// let negate = BoxTransformerOnce::new(|x: i32| -x);
555/// let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
556/// assert_eq!(conditional.apply(5), 10); // when branch executed
557///
558/// let double2 = BoxTransformerOnce::new(|x: i32| x * 2);
559/// let negate2 = BoxTransformerOnce::new(|x: i32| -x);
560/// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(negate2);
561/// assert_eq!(conditional2.apply(-5), 5); // or_else branch executed
562/// ```
563///
564/// # Author
565///
566/// Haixing Hu
567pub struct BoxConditionalTransformerOnce<T, R> {
568    transformer: BoxTransformerOnce<T, R>,
569    predicate: BoxPredicate<T>,
570}
571
572// Implement BoxConditionalTransformerOnce
573impl_box_conditional_transformer!(
574    BoxConditionalTransformerOnce<T, R>,
575    BoxTransformerOnce,
576    TransformerOnce
577);
578
579// Use macro to generate Debug and Display implementations
580impl_conditional_transformer_debug_display!(BoxConditionalTransformerOnce<T, R>);