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