prism3_function/transformers/
transformer_once.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism 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 prism3_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        T: 'static,
93        R: 'static,
94    {
95        BoxTransformerOnce::new(move |input: T| self.apply(input))
96    }
97
98    /// Converts transformer to a closure
99    ///
100    /// **⚠️ Consumes `self`**: The original transformer 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::TransformerOnce;
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 BoxTransformerOnce without consuming self
126    ///
127    /// **📌 Borrows `&self`**: The original transformer remains usable
128    /// after calling this method.
129    ///
130    /// # Default Implementation
131    ///
132    /// The default implementation creates a new `BoxTransformerOnce` that
133    /// captures a clone. Types implementing `Clone` can override this method
134    /// to provide more efficient conversions.
135    ///
136    /// # Returns
137    ///
138    /// Returns `BoxTransformerOnce<T, R>`
139    ///
140    /// # Examples
141    ///
142    /// ```rust
143    /// use prism3_function::TransformerOnce;
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) -> BoxTransformerOnce<T, R>
150    where
151        Self: Clone + 'static,
152        T: 'static,
153        R: 'static,
154    {
155        self.clone().into_box()
156    }
157
158    /// Converts transformer to a closure without consuming self
159    ///
160    /// **📌 Borrows `&self`**: The original transformer 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 `transform` 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::TransformerOnce;
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// BoxTransformerOnce - Box<dyn FnOnce(T) -> R>
194// ============================================================================
195
196/// BoxTransformerOnce - 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 BoxTransformerOnce<T, R> {
213    function: Box<dyn FnOnce(T) -> R>,
214    name: Option<String>,
215}
216
217// Implement BoxTransformerOnce
218impl<T, R> BoxTransformerOnce<T, R>
219where
220    T: 'static,
221    R: 'static,
222{
223    impl_transformer_common_methods!(
224        BoxTransformerOnce<T, R>,
225        (FnOnce(T) -> R + 'static),
226        |f| Box::new(f)
227    );
228
229    impl_box_transformer_methods!(
230        BoxTransformerOnce<T, R>,
231        BoxConditionalTransformerOnce,
232        TransformerOnce
233    );
234}
235
236// Implement TransformerOnce trait for BoxTransformerOnce
237impl<T, R> TransformerOnce<T, R> for BoxTransformerOnce<T, R> {
238    fn apply(self, input: T) -> R {
239        (self.function)(input)
240    }
241
242    impl_box_once_conversions!(
243        BoxTransformerOnce<T, R>,
244        TransformerOnce,
245        FnOnce(T) -> R
246    );
247}
248
249// Implement constant method for BoxTransformerOnce
250impl_transformer_constant_method!(BoxTransformerOnce<T, R>);
251
252// Use macro to generate Debug and Display implementations
253impl_transformer_debug_display!(BoxTransformerOnce<T, R>);
254
255// ============================================================================
256// Blanket implementation for standard FnOnce trait
257// ============================================================================
258
259// Implement TransformerOnce for all FnOnce(T) -> R using macro
260impl_closure_once_trait!(
261    TransformerOnce<T, R>,
262    apply,
263    BoxTransformerOnce,
264    FnOnce(input: T) -> R
265);
266
267// ============================================================================
268// FnTransformerOnceOps - Extension trait for FnOnce transformers
269// ============================================================================
270
271/// Extension trait for closures implementing `FnOnce(T) -> R`
272///
273/// Provides composition methods (`and_then`, `compose`, `when`) for one-time
274/// use closures and function pointers without requiring explicit wrapping in
275/// `BoxTransformerOnce`.
276///
277/// This trait is automatically implemented for all closures and function
278/// pointers that implement `FnOnce(T) -> R`.
279///
280/// # Design Rationale
281///
282/// While closures automatically implement `TransformerOnce<T, R>` through
283/// blanket implementation, they don't have access to instance methods like
284/// `and_then`, `compose`, and `when`. This extension trait provides those
285/// methods, returning `BoxTransformerOnce` for maximum flexibility.
286///
287/// # Examples
288///
289/// ## Chain composition with and_then
290///
291/// ```rust
292/// use prism3_function::{TransformerOnce, FnTransformerOnceOps};
293///
294/// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
295/// let double = |x: i32| x * 2;
296///
297/// let composed = parse.and_then(double);
298/// assert_eq!(composed.apply("21".to_string()), 42);
299/// ```
300///
301/// ## Reverse composition with compose
302///
303/// ```rust
304/// use prism3_function::{TransformerOnce, FnTransformerOnceOps};
305///
306/// let double = |x: i32| x * 2;
307/// let to_string = |x: i32| x.to_string();
308///
309/// let composed = to_string.compose(double);
310/// assert_eq!(composed.apply(21), "42");
311/// ```
312///
313/// ## Conditional transformation with when
314///
315/// ```rust
316/// use prism3_function::{TransformerOnce, FnTransformerOnceOps};
317///
318/// let double = |x: i32| x * 2;
319/// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
320///
321/// assert_eq!(conditional.apply(5), 10);
322/// ```
323///
324/// # Author
325///
326/// Haixing Hu
327pub trait FnTransformerOnceOps<T, R>: FnOnce(T) -> R + Sized + 'static {
328    /// Chain composition - applies self first, then after
329    ///
330    /// Creates a new transformer that applies this transformer first, then
331    /// applies the after transformer to the result. Consumes self and returns
332    /// a `BoxTransformerOnce`.
333    ///
334    /// # Type Parameters
335    ///
336    /// * `S` - The output type of the after transformer
337    /// * `G` - The type of the after transformer (must implement
338    ///   TransformerOnce<R, S>)
339    ///
340    /// # Parameters
341    ///
342    /// * `after` - The transformer to apply after self. **Note: This parameter
343    ///   is passed by value and will transfer ownership.** Since this is a
344    ///   `FnOnce` transformer, the parameter will be consumed. Can be:
345    ///   - A closure: `|x: R| -> S`
346    ///   - A function pointer: `fn(R) -> S`
347    ///   - A `BoxTransformerOnce<R, S>`
348    ///   - Any type implementing `TransformerOnce<R, S>`
349    ///
350    /// # Returns
351    ///
352    /// A new `BoxTransformerOnce<T, S>` representing the composition
353    ///
354    /// # Examples
355    ///
356    /// ```rust
357    /// use prism3_function::{TransformerOnce, FnTransformerOnceOps,
358    ///     BoxTransformerOnce};
359    ///
360    /// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
361    /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
362    ///
363    /// // double is moved and consumed
364    /// let composed = parse.and_then(double);
365    /// assert_eq!(composed.apply("21".to_string()), 42);
366    /// // double.apply(5); // Would not compile - moved
367    /// ```
368    fn and_then<S, G>(self, after: G) -> BoxTransformerOnce<T, S>
369    where
370        S: 'static,
371        G: TransformerOnce<R, S> + 'static,
372        T: 'static,
373        R: 'static,
374    {
375        BoxTransformerOnce::new(move |x: T| {
376            let intermediate = self(x);
377            after.apply(intermediate)
378        })
379    }
380
381    /// Creates a conditional transformer
382    ///
383    /// Returns a transformer that only executes when a predicate is satisfied.
384    /// You must call `or_else()` to provide an alternative transformer for when
385    /// the condition is not satisfied.
386    ///
387    /// # Parameters
388    ///
389    /// * `predicate` - The condition to check. **Note: This parameter is passed
390    ///   by value and will transfer ownership.** If you need to preserve the
391    ///   original predicate, clone it first (if it implements `Clone`). Can be:
392    ///   - A closure: `|x: &T| -> bool`
393    ///   - A function pointer: `fn(&T) -> bool`
394    ///   - A `BoxPredicate<T>`
395    ///   - An `RcPredicate<T>`
396    ///   - An `ArcPredicate<T>`
397    ///   - Any type implementing `Predicate<T>`
398    ///
399    /// # Returns
400    ///
401    /// Returns `BoxConditionalTransformerOnce<T, R>`
402    ///
403    /// # Examples
404    ///
405    /// ## Basic usage with or_else
406    ///
407    /// ```rust
408    /// use prism3_function::{TransformerOnce, FnTransformerOnceOps};
409    ///
410    /// let double = |x: i32| x * 2;
411    /// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
412    ///
413    /// assert_eq!(conditional.apply(5), 10);
414    /// ```
415    ///
416    /// ## Preserving predicate with clone
417    ///
418    /// ```rust
419    /// use prism3_function::{TransformerOnce, FnTransformerOnceOps,
420    ///     RcPredicate};
421    ///
422    /// let double = |x: i32| x * 2;
423    /// let is_positive = RcPredicate::new(|x: &i32| *x > 0);
424    ///
425    /// // Clone to preserve original predicate
426    /// let conditional = double.when(is_positive.clone())
427    ///     .or_else(|x: i32| -x);
428    ///
429    /// assert_eq!(conditional.apply(5), 10);
430    ///
431    /// // Original predicate still usable
432    /// assert!(is_positive.test(&3));
433    /// ```
434    fn when<P>(self, predicate: P) -> BoxConditionalTransformerOnce<T, R>
435    where
436        P: Predicate<T> + 'static,
437        T: 'static,
438        R: 'static,
439    {
440        BoxTransformerOnce::new(self).when(predicate)
441    }
442}
443
444/// Blanket implementation of FnTransformerOnceOps for all FnOnce closures
445///
446/// Automatically implements `FnTransformerOnceOps<T, R>` for any type that
447/// implements `FnOnce(T) -> R`.
448///
449/// # Author
450///
451/// Haixing Hu
452impl<T, R, F> FnTransformerOnceOps<T, R> for F where F: FnOnce(T) -> R + 'static {}
453
454// ============================================================================
455// UnaryOperatorOnce Trait - Marker trait for TransformerOnce<T, T>
456// ============================================================================
457
458/// UnaryOperatorOnce trait - marker trait for one-time use unary operators
459///
460/// A one-time use unary operator transforms a value of type `T` to another
461/// value of the same type `T`, consuming self in the process. This trait
462/// extends `TransformerOnce<T, T>` to provide semantic clarity for same-type
463/// transformations with consuming semantics. Equivalent to Java's
464/// `UnaryOperator<T>` but with FnOnce semantics.
465///
466/// # Automatic Implementation
467///
468/// This trait is automatically implemented for all types that implement
469/// `TransformerOnce<T, T>`, so you don't need to implement it manually.
470///
471/// # Type Parameters
472///
473/// * `T` - The type of both input and output values
474///
475/// # Examples
476///
477/// ## Using in generic constraints
478///
479/// ```rust
480/// use prism3_function::{UnaryOperatorOnce, TransformerOnce};
481///
482/// fn apply<T, O>(value: T, op: O) -> T
483/// where
484///     O: UnaryOperatorOnce<T>,
485/// {
486///     op.apply(value)
487/// }
488///
489/// let double = |x: i32| x * 2;
490/// assert_eq!(apply(21, double), 42);
491/// ```
492///
493/// # Author
494///
495/// Haixing Hu
496pub trait UnaryOperatorOnce<T>: TransformerOnce<T, T> {}
497
498/// Blanket implementation of UnaryOperatorOnce for all TransformerOnce<T, T>
499///
500/// This automatically implements `UnaryOperatorOnce<T>` for any type that
501/// implements `TransformerOnce<T, T>`.
502///
503/// # Author
504///
505/// Haixing Hu
506impl<F, T> UnaryOperatorOnce<T> for F
507where
508    F: TransformerOnce<T, T>,
509    T: 'static,
510{
511    // empty
512}
513
514// ============================================================================
515// Type Aliases for UnaryOperatorOnce (TransformerOnce<T, T>)
516// ============================================================================
517
518/// Type alias for `BoxTransformerOnce<T, T>`
519///
520/// Represents a one-time use unary operator that transforms a value of type `T`
521/// to another value of the same type `T`. Equivalent to Java's `UnaryOperator<T>`
522/// with consuming semantics (FnOnce).
523///
524/// # Examples
525///
526/// ```rust
527/// use prism3_function::{BoxUnaryOperatorOnce, TransformerOnce};
528///
529/// let increment: BoxUnaryOperatorOnce<i32> = BoxUnaryOperatorOnce::new(|x| x + 1);
530/// assert_eq!(increment.apply(41), 42);
531/// ```
532///
533/// # Author
534///
535/// Haixing Hu
536pub type BoxUnaryOperatorOnce<T> = BoxTransformerOnce<T, T>;
537
538// ============================================================================
539// BoxConditionalTransformerOnce - Box-based Conditional Transformer
540// ============================================================================
541
542/// BoxConditionalTransformerOnce struct
543///
544/// A conditional consuming transformer that only executes when a predicate is
545/// satisfied. Uses `BoxTransformerOnce` and `BoxPredicate` for single
546/// ownership semantics.
547///
548/// This type is typically created by calling `BoxTransformerOnce::when()` and
549/// is designed to work with the `or_else()` method to create if-then-else
550/// logic.
551///
552/// # Features
553///
554/// - **Single Ownership**: Not cloneable, consumes `self` on use
555/// - **One-time Use**: Can only be called once
556/// - **Conditional Execution**: Only transforms when predicate returns `true`
557/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
558///
559/// # Examples
560///
561/// ## With or_else Branch
562///
563/// ```rust
564/// use prism3_function::{TransformerOnce, BoxTransformerOnce};
565///
566/// let double = BoxTransformerOnce::new(|x: i32| x * 2);
567/// let negate = BoxTransformerOnce::new(|x: i32| -x);
568/// let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
569/// assert_eq!(conditional.apply(5), 10); // when branch executed
570///
571/// let double2 = BoxTransformerOnce::new(|x: i32| x * 2);
572/// let negate2 = BoxTransformerOnce::new(|x: i32| -x);
573/// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(negate2);
574/// assert_eq!(conditional2.apply(-5), 5); // or_else branch executed
575/// ```
576///
577/// # Author
578///
579/// Haixing Hu
580pub struct BoxConditionalTransformerOnce<T, R> {
581    transformer: BoxTransformerOnce<T, R>,
582    predicate: BoxPredicate<T>,
583}
584
585// Implement BoxConditionalTransformerOnce
586impl_box_conditional_transformer!(
587    BoxConditionalTransformerOnce<T, R>,
588    BoxTransformerOnce,
589    TransformerOnce
590);
591
592// Use macro to generate Debug and Display implementations
593impl_conditional_transformer_debug_display!(BoxConditionalTransformerOnce<T, R>);