Skip to main content

qubit_function/transformers/
bi_transformer_once.rs

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