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>);