Skip to main content

qubit_function/transformers/
bi_transformer.rs

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