prism3_function/bi_transformer.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025.
4 * 3-Prism Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # BiTransformer Types
10//!
11//! Provides Rust implementations of bi-transformer traits for type conversion
12//! and value transformation with two inputs. BiTransformers consume two input
13//! values (taking ownership) and produce an output value.
14//!
15//! This module provides the `BiTransformer<T, U, R>` trait and three
16//! implementations:
17//!
18//! - [`BoxBiTransformer`]: Single ownership, not cloneable
19//! - [`ArcBiTransformer`]: Thread-safe shared ownership, cloneable
20//! - [`RcBiTransformer`]: Single-threaded shared ownership, cloneable
21//!
22//! # Author
23//!
24//! Hu Haixing
25
26use std::rc::Rc;
27use std::sync::Arc;
28
29use crate::bi_predicate::{ArcBiPredicate, BiPredicate, BoxBiPredicate, RcBiPredicate};
30
31// ============================================================================
32// Core Trait
33// ============================================================================
34
35/// BiTransformer trait - transforms two values to produce a result
36///
37/// Defines the behavior of a bi-transformation: converting two values of types
38/// `T` and `U` to a value of type `R` by consuming the inputs. This is
39/// analogous to `Fn(T, U) -> R` in Rust's standard library.
40///
41/// # Type Parameters
42///
43/// * `T` - The type of the first input value (consumed)
44/// * `U` - The type of the second input value (consumed)
45/// * `R` - The type of the output value
46///
47/// # Author
48///
49/// Hu Haixing
50pub trait BiTransformer<T, U, R> {
51 /// Transforms two input values to produce an output value
52 ///
53 /// # Parameters
54 ///
55 /// * `first` - The first input value to transform (consumed)
56 /// * `second` - The second input value to transform (consumed)
57 ///
58 /// # Returns
59 ///
60 /// The transformed output value
61 fn apply(&self, first: T, second: U) -> R;
62
63 /// Converts to BoxBiTransformer
64 ///
65 /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
66 /// after calling this method.
67 ///
68 /// # Default Implementation
69 ///
70 /// The default implementation wraps `self` in a `Box` and creates a
71 /// `BoxBiTransformer`. Types can override this method to provide more
72 /// efficient conversions.
73 ///
74 /// # Returns
75 ///
76 /// Returns `BoxBiTransformer<T, U, R>`
77 fn into_box(self) -> BoxBiTransformer<T, U, R>
78 where
79 Self: Sized + 'static,
80 T: 'static,
81 U: 'static,
82 R: 'static,
83 {
84 BoxBiTransformer::new(move |x, y| self.apply(x, y))
85 }
86
87 /// Converts to RcBiTransformer
88 ///
89 /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
90 /// after calling this method.
91 ///
92 /// # Default Implementation
93 ///
94 /// The default implementation wraps `self` in an `Rc` and creates an
95 /// `RcBiTransformer`. Types can override this method to provide more
96 /// efficient conversions.
97 ///
98 /// # Returns
99 ///
100 /// Returns `RcBiTransformer<T, U, R>`
101 fn into_rc(self) -> RcBiTransformer<T, U, R>
102 where
103 Self: Sized + 'static,
104 T: 'static,
105 U: 'static,
106 R: 'static,
107 {
108 RcBiTransformer::new(move |x, y| self.apply(x, y))
109 }
110
111 /// Converts to ArcBiTransformer
112 ///
113 /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
114 /// after calling this method.
115 ///
116 /// # Default Implementation
117 ///
118 /// The default implementation wraps `self` in an `Arc` and creates an
119 /// `ArcBiTransformer`. Types can override this method to provide more
120 /// efficient conversions.
121 ///
122 /// # Returns
123 ///
124 /// Returns `ArcBiTransformer<T, U, R>`
125 fn into_arc(self) -> ArcBiTransformer<T, U, R>
126 where
127 Self: Sized + Send + Sync + 'static,
128 T: Send + Sync + 'static,
129 U: Send + Sync + 'static,
130 R: Send + Sync + 'static,
131 {
132 ArcBiTransformer::new(move |x, y| self.apply(x, y))
133 }
134
135 /// Converts bi-transformer to a closure
136 ///
137 /// **⚠️ Consumes `self`**: The original bi-transformer becomes unavailable
138 /// after calling this method.
139 ///
140 /// # Default Implementation
141 ///
142 /// The default implementation creates a closure that captures `self`
143 /// and calls its `apply` method. Types can override this method
144 /// to provide more efficient conversions.
145 ///
146 /// # Returns
147 ///
148 /// Returns a closure that implements `Fn(T, U) -> R`
149 fn into_fn(self) -> impl Fn(T, U) -> R
150 where
151 Self: Sized + 'static,
152 T: 'static,
153 U: 'static,
154 R: 'static,
155 {
156 move |t, u| self.apply(t, u)
157 }
158
159 /// Non-consuming conversion to `BoxBiTransformer` using `&self`.
160 ///
161 /// Default implementation clones `self` and delegates to `into_box`.
162 fn to_box(&self) -> BoxBiTransformer<T, U, R>
163 where
164 Self: Sized + Clone + 'static,
165 T: 'static,
166 U: 'static,
167 R: 'static,
168 {
169 self.clone().into_box()
170 }
171
172 /// Non-consuming conversion to `RcBiTransformer` using `&self`.
173 ///
174 /// Default implementation clones `self` and delegates to `into_rc`.
175 fn to_rc(&self) -> RcBiTransformer<T, U, R>
176 where
177 Self: Sized + Clone + 'static,
178 T: 'static,
179 U: 'static,
180 R: 'static,
181 {
182 self.clone().into_rc()
183 }
184
185 /// Non-consuming conversion to `ArcBiTransformer` using `&self`.
186 ///
187 /// Default implementation clones `self` and delegates to `into_arc`.
188 fn to_arc(&self) -> ArcBiTransformer<T, U, R>
189 where
190 Self: Sized + Clone + Send + Sync + 'static,
191 T: Send + Sync + 'static,
192 U: Send + Sync + 'static,
193 R: Send + Sync + 'static,
194 {
195 self.clone().into_arc()
196 }
197
198 /// Non-consuming conversion to a boxed function using `&self`.
199 ///
200 /// Returns a `Box<dyn Fn(T, U) -> R>` that clones `self` and calls
201 /// `apply` inside the boxed closure.
202 fn to_fn(&self) -> impl Fn(T, U) -> R
203 where
204 Self: Sized + Clone + 'static,
205 T: 'static,
206 U: 'static,
207 R: 'static,
208 {
209 self.clone().into_fn()
210 }
211}
212
213// ============================================================================
214// BoxBiTransformer - Box<dyn Fn(T, U) -> R>
215// ============================================================================
216
217/// BoxBiTransformer - bi-transformer wrapper based on `Box<dyn Fn>`
218///
219/// A bi-transformer wrapper that provides single ownership with reusable
220/// transformation. The bi-transformer consumes both inputs and can be called
221/// multiple times.
222///
223/// # Features
224///
225/// - **Based on**: `Box<dyn Fn(T, U) -> R>`
226/// - **Ownership**: Single ownership, cannot be cloned
227/// - **Reusability**: Can be called multiple times (each call consumes its
228/// inputs)
229/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
230///
231/// # Author
232///
233/// Hu Haixing
234pub struct BoxBiTransformer<T, U, R> {
235 function: Box<dyn Fn(T, U) -> R>,
236}
237
238impl<T, U, R> BoxBiTransformer<T, U, R>
239where
240 T: 'static,
241 U: 'static,
242 R: 'static,
243{
244 /// Creates a new BoxBiTransformer
245 ///
246 /// # Parameters
247 ///
248 /// * `f` - The closure or function to wrap
249 ///
250 /// # Examples
251 ///
252 /// ```rust
253 /// use prism3_function::{BoxBiTransformer, BiTransformer};
254 ///
255 /// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
256 /// assert_eq!(add.apply(20, 22), 42);
257 /// ```
258 pub fn new<F>(f: F) -> Self
259 where
260 F: Fn(T, U) -> R + 'static,
261 {
262 BoxBiTransformer {
263 function: Box::new(f),
264 }
265 }
266
267 /// Chain composition - applies self first, then after
268 ///
269 /// Creates a new bi-transformer that applies this bi-transformer first,
270 /// then applies the after transformer to the result. Consumes self.
271 ///
272 /// # Type Parameters
273 ///
274 /// * `S` - The output type of the after transformer
275 /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
276 ///
277 /// # Parameters
278 ///
279 /// * `after` - The transformer to apply after self. **Note: This parameter
280 /// is passed by value and will transfer ownership.** If you need to
281 /// preserve the original transformer, clone it first (if it implements
282 /// `Clone`). Can be:
283 /// - A closure: `|x: R| -> S`
284 /// - A function pointer: `fn(R) -> S`
285 /// - A `BoxTransformer<R, S>`
286 /// - An `RcTransformer<R, S>`
287 /// - An `ArcTransformer<R, S>`
288 /// - Any type implementing `Transformer<R, S>`
289 ///
290 /// # Returns
291 ///
292 /// A new `BoxBiTransformer<T, U, S>` representing the composition
293 ///
294 /// # Examples
295 ///
296 /// ## Direct value passing (ownership transfer)
297 ///
298 /// ```rust
299 /// use prism3_function::{BiTransformer, BoxBiTransformer, BoxTransformer};
300 ///
301 /// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
302 /// let double = BoxTransformer::new(|x: i32| x * 2);
303 ///
304 /// // double is moved here
305 /// let composed = add.and_then(double);
306 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
307 /// // double.apply(10); // Would not compile - moved
308 /// ```
309 ///
310 /// ## Preserving original with clone
311 ///
312 /// ```rust
313 /// use prism3_function::{BiTransformer, BoxBiTransformer, BoxTransformer};
314 ///
315 /// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
316 /// let double = BoxTransformer::new(|x: i32| x * 2);
317 ///
318 /// // Clone to preserve original
319 /// let composed = add.and_then(double.clone());
320 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
321 ///
322 /// // Original still usable
323 /// assert_eq!(double.apply(10), 20);
324 /// ```
325 pub fn and_then<S, F>(self, after: F) -> BoxBiTransformer<T, U, S>
326 where
327 S: 'static,
328 F: crate::transformer::Transformer<R, S> + 'static,
329 {
330 let self_fn = self.function;
331 BoxBiTransformer::new(move |t: T, u: U| after.apply(self_fn(t, u)))
332 }
333
334 /// Creates a conditional bi-transformer
335 ///
336 /// Returns a bi-transformer that only executes when a bi-predicate is
337 /// satisfied. You must call `or_else()` to provide an alternative
338 /// bi-transformer for when the condition is not satisfied.
339 ///
340 /// # Parameters
341 ///
342 /// * `predicate` - The condition to check. **Note: This parameter is passed
343 /// by value and will transfer ownership.** If you need to preserve the
344 /// original bi-predicate, clone it first (if it implements `Clone`).
345 /// Can be:
346 /// - A closure: `|x: &T, y: &U| -> bool`
347 /// - A function pointer: `fn(&T, &U) -> bool`
348 /// - A `BoxBiPredicate<T, U>`
349 /// - An `RcBiPredicate<T, U>`
350 /// - An `ArcBiPredicate<T, U>`
351 /// - Any type implementing `BiPredicate<T, U>`
352 ///
353 /// # Returns
354 ///
355 /// Returns `BoxConditionalBiTransformer<T, U, R>`
356 ///
357 /// # Examples
358 ///
359 /// ## Basic usage with or_else
360 ///
361 /// ```rust
362 /// use prism3_function::{BiTransformer, BoxBiTransformer};
363 ///
364 /// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
365 /// let multiply = BoxBiTransformer::new(|x: i32, y: i32| x * y);
366 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
367 /// .or_else(multiply);
368 ///
369 /// assert_eq!(conditional.apply(5, 3), 8); // add
370 /// assert_eq!(conditional.apply(-5, 3), -15); // multiply
371 /// ```
372 ///
373 /// ## Preserving bi-predicate with clone
374 ///
375 /// ```rust
376 /// use prism3_function::{BiTransformer, BoxBiTransformer, RcBiPredicate};
377 ///
378 /// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
379 /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
380 /// *x > 0 && *y > 0);
381 ///
382 /// // Clone to preserve original bi-predicate
383 /// let conditional = add.when(both_positive.clone())
384 /// .or_else(BoxBiTransformer::new(|x, y| x * y));
385 ///
386 /// assert_eq!(conditional.apply(5, 3), 8);
387 ///
388 /// // Original bi-predicate still usable
389 /// assert!(both_positive.test(&5, &3));
390 /// ```
391 pub fn when<P>(self, predicate: P) -> BoxConditionalBiTransformer<T, U, R>
392 where
393 P: BiPredicate<T, U> + 'static,
394 {
395 BoxConditionalBiTransformer {
396 transformer: self,
397 predicate: predicate.into_box(),
398 }
399 }
400}
401
402impl<T, U, R> BoxBiTransformer<T, U, R>
403where
404 T: 'static,
405 U: 'static,
406 R: Clone + 'static,
407{
408 /// Creates a constant bi-transformer
409 ///
410 /// # Examples
411 ///
412 /// ```rust
413 /// use prism3_function::{BoxBiTransformer, BiTransformer};
414 ///
415 /// let constant = BoxBiTransformer::constant("hello");
416 /// assert_eq!(constant.apply(123, 456), "hello");
417 /// ```
418 pub fn constant(value: R) -> BoxBiTransformer<T, U, R> {
419 BoxBiTransformer::new(move |_, _| value.clone())
420 }
421}
422
423impl<T, U, R> BiTransformer<T, U, R> for BoxBiTransformer<T, U, R> {
424 fn apply(&self, first: T, second: U) -> R {
425 (self.function)(first, second)
426 }
427
428 fn into_box(self) -> BoxBiTransformer<T, U, R>
429 where
430 T: 'static,
431 U: 'static,
432 R: 'static,
433 {
434 // Zero-cost: directly return itself
435 self
436 }
437
438 fn into_rc(self) -> RcBiTransformer<T, U, R>
439 where
440 T: 'static,
441 U: 'static,
442 R: 'static,
443 {
444 RcBiTransformer::new(move |t, u| (self.function)(t, u))
445 }
446
447 // do NOT override BoxBiTransformer::into_arc() because BoxBiTransformer is not Send + Sync
448 // and calling BoxBiTransformer::into_arc() will cause a compile error
449
450 fn into_fn(self) -> impl Fn(T, U) -> R
451 where
452 T: 'static,
453 U: 'static,
454 R: 'static,
455 {
456 move |t: T, u: U| (self.function)(t, u)
457 }
458
459 // do NOT override BoxBiTransformer::to_xxx() because BoxBiTransformer is not Clone
460 // and calling BoxBiTransformer::to_xxx() will cause a compile error
461}
462
463// ============================================================================
464// BoxBiTransformer BiTransformerOnce Implementation
465// ============================================================================
466
467impl<T, U, R> crate::bi_transformer_once::BiTransformerOnce<T, U, R> for BoxBiTransformer<T, U, R>
468where
469 T: 'static,
470 U: 'static,
471 R: 'static,
472{
473 /// Transforms two input values, consuming self and both inputs
474 ///
475 /// # Parameters
476 ///
477 /// * `first` - The first input value (consumed)
478 /// * `second` - The second input value (consumed)
479 ///
480 /// # Returns
481 ///
482 /// The transformed output value
483 fn apply_once(self, first: T, second: U) -> R {
484 (self.function)(first, second)
485 }
486
487 fn into_box_once(self) -> crate::bi_transformer_once::BoxBiTransformerOnce<T, U, R>
488 where
489 T: 'static,
490 U: 'static,
491 R: 'static,
492 {
493 // Zero-cost: directly return itself
494 crate::bi_transformer_once::BoxBiTransformerOnce::new(move |t: T, u: U| {
495 (self.function)(t, u)
496 })
497 }
498
499 fn into_fn_once(self) -> impl FnOnce(T, U) -> R
500 where
501 T: 'static,
502 U: 'static,
503 R: 'static,
504 {
505 move |t: T, u: U| (self.function)(t, u)
506 }
507
508 // do NOT override BoxBiTransformer::to_xxxx() because BoxBiTransformer is not Clone
509 // and calling BoxBiTransformer::to_xxxx() will cause a compile error
510}
511
512// ============================================================================
513// BoxConditionalBiTransformer - Box-based Conditional BiTransformer
514// ============================================================================
515
516/// BoxConditionalBiTransformer struct
517///
518/// A conditional bi-transformer that only executes when a bi-predicate is
519/// satisfied. Uses `BoxBiTransformer` and `BoxBiPredicate` for single
520/// ownership semantics.
521///
522/// This type is typically created by calling `BoxBiTransformer::when()` and is
523/// designed to work with the `or_else()` method to create if-then-else logic.
524///
525/// # Features
526///
527/// - **Single Ownership**: Not cloneable, consumes `self` on use
528/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
529/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
530/// - **Implements BiTransformer**: Can be used anywhere a `BiTransformer` is expected
531///
532/// # Examples
533///
534/// ## With or_else Branch
535///
536/// ```rust
537/// use prism3_function::{BiTransformer, BoxBiTransformer};
538///
539/// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
540/// let multiply = BoxBiTransformer::new(|x: i32, y: i32| x * y);
541/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
542///
543/// assert_eq!(conditional.apply(5, 3), 8); // when branch executed
544/// assert_eq!(conditional.apply(-5, 3), -15); // or_else branch executed
545/// ```
546///
547/// # Author
548///
549/// Haixing Hu
550pub struct BoxConditionalBiTransformer<T, U, R> {
551 transformer: BoxBiTransformer<T, U, R>,
552 predicate: BoxBiPredicate<T, U>,
553}
554
555impl<T, U, R> BoxConditionalBiTransformer<T, U, R>
556where
557 T: 'static,
558 U: 'static,
559 R: 'static,
560{
561 /// Adds an else branch
562 ///
563 /// Executes the original bi-transformer when the condition is satisfied,
564 /// otherwise executes else_transformer.
565 ///
566 /// # Parameters
567 ///
568 /// * `else_transformer` - The bi-transformer for the else branch, can be:
569 /// - Closure: `|x: T, y: U| -> R`
570 /// - `BoxBiTransformer<T, U, R>`, `RcBiTransformer<T, U, R>`, `ArcBiTransformer<T, U, R>`
571 /// - Any type implementing `BiTransformer<T, U, R>`
572 ///
573 /// # Returns
574 ///
575 /// Returns the composed `BoxBiTransformer<T, U, R>`
576 ///
577 /// # Examples
578 ///
579 /// ## Using a closure (recommended)
580 ///
581 /// ```rust
582 /// use prism3_function::{BiTransformer, BoxBiTransformer};
583 ///
584 /// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
585 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(|x: i32, y: i32| x * y);
586 ///
587 /// assert_eq!(conditional.apply(5, 3), 8); // Condition satisfied, execute add
588 /// assert_eq!(conditional.apply(-5, 3), -15); // Condition not satisfied, execute multiply
589 /// ```
590 pub fn or_else<F>(self, else_transformer: F) -> BoxBiTransformer<T, U, R>
591 where
592 F: BiTransformer<T, U, R> + 'static,
593 {
594 let pred = self.predicate;
595 let then_trans = self.transformer;
596 BoxBiTransformer::new(move |t, u| {
597 if pred.test(&t, &u) {
598 then_trans.apply(t, u)
599 } else {
600 else_transformer.apply(t, u)
601 }
602 })
603 }
604}
605
606// ============================================================================
607// ArcBiTransformer - Arc<dyn Fn(T, U) -> R + Send + Sync>
608// ============================================================================
609
610/// ArcBiTransformer - thread-safe bi-transformer wrapper
611///
612/// A thread-safe, clonable bi-transformer wrapper suitable for multi-threaded
613/// scenarios. Can be called multiple times and shared across threads.
614///
615/// # Features
616///
617/// - **Based on**: `Arc<dyn Fn(T, U) -> R + Send + Sync>`
618/// - **Ownership**: Shared ownership via reference counting
619/// - **Reusability**: Can be called multiple times (each call consumes its
620/// inputs)
621/// - **Thread Safety**: Thread-safe (`Send + Sync` required)
622/// - **Clonable**: Cheap cloning via `Arc::clone`
623///
624/// # Author
625///
626/// Hu Haixing
627pub struct ArcBiTransformer<T, U, R> {
628 function: Arc<dyn Fn(T, U) -> R + Send + Sync>,
629}
630
631impl<T, U, R> ArcBiTransformer<T, U, R>
632where
633 T: Send + Sync + 'static,
634 U: Send + Sync + 'static,
635 R: 'static,
636{
637 /// Creates a new ArcBiTransformer
638 ///
639 /// # Parameters
640 ///
641 /// * `f` - The closure or function to wrap (must be Send + Sync)
642 ///
643 /// # Examples
644 ///
645 /// ```rust
646 /// use prism3_function::{ArcBiTransformer, BiTransformer};
647 ///
648 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
649 /// assert_eq!(add.apply(20, 22), 42);
650 /// ```
651 pub fn new<F>(f: F) -> Self
652 where
653 F: Fn(T, U) -> R + Send + Sync + 'static,
654 {
655 ArcBiTransformer {
656 function: Arc::new(f),
657 }
658 }
659
660 /// Chain composition - applies self first, then after
661 ///
662 /// Creates a new bi-transformer that applies this bi-transformer first,
663 /// then applies the after transformer to the result. Uses &self, so original
664 /// bi-transformer remains usable.
665 ///
666 /// # Type Parameters
667 ///
668 /// * `S` - The output type of the after transformer
669 /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
670 ///
671 /// # Parameters
672 ///
673 /// * `after` - The transformer to apply after self. **Note: This parameter
674 /// is passed by value and will transfer ownership.** If you need to
675 /// preserve the original transformer, clone it first (if it implements
676 /// `Clone`). Must be `Send + Sync`, can be:
677 /// - A closure: `|x: R| -> S` (must be `Send + Sync`)
678 /// - A function pointer: `fn(R) -> S`
679 /// - A `BoxTransformer<R, S>`
680 /// - An `RcTransformer<R, S>`
681 /// - An `ArcTransformer<R, S>` (will be moved)
682 /// - Any type implementing `Transformer<R, S> + Send + Sync`
683 ///
684 /// # Returns
685 ///
686 /// A new `ArcBiTransformer<T, U, S>` representing the composition
687 ///
688 /// # Examples
689 ///
690 /// ## Direct value passing (ownership transfer)
691 ///
692 /// ```rust
693 /// use prism3_function::{BiTransformer, ArcBiTransformer, ArcTransformer};
694 ///
695 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
696 /// let double = ArcTransformer::new(|x: i32| x * 2);
697 ///
698 /// // double is moved here
699 /// let composed = add.and_then(double);
700 ///
701 /// // Original add bi-transformer still usable (uses &self)
702 /// assert_eq!(add.apply(20, 22), 42);
703 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
704 /// // double.apply(10); // Would not compile - moved
705 /// ```
706 ///
707 /// ## Preserving original with clone
708 ///
709 /// ```rust
710 /// use prism3_function::{BiTransformer, ArcBiTransformer, ArcTransformer};
711 ///
712 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
713 /// let double = ArcTransformer::new(|x: i32| x * 2);
714 ///
715 /// // Clone to preserve original
716 /// let composed = add.and_then(double.clone());
717 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
718 ///
719 /// // Both originals still usable
720 /// assert_eq!(add.apply(20, 22), 42);
721 /// assert_eq!(double.apply(10), 20);
722 /// ```
723 pub fn and_then<S, F>(&self, after: F) -> ArcBiTransformer<T, U, S>
724 where
725 S: Send + Sync + 'static,
726 F: crate::transformer::Transformer<R, S> + Send + Sync + 'static,
727 {
728 let self_clone = Arc::clone(&self.function);
729 ArcBiTransformer {
730 function: Arc::new(move |t: T, u: U| after.apply(self_clone(t, u))),
731 }
732 }
733
734 /// Creates a conditional bi-transformer (thread-safe version)
735 ///
736 /// Returns a bi-transformer that only executes when a bi-predicate is
737 /// satisfied. You must call `or_else()` to provide an alternative
738 /// bi-transformer.
739 ///
740 /// # Parameters
741 ///
742 /// * `predicate` - The condition to check. **Note: This parameter is passed
743 /// by value and will transfer ownership.** If you need to preserve the
744 /// original bi-predicate, clone it first (if it implements `Clone`).
745 /// Must be `Send + Sync`, can be:
746 /// - A closure: `|x: &T, y: &U| -> bool` (requires `Send + Sync`)
747 /// - A function pointer: `fn(&T, &U) -> bool`
748 /// - An `ArcBiPredicate<T, U>`
749 /// - Any type implementing `BiPredicate<T, U> + Send + Sync`
750 ///
751 /// # Returns
752 ///
753 /// Returns `ArcConditionalBiTransformer<T, U, R>`
754 ///
755 /// # Examples
756 ///
757 /// ## Basic usage with or_else
758 ///
759 /// ```rust
760 /// use prism3_function::{BiTransformer, ArcBiTransformer};
761 ///
762 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
763 /// let multiply = ArcBiTransformer::new(|x: i32, y: i32| x * y);
764 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
765 /// .or_else(multiply);
766 ///
767 /// let conditional_clone = conditional.clone();
768 ///
769 /// assert_eq!(conditional.apply(5, 3), 8);
770 /// assert_eq!(conditional_clone.apply(-5, 3), -15);
771 /// ```
772 ///
773 /// ## Preserving bi-predicate with clone
774 ///
775 /// ```rust
776 /// use prism3_function::{BiTransformer, ArcBiTransformer, ArcBiPredicate};
777 ///
778 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
779 /// let both_positive = ArcBiPredicate::new(|x: &i32, y: &i32|
780 /// *x > 0 && *y > 0);
781 ///
782 /// // Clone to preserve original bi-predicate
783 /// let conditional = add.when(both_positive.clone())
784 /// .or_else(ArcBiTransformer::new(|x, y| x * y));
785 ///
786 /// assert_eq!(conditional.apply(5, 3), 8);
787 ///
788 /// // Original bi-predicate still usable
789 /// assert!(both_positive.test(&5, &3));
790 /// ```
791 pub fn when<P>(&self, predicate: P) -> ArcConditionalBiTransformer<T, U, R>
792 where
793 P: BiPredicate<T, U> + Send + Sync + 'static,
794 {
795 ArcConditionalBiTransformer {
796 transformer: self.clone(),
797 predicate: predicate.into_arc(),
798 }
799 }
800}
801
802impl<T, U, R> ArcBiTransformer<T, U, R>
803where
804 T: Send + Sync + 'static,
805 U: Send + Sync + 'static,
806 R: Clone + 'static,
807{
808 /// Creates a constant bi-transformer
809 ///
810 /// # Examples
811 ///
812 /// ```rust
813 /// use prism3_function::{ArcBiTransformer, BiTransformer};
814 ///
815 /// let constant = ArcBiTransformer::constant("hello");
816 /// assert_eq!(constant.apply(123, 456), "hello");
817 /// ```
818 pub fn constant(value: R) -> ArcBiTransformer<T, U, R>
819 where
820 R: Send + Sync,
821 {
822 ArcBiTransformer::new(move |_, _| value.clone())
823 }
824}
825
826impl<T, U, R> BiTransformer<T, U, R> for ArcBiTransformer<T, U, R> {
827 fn apply(&self, first: T, second: U) -> R {
828 (self.function)(first, second)
829 }
830
831 fn into_box(self) -> BoxBiTransformer<T, U, R>
832 where
833 T: 'static,
834 U: 'static,
835 R: 'static,
836 {
837 BoxBiTransformer::new(move |t, u| (self.function)(t, u))
838 }
839
840 fn into_rc(self) -> RcBiTransformer<T, U, R>
841 where
842 T: 'static,
843 U: 'static,
844 R: 'static,
845 {
846 RcBiTransformer::new(move |t, u| (self.function)(t, u))
847 }
848
849 fn into_arc(self) -> ArcBiTransformer<T, U, R>
850 where
851 T: Send + Sync + 'static,
852 U: Send + Sync + 'static,
853 R: Send + Sync + 'static,
854 {
855 // Zero-cost: directly return itself
856 self
857 }
858
859 fn into_fn(self) -> impl Fn(T, U) -> R
860 where
861 T: 'static,
862 U: 'static,
863 R: 'static,
864 {
865 move |t: T, u: U| (self.function)(t, u)
866 }
867
868 fn to_box(&self) -> BoxBiTransformer<T, U, R>
869 where
870 T: 'static,
871 U: 'static,
872 R: 'static,
873 {
874 let self_fn = self.function.clone();
875 BoxBiTransformer::new(move |t, u| self_fn(t, u))
876 }
877
878 fn to_rc(&self) -> RcBiTransformer<T, U, R>
879 where
880 T: 'static,
881 U: 'static,
882 R: 'static,
883 {
884 let self_fn = self.function.clone();
885 RcBiTransformer::new(move |t, u| self_fn(t, u))
886 }
887
888 fn to_arc(&self) -> ArcBiTransformer<T, U, R>
889 where
890 T: Send + Sync + 'static,
891 U: Send + Sync + 'static,
892 R: Send + Sync + 'static,
893 {
894 self.clone()
895 }
896
897 fn to_fn(&self) -> impl Fn(T, U) -> R
898 where
899 T: 'static,
900 U: 'static,
901 R: 'static,
902 {
903 let self_fn = self.function.clone();
904 move |t: T, u: U| self_fn(t, u)
905 }
906}
907
908impl<T, U, R> Clone for ArcBiTransformer<T, U, R> {
909 fn clone(&self) -> Self {
910 ArcBiTransformer {
911 function: Arc::clone(&self.function),
912 }
913 }
914}
915
916// ============================================================================
917// ArcBiTransformer BiTransformerOnce Implementation
918// ============================================================================
919
920impl<T, U, R> crate::bi_transformer_once::BiTransformerOnce<T, U, R> for ArcBiTransformer<T, U, R>
921where
922 T: 'static,
923 U: 'static,
924 R: 'static,
925{
926 /// Transforms two input values, consuming self and both inputs
927 ///
928 /// # Parameters
929 ///
930 /// * `first` - The first input value (consumed)
931 /// * `second` - The second input value (consumed)
932 ///
933 /// # Returns
934 ///
935 /// The transformed output value
936 fn apply_once(self, first: T, second: U) -> R {
937 (self.function)(first, second)
938 }
939
940 fn into_box_once(self) -> crate::bi_transformer_once::BoxBiTransformerOnce<T, U, R>
941 where
942 T: 'static,
943 U: 'static,
944 R: 'static,
945 {
946 crate::bi_transformer_once::BoxBiTransformerOnce::new(move |t: T, u: U| {
947 (self.function)(t, u)
948 })
949 }
950
951 fn into_fn_once(self) -> impl FnOnce(T, U) -> R
952 where
953 T: 'static,
954 U: 'static,
955 R: 'static,
956 {
957 move |t: T, u: U| (self.function)(t, u)
958 }
959
960 fn to_box_once(&self) -> crate::bi_transformer_once::BoxBiTransformerOnce<T, U, R>
961 where
962 T: 'static,
963 U: 'static,
964 R: 'static,
965 {
966 let self_fn = self.function.clone();
967 crate::bi_transformer_once::BoxBiTransformerOnce::new(move |t: T, u: U| self_fn(t, u))
968 }
969
970 fn to_fn_once(&self) -> impl FnOnce(T, U) -> R
971 where
972 T: 'static,
973 U: 'static,
974 R: 'static,
975 {
976 let self_fn = self.function.clone();
977 move |t: T, u: U| self_fn(t, u)
978 }
979}
980
981// ============================================================================
982// ArcConditionalBiTransformer - Arc-based Conditional BiTransformer
983// ============================================================================
984
985/// ArcConditionalBiTransformer struct
986///
987/// A thread-safe conditional bi-transformer that only executes when a
988/// bi-predicate is satisfied. Uses `ArcBiTransformer` and `ArcBiPredicate` for
989/// shared ownership across threads.
990///
991/// This type is typically created by calling `ArcBiTransformer::when()` and is
992/// designed to work with the `or_else()` method to create if-then-else logic.
993///
994/// # Features
995///
996/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
997/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
998/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
999/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
1000///
1001/// # Examples
1002///
1003/// ```rust
1004/// use prism3_function::{BiTransformer, ArcBiTransformer};
1005///
1006/// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
1007/// let multiply = ArcBiTransformer::new(|x: i32, y: i32| x * y);
1008/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
1009///
1010/// let conditional_clone = conditional.clone();
1011///
1012/// assert_eq!(conditional.apply(5, 3), 8);
1013/// assert_eq!(conditional_clone.apply(-5, 3), -15);
1014/// ```
1015///
1016/// # Author
1017///
1018/// Haixing Hu
1019pub struct ArcConditionalBiTransformer<T, U, R> {
1020 transformer: ArcBiTransformer<T, U, R>,
1021 predicate: ArcBiPredicate<T, U>,
1022}
1023
1024impl<T, U, R> ArcConditionalBiTransformer<T, U, R>
1025where
1026 T: Send + Sync + 'static,
1027 U: Send + Sync + 'static,
1028 R: 'static,
1029{
1030 /// Adds an else branch (thread-safe version)
1031 ///
1032 /// Executes the original bi-transformer when the condition is satisfied,
1033 /// otherwise executes else_transformer.
1034 ///
1035 /// # Parameters
1036 ///
1037 /// * `else_transformer` - The bi-transformer for the else branch, can be:
1038 /// - Closure: `|x: T, y: U| -> R` (must be `Send + Sync`)
1039 /// - `ArcBiTransformer<T, U, R>`, `BoxBiTransformer<T, U, R>`
1040 /// - Any type implementing `BiTransformer<T, U, R> + Send + Sync`
1041 ///
1042 /// # Returns
1043 ///
1044 /// Returns the composed `ArcBiTransformer<T, U, R>`
1045 ///
1046 /// # Examples
1047 ///
1048 /// ## Using a closure (recommended)
1049 ///
1050 /// ```rust
1051 /// use prism3_function::{BiTransformer, ArcBiTransformer};
1052 ///
1053 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
1054 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(|x: i32, y: i32| x * y);
1055 ///
1056 /// assert_eq!(conditional.apply(5, 3), 8);
1057 /// assert_eq!(conditional.apply(-5, 3), -15);
1058 /// ```
1059 pub fn or_else<F>(&self, else_transformer: F) -> ArcBiTransformer<T, U, R>
1060 where
1061 F: BiTransformer<T, U, R> + Send + Sync + 'static,
1062 R: Send + Sync,
1063 {
1064 let pred = self.predicate.clone();
1065 let then_trans = self.transformer.clone();
1066 ArcBiTransformer::new(move |t, u| {
1067 if pred.test(&t, &u) {
1068 then_trans.apply(t, u)
1069 } else {
1070 else_transformer.apply(t, u)
1071 }
1072 })
1073 }
1074}
1075
1076impl<T, U, R> Clone for ArcConditionalBiTransformer<T, U, R> {
1077 /// Clones the conditional bi-transformer
1078 ///
1079 /// Creates a new instance that shares the underlying bi-transformer and
1080 /// bi-predicate with the original instance.
1081 fn clone(&self) -> Self {
1082 ArcConditionalBiTransformer {
1083 transformer: self.transformer.clone(),
1084 predicate: self.predicate.clone(),
1085 }
1086 }
1087}
1088
1089// ============================================================================
1090// RcBiTransformer - Rc<dyn Fn(T, U) -> R>
1091// ============================================================================
1092
1093/// RcBiTransformer - single-threaded bi-transformer wrapper
1094///
1095/// A single-threaded, clonable bi-transformer wrapper optimized for scenarios
1096/// that require sharing without thread-safety overhead.
1097///
1098/// # Features
1099///
1100/// - **Based on**: `Rc<dyn Fn(T, U) -> R>`
1101/// - **Ownership**: Shared ownership via reference counting (non-atomic)
1102/// - **Reusability**: Can be called multiple times (each call consumes its
1103/// inputs)
1104/// - **Thread Safety**: Not thread-safe (no `Send + Sync`)
1105/// - **Clonable**: Cheap cloning via `Rc::clone`
1106///
1107/// # Author
1108///
1109/// Hu Haixing
1110pub struct RcBiTransformer<T, U, R> {
1111 function: Rc<dyn Fn(T, U) -> R>,
1112}
1113
1114impl<T, U, R> RcBiTransformer<T, U, R>
1115where
1116 T: 'static,
1117 U: 'static,
1118 R: 'static,
1119{
1120 /// Creates a new RcBiTransformer
1121 ///
1122 /// # Parameters
1123 ///
1124 /// * `f` - The closure or function to wrap
1125 ///
1126 /// # Examples
1127 ///
1128 /// ```rust
1129 /// use prism3_function::{RcBiTransformer, BiTransformer};
1130 ///
1131 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1132 /// assert_eq!(add.apply(20, 22), 42);
1133 /// ```
1134 pub fn new<F>(f: F) -> Self
1135 where
1136 F: Fn(T, U) -> R + 'static,
1137 {
1138 RcBiTransformer {
1139 function: Rc::new(f),
1140 }
1141 }
1142
1143 /// Chain composition - applies self first, then after
1144 ///
1145 /// Creates a new bi-transformer that applies this bi-transformer first,
1146 /// then applies the after transformer to the result. Uses &self, so original
1147 /// bi-transformer remains usable.
1148 ///
1149 /// # Type Parameters
1150 ///
1151 /// * `S` - The output type of the after transformer
1152 /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
1153 ///
1154 /// # Parameters
1155 ///
1156 /// * `after` - The transformer to apply after self. **Note: This parameter
1157 /// is passed by value and will transfer ownership.** If you need to
1158 /// preserve the original transformer, clone it first (if it implements
1159 /// `Clone`). Can be:
1160 /// - A closure: `|x: R| -> S`
1161 /// - A function pointer: `fn(R) -> S`
1162 /// - A `BoxTransformer<R, S>`
1163 /// - An `RcTransformer<R, S>` (will be moved)
1164 /// - An `ArcTransformer<R, S>`
1165 /// - Any type implementing `Transformer<R, S>`
1166 ///
1167 /// # Returns
1168 ///
1169 /// A new `RcBiTransformer<T, U, S>` representing the composition
1170 ///
1171 /// # Examples
1172 ///
1173 /// ## Direct value passing (ownership transfer)
1174 ///
1175 /// ```rust
1176 /// use prism3_function::{BiTransformer, RcBiTransformer, RcTransformer};
1177 ///
1178 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1179 /// let double = RcTransformer::new(|x: i32| x * 2);
1180 ///
1181 /// // double is moved here
1182 /// let composed = add.and_then(double);
1183 ///
1184 /// // Original add bi-transformer still usable (uses &self)
1185 /// assert_eq!(add.apply(20, 22), 42);
1186 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
1187 /// // double.apply(10); // Would not compile - moved
1188 /// ```
1189 ///
1190 /// ## Preserving original with clone
1191 ///
1192 /// ```rust
1193 /// use prism3_function::{BiTransformer, RcBiTransformer, RcTransformer};
1194 ///
1195 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1196 /// let double = RcTransformer::new(|x: i32| x * 2);
1197 ///
1198 /// // Clone to preserve original
1199 /// let composed = add.and_then(double.clone());
1200 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
1201 ///
1202 /// // Both originals still usable
1203 /// assert_eq!(add.apply(20, 22), 42);
1204 /// assert_eq!(double.apply(10), 20);
1205 /// ```
1206 pub fn and_then<S, F>(&self, after: F) -> RcBiTransformer<T, U, S>
1207 where
1208 S: 'static,
1209 F: crate::transformer::Transformer<R, S> + 'static,
1210 {
1211 let self_clone = Rc::clone(&self.function);
1212 RcBiTransformer {
1213 function: Rc::new(move |t: T, u: U| after.apply(self_clone(t, u))),
1214 }
1215 }
1216
1217 /// Creates a conditional bi-transformer (single-threaded shared version)
1218 ///
1219 /// Returns a bi-transformer that only executes when a bi-predicate is
1220 /// satisfied. You must call `or_else()` to provide an alternative
1221 /// bi-transformer.
1222 ///
1223 /// # Parameters
1224 ///
1225 /// * `predicate` - The condition to check. **Note: This parameter is passed
1226 /// by value and will transfer ownership.** If you need to preserve the
1227 /// original bi-predicate, clone it first (if it implements `Clone`).
1228 /// Can be:
1229 /// - A closure: `|x: &T, y: &U| -> bool`
1230 /// - A function pointer: `fn(&T, &U) -> bool`
1231 /// - A `BoxBiPredicate<T, U>`
1232 /// - An `RcBiPredicate<T, U>`
1233 /// - An `ArcBiPredicate<T, U>`
1234 /// - Any type implementing `BiPredicate<T, U>`
1235 ///
1236 /// # Returns
1237 ///
1238 /// Returns `RcConditionalBiTransformer<T, U, R>`
1239 ///
1240 /// # Examples
1241 ///
1242 /// ## Basic usage with or_else
1243 ///
1244 /// ```rust
1245 /// use prism3_function::{BiTransformer, RcBiTransformer};
1246 ///
1247 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1248 /// let multiply = RcBiTransformer::new(|x: i32, y: i32| x * y);
1249 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
1250 /// .or_else(multiply);
1251 ///
1252 /// let conditional_clone = conditional.clone();
1253 ///
1254 /// assert_eq!(conditional.apply(5, 3), 8);
1255 /// assert_eq!(conditional_clone.apply(-5, 3), -15);
1256 /// ```
1257 ///
1258 /// ## Preserving bi-predicate with clone
1259 ///
1260 /// ```rust
1261 /// use prism3_function::{BiTransformer, RcBiTransformer, RcBiPredicate};
1262 ///
1263 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1264 /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
1265 /// *x > 0 && *y > 0);
1266 ///
1267 /// // Clone to preserve original bi-predicate
1268 /// let conditional = add.when(both_positive.clone())
1269 /// .or_else(RcBiTransformer::new(|x, y| x * y));
1270 ///
1271 /// assert_eq!(conditional.apply(5, 3), 8);
1272 ///
1273 /// // Original bi-predicate still usable
1274 /// assert!(both_positive.test(&5, &3));
1275 /// ```
1276 pub fn when<P>(&self, predicate: P) -> RcConditionalBiTransformer<T, U, R>
1277 where
1278 P: BiPredicate<T, U> + 'static,
1279 {
1280 RcConditionalBiTransformer {
1281 transformer: self.clone(),
1282 predicate: predicate.into_rc(),
1283 }
1284 }
1285}
1286
1287impl<T, U, R> RcBiTransformer<T, U, R>
1288where
1289 T: 'static,
1290 U: 'static,
1291 R: Clone + 'static,
1292{
1293 /// Creates a constant bi-transformer
1294 ///
1295 /// # Examples
1296 ///
1297 /// ```rust
1298 /// use prism3_function::{RcBiTransformer, BiTransformer};
1299 ///
1300 /// let constant = RcBiTransformer::constant("hello");
1301 /// assert_eq!(constant.apply(123, 456), "hello");
1302 /// ```
1303 pub fn constant(value: R) -> RcBiTransformer<T, U, R> {
1304 RcBiTransformer::new(move |_, _| value.clone())
1305 }
1306}
1307
1308impl<T, U, R> BiTransformer<T, U, R> for RcBiTransformer<T, U, R> {
1309 fn apply(&self, first: T, second: U) -> R {
1310 (self.function)(first, second)
1311 }
1312
1313 fn into_box(self) -> BoxBiTransformer<T, U, R>
1314 where
1315 T: 'static,
1316 U: 'static,
1317 R: 'static,
1318 {
1319 BoxBiTransformer::new(move |t, u| (self.function)(t, u))
1320 }
1321
1322 fn into_rc(self) -> RcBiTransformer<T, U, R>
1323 where
1324 T: 'static,
1325 U: 'static,
1326 R: 'static,
1327 {
1328 // Zero-cost: directly return itself
1329 self
1330 }
1331
1332 // do NOT override RcBiTransformer::into_arc() because RcBiTransformer is not Send + Sync
1333 // and calling RcBiTransformer::into_arc() will cause a compile error
1334
1335 fn into_fn(self) -> impl Fn(T, U) -> R
1336 where
1337 T: 'static,
1338 U: 'static,
1339 R: 'static,
1340 {
1341 move |t: T, u: U| (self.function)(t, u)
1342 }
1343
1344 fn to_box(&self) -> BoxBiTransformer<T, U, R>
1345 where
1346 T: 'static,
1347 U: 'static,
1348 R: 'static,
1349 {
1350 let self_fn = self.function.clone();
1351 BoxBiTransformer::new(move |t, u| self_fn(t, u))
1352 }
1353
1354 fn to_rc(&self) -> RcBiTransformer<T, U, R>
1355 where
1356 T: 'static,
1357 U: 'static,
1358 R: 'static,
1359 {
1360 self.clone()
1361 }
1362
1363 // do NOT override RcBiTransformer::to_arc() because RcBiTransformer is not Send + Sync
1364 // and calling RcBiTransformer::to_arc() will cause a compile error
1365
1366 fn to_fn(&self) -> impl Fn(T, U) -> R
1367 where
1368 T: 'static,
1369 U: 'static,
1370 R: 'static,
1371 {
1372 let self_fn = self.function.clone();
1373 move |t: T, u: U| self_fn(t, u)
1374 }
1375}
1376
1377impl<T, U, R> Clone for RcBiTransformer<T, U, R> {
1378 fn clone(&self) -> Self {
1379 RcBiTransformer {
1380 function: Rc::clone(&self.function),
1381 }
1382 }
1383}
1384
1385// ============================================================================
1386// RcBiTransformer BiTransformerOnce Implementation
1387// ============================================================================
1388
1389impl<T, U, R> crate::bi_transformer_once::BiTransformerOnce<T, U, R> for RcBiTransformer<T, U, R>
1390where
1391 T: 'static,
1392 U: 'static,
1393 R: 'static,
1394{
1395 /// Transforms two input values, consuming self and both inputs
1396 ///
1397 /// # Parameters
1398 ///
1399 /// * `first` - The first input value (consumed)
1400 /// * `second` - The second input value (consumed)
1401 ///
1402 /// # Returns
1403 ///
1404 /// The transformed output value
1405 fn apply_once(self, first: T, second: U) -> R {
1406 (self.function)(first, second)
1407 }
1408
1409 fn into_box_once(self) -> crate::bi_transformer_once::BoxBiTransformerOnce<T, U, R>
1410 where
1411 T: 'static,
1412 U: 'static,
1413 R: 'static,
1414 {
1415 crate::bi_transformer_once::BoxBiTransformerOnce::new(move |t: T, u: U| {
1416 (self.function)(t, u)
1417 })
1418 }
1419
1420 fn into_fn_once(self) -> impl FnOnce(T, U) -> R
1421 where
1422 T: 'static,
1423 U: 'static,
1424 R: 'static,
1425 {
1426 move |t: T, u: U| (self.function)(t, u)
1427 }
1428
1429 fn to_box_once(&self) -> crate::bi_transformer_once::BoxBiTransformerOnce<T, U, R>
1430 where
1431 T: 'static,
1432 U: 'static,
1433 R: 'static,
1434 {
1435 let self_fn = self.function.clone();
1436 crate::bi_transformer_once::BoxBiTransformerOnce::new(move |t: T, u: U| self_fn(t, u))
1437 }
1438
1439 fn to_fn_once(&self) -> impl FnOnce(T, U) -> R
1440 where
1441 T: 'static,
1442 U: 'static,
1443 R: 'static,
1444 {
1445 let self_fn = self.function.clone();
1446 move |t: T, u: U| self_fn(t, u)
1447 }
1448}
1449
1450// ============================================================================
1451// RcConditionalBiTransformer - Rc-based Conditional BiTransformer
1452// ============================================================================
1453
1454/// RcConditionalBiTransformer struct
1455///
1456/// A single-threaded conditional bi-transformer that only executes when a
1457/// bi-predicate is satisfied. Uses `RcBiTransformer` and `RcBiPredicate` for
1458/// shared ownership within a single thread.
1459///
1460/// This type is typically created by calling `RcBiTransformer::when()` and is
1461/// designed to work with the `or_else()` method to create if-then-else logic.
1462///
1463/// # Features
1464///
1465/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
1466/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
1467/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
1468/// - **No Lock Overhead**: More efficient than `ArcConditionalBiTransformer`
1469///
1470/// # Examples
1471///
1472/// ```rust
1473/// use prism3_function::{BiTransformer, RcBiTransformer};
1474///
1475/// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1476/// let multiply = RcBiTransformer::new(|x: i32, y: i32| x * y);
1477/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
1478///
1479/// let conditional_clone = conditional.clone();
1480///
1481/// assert_eq!(conditional.apply(5, 3), 8);
1482/// assert_eq!(conditional_clone.apply(-5, 3), -15);
1483/// ```
1484///
1485/// # Author
1486///
1487/// Haixing Hu
1488pub struct RcConditionalBiTransformer<T, U, R> {
1489 transformer: RcBiTransformer<T, U, R>,
1490 predicate: RcBiPredicate<T, U>,
1491}
1492
1493impl<T, U, R> RcConditionalBiTransformer<T, U, R>
1494where
1495 T: 'static,
1496 U: 'static,
1497 R: 'static,
1498{
1499 /// Adds an else branch (single-threaded shared version)
1500 ///
1501 /// Executes the original bi-transformer when the condition is satisfied,
1502 /// otherwise executes else_transformer.
1503 ///
1504 /// # Parameters
1505 ///
1506 /// * `else_transformer` - The bi-transformer for the else branch, can be:
1507 /// - Closure: `|x: T, y: U| -> R`
1508 /// - `RcBiTransformer<T, U, R>`, `BoxBiTransformer<T, U, R>`
1509 /// - Any type implementing `BiTransformer<T, U, R>`
1510 ///
1511 /// # Returns
1512 ///
1513 /// Returns the composed `RcBiTransformer<T, U, R>`
1514 ///
1515 /// # Examples
1516 ///
1517 /// ## Using a closure (recommended)
1518 ///
1519 /// ```rust
1520 /// use prism3_function::{BiTransformer, RcBiTransformer};
1521 ///
1522 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1523 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(|x: i32, y: i32| x * y);
1524 ///
1525 /// assert_eq!(conditional.apply(5, 3), 8);
1526 /// assert_eq!(conditional.apply(-5, 3), -15);
1527 /// ```
1528 pub fn or_else<F>(&self, else_transformer: F) -> RcBiTransformer<T, U, R>
1529 where
1530 F: BiTransformer<T, U, R> + 'static,
1531 {
1532 let pred = self.predicate.clone();
1533 let then_trans = self.transformer.clone();
1534 RcBiTransformer::new(move |t, u| {
1535 if pred.test(&t, &u) {
1536 then_trans.apply(t, u)
1537 } else {
1538 else_transformer.apply(t, u)
1539 }
1540 })
1541 }
1542}
1543
1544impl<T, U, R> Clone for RcConditionalBiTransformer<T, U, R> {
1545 /// Clones the conditional bi-transformer
1546 ///
1547 /// Creates a new instance that shares the underlying bi-transformer and
1548 /// bi-predicate with the original instance.
1549 fn clone(&self) -> Self {
1550 RcConditionalBiTransformer {
1551 transformer: self.transformer.clone(),
1552 predicate: self.predicate.clone(),
1553 }
1554 }
1555}
1556
1557// ============================================================================
1558// Blanket implementation for standard Fn trait
1559// ============================================================================
1560
1561/// Implement BiTransformer<T, U, R> for any type that implements Fn(T, U) -> R
1562///
1563/// This allows closures and function pointers to be used directly with our
1564/// BiTransformer trait without wrapping.
1565///
1566/// # Examples
1567///
1568/// ```rust
1569/// use prism3_function::BiTransformer;
1570///
1571/// fn add(x: i32, y: i32) -> i32 { x + y }
1572///
1573/// assert_eq!(add.apply(20, 22), 42);
1574///
1575/// let multiply = |x: i32, y: i32| x * y;
1576/// assert_eq!(multiply.apply(6, 7), 42);
1577/// ```
1578///
1579/// # Author
1580///
1581/// Hu Haixing
1582impl<F, T, U, R> BiTransformer<T, U, R> for F
1583where
1584 F: Fn(T, U) -> R,
1585 T: 'static,
1586 U: 'static,
1587 R: 'static,
1588{
1589 fn apply(&self, first: T, second: U) -> R {
1590 self(first, second)
1591 }
1592
1593 fn into_box(self) -> BoxBiTransformer<T, U, R>
1594 where
1595 Self: Sized + 'static,
1596 {
1597 BoxBiTransformer::new(self)
1598 }
1599
1600 fn into_rc(self) -> RcBiTransformer<T, U, R>
1601 where
1602 Self: Sized + 'static,
1603 {
1604 RcBiTransformer::new(self)
1605 }
1606
1607 fn into_arc(self) -> ArcBiTransformer<T, U, R>
1608 where
1609 Self: Sized + Send + Sync + 'static,
1610 T: Send + Sync + 'static,
1611 U: Send + Sync + 'static,
1612 R: Send + Sync + 'static,
1613 {
1614 ArcBiTransformer::new(self)
1615 }
1616
1617 fn into_fn(self) -> impl Fn(T, U) -> R
1618 where
1619 Self: Sized + 'static,
1620 {
1621 move |t: T, u: U| self(t, u)
1622 }
1623
1624 fn to_box(&self) -> BoxBiTransformer<T, U, R>
1625 where
1626 Self: Sized + Clone + 'static,
1627 T: 'static,
1628 U: 'static,
1629 R: 'static,
1630 {
1631 BoxBiTransformer::new(self.clone())
1632 }
1633
1634 fn to_rc(&self) -> RcBiTransformer<T, U, R>
1635 where
1636 Self: Sized + Clone + 'static,
1637 T: 'static,
1638 U: 'static,
1639 R: 'static,
1640 {
1641 RcBiTransformer::new(self.clone())
1642 }
1643
1644 fn to_arc(&self) -> ArcBiTransformer<T, U, R>
1645 where
1646 Self: Sized + Clone + Send + Sync + 'static,
1647 T: Send + Sync + 'static,
1648 U: Send + Sync + 'static,
1649 R: Send + Sync + 'static,
1650 {
1651 ArcBiTransformer::new(self.clone())
1652 }
1653
1654 fn to_fn(&self) -> impl Fn(T, U) -> R
1655 where
1656 Self: Sized + Clone + 'static,
1657 T: 'static,
1658 U: 'static,
1659 R: 'static,
1660 {
1661 self.clone()
1662 }
1663}
1664
1665// ============================================================================
1666// FnBiTransformerOps - Extension trait for Fn(T, U) -> R bi-transformers
1667// ============================================================================
1668
1669/// Extension trait for closures implementing `Fn(T, U) -> R`
1670///
1671/// Provides composition methods (`and_then`, `when`) for bi-transformer
1672/// closures and function pointers without requiring explicit wrapping in
1673/// `BoxBiTransformer`.
1674///
1675/// This trait is automatically implemented for all closures and function
1676/// pointers that implement `Fn(T, U) -> R`.
1677///
1678/// # Design Rationale
1679///
1680/// While closures automatically implement `BiTransformer<T, U, R>` through
1681/// blanket implementation, they don't have access to instance methods like
1682/// `and_then` and `when`. This extension trait provides those methods,
1683/// returning `BoxBiTransformer` for maximum flexibility.
1684///
1685/// # Examples
1686///
1687/// ## Chain composition with and_then
1688///
1689/// ```rust
1690/// use prism3_function::{BiTransformer, FnBiTransformerOps};
1691///
1692/// let add = |x: i32, y: i32| x + y;
1693/// let double = |x: i32| x * 2;
1694///
1695/// let composed = add.and_then(double);
1696/// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
1697/// ```
1698///
1699/// ## Conditional execution with when
1700///
1701/// ```rust
1702/// use prism3_function::{BiTransformer, FnBiTransformerOps};
1703///
1704/// let add = |x: i32, y: i32| x + y;
1705/// let multiply = |x: i32, y: i32| x * y;
1706///
1707/// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(multiply);
1708///
1709/// assert_eq!(conditional.apply(5, 3), 8); // add
1710/// assert_eq!(conditional.apply(-5, 3), -15); // multiply
1711/// ```
1712///
1713/// # Author
1714///
1715/// Hu Haixing
1716pub trait FnBiTransformerOps<T, U, R>: Fn(T, U) -> R + Sized + 'static {
1717 /// Chain composition - applies self first, then after
1718 ///
1719 /// Creates a new bi-transformer that applies this bi-transformer first,
1720 /// then applies the after transformer to the result. Consumes self and
1721 /// returns a `BoxBiTransformer`.
1722 ///
1723 /// # Type Parameters
1724 ///
1725 /// * `S` - The output type of the after transformer
1726 /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
1727 ///
1728 /// # Parameters
1729 ///
1730 /// * `after` - The transformer to apply after self. **Note: This parameter
1731 /// is passed by value and will transfer ownership.** If you need to
1732 /// preserve the original transformer, clone it first (if it implements
1733 /// `Clone`). Can be:
1734 /// - A closure: `|x: R| -> S`
1735 /// - A function pointer: `fn(R) -> S`
1736 /// - A `BoxTransformer<R, S>`
1737 /// - An `RcTransformer<R, S>`
1738 /// - An `ArcTransformer<R, S>`
1739 /// - Any type implementing `Transformer<R, S>`
1740 ///
1741 /// # Returns
1742 ///
1743 /// A new `BoxBiTransformer<T, U, S>` representing the composition
1744 ///
1745 /// # Examples
1746 ///
1747 /// ## Direct value passing (ownership transfer)
1748 ///
1749 /// ```rust
1750 /// use prism3_function::{BiTransformer, FnBiTransformerOps,
1751 /// BoxTransformer};
1752 ///
1753 /// let add = |x: i32, y: i32| x + y;
1754 /// let to_string = BoxTransformer::new(|x: i32| x.to_string());
1755 ///
1756 /// // to_string is moved here
1757 /// let composed = add.and_then(to_string);
1758 /// assert_eq!(composed.apply(20, 22), "42");
1759 /// // to_string.apply(10); // Would not compile - moved
1760 /// ```
1761 ///
1762 /// ## Preserving original with clone
1763 ///
1764 /// ```rust
1765 /// use prism3_function::{BiTransformer, FnBiTransformerOps,
1766 /// BoxTransformer};
1767 ///
1768 /// let add = |x: i32, y: i32| x + y;
1769 /// let to_string = BoxTransformer::new(|x: i32| x.to_string());
1770 ///
1771 /// // Clone to preserve original
1772 /// let composed = add.and_then(to_string.clone());
1773 /// assert_eq!(composed.apply(20, 22), "42");
1774 ///
1775 /// // Original still usable
1776 /// assert_eq!(to_string.apply(10), "10");
1777 /// ```
1778 fn and_then<S, F>(self, after: F) -> BoxBiTransformer<T, U, S>
1779 where
1780 S: 'static,
1781 F: crate::transformer::Transformer<R, S> + 'static,
1782 T: 'static,
1783 U: 'static,
1784 R: 'static,
1785 {
1786 BoxBiTransformer::new(move |t: T, u: U| after.apply(self(t, u)))
1787 }
1788
1789 /// Creates a conditional bi-transformer
1790 ///
1791 /// Returns a bi-transformer that only executes when a bi-predicate is
1792 /// satisfied. You must call `or_else()` to provide an alternative
1793 /// bi-transformer for when the condition is not satisfied.
1794 ///
1795 /// # Parameters
1796 ///
1797 /// * `predicate` - The condition to check. **Note: This parameter is passed
1798 /// by value and will transfer ownership.** If you need to preserve the
1799 /// original bi-predicate, clone it first (if it implements `Clone`).
1800 /// Can be:
1801 /// - A closure: `|x: &T, y: &U| -> bool`
1802 /// - A function pointer: `fn(&T, &U) -> bool`
1803 /// - A `BoxBiPredicate<T, U>`
1804 /// - An `RcBiPredicate<T, U>`
1805 /// - An `ArcBiPredicate<T, U>`
1806 /// - Any type implementing `BiPredicate<T, U>`
1807 ///
1808 /// # Returns
1809 ///
1810 /// Returns `BoxConditionalBiTransformer<T, U, R>`
1811 ///
1812 /// # Examples
1813 ///
1814 /// ## Basic usage with or_else
1815 ///
1816 /// ```rust
1817 /// use prism3_function::{BiTransformer, FnBiTransformerOps};
1818 ///
1819 /// let add = |x: i32, y: i32| x + y;
1820 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0)
1821 /// .or_else(|x: i32, y: i32| x * y);
1822 ///
1823 /// assert_eq!(conditional.apply(5, 3), 8);
1824 /// assert_eq!(conditional.apply(-5, 3), -15);
1825 /// ```
1826 ///
1827 /// ## Preserving bi-predicate with clone
1828 ///
1829 /// ```rust
1830 /// use prism3_function::{BiTransformer, FnBiTransformerOps,
1831 /// RcBiPredicate};
1832 ///
1833 /// let add = |x: i32, y: i32| x + y;
1834 /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
1835 /// *x > 0 && *y > 0);
1836 ///
1837 /// // Clone to preserve original bi-predicate
1838 /// let conditional = add.when(both_positive.clone())
1839 /// .or_else(|x: i32, y: i32| x * y);
1840 ///
1841 /// assert_eq!(conditional.apply(5, 3), 8);
1842 ///
1843 /// // Original bi-predicate still usable
1844 /// assert!(both_positive.test(&5, &3));
1845 /// ```
1846 fn when<P>(self, predicate: P) -> BoxConditionalBiTransformer<T, U, R>
1847 where
1848 P: BiPredicate<T, U> + 'static,
1849 T: 'static,
1850 U: 'static,
1851 R: 'static,
1852 {
1853 BoxBiTransformer::new(self).when(predicate)
1854 }
1855}
1856
1857/// Blanket implementation of FnBiTransformerOps for all closures
1858///
1859/// Automatically implements `FnBiTransformerOps<T, U, R>` for any type that
1860/// implements `Fn(T, U) -> R`.
1861///
1862/// # Author
1863///
1864/// Hu Haixing
1865impl<T, U, R, F> FnBiTransformerOps<T, U, R> for F where F: Fn(T, U) -> R + 'static {}
1866
1867// ============================================================================
1868// BinaryOperator Trait - Marker trait for BiTransformer<T, T, T>
1869// ============================================================================
1870
1871/// BinaryOperator trait - marker trait for binary operators
1872///
1873/// A binary operator takes two values of type `T` and produces a value of the
1874/// same type `T`. This trait extends `BiTransformer<T, T, T>` to provide
1875/// semantic clarity for same-type binary operations. Equivalent to Java's
1876/// `BinaryOperator<T>` which extends `BiFunction<T, T, T>`.
1877///
1878/// # Automatic Implementation
1879///
1880/// This trait is automatically implemented for all types that implement
1881/// `BiTransformer<T, T, T>`, so you don't need to implement it manually.
1882///
1883/// # Type Parameters
1884///
1885/// * `T` - The type of both input values and the output value
1886///
1887/// # Examples
1888///
1889/// ## Using in generic constraints
1890///
1891/// ```rust
1892/// use prism3_function::{BinaryOperator, BiTransformer};
1893///
1894/// fn reduce<T, O>(values: Vec<T>, initial: T, op: O) -> T
1895/// where
1896/// O: BinaryOperator<T>,
1897/// T: Clone,
1898/// {
1899/// values.into_iter().fold(initial, |acc, val| op.apply(acc, val))
1900/// }
1901///
1902/// let sum = |a: i32, b: i32| a + b;
1903/// assert_eq!(reduce(vec![1, 2, 3, 4], 0, sum), 10);
1904/// ```
1905///
1906/// ## With concrete types
1907///
1908/// ```rust
1909/// use prism3_function::{BoxBinaryOperator, BinaryOperator, BiTransformer};
1910///
1911/// fn create_adder() -> BoxBinaryOperator<i32> {
1912/// BoxBinaryOperator::new(|x, y| x + y)
1913/// }
1914///
1915/// let op = create_adder();
1916/// assert_eq!(op.apply(20, 22), 42);
1917/// ```
1918///
1919/// # Author
1920///
1921/// Hu Haixing
1922pub trait BinaryOperator<T>: BiTransformer<T, T, T> {}
1923
1924/// Blanket implementation of BinaryOperator for all BiTransformer<T, T, T>
1925///
1926/// This automatically implements `BinaryOperator<T>` for any type that
1927/// implements `BiTransformer<T, T, T>`.
1928///
1929/// # Author
1930///
1931/// Hu Haixing
1932impl<F, T> BinaryOperator<T> for F
1933where
1934 F: BiTransformer<T, T, T>,
1935 T: 'static,
1936{
1937 // empty
1938}
1939
1940// ============================================================================
1941// Type Aliases for BinaryOperator (BiTransformer<T, T, T>)
1942// ============================================================================
1943
1944/// Type alias for `BoxBiTransformer<T, T, T>`
1945///
1946/// Represents a binary operator that takes two values of type `T` and produces
1947/// a value of the same type `T`, with single ownership semantics. Equivalent to
1948/// Java's `BinaryOperator<T>`.
1949///
1950/// # Examples
1951///
1952/// ```rust
1953/// use prism3_function::{BoxBinaryOperator, BiTransformer};
1954///
1955/// let add: BoxBinaryOperator<i32> = BoxBinaryOperator::new(|x, y| x + y);
1956/// assert_eq!(add.apply(20, 22), 42);
1957/// ```
1958///
1959/// # Author
1960///
1961/// Hu Haixing
1962pub type BoxBinaryOperator<T> = BoxBiTransformer<T, T, T>;
1963
1964/// Type alias for `ArcBiTransformer<T, T, T>`
1965///
1966/// Represents a thread-safe binary operator that takes two values of type `T`
1967/// and produces a value of the same type `T`. Equivalent to Java's
1968/// `BinaryOperator<T>` with shared, thread-safe ownership.
1969///
1970/// # Examples
1971///
1972/// ```rust
1973/// use prism3_function::{ArcBinaryOperator, BiTransformer};
1974///
1975/// let multiply: ArcBinaryOperator<i32> = ArcBinaryOperator::new(|x, y| x * y);
1976/// let multiply_clone = multiply.clone();
1977/// assert_eq!(multiply.apply(6, 7), 42);
1978/// assert_eq!(multiply_clone.apply(6, 7), 42);
1979/// ```
1980///
1981/// # Author
1982///
1983/// Hu Haixing
1984pub type ArcBinaryOperator<T> = ArcBiTransformer<T, T, T>;
1985
1986/// Type alias for `RcBiTransformer<T, T, T>`
1987///
1988/// Represents a single-threaded binary operator that takes two values of type
1989/// `T` and produces a value of the same type `T`. Equivalent to Java's
1990/// `BinaryOperator<T>` with shared, single-threaded ownership.
1991///
1992/// # Examples
1993///
1994/// ```rust
1995/// use prism3_function::{RcBinaryOperator, BiTransformer};
1996///
1997/// let max: RcBinaryOperator<i32> = RcBinaryOperator::new(|x, y| if x > y { x } else { y });
1998/// let max_clone = max.clone();
1999/// assert_eq!(max.apply(30, 42), 42);
2000/// assert_eq!(max_clone.apply(30, 42), 42);
2001/// ```
2002///
2003/// # Author
2004///
2005/// Hu Haixing
2006pub type RcBinaryOperator<T> = RcBiTransformer<T, T, T>;