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