prism3_function/transformers/
bi_transformer.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # BiTransformer Types
10//!
11//! Provides Rust implementations of bi-transformer traits for type conversion
12//! and value transformation with two inputs. BiTransformers consume two input
13//! values (taking ownership) and produce an output value.
14//!
15//! This module provides the `BiTransformer<T, U, R>` trait and three
16//! implementations:
17//!
18//! - [`BoxBiTransformer`]: Single ownership, not cloneable
19//! - [`ArcBiTransformer`]: Thread-safe shared ownership, cloneable
20//! - [`RcBiTransformer`]: Single-threaded shared ownership, cloneable
21//!
22//! # Author
23//!
24//! Haixing Hu
25use std::rc::Rc;
26use std::sync::Arc;
27
28use crate::macros::{
29    impl_arc_conversions,
30    impl_box_conversions,
31    impl_rc_conversions,
32};
33use crate::predicates::bi_predicate::{
34    ArcBiPredicate,
35    BiPredicate,
36    BoxBiPredicate,
37    RcBiPredicate,
38};
39use crate::transformers::{
40    bi_transformer_once::BoxBiTransformerOnce,
41    macros::{
42        impl_box_conditional_transformer,
43        impl_box_transformer_methods,
44        impl_conditional_transformer_clone,
45        impl_conditional_transformer_debug_display,
46        impl_shared_conditional_transformer,
47        impl_shared_transformer_methods,
48        impl_transformer_clone,
49        impl_transformer_common_methods,
50        impl_transformer_constant_method,
51        impl_transformer_debug_display,
52    },
53    transformer::Transformer,
54};
55
56// ============================================================================
57// Core Trait
58// ============================================================================
59
60/// BiTransformer trait - transforms two values to produce a result
61///
62/// Defines the behavior of a bi-transformation: converting two values of types
63/// `T` and `U` to a value of type `R` by consuming the inputs. This is
64/// analogous to `Fn(T, U) -> R` in Rust's standard library.
65///
66/// # Type Parameters
67///
68/// * `T` - The type of the first input value (consumed)
69/// * `U` - The type of the second input value (consumed)
70/// * `R` - The type of the output value
71///
72/// # Author
73///
74/// Haixing Hu
75pub trait BiTransformer<T, U, R> {
76    /// Transforms two input values to produce an output value
77    ///
78    /// # Parameters
79    ///
80    /// * `first` - The first input value to transform (consumed)
81    /// * `second` - The second input value to transform (consumed)
82    ///
83    /// # Returns
84    ///
85    /// The transformed output value
86    fn apply(&self, first: T, second: U) -> R;
87
88    /// Converts to BoxBiTransformer
89    ///
90    /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
91    /// after calling this method.
92    ///
93    /// # Default Implementation
94    ///
95    /// The default implementation wraps `self` in a `Box` and creates a
96    /// `BoxBiTransformer`. Types can override this method to provide more
97    /// efficient conversions.
98    ///
99    /// # Returns
100    ///
101    /// Returns `BoxBiTransformer<T, U, R>`
102    fn into_box(self) -> BoxBiTransformer<T, U, R>
103    where
104        Self: Sized + 'static,
105        T: 'static,
106        U: 'static,
107        R: 'static,
108    {
109        BoxBiTransformer::new(move |x, y| self.apply(x, y))
110    }
111
112    /// Converts to RcBiTransformer
113    ///
114    /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
115    /// after calling this method.
116    ///
117    /// # Default Implementation
118    ///
119    /// The default implementation wraps `self` in an `Rc` and creates an
120    /// `RcBiTransformer`. Types can override this method to provide more
121    /// efficient conversions.
122    ///
123    /// # Returns
124    ///
125    /// Returns `RcBiTransformer<T, U, R>`
126    fn into_rc(self) -> RcBiTransformer<T, U, R>
127    where
128        Self: Sized + 'static,
129        T: 'static,
130        U: 'static,
131        R: 'static,
132    {
133        RcBiTransformer::new(move |x, y| self.apply(x, y))
134    }
135
136    /// Converts to ArcBiTransformer
137    ///
138    /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
139    /// after calling this method.
140    ///
141    /// # Default Implementation
142    ///
143    /// The default implementation wraps `self` in an `Arc` and creates an
144    /// `ArcBiTransformer`. Types can override this method to provide more
145    /// efficient conversions.
146    ///
147    /// # Returns
148    ///
149    /// Returns `ArcBiTransformer<T, U, R>`
150    fn into_arc(self) -> ArcBiTransformer<T, U, R>
151    where
152        Self: Sized + Send + Sync + 'static,
153        T: Send + Sync + 'static,
154        U: Send + Sync + 'static,
155        R: Send + Sync + 'static,
156    {
157        ArcBiTransformer::new(move |x, y| self.apply(x, y))
158    }
159
160    /// Converts bi-transformer to a closure
161    ///
162    /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
163    /// after calling this method.
164    ///
165    /// # Default Implementation
166    ///
167    /// The default implementation creates a closure that captures `self`
168    /// and calls its `apply` method. Types can override this method
169    /// to provide more efficient conversions.
170    ///
171    /// # Returns
172    ///
173    /// Returns a closure that implements `Fn(T, U) -> R`
174    fn into_fn(self) -> impl Fn(T, U) -> R
175    where
176        Self: Sized + 'static,
177        T: 'static,
178        U: 'static,
179        R: 'static,
180    {
181        move |t, u| self.apply(t, u)
182    }
183
184    /// Convert to BiTransformerOnce
185    ///
186    /// **⚠️ Consumes `self`**: The original bi-transformer will be unavailable after calling this method.
187    ///
188    /// Converts a reusable bi-transformer to a one-time bi-transformer that consumes itself on use.
189    /// This enables passing `BiTransformer` to functions that require `BiTransformerOnce`.
190    ///
191    /// # Returns
192    ///
193    /// Returns a `BoxBiTransformerOnce<T, U, R>`
194    fn into_once(self) -> BoxBiTransformerOnce<T, U, R>
195    where
196        Self: Sized + 'static,
197        T: 'static,
198        U: 'static,
199        R: 'static,
200    {
201        BoxBiTransformerOnce::new(move |t, u| self.apply(t, u))
202    }
203
204    /// Non-consuming conversion to `BoxBiTransformer` using `&self`.
205    ///
206    /// Default implementation clones `self` and delegates to `into_box`.
207    fn to_box(&self) -> BoxBiTransformer<T, U, R>
208    where
209        Self: Sized + Clone + 'static,
210        T: 'static,
211        U: 'static,
212        R: 'static,
213    {
214        self.clone().into_box()
215    }
216
217    /// Non-consuming conversion to `RcBiTransformer` using `&self`.
218    ///
219    /// Default implementation clones `self` and delegates to `into_rc`.
220    fn to_rc(&self) -> RcBiTransformer<T, U, R>
221    where
222        Self: Sized + Clone + 'static,
223        T: 'static,
224        U: 'static,
225        R: 'static,
226    {
227        self.clone().into_rc()
228    }
229
230    /// Non-consuming conversion to `ArcBiTransformer` using `&self`.
231    ///
232    /// Default implementation clones `self` and delegates to `into_arc`.
233    fn to_arc(&self) -> ArcBiTransformer<T, U, R>
234    where
235        Self: Sized + Clone + Send + Sync + 'static,
236        T: Send + Sync + 'static,
237        U: Send + Sync + 'static,
238        R: Send + Sync + 'static,
239    {
240        self.clone().into_arc()
241    }
242
243    /// Non-consuming conversion to a boxed function using `&self`.
244    ///
245    /// Returns a `Box<dyn Fn(T, U) -> R>` that clones `self` and calls
246    /// `apply` inside the boxed closure.
247    fn to_fn(&self) -> impl Fn(T, U) -> R
248    where
249        Self: Sized + Clone + 'static,
250        T: 'static,
251        U: 'static,
252        R: 'static,
253    {
254        self.clone().into_fn()
255    }
256
257    /// Convert to BiTransformerOnce without consuming self
258    ///
259    /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
260    /// Clones the current bi-transformer and converts the clone to a one-time bi-transformer.
261    ///
262    /// # Returns
263    ///
264    /// Returns a `BoxBiTransformerOnce<T, U, R>`
265    fn to_once(&self) -> BoxBiTransformerOnce<T, U, R>
266    where
267        Self: Clone + 'static,
268        T: 'static,
269        U: 'static,
270        R: 'static,
271    {
272        self.clone().into_once()
273    }
274}
275
276// ============================================================================
277// BoxBiTransformer - Box<dyn Fn(T, U) -> R>
278// ============================================================================
279
280/// BoxBiTransformer - bi-transformer wrapper based on `Box<dyn Fn>`
281///
282/// A bi-transformer wrapper that provides single ownership with reusable
283/// transformation. The bi-transformer consumes both inputs and can be called
284/// multiple times.
285///
286/// # Features
287///
288/// - **Based on**: `Box<dyn Fn(T, U) -> R>`
289/// - **Ownership**: Single ownership, cannot be cloned
290/// - **Reusability**: Can be called multiple times (each call consumes its
291///   inputs)
292/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
293///
294/// # Author
295///
296/// Haixing Hu
297pub struct BoxBiTransformer<T, U, R> {
298    function: Box<dyn Fn(T, U) -> R>,
299    name: Option<String>,
300}
301
302// Implement BoxBiTransformer
303impl<T, U, R> BoxBiTransformer<T, U, R>
304where
305    T: 'static,
306    U: 'static,
307    R: 'static,
308{
309    impl_transformer_common_methods!(
310        BoxBiTransformer<T, U, R>,
311        (Fn(T, U) -> R + 'static),
312        |f| Box::new(f)
313    );
314
315    impl_box_transformer_methods!(
316        BoxBiTransformer<T, U, R>,
317        BoxConditionalBiTransformer,
318        Transformer
319    );
320}
321
322// Implement constant method for BoxBiTransformer
323impl_transformer_constant_method!(BoxBiTransformer<T, U, R>);
324
325// Implement Debug and Display for BoxBiTransformer
326impl_transformer_debug_display!(BoxBiTransformer<T, U, R>);
327
328// Implement BiTransformer trait for BoxBiTransformer
329impl<T, U, R> BiTransformer<T, U, R> for BoxBiTransformer<T, U, R> {
330    fn apply(&self, first: T, second: U) -> R {
331        (self.function)(first, second)
332    }
333
334    // Generates: into_box(), into_rc(), into_fn(), into_once()
335    impl_box_conversions!(
336        BoxBiTransformer<T, U, R>,
337        RcBiTransformer,
338        Fn(T, U) -> R,
339        BoxBiTransformerOnce
340    );
341}
342
343// ============================================================================
344// RcBiTransformer - Rc<dyn Fn(T, U) -> R>
345// ============================================================================
346
347/// RcBiTransformer - single-threaded bi-transformer wrapper
348///
349/// A single-threaded, clonable bi-transformer wrapper optimized for scenarios
350/// that require sharing without thread-safety overhead.
351///
352/// # Features
353///
354/// - **Based on**: `Rc<dyn Fn(T, U) -> R>`
355/// - **Ownership**: Shared ownership via reference counting (non-atomic)
356/// - **Reusability**: Can be called multiple times (each call consumes its
357///   inputs)
358/// - **Thread Safety**: Not thread-safe (no `Send + Sync`)
359/// - **Clonable**: Cheap cloning via `Rc::clone`
360///
361/// # Author
362///
363/// Haixing Hu
364pub struct RcBiTransformer<T, U, R> {
365    function: Rc<dyn Fn(T, U) -> R>,
366    name: Option<String>,
367}
368
369impl<T, U, R> RcBiTransformer<T, U, R>
370where
371    T: 'static,
372    U: 'static,
373    R: 'static,
374{
375    impl_transformer_common_methods!(
376        RcBiTransformer<T, U, R>,
377        (Fn(T, U) -> R + 'static),
378        |f| Rc::new(f)
379    );
380
381    impl_shared_transformer_methods!(
382        RcBiTransformer<T, U, R>,
383        RcConditionalBiTransformer,
384        into_rc,
385        Transformer,
386        'static
387    );
388}
389
390// Implement constant method for RcBiTransformer
391impl_transformer_constant_method!(RcBiTransformer<T, U, R>);
392
393// Implement Debug and Display for RcBiTransformer
394impl_transformer_debug_display!(RcBiTransformer<T, U, R>);
395
396// Implement Clone for RcBiTransformer
397impl_transformer_clone!(RcBiTransformer<T, U, R>);
398
399// Implement BiTransformer trait for RcBiTransformer
400impl<T, U, R> BiTransformer<T, U, R> for RcBiTransformer<T, U, R> {
401    fn apply(&self, first: T, second: U) -> R {
402        (self.function)(first, second)
403    }
404
405    // Generate all conversion methods using the unified macro
406    impl_rc_conversions!(
407        RcBiTransformer<T, U, R>,
408        BoxBiTransformer,
409        BoxBiTransformerOnce,
410        Fn(first: T, second: U) -> R
411    );
412
413    // do NOT override RcBiTransformer::into_arc() because RcBiTransformer is not Send + Sync
414    // and calling RcBiTransformer::into_arc() will cause a compile error
415
416    // do NOT override RcBiTransformer::to_arc() because RcBiTransformer is not Send + Sync
417    // and calling RcBiTransformer::to_arc() will cause a compile error
418}
419
420// ============================================================================
421// ArcBiTransformer - Arc<dyn Fn(T, U) -> R + Send + Sync>
422// ============================================================================
423
424/// ArcBiTransformer - thread-safe bi-transformer wrapper
425///
426/// A thread-safe, clonable bi-transformer wrapper suitable for multi-threaded
427/// scenarios. Can be called multiple times and shared across threads.
428///
429/// # Features
430///
431/// - **Based on**: `Arc<dyn Fn(T, U) -> R + Send + Sync>`
432/// - **Ownership**: Shared ownership via reference counting
433/// - **Reusability**: Can be called multiple times (each call consumes its
434///   inputs)
435/// - **Thread Safety**: Thread-safe (`Send + Sync` required)
436/// - **Clonable**: Cheap cloning via `Arc::clone`
437///
438/// # Author
439///
440/// Haixing Hu
441pub struct ArcBiTransformer<T, U, R> {
442    function: Arc<dyn Fn(T, U) -> R + Send + Sync>,
443    name: Option<String>,
444}
445
446impl<T, U, R> ArcBiTransformer<T, U, R>
447where
448    T: 'static,
449    U: 'static,
450    R: 'static,
451{
452    impl_transformer_common_methods!(
453        ArcBiTransformer<T, U, R>,
454        (Fn(T, U) -> R + Send + Sync + 'static),
455        |f| Arc::new(f)
456    );
457
458    impl_shared_transformer_methods!(
459        ArcBiTransformer<T, U, R>,
460        ArcConditionalBiTransformer,
461        into_arc,
462        Transformer,
463        Send + Sync + 'static
464    );
465}
466
467// Implement constant method for ArcBiTransformer
468impl_transformer_constant_method!(thread_safe ArcBiTransformer<T, U, R>);
469
470// Implement Debug and Display for ArcBiTransformer
471impl_transformer_debug_display!(ArcBiTransformer<T, U, R>);
472
473// Implement Clone for ArcBiTransformer
474impl_transformer_clone!(ArcBiTransformer<T, U, R>);
475
476// Implement BiTransformer trait for ArcBiTransformer
477impl<T, U, R> BiTransformer<T, U, R> for ArcBiTransformer<T, U, R> {
478    fn apply(&self, first: T, second: U) -> R {
479        (self.function)(first, second)
480    }
481
482    // Use macro to implement conversion methods
483    impl_arc_conversions!(
484        ArcBiTransformer<T, U, R>,
485        BoxBiTransformer,
486        RcBiTransformer,
487        BoxBiTransformerOnce,
488        Fn(t: T, u: U) -> R
489    );
490}
491
492// ============================================================================
493// Blanket implementation for standard Fn trait
494// ============================================================================
495
496/// Implement BiTransformer<T, U, R> for any type that implements Fn(T, U) -> R
497///
498/// This allows closures and function pointers to be used directly with our
499/// BiTransformer trait without wrapping.
500///
501/// # Examples
502///
503/// ```rust
504/// use prism3_function::BiTransformer;
505///
506/// fn add(x: i32, y: i32) -> i32 { x + y }
507///
508/// assert_eq!(add.apply(20, 22), 42);
509///
510/// let multiply = |x: i32, y: i32| x * y;
511/// assert_eq!(multiply.apply(6, 7), 42);
512/// ```
513///
514/// # Author
515///
516/// Haixing Hu
517impl<F, T, U, R> BiTransformer<T, U, R> for F
518where
519    F: Fn(T, U) -> R,
520    T: 'static,
521    U: 'static,
522    R: 'static,
523{
524    fn apply(&self, first: T, second: U) -> R {
525        self(first, second)
526    }
527
528    fn into_box(self) -> BoxBiTransformer<T, U, R>
529    where
530        Self: Sized + 'static,
531    {
532        BoxBiTransformer::new(self)
533    }
534
535    fn into_rc(self) -> RcBiTransformer<T, U, R>
536    where
537        Self: Sized + 'static,
538    {
539        RcBiTransformer::new(self)
540    }
541
542    fn into_arc(self) -> ArcBiTransformer<T, U, R>
543    where
544        Self: Sized + Send + Sync + 'static,
545        T: Send + Sync + 'static,
546        U: Send + Sync + 'static,
547        R: Send + Sync + 'static,
548    {
549        ArcBiTransformer::new(self)
550    }
551
552    fn into_fn(self) -> impl Fn(T, U) -> R
553    where
554        Self: Sized + 'static,
555    {
556        move |t: T, u: U| self(t, u)
557    }
558
559    // use the default implementation of to_box(), to_rc(), to_arc() from
560    // BiTransformer trait
561
562    fn to_fn(&self) -> impl Fn(T, U) -> R
563    where
564        Self: Sized + Clone + 'static,
565        T: 'static,
566        U: 'static,
567        R: 'static,
568    {
569        self.clone()
570    }
571}
572
573// ============================================================================
574// FnBiTransformerOps - Extension trait for Fn(T, U) -> R bi-transformers
575// ============================================================================
576
577/// Extension trait for closures implementing `Fn(T, U) -> R`
578///
579/// Provides composition methods (`and_then`, `when`) for bi-transformer
580/// closures and function pointers without requiring explicit wrapping in
581/// `BoxBiTransformer`.
582///
583/// This trait is automatically implemented for all closures and function
584/// pointers that implement `Fn(T, U) -> R`.
585///
586/// # Design Rationale
587///
588/// While closures automatically implement `BiTransformer<T, U, R>` through
589/// blanket implementation, they don't have access to instance methods like
590/// `and_then` and `when`. This extension trait provides those methods,
591/// returning `BoxBiTransformer` for maximum flexibility.
592///
593/// # Examples
594///
595/// ## Chain composition with and_then
596///
597/// ```rust
598/// use prism3_function::{BiTransformer, FnBiTransformerOps};
599///
600/// let add = |x: i32, y: i32| x + y;
601/// let double = |x: i32| x * 2;
602///
603/// let composed = add.and_then(double);
604/// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
605/// ```
606///
607/// ## Conditional execution with when
608///
609/// ```rust
610/// use prism3_function::{BiTransformer, FnBiTransformerOps};
611///
612/// let add = |x: i32, y: i32| x + y;
613/// let multiply = |x: i32, y: i32| x * y;
614///
615/// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(multiply);
616///
617/// assert_eq!(conditional.apply(5, 3), 8);   // add
618/// assert_eq!(conditional.apply(-5, 3), -15); // multiply
619/// ```
620///
621/// # Author
622///
623/// Haixing Hu
624pub trait FnBiTransformerOps<T, U, R>: Fn(T, U) -> R + Sized + 'static {
625    /// Chain composition - applies self first, then after
626    ///
627    /// Creates a new bi-transformer that applies this bi-transformer first,
628    /// then applies the after transformer to the result. Consumes self and
629    /// returns a `BoxBiTransformer`.
630    ///
631    /// # Type Parameters
632    ///
633    /// * `S` - The output type of the after transformer
634    /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
635    ///
636    /// # Parameters
637    ///
638    /// * `after` - The transformer to apply after self. **Note: This parameter
639    ///   is passed by value and will transfer ownership.** If you need to
640    ///   preserve the original transformer, clone it first (if it implements
641    ///   `Clone`). Can be:
642    ///   - A closure: `|x: R| -> S`
643    ///   - A function pointer: `fn(R) -> S`
644    ///   - A `BoxTransformer<R, S>`
645    ///   - An `RcTransformer<R, S>`
646    ///   - An `ArcTransformer<R, S>`
647    ///   - Any type implementing `Transformer<R, S>`
648    ///
649    /// # Returns
650    ///
651    /// A new `BoxBiTransformer<T, U, S>` representing the composition
652    ///
653    /// # Examples
654    ///
655    /// ## Direct value passing (ownership transfer)
656    ///
657    /// ```rust
658    /// use prism3_function::{BiTransformer, FnBiTransformerOps,
659    ///     BoxTransformer};
660    ///
661    /// let add = |x: i32, y: i32| x + y;
662    /// let to_string = BoxTransformer::new(|x: i32| x.to_string());
663    ///
664    /// // to_string is moved here
665    /// let composed = add.and_then(to_string);
666    /// assert_eq!(composed.apply(20, 22), "42");
667    /// // to_string.apply(10); // Would not compile - moved
668    /// ```
669    ///
670    /// ## Preserving original with clone
671    ///
672    /// ```rust
673    /// use prism3_function::{BiTransformer, FnBiTransformerOps,
674    ///     BoxTransformer};
675    ///
676    /// let add = |x: i32, y: i32| x + y;
677    /// let to_string = BoxTransformer::new(|x: i32| x.to_string());
678    ///
679    /// // Clone to preserve original
680    /// let composed = add.and_then(to_string.clone());
681    /// assert_eq!(composed.apply(20, 22), "42");
682    ///
683    /// // Original still usable
684    /// assert_eq!(to_string.apply(10), "10");
685    /// ```
686    fn and_then<S, F>(self, after: F) -> BoxBiTransformer<T, U, S>
687    where
688        S: 'static,
689        F: crate::transformers::transformer::Transformer<R, S> + 'static,
690        T: 'static,
691        U: 'static,
692        R: 'static,
693    {
694        BoxBiTransformer::new(move |t: T, u: U| after.apply(self(t, u)))
695    }
696
697    /// Creates a conditional bi-transformer
698    ///
699    /// Returns a bi-transformer that only executes when a bi-predicate is
700    /// satisfied. You must call `or_else()` to provide an alternative
701    /// bi-transformer for when the condition is not satisfied.
702    ///
703    /// # Parameters
704    ///
705    /// * `predicate` - The condition to check. **Note: This parameter is passed
706    ///   by value and will transfer ownership.** If you need to preserve the
707    ///   original bi-predicate, clone it first (if it implements `Clone`).
708    ///   Can be:
709    ///   - A closure: `|x: &T, y: &U| -> bool`
710    ///   - A function pointer: `fn(&T, &U) -> bool`
711    ///   - A `BoxBiPredicate<T, U>`
712    ///   - An `RcBiPredicate<T, U>`
713    ///   - An `ArcBiPredicate<T, U>`
714    ///   - Any type implementing `BiPredicate<T, U>`
715    ///
716    /// # Returns
717    ///
718    /// Returns `BoxConditionalBiTransformer<T, U, R>`
719    ///
720    /// # Examples
721    ///
722    /// ## Basic usage with or_else
723    ///
724    /// ```rust
725    /// use prism3_function::{BiTransformer, FnBiTransformerOps};
726    ///
727    /// let add = |x: i32, y: i32| x + y;
728    /// let conditional = add.when(|x: &i32, y: &i32| *x > 0)
729    ///     .or_else(|x: i32, y: i32| x * y);
730    ///
731    /// assert_eq!(conditional.apply(5, 3), 8);
732    /// assert_eq!(conditional.apply(-5, 3), -15);
733    /// ```
734    ///
735    /// ## Preserving bi-predicate with clone
736    ///
737    /// ```rust
738    /// use prism3_function::{BiTransformer, FnBiTransformerOps,
739    ///     RcBiPredicate};
740    ///
741    /// let add = |x: i32, y: i32| x + y;
742    /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
743    ///     *x > 0 && *y > 0);
744    ///
745    /// // Clone to preserve original bi-predicate
746    /// let conditional = add.when(both_positive.clone())
747    ///     .or_else(|x: i32, y: i32| x * y);
748    ///
749    /// assert_eq!(conditional.apply(5, 3), 8);
750    ///
751    /// // Original bi-predicate still usable
752    /// assert!(both_positive.test(&5, &3));
753    /// ```
754    fn when<P>(self, predicate: P) -> BoxConditionalBiTransformer<T, U, R>
755    where
756        P: BiPredicate<T, U> + 'static,
757        T: 'static,
758        U: 'static,
759        R: 'static,
760    {
761        BoxBiTransformer::new(self).when(predicate)
762    }
763}
764
765/// Blanket implementation of FnBiTransformerOps for all closures
766///
767/// Automatically implements `FnBiTransformerOps<T, U, R>` for any type that
768/// implements `Fn(T, U) -> R`.
769///
770/// # Author
771///
772/// Haixing Hu
773impl<T, U, R, F> FnBiTransformerOps<T, U, R> for F where F: Fn(T, U) -> R + 'static {}
774
775// ============================================================================
776// BinaryOperator Trait - Marker trait for BiTransformer<T, T, T>
777// ============================================================================
778
779/// BinaryOperator trait - marker trait for binary operators
780///
781/// A binary operator takes two values of type `T` and produces a value of the
782/// same type `T`. This trait extends `BiTransformer<T, T, T>` to provide
783/// semantic clarity for same-type binary operations. Equivalent to Java's
784/// `BinaryOperator<T>` which extends `BiFunction<T, T, T>`.
785///
786/// # Automatic Implementation
787///
788/// This trait is automatically implemented for all types that implement
789/// `BiTransformer<T, T, T>`, so you don't need to implement it manually.
790///
791/// # Type Parameters
792///
793/// * `T` - The type of both input values and the output value
794///
795/// # Examples
796///
797/// ## Using in generic constraints
798///
799/// ```rust
800/// use prism3_function::{BinaryOperator, BiTransformer};
801///
802/// fn reduce<T, O>(values: Vec<T>, initial: T, op: O) -> T
803/// where
804///     O: BinaryOperator<T>,
805///     T: Clone,
806/// {
807///     values.into_iter().fold(initial, |acc, val| op.apply(acc, val))
808/// }
809///
810/// let sum = |a: i32, b: i32| a + b;
811/// assert_eq!(reduce(vec![1, 2, 3, 4], 0, sum), 10);
812/// ```
813///
814/// ## With concrete types
815///
816/// ```rust
817/// use prism3_function::{BoxBinaryOperator, BinaryOperator, BiTransformer};
818///
819/// fn create_adder() -> BoxBinaryOperator<i32> {
820///     BoxBinaryOperator::new(|x, y| x + y)
821/// }
822///
823/// let op = create_adder();
824/// assert_eq!(op.apply(20, 22), 42);
825/// ```
826///
827/// # Author
828///
829/// Haixing Hu
830pub trait BinaryOperator<T>: BiTransformer<T, T, T> {}
831
832/// Blanket implementation of BinaryOperator for all BiTransformer<T, T, T>
833///
834/// This automatically implements `BinaryOperator<T>` for any type that
835/// implements `BiTransformer<T, T, T>`.
836///
837/// # Author
838///
839/// Haixing Hu
840impl<F, T> BinaryOperator<T> for F
841where
842    F: BiTransformer<T, T, T>,
843    T: 'static,
844{
845    // empty
846}
847
848// ============================================================================
849// Type Aliases for BinaryOperator (BiTransformer<T, T, T>)
850// ============================================================================
851
852/// Type alias for `BoxBiTransformer<T, T, T>`
853///
854/// Represents a binary operator that takes two values of type `T` and produces
855/// a value of the same type `T`, with single ownership semantics. Equivalent to
856/// Java's `BinaryOperator<T>`.
857///
858/// # Examples
859///
860/// ```rust
861/// use prism3_function::{BoxBinaryOperator, BiTransformer};
862///
863/// let add: BoxBinaryOperator<i32> = BoxBinaryOperator::new(|x, y| x + y);
864/// assert_eq!(add.apply(20, 22), 42);
865/// ```
866///
867/// # Author
868///
869/// Haixing Hu
870pub type BoxBinaryOperator<T> = BoxBiTransformer<T, T, T>;
871
872/// Type alias for `ArcBiTransformer<T, T, T>`
873///
874/// Represents a thread-safe binary operator that takes two values of type `T`
875/// and produces a value of the same type `T`. Equivalent to Java's
876/// `BinaryOperator<T>` with shared, thread-safe ownership.
877///
878/// # Examples
879///
880/// ```rust
881/// use prism3_function::{ArcBinaryOperator, BiTransformer};
882///
883/// let multiply: ArcBinaryOperator<i32> = ArcBinaryOperator::new(|x, y| x * y);
884/// let multiply_clone = multiply.clone();
885/// assert_eq!(multiply.apply(6, 7), 42);
886/// assert_eq!(multiply_clone.apply(6, 7), 42);
887/// ```
888///
889/// # Author
890///
891/// Haixing Hu
892pub type ArcBinaryOperator<T> = ArcBiTransformer<T, T, T>;
893
894/// Type alias for `RcBiTransformer<T, T, T>`
895///
896/// Represents a single-threaded binary operator that takes two values of type
897/// `T` and produces a value of the same type `T`. Equivalent to Java's
898/// `BinaryOperator<T>` with shared, single-threaded ownership.
899///
900/// # Examples
901///
902/// ```rust
903/// use prism3_function::{RcBinaryOperator, BiTransformer};
904///
905/// let max: RcBinaryOperator<i32> = RcBinaryOperator::new(|x, y| if x > y { x } else { y });
906/// let max_clone = max.clone();
907/// assert_eq!(max.apply(30, 42), 42);
908/// assert_eq!(max_clone.apply(30, 42), 42);
909/// ```
910///
911/// # Author
912///
913/// Haixing Hu
914pub type RcBinaryOperator<T> = RcBiTransformer<T, T, T>;
915
916// ============================================================================
917// BoxConditionalBiTransformer - Box-based Conditional BiTransformer
918// ============================================================================
919
920/// BoxConditionalBiTransformer struct
921///
922/// A conditional bi-transformer that only executes when a bi-predicate is
923/// satisfied. Uses `BoxBiTransformer` and `BoxBiPredicate` for single
924/// ownership semantics.
925///
926/// This type is typically created by calling `BoxBiTransformer::when()` and is
927/// designed to work with the `or_else()` method to create if-then-else logic.
928///
929/// # Features
930///
931/// - **Single Ownership**: Not cloneable, consumes `self` on use
932/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
933/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
934/// - **Implements BiTransformer**: Can be used anywhere a `BiTransformer` is expected
935///
936/// # Examples
937///
938/// ## With or_else Branch
939///
940/// ```rust
941/// use prism3_function::{BiTransformer, BoxBiTransformer};
942///
943/// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
944/// let multiply = BoxBiTransformer::new(|x: i32, y: i32| x * y);
945/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
946///
947/// assert_eq!(conditional.apply(5, 3), 8);  // when branch executed
948/// assert_eq!(conditional.apply(-5, 3), -15); // or_else branch executed
949/// ```
950///
951/// # Author
952///
953/// Haixing Hu
954pub struct BoxConditionalBiTransformer<T, U, R> {
955    transformer: BoxBiTransformer<T, U, R>,
956    predicate: BoxBiPredicate<T, U>,
957}
958
959// Implement BoxConditionalTransformer
960impl_box_conditional_transformer!(
961    BoxConditionalBiTransformer<T, U, R>,
962    BoxBiTransformer,
963    BiTransformer
964);
965
966// Use macro to generate Debug and Display implementations
967impl_conditional_transformer_debug_display!(BoxConditionalBiTransformer<T, U, R>);
968
969// ============================================================================
970// RcConditionalBiTransformer - Rc-based Conditional BiTransformer
971// ============================================================================
972
973/// RcConditionalBiTransformer struct
974///
975/// A single-threaded conditional bi-transformer that only executes when a
976/// bi-predicate is satisfied. Uses `RcBiTransformer` and `RcBiPredicate` for
977/// shared ownership within a single thread.
978///
979/// This type is typically created by calling `RcBiTransformer::when()` and is
980/// designed to work with the `or_else()` method to create if-then-else logic.
981///
982/// # Features
983///
984/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
985/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
986/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
987/// - **No Lock Overhead**: More efficient than `ArcConditionalBiTransformer`
988///
989/// # Examples
990///
991/// ```rust
992/// use prism3_function::{BiTransformer, RcBiTransformer};
993///
994/// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
995/// let multiply = RcBiTransformer::new(|x: i32, y: i32| x * y);
996/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
997///
998/// let conditional_clone = conditional.clone();
999///
1000/// assert_eq!(conditional.apply(5, 3), 8);
1001/// assert_eq!(conditional_clone.apply(-5, 3), -15);
1002/// ```
1003///
1004/// # Author
1005///
1006/// Haixing Hu
1007pub struct RcConditionalBiTransformer<T, U, R> {
1008    transformer: RcBiTransformer<T, U, R>,
1009    predicate: RcBiPredicate<T, U>,
1010}
1011
1012// Implement RcConditionalBiTransformer
1013impl_shared_conditional_transformer!(
1014    RcConditionalBiTransformer<T, U, R>,
1015    RcBiTransformer,
1016    BiTransformer,
1017    into_rc,
1018    'static
1019);
1020
1021// Use macro to generate Debug and Display implementations
1022impl_conditional_transformer_debug_display!(RcConditionalBiTransformer<T, U, R>);
1023
1024// Implement Clone for RcConditionalBiTransformer
1025impl_conditional_transformer_clone!(RcConditionalBiTransformer<T, U, R>);
1026
1027// ============================================================================
1028// ArcConditionalBiTransformer - Arc-based Conditional BiTransformer
1029// ============================================================================
1030
1031/// ArcConditionalBiTransformer struct
1032///
1033/// A thread-safe conditional bi-transformer that only executes when a
1034/// bi-predicate is satisfied. Uses `ArcBiTransformer` and `ArcBiPredicate` for
1035/// shared ownership across threads.
1036///
1037/// This type is typically created by calling `ArcBiTransformer::when()` and is
1038/// designed to work with the `or_else()` method to create if-then-else logic.
1039///
1040/// # Features
1041///
1042/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
1043/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
1044/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
1045/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
1046///
1047/// # Examples
1048///
1049/// ```rust
1050/// use prism3_function::{BiTransformer, ArcBiTransformer};
1051///
1052/// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
1053/// let multiply = ArcBiTransformer::new(|x: i32, y: i32| x * y);
1054/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
1055///
1056/// let conditional_clone = conditional.clone();
1057///
1058/// assert_eq!(conditional.apply(5, 3), 8);
1059/// assert_eq!(conditional_clone.apply(-5, 3), -15);
1060/// ```
1061///
1062/// # Author
1063///
1064/// Haixing Hu
1065pub struct ArcConditionalBiTransformer<T, U, R> {
1066    transformer: ArcBiTransformer<T, U, R>,
1067    predicate: ArcBiPredicate<T, U>,
1068}
1069
1070// Implement ArcConditionalBiTransformer
1071impl_shared_conditional_transformer!(
1072    ArcConditionalBiTransformer<T, U, R>,
1073    ArcBiTransformer,
1074    BiTransformer,
1075    into_arc,
1076    Send + Sync + 'static
1077);
1078
1079// Implement Debug and Display for ArcConditionalBiTransformer
1080impl_conditional_transformer_debug_display!(ArcConditionalBiTransformer<T, U, R>);
1081
1082// Implement Clone for ArcConditionalBiTransformer
1083impl_conditional_transformer_clone!(ArcConditionalBiTransformer<T, U, R>);