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// BoxConditionalBiTransformer - Box-based Conditional BiTransformer
465// ============================================================================
466
467/// BoxConditionalBiTransformer struct
468///
469/// A conditional bi-transformer that only executes when a bi-predicate is
470/// satisfied. Uses `BoxBiTransformer` and `BoxBiPredicate` for single
471/// ownership semantics.
472///
473/// This type is typically created by calling `BoxBiTransformer::when()` and is
474/// designed to work with the `or_else()` method to create if-then-else logic.
475///
476/// # Features
477///
478/// - **Single Ownership**: Not cloneable, consumes `self` on use
479/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
480/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
481/// - **Implements BiTransformer**: Can be used anywhere a `BiTransformer` is expected
482///
483/// # Examples
484///
485/// ## With or_else Branch
486///
487/// ```rust
488/// use prism3_function::{BiTransformer, BoxBiTransformer};
489///
490/// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
491/// let multiply = BoxBiTransformer::new(|x: i32, y: i32| x * y);
492/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
493///
494/// assert_eq!(conditional.apply(5, 3), 8); // when branch executed
495/// assert_eq!(conditional.apply(-5, 3), -15); // or_else branch executed
496/// ```
497///
498/// # Author
499///
500/// Haixing Hu
501pub struct BoxConditionalBiTransformer<T, U, R> {
502 transformer: BoxBiTransformer<T, U, R>,
503 predicate: BoxBiPredicate<T, U>,
504}
505
506impl<T, U, R> BoxConditionalBiTransformer<T, U, R>
507where
508 T: 'static,
509 U: 'static,
510 R: 'static,
511{
512 /// Adds an else branch
513 ///
514 /// Executes the original bi-transformer when the condition is satisfied,
515 /// otherwise executes else_transformer.
516 ///
517 /// # Parameters
518 ///
519 /// * `else_transformer` - The bi-transformer for the else branch, can be:
520 /// - Closure: `|x: T, y: U| -> R`
521 /// - `BoxBiTransformer<T, U, R>`, `RcBiTransformer<T, U, R>`, `ArcBiTransformer<T, U, R>`
522 /// - Any type implementing `BiTransformer<T, U, R>`
523 ///
524 /// # Returns
525 ///
526 /// Returns the composed `BoxBiTransformer<T, U, R>`
527 ///
528 /// # Examples
529 ///
530 /// ## Using a closure (recommended)
531 ///
532 /// ```rust
533 /// use prism3_function::{BiTransformer, BoxBiTransformer};
534 ///
535 /// let add = BoxBiTransformer::new(|x: i32, y: i32| x + y);
536 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(|x: i32, y: i32| x * y);
537 ///
538 /// assert_eq!(conditional.apply(5, 3), 8); // Condition satisfied, execute add
539 /// assert_eq!(conditional.apply(-5, 3), -15); // Condition not satisfied, execute multiply
540 /// ```
541 pub fn or_else<F>(self, else_transformer: F) -> BoxBiTransformer<T, U, R>
542 where
543 F: BiTransformer<T, U, R> + 'static,
544 {
545 let pred = self.predicate;
546 let then_trans = self.transformer;
547 BoxBiTransformer::new(move |t, u| {
548 if pred.test(&t, &u) {
549 then_trans.apply(t, u)
550 } else {
551 else_transformer.apply(t, u)
552 }
553 })
554 }
555}
556
557// ============================================================================
558// ArcBiTransformer - Arc<dyn Fn(T, U) -> R + Send + Sync>
559// ============================================================================
560
561/// ArcBiTransformer - thread-safe bi-transformer wrapper
562///
563/// A thread-safe, clonable bi-transformer wrapper suitable for multi-threaded
564/// scenarios. Can be called multiple times and shared across threads.
565///
566/// # Features
567///
568/// - **Based on**: `Arc<dyn Fn(T, U) -> R + Send + Sync>`
569/// - **Ownership**: Shared ownership via reference counting
570/// - **Reusability**: Can be called multiple times (each call consumes its
571/// inputs)
572/// - **Thread Safety**: Thread-safe (`Send + Sync` required)
573/// - **Clonable**: Cheap cloning via `Arc::clone`
574///
575/// # Author
576///
577/// Hu Haixing
578pub struct ArcBiTransformer<T, U, R> {
579 function: Arc<dyn Fn(T, U) -> R + Send + Sync>,
580}
581
582impl<T, U, R> ArcBiTransformer<T, U, R>
583where
584 T: Send + Sync + 'static,
585 U: Send + Sync + 'static,
586 R: 'static,
587{
588 /// Creates a new ArcBiTransformer
589 ///
590 /// # Parameters
591 ///
592 /// * `f` - The closure or function to wrap (must be Send + Sync)
593 ///
594 /// # Examples
595 ///
596 /// ```rust
597 /// use prism3_function::{ArcBiTransformer, BiTransformer};
598 ///
599 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
600 /// assert_eq!(add.apply(20, 22), 42);
601 /// ```
602 pub fn new<F>(f: F) -> Self
603 where
604 F: Fn(T, U) -> R + Send + Sync + 'static,
605 {
606 ArcBiTransformer {
607 function: Arc::new(f),
608 }
609 }
610
611 /// Chain composition - applies self first, then after
612 ///
613 /// Creates a new bi-transformer that applies this bi-transformer first,
614 /// then applies the after transformer to the result. Uses &self, so original
615 /// bi-transformer remains usable.
616 ///
617 /// # Type Parameters
618 ///
619 /// * `S` - The output type of the after transformer
620 /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
621 ///
622 /// # Parameters
623 ///
624 /// * `after` - The transformer to apply after self. **Note: This parameter
625 /// is passed by value and will transfer ownership.** If you need to
626 /// preserve the original transformer, clone it first (if it implements
627 /// `Clone`). Must be `Send + Sync`, can be:
628 /// - A closure: `|x: R| -> S` (must be `Send + Sync`)
629 /// - A function pointer: `fn(R) -> S`
630 /// - A `BoxTransformer<R, S>`
631 /// - An `RcTransformer<R, S>`
632 /// - An `ArcTransformer<R, S>` (will be moved)
633 /// - Any type implementing `Transformer<R, S> + Send + Sync`
634 ///
635 /// # Returns
636 ///
637 /// A new `ArcBiTransformer<T, U, S>` representing the composition
638 ///
639 /// # Examples
640 ///
641 /// ## Direct value passing (ownership transfer)
642 ///
643 /// ```rust
644 /// use prism3_function::{BiTransformer, ArcBiTransformer, ArcTransformer};
645 ///
646 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
647 /// let double = ArcTransformer::new(|x: i32| x * 2);
648 ///
649 /// // double is moved here
650 /// let composed = add.and_then(double);
651 ///
652 /// // Original add bi-transformer still usable (uses &self)
653 /// assert_eq!(add.apply(20, 22), 42);
654 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
655 /// // double.apply(10); // Would not compile - moved
656 /// ```
657 ///
658 /// ## Preserving original with clone
659 ///
660 /// ```rust
661 /// use prism3_function::{BiTransformer, ArcBiTransformer, ArcTransformer};
662 ///
663 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
664 /// let double = ArcTransformer::new(|x: i32| x * 2);
665 ///
666 /// // Clone to preserve original
667 /// let composed = add.and_then(double.clone());
668 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
669 ///
670 /// // Both originals still usable
671 /// assert_eq!(add.apply(20, 22), 42);
672 /// assert_eq!(double.apply(10), 20);
673 /// ```
674 pub fn and_then<S, F>(&self, after: F) -> ArcBiTransformer<T, U, S>
675 where
676 S: Send + Sync + 'static,
677 F: crate::transformer::Transformer<R, S> + Send + Sync + 'static,
678 {
679 let self_clone = Arc::clone(&self.function);
680 ArcBiTransformer {
681 function: Arc::new(move |t: T, u: U| after.apply(self_clone(t, u))),
682 }
683 }
684
685 /// Creates a conditional bi-transformer (thread-safe version)
686 ///
687 /// Returns a bi-transformer that only executes when a bi-predicate is
688 /// satisfied. You must call `or_else()` to provide an alternative
689 /// bi-transformer.
690 ///
691 /// # Parameters
692 ///
693 /// * `predicate` - The condition to check. **Note: This parameter is passed
694 /// by value and will transfer ownership.** If you need to preserve the
695 /// original bi-predicate, clone it first (if it implements `Clone`).
696 /// Must be `Send + Sync`, can be:
697 /// - A closure: `|x: &T, y: &U| -> bool` (requires `Send + Sync`)
698 /// - A function pointer: `fn(&T, &U) -> bool`
699 /// - An `ArcBiPredicate<T, U>`
700 /// - Any type implementing `BiPredicate<T, U> + Send + Sync`
701 ///
702 /// # Returns
703 ///
704 /// Returns `ArcConditionalBiTransformer<T, U, R>`
705 ///
706 /// # Examples
707 ///
708 /// ## Basic usage with or_else
709 ///
710 /// ```rust
711 /// use prism3_function::{BiTransformer, ArcBiTransformer};
712 ///
713 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
714 /// let multiply = ArcBiTransformer::new(|x: i32, y: i32| x * y);
715 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
716 /// .or_else(multiply);
717 ///
718 /// let conditional_clone = conditional.clone();
719 ///
720 /// assert_eq!(conditional.apply(5, 3), 8);
721 /// assert_eq!(conditional_clone.apply(-5, 3), -15);
722 /// ```
723 ///
724 /// ## Preserving bi-predicate with clone
725 ///
726 /// ```rust
727 /// use prism3_function::{BiTransformer, ArcBiTransformer, ArcBiPredicate};
728 ///
729 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
730 /// let both_positive = ArcBiPredicate::new(|x: &i32, y: &i32|
731 /// *x > 0 && *y > 0);
732 ///
733 /// // Clone to preserve original bi-predicate
734 /// let conditional = add.when(both_positive.clone())
735 /// .or_else(ArcBiTransformer::new(|x, y| x * y));
736 ///
737 /// assert_eq!(conditional.apply(5, 3), 8);
738 ///
739 /// // Original bi-predicate still usable
740 /// assert!(both_positive.test(&5, &3));
741 /// ```
742 pub fn when<P>(&self, predicate: P) -> ArcConditionalBiTransformer<T, U, R>
743 where
744 P: BiPredicate<T, U> + Send + Sync + 'static,
745 {
746 ArcConditionalBiTransformer {
747 transformer: self.clone(),
748 predicate: predicate.into_arc(),
749 }
750 }
751}
752
753impl<T, U, R> ArcBiTransformer<T, U, R>
754where
755 T: Send + Sync + 'static,
756 U: Send + Sync + 'static,
757 R: Clone + 'static,
758{
759 /// Creates a constant bi-transformer
760 ///
761 /// # Examples
762 ///
763 /// ```rust
764 /// use prism3_function::{ArcBiTransformer, BiTransformer};
765 ///
766 /// let constant = ArcBiTransformer::constant("hello");
767 /// assert_eq!(constant.apply(123, 456), "hello");
768 /// ```
769 pub fn constant(value: R) -> ArcBiTransformer<T, U, R>
770 where
771 R: Send + Sync,
772 {
773 ArcBiTransformer::new(move |_, _| value.clone())
774 }
775}
776
777impl<T, U, R> BiTransformer<T, U, R> for ArcBiTransformer<T, U, R> {
778 fn apply(&self, first: T, second: U) -> R {
779 (self.function)(first, second)
780 }
781
782 fn into_box(self) -> BoxBiTransformer<T, U, R>
783 where
784 T: 'static,
785 U: 'static,
786 R: 'static,
787 {
788 BoxBiTransformer::new(move |t, u| (self.function)(t, u))
789 }
790
791 fn into_rc(self) -> RcBiTransformer<T, U, R>
792 where
793 T: 'static,
794 U: 'static,
795 R: 'static,
796 {
797 RcBiTransformer::new(move |t, u| (self.function)(t, u))
798 }
799
800 fn into_arc(self) -> ArcBiTransformer<T, U, R>
801 where
802 T: Send + Sync + 'static,
803 U: Send + Sync + 'static,
804 R: Send + Sync + 'static,
805 {
806 // Zero-cost: directly return itself
807 self
808 }
809
810 fn into_fn(self) -> impl Fn(T, U) -> R
811 where
812 T: 'static,
813 U: 'static,
814 R: 'static,
815 {
816 move |t: T, u: U| (self.function)(t, u)
817 }
818
819 fn to_box(&self) -> BoxBiTransformer<T, U, R>
820 where
821 T: 'static,
822 U: 'static,
823 R: 'static,
824 {
825 let self_fn = self.function.clone();
826 BoxBiTransformer::new(move |t, u| self_fn(t, u))
827 }
828
829 fn to_rc(&self) -> RcBiTransformer<T, U, R>
830 where
831 T: 'static,
832 U: 'static,
833 R: 'static,
834 {
835 let self_fn = self.function.clone();
836 RcBiTransformer::new(move |t, u| self_fn(t, u))
837 }
838
839 fn to_arc(&self) -> ArcBiTransformer<T, U, R>
840 where
841 T: Send + Sync + 'static,
842 U: Send + Sync + 'static,
843 R: Send + Sync + 'static,
844 {
845 self.clone()
846 }
847
848 fn to_fn(&self) -> impl Fn(T, U) -> R
849 where
850 T: 'static,
851 U: 'static,
852 R: 'static,
853 {
854 let self_fn = self.function.clone();
855 move |t: T, u: U| self_fn(t, u)
856 }
857}
858
859impl<T, U, R> Clone for ArcBiTransformer<T, U, R> {
860 fn clone(&self) -> Self {
861 ArcBiTransformer {
862 function: Arc::clone(&self.function),
863 }
864 }
865}
866
867// ============================================================================
868// ArcConditionalBiTransformer - Arc-based Conditional BiTransformer
869// ============================================================================
870
871/// ArcConditionalBiTransformer struct
872///
873/// A thread-safe conditional bi-transformer that only executes when a
874/// bi-predicate is satisfied. Uses `ArcBiTransformer` and `ArcBiPredicate` for
875/// shared ownership across threads.
876///
877/// This type is typically created by calling `ArcBiTransformer::when()` and is
878/// designed to work with the `or_else()` method to create if-then-else logic.
879///
880/// # Features
881///
882/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
883/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
884/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
885/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
886///
887/// # Examples
888///
889/// ```rust
890/// use prism3_function::{BiTransformer, ArcBiTransformer};
891///
892/// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
893/// let multiply = ArcBiTransformer::new(|x: i32, y: i32| x * y);
894/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
895///
896/// let conditional_clone = conditional.clone();
897///
898/// assert_eq!(conditional.apply(5, 3), 8);
899/// assert_eq!(conditional_clone.apply(-5, 3), -15);
900/// ```
901///
902/// # Author
903///
904/// Haixing Hu
905pub struct ArcConditionalBiTransformer<T, U, R> {
906 transformer: ArcBiTransformer<T, U, R>,
907 predicate: ArcBiPredicate<T, U>,
908}
909
910impl<T, U, R> ArcConditionalBiTransformer<T, U, R>
911where
912 T: Send + Sync + 'static,
913 U: Send + Sync + 'static,
914 R: 'static,
915{
916 /// Adds an else branch (thread-safe version)
917 ///
918 /// Executes the original bi-transformer when the condition is satisfied,
919 /// otherwise executes else_transformer.
920 ///
921 /// # Parameters
922 ///
923 /// * `else_transformer` - The bi-transformer for the else branch, can be:
924 /// - Closure: `|x: T, y: U| -> R` (must be `Send + Sync`)
925 /// - `ArcBiTransformer<T, U, R>`, `BoxBiTransformer<T, U, R>`
926 /// - Any type implementing `BiTransformer<T, U, R> + Send + Sync`
927 ///
928 /// # Returns
929 ///
930 /// Returns the composed `ArcBiTransformer<T, U, R>`
931 ///
932 /// # Examples
933 ///
934 /// ## Using a closure (recommended)
935 ///
936 /// ```rust
937 /// use prism3_function::{BiTransformer, ArcBiTransformer};
938 ///
939 /// let add = ArcBiTransformer::new(|x: i32, y: i32| x + y);
940 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(|x: i32, y: i32| x * y);
941 ///
942 /// assert_eq!(conditional.apply(5, 3), 8);
943 /// assert_eq!(conditional.apply(-5, 3), -15);
944 /// ```
945 pub fn or_else<F>(&self, else_transformer: F) -> ArcBiTransformer<T, U, R>
946 where
947 F: BiTransformer<T, U, R> + Send + Sync + 'static,
948 R: Send + Sync,
949 {
950 let pred = self.predicate.clone();
951 let then_trans = self.transformer.clone();
952 ArcBiTransformer::new(move |t, u| {
953 if pred.test(&t, &u) {
954 then_trans.apply(t, u)
955 } else {
956 else_transformer.apply(t, u)
957 }
958 })
959 }
960}
961
962impl<T, U, R> Clone for ArcConditionalBiTransformer<T, U, R> {
963 /// Clones the conditional bi-transformer
964 ///
965 /// Creates a new instance that shares the underlying bi-transformer and
966 /// bi-predicate with the original instance.
967 fn clone(&self) -> Self {
968 ArcConditionalBiTransformer {
969 transformer: self.transformer.clone(),
970 predicate: self.predicate.clone(),
971 }
972 }
973}
974
975// ============================================================================
976// RcBiTransformer - Rc<dyn Fn(T, U) -> R>
977// ============================================================================
978
979/// RcBiTransformer - single-threaded bi-transformer wrapper
980///
981/// A single-threaded, clonable bi-transformer wrapper optimized for scenarios
982/// that require sharing without thread-safety overhead.
983///
984/// # Features
985///
986/// - **Based on**: `Rc<dyn Fn(T, U) -> R>`
987/// - **Ownership**: Shared ownership via reference counting (non-atomic)
988/// - **Reusability**: Can be called multiple times (each call consumes its
989/// inputs)
990/// - **Thread Safety**: Not thread-safe (no `Send + Sync`)
991/// - **Clonable**: Cheap cloning via `Rc::clone`
992///
993/// # Author
994///
995/// Hu Haixing
996pub struct RcBiTransformer<T, U, R> {
997 function: Rc<dyn Fn(T, U) -> R>,
998}
999
1000impl<T, U, R> RcBiTransformer<T, U, R>
1001where
1002 T: 'static,
1003 U: 'static,
1004 R: 'static,
1005{
1006 /// Creates a new RcBiTransformer
1007 ///
1008 /// # Parameters
1009 ///
1010 /// * `f` - The closure or function to wrap
1011 ///
1012 /// # Examples
1013 ///
1014 /// ```rust
1015 /// use prism3_function::{RcBiTransformer, BiTransformer};
1016 ///
1017 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1018 /// assert_eq!(add.apply(20, 22), 42);
1019 /// ```
1020 pub fn new<F>(f: F) -> Self
1021 where
1022 F: Fn(T, U) -> R + 'static,
1023 {
1024 RcBiTransformer {
1025 function: Rc::new(f),
1026 }
1027 }
1028
1029 /// Chain composition - applies self first, then after
1030 ///
1031 /// Creates a new bi-transformer that applies this bi-transformer first,
1032 /// then applies the after transformer to the result. Uses &self, so original
1033 /// bi-transformer remains usable.
1034 ///
1035 /// # Type Parameters
1036 ///
1037 /// * `S` - The output type of the after transformer
1038 /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
1039 ///
1040 /// # Parameters
1041 ///
1042 /// * `after` - The transformer to apply after self. **Note: This parameter
1043 /// is passed by value and will transfer ownership.** If you need to
1044 /// preserve the original transformer, clone it first (if it implements
1045 /// `Clone`). Can be:
1046 /// - A closure: `|x: R| -> S`
1047 /// - A function pointer: `fn(R) -> S`
1048 /// - A `BoxTransformer<R, S>`
1049 /// - An `RcTransformer<R, S>` (will be moved)
1050 /// - An `ArcTransformer<R, S>`
1051 /// - Any type implementing `Transformer<R, S>`
1052 ///
1053 /// # Returns
1054 ///
1055 /// A new `RcBiTransformer<T, U, S>` representing the composition
1056 ///
1057 /// # Examples
1058 ///
1059 /// ## Direct value passing (ownership transfer)
1060 ///
1061 /// ```rust
1062 /// use prism3_function::{BiTransformer, RcBiTransformer, RcTransformer};
1063 ///
1064 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1065 /// let double = RcTransformer::new(|x: i32| x * 2);
1066 ///
1067 /// // double is moved here
1068 /// let composed = add.and_then(double);
1069 ///
1070 /// // Original add bi-transformer still usable (uses &self)
1071 /// assert_eq!(add.apply(20, 22), 42);
1072 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
1073 /// // double.apply(10); // Would not compile - moved
1074 /// ```
1075 ///
1076 /// ## Preserving original with clone
1077 ///
1078 /// ```rust
1079 /// use prism3_function::{BiTransformer, RcBiTransformer, RcTransformer};
1080 ///
1081 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1082 /// let double = RcTransformer::new(|x: i32| x * 2);
1083 ///
1084 /// // Clone to preserve original
1085 /// let composed = add.and_then(double.clone());
1086 /// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
1087 ///
1088 /// // Both originals still usable
1089 /// assert_eq!(add.apply(20, 22), 42);
1090 /// assert_eq!(double.apply(10), 20);
1091 /// ```
1092 pub fn and_then<S, F>(&self, after: F) -> RcBiTransformer<T, U, S>
1093 where
1094 S: 'static,
1095 F: crate::transformer::Transformer<R, S> + 'static,
1096 {
1097 let self_clone = Rc::clone(&self.function);
1098 RcBiTransformer {
1099 function: Rc::new(move |t: T, u: U| after.apply(self_clone(t, u))),
1100 }
1101 }
1102
1103 /// Creates a conditional bi-transformer (single-threaded shared version)
1104 ///
1105 /// Returns a bi-transformer that only executes when a bi-predicate is
1106 /// satisfied. You must call `or_else()` to provide an alternative
1107 /// bi-transformer.
1108 ///
1109 /// # Parameters
1110 ///
1111 /// * `predicate` - The condition to check. **Note: This parameter is passed
1112 /// by value and will transfer ownership.** If you need to preserve the
1113 /// original bi-predicate, clone it first (if it implements `Clone`).
1114 /// Can be:
1115 /// - A closure: `|x: &T, y: &U| -> bool`
1116 /// - A function pointer: `fn(&T, &U) -> bool`
1117 /// - A `BoxBiPredicate<T, U>`
1118 /// - An `RcBiPredicate<T, U>`
1119 /// - An `ArcBiPredicate<T, U>`
1120 /// - Any type implementing `BiPredicate<T, U>`
1121 ///
1122 /// # Returns
1123 ///
1124 /// Returns `RcConditionalBiTransformer<T, U, R>`
1125 ///
1126 /// # Examples
1127 ///
1128 /// ## Basic usage with or_else
1129 ///
1130 /// ```rust
1131 /// use prism3_function::{BiTransformer, RcBiTransformer};
1132 ///
1133 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1134 /// let multiply = RcBiTransformer::new(|x: i32, y: i32| x * y);
1135 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0)
1136 /// .or_else(multiply);
1137 ///
1138 /// let conditional_clone = conditional.clone();
1139 ///
1140 /// assert_eq!(conditional.apply(5, 3), 8);
1141 /// assert_eq!(conditional_clone.apply(-5, 3), -15);
1142 /// ```
1143 ///
1144 /// ## Preserving bi-predicate with clone
1145 ///
1146 /// ```rust
1147 /// use prism3_function::{BiTransformer, RcBiTransformer, RcBiPredicate};
1148 ///
1149 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1150 /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
1151 /// *x > 0 && *y > 0);
1152 ///
1153 /// // Clone to preserve original bi-predicate
1154 /// let conditional = add.when(both_positive.clone())
1155 /// .or_else(RcBiTransformer::new(|x, y| x * y));
1156 ///
1157 /// assert_eq!(conditional.apply(5, 3), 8);
1158 ///
1159 /// // Original bi-predicate still usable
1160 /// assert!(both_positive.test(&5, &3));
1161 /// ```
1162 pub fn when<P>(&self, predicate: P) -> RcConditionalBiTransformer<T, U, R>
1163 where
1164 P: BiPredicate<T, U> + 'static,
1165 {
1166 RcConditionalBiTransformer {
1167 transformer: self.clone(),
1168 predicate: predicate.into_rc(),
1169 }
1170 }
1171}
1172
1173impl<T, U, R> RcBiTransformer<T, U, R>
1174where
1175 T: 'static,
1176 U: 'static,
1177 R: Clone + 'static,
1178{
1179 /// Creates a constant bi-transformer
1180 ///
1181 /// # Examples
1182 ///
1183 /// ```rust
1184 /// use prism3_function::{RcBiTransformer, BiTransformer};
1185 ///
1186 /// let constant = RcBiTransformer::constant("hello");
1187 /// assert_eq!(constant.apply(123, 456), "hello");
1188 /// ```
1189 pub fn constant(value: R) -> RcBiTransformer<T, U, R> {
1190 RcBiTransformer::new(move |_, _| value.clone())
1191 }
1192}
1193
1194impl<T, U, R> BiTransformer<T, U, R> for RcBiTransformer<T, U, R> {
1195 fn apply(&self, first: T, second: U) -> R {
1196 (self.function)(first, second)
1197 }
1198
1199 fn into_box(self) -> BoxBiTransformer<T, U, R>
1200 where
1201 T: 'static,
1202 U: 'static,
1203 R: 'static,
1204 {
1205 BoxBiTransformer::new(move |t, u| (self.function)(t, u))
1206 }
1207
1208 fn into_rc(self) -> RcBiTransformer<T, U, R>
1209 where
1210 T: 'static,
1211 U: 'static,
1212 R: 'static,
1213 {
1214 // Zero-cost: directly return itself
1215 self
1216 }
1217
1218 // do NOT override RcBiTransformer::into_arc() because RcBiTransformer is not Send + Sync
1219 // and calling RcBiTransformer::into_arc() will cause a compile error
1220
1221 fn into_fn(self) -> impl Fn(T, U) -> R
1222 where
1223 T: 'static,
1224 U: 'static,
1225 R: 'static,
1226 {
1227 move |t: T, u: U| (self.function)(t, u)
1228 }
1229
1230 fn to_box(&self) -> BoxBiTransformer<T, U, R>
1231 where
1232 T: 'static,
1233 U: 'static,
1234 R: 'static,
1235 {
1236 let self_fn = self.function.clone();
1237 BoxBiTransformer::new(move |t, u| self_fn(t, u))
1238 }
1239
1240 fn to_rc(&self) -> RcBiTransformer<T, U, R>
1241 where
1242 T: 'static,
1243 U: 'static,
1244 R: 'static,
1245 {
1246 self.clone()
1247 }
1248
1249 // do NOT override RcBiTransformer::to_arc() because RcBiTransformer is not Send + Sync
1250 // and calling RcBiTransformer::to_arc() will cause a compile error
1251
1252 fn to_fn(&self) -> impl Fn(T, U) -> R
1253 where
1254 T: 'static,
1255 U: 'static,
1256 R: 'static,
1257 {
1258 let self_fn = self.function.clone();
1259 move |t: T, u: U| self_fn(t, u)
1260 }
1261}
1262
1263impl<T, U, R> Clone for RcBiTransformer<T, U, R> {
1264 fn clone(&self) -> Self {
1265 RcBiTransformer {
1266 function: Rc::clone(&self.function),
1267 }
1268 }
1269}
1270
1271// ============================================================================
1272// RcConditionalBiTransformer - Rc-based Conditional BiTransformer
1273// ============================================================================
1274
1275/// RcConditionalBiTransformer struct
1276///
1277/// A single-threaded conditional bi-transformer that only executes when a
1278/// bi-predicate is satisfied. Uses `RcBiTransformer` and `RcBiPredicate` for
1279/// shared ownership within a single thread.
1280///
1281/// This type is typically created by calling `RcBiTransformer::when()` and is
1282/// designed to work with the `or_else()` method to create if-then-else logic.
1283///
1284/// # Features
1285///
1286/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
1287/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
1288/// - **Conditional Execution**: Only transforms when bi-predicate returns `true`
1289/// - **No Lock Overhead**: More efficient than `ArcConditionalBiTransformer`
1290///
1291/// # Examples
1292///
1293/// ```rust
1294/// use prism3_function::{BiTransformer, RcBiTransformer};
1295///
1296/// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1297/// let multiply = RcBiTransformer::new(|x: i32, y: i32| x * y);
1298/// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(multiply);
1299///
1300/// let conditional_clone = conditional.clone();
1301///
1302/// assert_eq!(conditional.apply(5, 3), 8);
1303/// assert_eq!(conditional_clone.apply(-5, 3), -15);
1304/// ```
1305///
1306/// # Author
1307///
1308/// Haixing Hu
1309pub struct RcConditionalBiTransformer<T, U, R> {
1310 transformer: RcBiTransformer<T, U, R>,
1311 predicate: RcBiPredicate<T, U>,
1312}
1313
1314impl<T, U, R> RcConditionalBiTransformer<T, U, R>
1315where
1316 T: 'static,
1317 U: 'static,
1318 R: 'static,
1319{
1320 /// Adds an else branch (single-threaded shared version)
1321 ///
1322 /// Executes the original bi-transformer when the condition is satisfied,
1323 /// otherwise executes else_transformer.
1324 ///
1325 /// # Parameters
1326 ///
1327 /// * `else_transformer` - The bi-transformer for the else branch, can be:
1328 /// - Closure: `|x: T, y: U| -> R`
1329 /// - `RcBiTransformer<T, U, R>`, `BoxBiTransformer<T, U, R>`
1330 /// - Any type implementing `BiTransformer<T, U, R>`
1331 ///
1332 /// # Returns
1333 ///
1334 /// Returns the composed `RcBiTransformer<T, U, R>`
1335 ///
1336 /// # Examples
1337 ///
1338 /// ## Using a closure (recommended)
1339 ///
1340 /// ```rust
1341 /// use prism3_function::{BiTransformer, RcBiTransformer};
1342 ///
1343 /// let add = RcBiTransformer::new(|x: i32, y: i32| x + y);
1344 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0).or_else(|x: i32, y: i32| x * y);
1345 ///
1346 /// assert_eq!(conditional.apply(5, 3), 8);
1347 /// assert_eq!(conditional.apply(-5, 3), -15);
1348 /// ```
1349 pub fn or_else<F>(&self, else_transformer: F) -> RcBiTransformer<T, U, R>
1350 where
1351 F: BiTransformer<T, U, R> + 'static,
1352 {
1353 let pred = self.predicate.clone();
1354 let then_trans = self.transformer.clone();
1355 RcBiTransformer::new(move |t, u| {
1356 if pred.test(&t, &u) {
1357 then_trans.apply(t, u)
1358 } else {
1359 else_transformer.apply(t, u)
1360 }
1361 })
1362 }
1363}
1364
1365impl<T, U, R> Clone for RcConditionalBiTransformer<T, U, R> {
1366 /// Clones the conditional bi-transformer
1367 ///
1368 /// Creates a new instance that shares the underlying bi-transformer and
1369 /// bi-predicate with the original instance.
1370 fn clone(&self) -> Self {
1371 RcConditionalBiTransformer {
1372 transformer: self.transformer.clone(),
1373 predicate: self.predicate.clone(),
1374 }
1375 }
1376}
1377
1378// ============================================================================
1379// Blanket implementation for standard Fn trait
1380// ============================================================================
1381
1382/// Implement BiTransformer<T, U, R> for any type that implements Fn(T, U) -> R
1383///
1384/// This allows closures and function pointers to be used directly with our
1385/// BiTransformer trait without wrapping.
1386///
1387/// # Examples
1388///
1389/// ```rust
1390/// use prism3_function::BiTransformer;
1391///
1392/// fn add(x: i32, y: i32) -> i32 { x + y }
1393///
1394/// assert_eq!(add.apply(20, 22), 42);
1395///
1396/// let multiply = |x: i32, y: i32| x * y;
1397/// assert_eq!(multiply.apply(6, 7), 42);
1398/// ```
1399///
1400/// # Author
1401///
1402/// Hu Haixing
1403impl<F, T, U, R> BiTransformer<T, U, R> for F
1404where
1405 F: Fn(T, U) -> R,
1406 T: 'static,
1407 U: 'static,
1408 R: 'static,
1409{
1410 fn apply(&self, first: T, second: U) -> R {
1411 self(first, second)
1412 }
1413
1414 fn into_box(self) -> BoxBiTransformer<T, U, R>
1415 where
1416 Self: Sized + 'static,
1417 {
1418 BoxBiTransformer::new(self)
1419 }
1420
1421 fn into_rc(self) -> RcBiTransformer<T, U, R>
1422 where
1423 Self: Sized + 'static,
1424 {
1425 RcBiTransformer::new(self)
1426 }
1427
1428 fn into_arc(self) -> ArcBiTransformer<T, U, R>
1429 where
1430 Self: Sized + Send + Sync + 'static,
1431 T: Send + Sync + 'static,
1432 U: Send + Sync + 'static,
1433 R: Send + Sync + 'static,
1434 {
1435 ArcBiTransformer::new(self)
1436 }
1437
1438 fn into_fn(self) -> impl Fn(T, U) -> R
1439 where
1440 Self: Sized + 'static,
1441 {
1442 move |t: T, u: U| self(t, u)
1443 }
1444
1445 fn to_box(&self) -> BoxBiTransformer<T, U, R>
1446 where
1447 Self: Sized + Clone + 'static,
1448 T: 'static,
1449 U: 'static,
1450 R: 'static,
1451 {
1452 BoxBiTransformer::new(self.clone())
1453 }
1454
1455 fn to_rc(&self) -> RcBiTransformer<T, U, R>
1456 where
1457 Self: Sized + Clone + 'static,
1458 T: 'static,
1459 U: 'static,
1460 R: 'static,
1461 {
1462 RcBiTransformer::new(self.clone())
1463 }
1464
1465 fn to_arc(&self) -> ArcBiTransformer<T, U, R>
1466 where
1467 Self: Sized + Clone + Send + Sync + 'static,
1468 T: Send + Sync + 'static,
1469 U: Send + Sync + 'static,
1470 R: Send + Sync + 'static,
1471 {
1472 ArcBiTransformer::new(self.clone())
1473 }
1474
1475 fn to_fn(&self) -> impl Fn(T, U) -> R
1476 where
1477 Self: Sized + Clone + 'static,
1478 T: 'static,
1479 U: 'static,
1480 R: 'static,
1481 {
1482 self.clone()
1483 }
1484}
1485
1486// ============================================================================
1487// FnBiTransformerOps - Extension trait for Fn(T, U) -> R bi-transformers
1488// ============================================================================
1489
1490/// Extension trait for closures implementing `Fn(T, U) -> R`
1491///
1492/// Provides composition methods (`and_then`, `when`) for bi-transformer
1493/// closures and function pointers without requiring explicit wrapping in
1494/// `BoxBiTransformer`.
1495///
1496/// This trait is automatically implemented for all closures and function
1497/// pointers that implement `Fn(T, U) -> R`.
1498///
1499/// # Design Rationale
1500///
1501/// While closures automatically implement `BiTransformer<T, U, R>` through
1502/// blanket implementation, they don't have access to instance methods like
1503/// `and_then` and `when`. This extension trait provides those methods,
1504/// returning `BoxBiTransformer` for maximum flexibility.
1505///
1506/// # Examples
1507///
1508/// ## Chain composition with and_then
1509///
1510/// ```rust
1511/// use prism3_function::{BiTransformer, FnBiTransformerOps};
1512///
1513/// let add = |x: i32, y: i32| x + y;
1514/// let double = |x: i32| x * 2;
1515///
1516/// let composed = add.and_then(double);
1517/// assert_eq!(composed.apply(3, 5), 16); // (3 + 5) * 2
1518/// ```
1519///
1520/// ## Conditional execution with when
1521///
1522/// ```rust
1523/// use prism3_function::{BiTransformer, FnBiTransformerOps};
1524///
1525/// let add = |x: i32, y: i32| x + y;
1526/// let multiply = |x: i32, y: i32| x * y;
1527///
1528/// let conditional = add.when(|x: &i32, y: &i32| *x > 0 && *y > 0).or_else(multiply);
1529///
1530/// assert_eq!(conditional.apply(5, 3), 8); // add
1531/// assert_eq!(conditional.apply(-5, 3), -15); // multiply
1532/// ```
1533///
1534/// # Author
1535///
1536/// Hu Haixing
1537pub trait FnBiTransformerOps<T, U, R>: Fn(T, U) -> R + Sized + 'static {
1538 /// Chain composition - applies self first, then after
1539 ///
1540 /// Creates a new bi-transformer that applies this bi-transformer first,
1541 /// then applies the after transformer to the result. Consumes self and
1542 /// returns a `BoxBiTransformer`.
1543 ///
1544 /// # Type Parameters
1545 ///
1546 /// * `S` - The output type of the after transformer
1547 /// * `F` - The type of the after transformer (must implement Transformer<R, S>)
1548 ///
1549 /// # Parameters
1550 ///
1551 /// * `after` - The transformer to apply after self. **Note: This parameter
1552 /// is passed by value and will transfer ownership.** If you need to
1553 /// preserve the original transformer, clone it first (if it implements
1554 /// `Clone`). Can be:
1555 /// - A closure: `|x: R| -> S`
1556 /// - A function pointer: `fn(R) -> S`
1557 /// - A `BoxTransformer<R, S>`
1558 /// - An `RcTransformer<R, S>`
1559 /// - An `ArcTransformer<R, S>`
1560 /// - Any type implementing `Transformer<R, S>`
1561 ///
1562 /// # Returns
1563 ///
1564 /// A new `BoxBiTransformer<T, U, S>` representing the composition
1565 ///
1566 /// # Examples
1567 ///
1568 /// ## Direct value passing (ownership transfer)
1569 ///
1570 /// ```rust
1571 /// use prism3_function::{BiTransformer, FnBiTransformerOps,
1572 /// BoxTransformer};
1573 ///
1574 /// let add = |x: i32, y: i32| x + y;
1575 /// let to_string = BoxTransformer::new(|x: i32| x.to_string());
1576 ///
1577 /// // to_string is moved here
1578 /// let composed = add.and_then(to_string);
1579 /// assert_eq!(composed.apply(20, 22), "42");
1580 /// // to_string.apply(10); // Would not compile - moved
1581 /// ```
1582 ///
1583 /// ## Preserving original with clone
1584 ///
1585 /// ```rust
1586 /// use prism3_function::{BiTransformer, FnBiTransformerOps,
1587 /// BoxTransformer};
1588 ///
1589 /// let add = |x: i32, y: i32| x + y;
1590 /// let to_string = BoxTransformer::new(|x: i32| x.to_string());
1591 ///
1592 /// // Clone to preserve original
1593 /// let composed = add.and_then(to_string.clone());
1594 /// assert_eq!(composed.apply(20, 22), "42");
1595 ///
1596 /// // Original still usable
1597 /// assert_eq!(to_string.apply(10), "10");
1598 /// ```
1599 fn and_then<S, F>(self, after: F) -> BoxBiTransformer<T, U, S>
1600 where
1601 S: 'static,
1602 F: crate::transformer::Transformer<R, S> + 'static,
1603 T: 'static,
1604 U: 'static,
1605 R: 'static,
1606 {
1607 BoxBiTransformer::new(move |t: T, u: U| after.apply(self(t, u)))
1608 }
1609
1610 /// Creates a conditional bi-transformer
1611 ///
1612 /// Returns a bi-transformer that only executes when a bi-predicate is
1613 /// satisfied. You must call `or_else()` to provide an alternative
1614 /// bi-transformer for when the condition is not satisfied.
1615 ///
1616 /// # Parameters
1617 ///
1618 /// * `predicate` - The condition to check. **Note: This parameter is passed
1619 /// by value and will transfer ownership.** If you need to preserve the
1620 /// original bi-predicate, clone it first (if it implements `Clone`).
1621 /// Can be:
1622 /// - A closure: `|x: &T, y: &U| -> bool`
1623 /// - A function pointer: `fn(&T, &U) -> bool`
1624 /// - A `BoxBiPredicate<T, U>`
1625 /// - An `RcBiPredicate<T, U>`
1626 /// - An `ArcBiPredicate<T, U>`
1627 /// - Any type implementing `BiPredicate<T, U>`
1628 ///
1629 /// # Returns
1630 ///
1631 /// Returns `BoxConditionalBiTransformer<T, U, R>`
1632 ///
1633 /// # Examples
1634 ///
1635 /// ## Basic usage with or_else
1636 ///
1637 /// ```rust
1638 /// use prism3_function::{BiTransformer, FnBiTransformerOps};
1639 ///
1640 /// let add = |x: i32, y: i32| x + y;
1641 /// let conditional = add.when(|x: &i32, y: &i32| *x > 0)
1642 /// .or_else(|x: i32, y: i32| x * y);
1643 ///
1644 /// assert_eq!(conditional.apply(5, 3), 8);
1645 /// assert_eq!(conditional.apply(-5, 3), -15);
1646 /// ```
1647 ///
1648 /// ## Preserving bi-predicate with clone
1649 ///
1650 /// ```rust
1651 /// use prism3_function::{BiTransformer, FnBiTransformerOps,
1652 /// RcBiPredicate};
1653 ///
1654 /// let add = |x: i32, y: i32| x + y;
1655 /// let both_positive = RcBiPredicate::new(|x: &i32, y: &i32|
1656 /// *x > 0 && *y > 0);
1657 ///
1658 /// // Clone to preserve original bi-predicate
1659 /// let conditional = add.when(both_positive.clone())
1660 /// .or_else(|x: i32, y: i32| x * y);
1661 ///
1662 /// assert_eq!(conditional.apply(5, 3), 8);
1663 ///
1664 /// // Original bi-predicate still usable
1665 /// assert!(both_positive.test(&5, &3));
1666 /// ```
1667 fn when<P>(self, predicate: P) -> BoxConditionalBiTransformer<T, U, R>
1668 where
1669 P: BiPredicate<T, U> + 'static,
1670 T: 'static,
1671 U: 'static,
1672 R: 'static,
1673 {
1674 BoxBiTransformer::new(self).when(predicate)
1675 }
1676}
1677
1678/// Blanket implementation of FnBiTransformerOps for all closures
1679///
1680/// Automatically implements `FnBiTransformerOps<T, U, R>` for any type that
1681/// implements `Fn(T, U) -> R`.
1682///
1683/// # Author
1684///
1685/// Hu Haixing
1686impl<T, U, R, F> FnBiTransformerOps<T, U, R> for F where F: Fn(T, U) -> R + 'static {}
1687
1688// ============================================================================
1689// BinaryOperator Trait - Marker trait for BiTransformer<T, T, T>
1690// ============================================================================
1691
1692/// BinaryOperator trait - marker trait for binary operators
1693///
1694/// A binary operator takes two values of type `T` and produces a value of the
1695/// same type `T`. This trait extends `BiTransformer<T, T, T>` to provide
1696/// semantic clarity for same-type binary operations. Equivalent to Java's
1697/// `BinaryOperator<T>` which extends `BiFunction<T, T, T>`.
1698///
1699/// # Automatic Implementation
1700///
1701/// This trait is automatically implemented for all types that implement
1702/// `BiTransformer<T, T, T>`, so you don't need to implement it manually.
1703///
1704/// # Type Parameters
1705///
1706/// * `T` - The type of both input values and the output value
1707///
1708/// # Examples
1709///
1710/// ## Using in generic constraints
1711///
1712/// ```rust
1713/// use prism3_function::{BinaryOperator, BiTransformer};
1714///
1715/// fn reduce<T, O>(values: Vec<T>, initial: T, op: O) -> T
1716/// where
1717/// O: BinaryOperator<T>,
1718/// T: Clone,
1719/// {
1720/// values.into_iter().fold(initial, |acc, val| op.apply(acc, val))
1721/// }
1722///
1723/// let sum = |a: i32, b: i32| a + b;
1724/// assert_eq!(reduce(vec![1, 2, 3, 4], 0, sum), 10);
1725/// ```
1726///
1727/// ## With concrete types
1728///
1729/// ```rust
1730/// use prism3_function::{BoxBinaryOperator, BinaryOperator, BiTransformer};
1731///
1732/// fn create_adder() -> BoxBinaryOperator<i32> {
1733/// BoxBinaryOperator::new(|x, y| x + y)
1734/// }
1735///
1736/// let op = create_adder();
1737/// assert_eq!(op.apply(20, 22), 42);
1738/// ```
1739///
1740/// # Author
1741///
1742/// Hu Haixing
1743pub trait BinaryOperator<T>: BiTransformer<T, T, T> {}
1744
1745/// Blanket implementation of BinaryOperator for all BiTransformer<T, T, T>
1746///
1747/// This automatically implements `BinaryOperator<T>` for any type that
1748/// implements `BiTransformer<T, T, T>`.
1749///
1750/// # Author
1751///
1752/// Hu Haixing
1753impl<F, T> BinaryOperator<T> for F
1754where
1755 F: BiTransformer<T, T, T>,
1756 T: 'static,
1757{
1758 // empty
1759}
1760
1761// ============================================================================
1762// Type Aliases for BinaryOperator (BiTransformer<T, T, T>)
1763// ============================================================================
1764
1765/// Type alias for `BoxBiTransformer<T, T, T>`
1766///
1767/// Represents a binary operator that takes two values of type `T` and produces
1768/// a value of the same type `T`, with single ownership semantics. Equivalent to
1769/// Java's `BinaryOperator<T>`.
1770///
1771/// # Examples
1772///
1773/// ```rust
1774/// use prism3_function::{BoxBinaryOperator, BiTransformer};
1775///
1776/// let add: BoxBinaryOperator<i32> = BoxBinaryOperator::new(|x, y| x + y);
1777/// assert_eq!(add.apply(20, 22), 42);
1778/// ```
1779///
1780/// # Author
1781///
1782/// Hu Haixing
1783pub type BoxBinaryOperator<T> = BoxBiTransformer<T, T, T>;
1784
1785/// Type alias for `ArcBiTransformer<T, T, T>`
1786///
1787/// Represents a thread-safe binary operator that takes two values of type `T`
1788/// and produces a value of the same type `T`. Equivalent to Java's
1789/// `BinaryOperator<T>` with shared, thread-safe ownership.
1790///
1791/// # Examples
1792///
1793/// ```rust
1794/// use prism3_function::{ArcBinaryOperator, BiTransformer};
1795///
1796/// let multiply: ArcBinaryOperator<i32> = ArcBinaryOperator::new(|x, y| x * y);
1797/// let multiply_clone = multiply.clone();
1798/// assert_eq!(multiply.apply(6, 7), 42);
1799/// assert_eq!(multiply_clone.apply(6, 7), 42);
1800/// ```
1801///
1802/// # Author
1803///
1804/// Hu Haixing
1805pub type ArcBinaryOperator<T> = ArcBiTransformer<T, T, T>;
1806
1807/// Type alias for `RcBiTransformer<T, T, T>`
1808///
1809/// Represents a single-threaded binary operator that takes two values of type
1810/// `T` and produces a value of the same type `T`. Equivalent to Java's
1811/// `BinaryOperator<T>` with shared, single-threaded ownership.
1812///
1813/// # Examples
1814///
1815/// ```rust
1816/// use prism3_function::{RcBinaryOperator, BiTransformer};
1817///
1818/// let max: RcBinaryOperator<i32> = RcBinaryOperator::new(|x, y| if x > y { x } else { y });
1819/// let max_clone = max.clone();
1820/// assert_eq!(max.apply(30, 42), 42);
1821/// assert_eq!(max_clone.apply(30, 42), 42);
1822/// ```
1823///
1824/// # Author
1825///
1826/// Hu Haixing
1827pub type RcBinaryOperator<T> = RcBiTransformer<T, T, T>;