prism3_function/transformer_once.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025.
4 * 3-Prism Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # TransformerOnce Types
10//!
11//! Provides Rust implementations of consuming transformer traits similar to
12//! Rust's `FnOnce` trait, but with value-oriented semantics for functional
13//! programming patterns.
14//!
15//! This module provides the `TransformerOnce<T, R>` trait and one-time use
16//! implementations:
17//!
18//! - [`BoxTransformerOnce`]: Single ownership, one-time use
19//!
20//! # Author
21//!
22//! Hu Haixing
23
24use crate::predicate::{BoxPredicate, Predicate};
25
26// ============================================================================
27// Core Trait
28// ============================================================================
29
30/// TransformerOnce trait - consuming transformation that takes ownership
31///
32/// Defines the behavior of a consuming transformer: converting a value of
33/// type `T` to a value of type `R` by taking ownership of both self and the
34/// input. This trait is analogous to `FnOnce(T) -> R`.
35///
36/// # Type Parameters
37///
38/// * `T` - The type of the input value (consumed)
39/// * `R` - The type of the output value
40///
41/// # Author
42///
43/// Hu Haixing
44pub trait TransformerOnce<T, R> {
45 /// Transforms the input value, consuming both self and input
46 ///
47 /// # Parameters
48 ///
49 /// * `input` - The input value (consumed)
50 ///
51 /// # Returns
52 ///
53 /// The transformed output value
54 fn transform(self, input: T) -> R;
55
56 /// Converts to BoxTransformerOnce
57 ///
58 /// **⚠️ Consumes `self`**: The original transformer becomes unavailable
59 /// after calling this method.
60 ///
61 /// # Returns
62 ///
63 /// Returns `BoxTransformerOnce<T, R>`
64 fn into_box(self) -> BoxTransformerOnce<T, R>
65 where
66 Self: Sized + 'static,
67 T: 'static,
68 R: 'static;
69
70 /// Converts transformer to a closure
71 ///
72 /// **⚠️ Consumes `self`**: The original transformer becomes unavailable
73 /// after calling this method.
74 ///
75 /// # Returns
76 ///
77 /// Returns a closure that implements `FnOnce(T) -> R`
78 fn into_fn(self) -> impl FnOnce(T) -> R
79 where
80 Self: Sized + 'static,
81 T: 'static,
82 R: 'static;
83}
84
85// ============================================================================
86// BoxTransformerOnce - Box<dyn FnOnce(T) -> R>
87// ============================================================================
88
89/// BoxTransformerOnce - consuming transformer wrapper based on
90/// `Box<dyn FnOnce>`
91///
92/// A transformer wrapper that provides single ownership with one-time use
93/// semantics. Consumes both self and the input value.
94///
95/// # Features
96///
97/// - **Based on**: `Box<dyn FnOnce(T) -> R>`
98/// - **Ownership**: Single ownership, cannot be cloned
99/// - **Reusability**: Can only be called once (consumes self and input)
100/// - **Thread Safety**: Not thread-safe (no `Send + Sync` requirement)
101///
102/// # Author
103///
104/// Hu Haixing
105pub struct BoxTransformerOnce<T, R> {
106 function: Box<dyn FnOnce(T) -> R>,
107}
108
109impl<T, R> BoxTransformerOnce<T, R>
110where
111 T: 'static,
112 R: 'static,
113{
114 /// Creates a new BoxTransformerOnce
115 ///
116 /// # Parameters
117 ///
118 /// * `f` - The closure or function to wrap
119 ///
120 /// # Examples
121 ///
122 /// ```rust
123 /// use prism3_function::{BoxTransformerOnce, TransformerOnce};
124 ///
125 /// let parse = BoxTransformerOnce::new(|s: String| {
126 /// s.parse::<i32>().unwrap_or(0)
127 /// });
128 ///
129 /// assert_eq!(parse.transform("42".to_string()), 42);
130 /// ```
131 pub fn new<F>(f: F) -> Self
132 where
133 F: FnOnce(T) -> R + 'static,
134 {
135 BoxTransformerOnce {
136 function: Box::new(f),
137 }
138 }
139
140 /// Creates an identity transformer
141 ///
142 /// # Examples
143 ///
144 /// ```rust
145 /// use prism3_function::{BoxTransformerOnce, TransformerOnce};
146 ///
147 /// let identity = BoxTransformerOnce::<i32, i32>::identity();
148 /// assert_eq!(identity.transform(42), 42);
149 /// ```
150 pub fn identity() -> BoxTransformerOnce<T, T> {
151 BoxTransformerOnce::new(|x| x)
152 }
153
154 /// Chain composition - applies self first, then after
155 ///
156 /// # Type Parameters
157 ///
158 /// * `S` - The output type of the after transformer
159 /// * `G` - The type of the after transformer (must implement
160 /// TransformerOnce<R, S>)
161 ///
162 /// # Parameters
163 ///
164 /// * `after` - The transformer to apply after self. **Note: This parameter
165 /// is passed by value and will transfer ownership.** Since
166 /// `BoxTransformerOnce` cannot be cloned, the parameter will be consumed.
167 /// Can be:
168 /// - A closure: `|x: R| -> S`
169 /// - A function pointer: `fn(R) -> S`
170 /// - A `BoxTransformerOnce<R, S>`
171 /// - Any type implementing `TransformerOnce<R, S>`
172 ///
173 /// # Returns
174 ///
175 /// A new BoxTransformerOnce representing the composition
176 ///
177 /// # Examples
178 ///
179 /// ```rust
180 /// use prism3_function::{BoxTransformerOnce, TransformerOnce};
181 ///
182 /// let add_one = BoxTransformerOnce::new(|x: i32| x + 1);
183 /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
184 ///
185 /// // Both add_one and double are moved and consumed
186 /// let composed = add_one.and_then(double);
187 /// assert_eq!(composed.transform(5), 12); // (5 + 1) * 2
188 /// // add_one.transform(3); // Would not compile - moved
189 /// // double.transform(4); // Would not compile - moved
190 /// ```
191 pub fn and_then<S, G>(self, after: G) -> BoxTransformerOnce<T, S>
192 where
193 S: 'static,
194 G: TransformerOnce<R, S> + 'static,
195 {
196 BoxTransformerOnce::new(move |x| {
197 let intermediate = (self.function)(x);
198 after.transform(intermediate)
199 })
200 }
201
202 /// Reverse composition - applies before first, then self
203 ///
204 /// # Type Parameters
205 ///
206 /// * `S` - The input type of the before transformer
207 /// * `G` - The type of the before transformer (must implement
208 /// TransformerOnce<S, T>)
209 ///
210 /// # Parameters
211 ///
212 /// * `before` - The transformer to apply before self. **Note: This parameter
213 /// is passed by value and will transfer ownership.** Since
214 /// `BoxTransformerOnce` cannot be cloned, the parameter will be consumed.
215 /// Can be:
216 /// - A closure: `|x: S| -> T`
217 /// - A function pointer: `fn(S) -> T`
218 /// - A `BoxTransformerOnce<S, T>`
219 /// - Any type implementing `TransformerOnce<S, T>`
220 ///
221 /// # Returns
222 ///
223 /// A new BoxTransformerOnce representing the composition
224 ///
225 /// # Examples
226 ///
227 /// ```rust
228 /// use prism3_function::{BoxTransformerOnce, TransformerOnce};
229 ///
230 /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
231 /// let add_one = BoxTransformerOnce::new(|x: i32| x + 1);
232 ///
233 /// // Both double and add_one are moved and consumed
234 /// let composed = double.compose(add_one);
235 /// assert_eq!(composed.transform(5), 12); // (5 + 1) * 2
236 /// // double.transform(3); // Would not compile - moved
237 /// // add_one.transform(4); // Would not compile - moved
238 /// ```
239 pub fn compose<S, G>(self, before: G) -> BoxTransformerOnce<S, R>
240 where
241 S: 'static,
242 G: TransformerOnce<S, T> + 'static,
243 {
244 BoxTransformerOnce::new(move |x| {
245 let intermediate = before.transform(x);
246 (self.function)(intermediate)
247 })
248 }
249
250 /// Creates a conditional transformer
251 ///
252 /// Returns a transformer that only executes when a predicate is satisfied.
253 /// You must call `or_else()` to provide an alternative transformer.
254 ///
255 /// # Parameters
256 ///
257 /// * `predicate` - The condition to check. **Note: This parameter is passed
258 /// by value and will transfer ownership.** If you need to preserve the
259 /// original predicate, clone it first (if it implements `Clone`). Can be:
260 /// - A closure: `|x: &T| -> bool`
261 /// - A function pointer: `fn(&T) -> bool`
262 /// - A `BoxPredicate<T>`
263 /// - An `RcPredicate<T>`
264 /// - An `ArcPredicate<T>`
265 /// - Any type implementing `Predicate<T>`
266 ///
267 /// # Returns
268 ///
269 /// Returns `BoxConditionalTransformerOnce<T, R>`
270 ///
271 /// # Examples
272 ///
273 /// ## Basic usage with or_else
274 ///
275 /// ```rust
276 /// use prism3_function::{TransformerOnce, BoxTransformerOnce};
277 ///
278 /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
279 /// let identity = BoxTransformerOnce::<i32, i32>::identity();
280 /// let conditional = double.when(|x: &i32| *x > 0).or_else(identity);
281 /// assert_eq!(conditional.transform(5), 10);
282 ///
283 /// let double2 = BoxTransformerOnce::new(|x: i32| x * 2);
284 /// let identity2 = BoxTransformerOnce::<i32, i32>::identity();
285 /// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(identity2);
286 /// assert_eq!(conditional2.transform(-5), -5);
287 /// ```
288 ///
289 /// ## Preserving predicate with clone
290 ///
291 /// ```rust
292 /// use prism3_function::{TransformerOnce, BoxTransformerOnce, RcPredicate};
293 ///
294 /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
295 /// let is_positive = RcPredicate::new(|x: &i32| *x > 0);
296 ///
297 /// // Clone to preserve original predicate
298 /// let conditional = double.when(is_positive.clone())
299 /// .or_else(BoxTransformerOnce::identity());
300 ///
301 /// assert_eq!(conditional.transform(5), 10);
302 ///
303 /// // Original predicate still usable
304 /// assert!(is_positive.test(&3));
305 /// ```
306 pub fn when<P>(self, predicate: P) -> BoxConditionalTransformerOnce<T, R>
307 where
308 P: Predicate<T> + 'static,
309 {
310 BoxConditionalTransformerOnce {
311 transformer: self,
312 predicate: predicate.into_box(),
313 }
314 }
315}
316
317impl<T, R> BoxTransformerOnce<T, R>
318where
319 T: 'static,
320 R: Clone + 'static,
321{
322 /// Creates a constant transformer
323 ///
324 /// # Examples
325 ///
326 /// ```rust
327 /// use prism3_function::{BoxTransformerOnce, TransformerOnce};
328 ///
329 /// let constant = BoxTransformerOnce::constant("hello");
330 /// assert_eq!(constant.transform(123), "hello");
331 /// ```
332 pub fn constant(value: R) -> BoxTransformerOnce<T, R> {
333 BoxTransformerOnce::new(move |_| value.clone())
334 }
335}
336
337impl<T, R> TransformerOnce<T, R> for BoxTransformerOnce<T, R> {
338 fn transform(self, input: T) -> R {
339 (self.function)(input)
340 }
341
342 fn into_box(self) -> BoxTransformerOnce<T, R>
343 where
344 T: 'static,
345 R: 'static,
346 {
347 // Zero-cost: directly return itself
348 self
349 }
350
351 fn into_fn(self) -> impl FnOnce(T) -> R
352 where
353 T: 'static,
354 R: 'static,
355 {
356 move |t: T| self.transform(t)
357 }
358}
359
360// ============================================================================
361// BoxConditionalTransformerOnce - Box-based Conditional Transformer
362// ============================================================================
363
364/// BoxConditionalTransformerOnce struct
365///
366/// A conditional consuming transformer that only executes when a predicate is
367/// satisfied. Uses `BoxTransformerOnce` and `BoxPredicate` for single
368/// ownership semantics.
369///
370/// This type is typically created by calling `BoxTransformerOnce::when()` and
371/// is designed to work with the `or_else()` method to create if-then-else
372/// logic.
373///
374/// # Features
375///
376/// - **Single Ownership**: Not cloneable, consumes `self` on use
377/// - **One-time Use**: Can only be called once
378/// - **Conditional Execution**: Only transforms when predicate returns `true`
379/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
380///
381/// # Examples
382///
383/// ## With or_else Branch
384///
385/// ```rust
386/// use prism3_function::{TransformerOnce, BoxTransformerOnce};
387///
388/// let double = BoxTransformerOnce::new(|x: i32| x * 2);
389/// let negate = BoxTransformerOnce::new(|x: i32| -x);
390/// let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
391/// assert_eq!(conditional.transform(5), 10); // when branch executed
392///
393/// let double2 = BoxTransformerOnce::new(|x: i32| x * 2);
394/// let negate2 = BoxTransformerOnce::new(|x: i32| -x);
395/// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(negate2);
396/// assert_eq!(conditional2.transform(-5), 5); // or_else branch executed
397/// ```
398///
399/// # Author
400///
401/// Haixing Hu
402pub struct BoxConditionalTransformerOnce<T, R> {
403 transformer: BoxTransformerOnce<T, R>,
404 predicate: BoxPredicate<T>,
405}
406
407impl<T, R> BoxConditionalTransformerOnce<T, R>
408where
409 T: 'static,
410 R: 'static,
411{
412 /// Adds an else branch
413 ///
414 /// Executes the original transformer when the condition is satisfied,
415 /// otherwise executes else_transformer.
416 ///
417 /// # Parameters
418 ///
419 /// * `else_transformer` - The transformer for the else branch, can be:
420 /// - Closure: `|x: T| -> R`
421 /// - `BoxTransformerOnce<T, R>`
422 /// - Any type implementing `TransformerOnce<T, R>`
423 ///
424 /// # Returns
425 ///
426 /// Returns the composed `BoxTransformerOnce<T, R>`
427 ///
428 /// # Examples
429 ///
430 /// ## Using a closure (recommended)
431 ///
432 /// ```rust
433 /// use prism3_function::{TransformerOnce, BoxTransformerOnce};
434 ///
435 /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
436 /// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
437 /// assert_eq!(conditional.transform(5), 10); // Condition satisfied, execute double
438 ///
439 /// let double2 = BoxTransformerOnce::new(|x: i32| x * 2);
440 /// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
441 /// assert_eq!(conditional2.transform(-5), 5); // Condition not satisfied, execute negate
442 /// ```
443 pub fn or_else<F>(self, else_transformer: F) -> BoxTransformerOnce<T, R>
444 where
445 F: TransformerOnce<T, R> + 'static,
446 {
447 let pred = self.predicate;
448 let then_trans = self.transformer;
449 BoxTransformerOnce::new(move |t| {
450 if pred.test(&t) {
451 then_trans.transform(t)
452 } else {
453 else_transformer.transform(t)
454 }
455 })
456 }
457}
458
459// ============================================================================
460// Blanket implementation for standard FnOnce trait
461// ============================================================================
462
463/// Implement TransformerOnce<T, R> for any type that implements
464/// FnOnce(T) -> R
465///
466/// This allows once-callable closures and function pointers to be used
467/// directly with our TransformerOnce trait without wrapping.
468///
469/// # Examples
470///
471/// ```rust
472/// use prism3_function::TransformerOnce;
473///
474/// fn parse(s: String) -> i32 {
475/// s.parse().unwrap_or(0)
476/// }
477///
478/// assert_eq!(parse.transform("42".to_string()), 42);
479///
480/// let owned_value = String::from("hello");
481/// let consume = |s: String| {
482/// format!("{} world", s)
483/// };
484/// assert_eq!(consume.transform(owned_value), "hello world");
485/// ```
486///
487/// # Author
488///
489/// Hu Haixing
490impl<F, T, R> TransformerOnce<T, R> for F
491where
492 F: FnOnce(T) -> R,
493 T: 'static,
494 R: 'static,
495{
496 fn transform(self, input: T) -> R {
497 self(input)
498 }
499
500 fn into_box(self) -> BoxTransformerOnce<T, R>
501 where
502 Self: Sized + 'static,
503 {
504 BoxTransformerOnce::new(self)
505 }
506
507 fn into_fn(self) -> impl FnOnce(T) -> R
508 where
509 Self: Sized + 'static,
510 {
511 move |input: T| -> R { self(input) }
512 }
513}
514
515// ============================================================================
516// FnTransformerOnceOps - Extension trait for FnOnce transformers
517// ============================================================================
518
519/// Extension trait for closures implementing `FnOnce(T) -> R`
520///
521/// Provides composition methods (`and_then`, `compose`, `when`) for one-time
522/// use closures and function pointers without requiring explicit wrapping in
523/// `BoxTransformerOnce`.
524///
525/// This trait is automatically implemented for all closures and function
526/// pointers that implement `FnOnce(T) -> R`.
527///
528/// # Design Rationale
529///
530/// While closures automatically implement `TransformerOnce<T, R>` through
531/// blanket implementation, they don't have access to instance methods like
532/// `and_then`, `compose`, and `when`. This extension trait provides those
533/// methods, returning `BoxTransformerOnce` for maximum flexibility.
534///
535/// # Examples
536///
537/// ## Chain composition with and_then
538///
539/// ```rust
540/// use prism3_function::{TransformerOnce, FnTransformerOnceOps};
541///
542/// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
543/// let double = |x: i32| x * 2;
544///
545/// let composed = parse.and_then(double);
546/// assert_eq!(composed.transform("21".to_string()), 42);
547/// ```
548///
549/// ## Reverse composition with compose
550///
551/// ```rust
552/// use prism3_function::{TransformerOnce, FnTransformerOnceOps};
553///
554/// let double = |x: i32| x * 2;
555/// let to_string = |x: i32| x.to_string();
556///
557/// let composed = to_string.compose(double);
558/// assert_eq!(composed.transform(21), "42");
559/// ```
560///
561/// ## Conditional transformation with when
562///
563/// ```rust
564/// use prism3_function::{TransformerOnce, FnTransformerOnceOps};
565///
566/// let double = |x: i32| x * 2;
567/// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
568///
569/// assert_eq!(conditional.transform(5), 10);
570/// ```
571///
572/// # Author
573///
574/// Hu Haixing
575pub trait FnTransformerOnceOps<T, R>: FnOnce(T) -> R + Sized + 'static {
576 /// Chain composition - applies self first, then after
577 ///
578 /// Creates a new transformer that applies this transformer first, then
579 /// applies the after transformer to the result. Consumes self and returns
580 /// a `BoxTransformerOnce`.
581 ///
582 /// # Type Parameters
583 ///
584 /// * `S` - The output type of the after transformer
585 /// * `G` - The type of the after transformer (must implement
586 /// TransformerOnce<R, S>)
587 ///
588 /// # Parameters
589 ///
590 /// * `after` - The transformer to apply after self. **Note: This parameter
591 /// is passed by value and will transfer ownership.** Since this is a
592 /// `FnOnce` transformer, the parameter will be consumed. Can be:
593 /// - A closure: `|x: R| -> S`
594 /// - A function pointer: `fn(R) -> S`
595 /// - A `BoxTransformerOnce<R, S>`
596 /// - Any type implementing `TransformerOnce<R, S>`
597 ///
598 /// # Returns
599 ///
600 /// A new `BoxTransformerOnce<T, S>` representing the composition
601 ///
602 /// # Examples
603 ///
604 /// ```rust
605 /// use prism3_function::{TransformerOnce, FnTransformerOnceOps,
606 /// BoxTransformerOnce};
607 ///
608 /// let parse = |s: String| s.parse::<i32>().unwrap_or(0);
609 /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
610 ///
611 /// // double is moved and consumed
612 /// let composed = parse.and_then(double);
613 /// assert_eq!(composed.transform("21".to_string()), 42);
614 /// // double.transform(5); // Would not compile - moved
615 /// ```
616 fn and_then<S, G>(self, after: G) -> BoxTransformerOnce<T, S>
617 where
618 S: 'static,
619 G: TransformerOnce<R, S> + 'static,
620 T: 'static,
621 R: 'static,
622 {
623 BoxTransformerOnce::new(move |x: T| {
624 let intermediate = self(x);
625 after.transform(intermediate)
626 })
627 }
628
629 /// Reverse composition - applies before first, then self
630 ///
631 /// Creates a new transformer that applies the before transformer first,
632 /// then applies this transformer to the result. Consumes self and returns
633 /// a `BoxTransformerOnce`.
634 ///
635 /// # Type Parameters
636 ///
637 /// * `S` - The input type of the before transformer
638 /// * `G` - The type of the before transformer (must implement
639 /// TransformerOnce<S, T>)
640 ///
641 /// # Parameters
642 ///
643 /// * `before` - The transformer to apply before self. **Note: This parameter
644 /// is passed by value and will transfer ownership.** Since this is a
645 /// `FnOnce` transformer, the parameter will be consumed. Can be:
646 /// - A closure: `|x: S| -> T`
647 /// - A function pointer: `fn(S) -> T`
648 /// - A `BoxTransformerOnce<S, T>`
649 /// - Any type implementing `TransformerOnce<S, T>`
650 ///
651 /// # Returns
652 ///
653 /// A new `BoxTransformerOnce<S, R>` representing the composition
654 ///
655 /// # Examples
656 ///
657 /// ```rust
658 /// use prism3_function::{TransformerOnce, FnTransformerOnceOps,
659 /// BoxTransformerOnce};
660 ///
661 /// let double = BoxTransformerOnce::new(|x: i32| x * 2);
662 /// let to_string = |x: i32| x.to_string();
663 ///
664 /// // double is moved and consumed
665 /// let composed = to_string.compose(double);
666 /// assert_eq!(composed.transform(21), "42");
667 /// // double.transform(5); // Would not compile - moved
668 /// ```
669 fn compose<S, G>(self, before: G) -> BoxTransformerOnce<S, R>
670 where
671 S: 'static,
672 G: TransformerOnce<S, T> + 'static,
673 T: 'static,
674 R: 'static,
675 {
676 BoxTransformerOnce::new(move |x: S| {
677 let intermediate = before.transform(x);
678 self(intermediate)
679 })
680 }
681
682 /// Creates a conditional transformer
683 ///
684 /// Returns a transformer that only executes when a predicate is satisfied.
685 /// You must call `or_else()` to provide an alternative transformer for when
686 /// the condition is not satisfied.
687 ///
688 /// # Parameters
689 ///
690 /// * `predicate` - The condition to check. **Note: This parameter is passed
691 /// by value and will transfer ownership.** If you need to preserve the
692 /// original predicate, clone it first (if it implements `Clone`). Can be:
693 /// - A closure: `|x: &T| -> bool`
694 /// - A function pointer: `fn(&T) -> bool`
695 /// - A `BoxPredicate<T>`
696 /// - An `RcPredicate<T>`
697 /// - An `ArcPredicate<T>`
698 /// - Any type implementing `Predicate<T>`
699 ///
700 /// # Returns
701 ///
702 /// Returns `BoxConditionalTransformerOnce<T, R>`
703 ///
704 /// # Examples
705 ///
706 /// ## Basic usage with or_else
707 ///
708 /// ```rust
709 /// use prism3_function::{TransformerOnce, FnTransformerOnceOps};
710 ///
711 /// let double = |x: i32| x * 2;
712 /// let conditional = double.when(|x: &i32| *x > 0).or_else(|x: i32| -x);
713 ///
714 /// assert_eq!(conditional.transform(5), 10);
715 /// ```
716 ///
717 /// ## Preserving predicate with clone
718 ///
719 /// ```rust
720 /// use prism3_function::{TransformerOnce, FnTransformerOnceOps,
721 /// RcPredicate};
722 ///
723 /// let double = |x: i32| x * 2;
724 /// let is_positive = RcPredicate::new(|x: &i32| *x > 0);
725 ///
726 /// // Clone to preserve original predicate
727 /// let conditional = double.when(is_positive.clone())
728 /// .or_else(|x: i32| -x);
729 ///
730 /// assert_eq!(conditional.transform(5), 10);
731 ///
732 /// // Original predicate still usable
733 /// assert!(is_positive.test(&3));
734 /// ```
735 fn when<P>(self, predicate: P) -> BoxConditionalTransformerOnce<T, R>
736 where
737 P: Predicate<T> + 'static,
738 T: 'static,
739 R: 'static,
740 {
741 BoxTransformerOnce::new(self).when(predicate)
742 }
743}
744
745/// Blanket implementation of FnTransformerOnceOps for all FnOnce closures
746///
747/// Automatically implements `FnTransformerOnceOps<T, R>` for any type that
748/// implements `FnOnce(T) -> R`.
749///
750/// # Author
751///
752/// Hu Haixing
753impl<T, R, F> FnTransformerOnceOps<T, R> for F where F: FnOnce(T) -> R + 'static {}
754
755// ============================================================================
756// UnaryOperatorOnce Trait - Marker trait for TransformerOnce<T, T>
757// ============================================================================
758
759/// UnaryOperatorOnce trait - marker trait for one-time use unary operators
760///
761/// A one-time use unary operator transforms a value of type `T` to another
762/// value of the same type `T`, consuming self in the process. This trait
763/// extends `TransformerOnce<T, T>` to provide semantic clarity for same-type
764/// transformations with consuming semantics. Equivalent to Java's
765/// `UnaryOperator<T>` but with FnOnce semantics.
766///
767/// # Automatic Implementation
768///
769/// This trait is automatically implemented for all types that implement
770/// `TransformerOnce<T, T>`, so you don't need to implement it manually.
771///
772/// # Type Parameters
773///
774/// * `T` - The type of both input and output values
775///
776/// # Examples
777///
778/// ## Using in generic constraints
779///
780/// ```rust
781/// use prism3_function::{UnaryOperatorOnce, TransformerOnce};
782///
783/// fn apply_once<T, O>(value: T, op: O) -> T
784/// where
785/// O: UnaryOperatorOnce<T>,
786/// {
787/// op.transform(value)
788/// }
789///
790/// let double = |x: i32| x * 2;
791/// assert_eq!(apply_once(21, double), 42);
792/// ```
793///
794/// # Author
795///
796/// Hu Haixing
797pub trait UnaryOperatorOnce<T>: TransformerOnce<T, T> {}
798
799/// Blanket implementation of UnaryOperatorOnce for all TransformerOnce<T, T>
800///
801/// This automatically implements `UnaryOperatorOnce<T>` for any type that
802/// implements `TransformerOnce<T, T>`.
803///
804/// # Author
805///
806/// Hu Haixing
807impl<F, T> UnaryOperatorOnce<T> for F
808where
809 F: TransformerOnce<T, T>,
810 T: 'static,
811{
812 // empty
813}
814
815// ============================================================================
816// Type Aliases for UnaryOperatorOnce (TransformerOnce<T, T>)
817// ============================================================================
818
819/// Type alias for `BoxTransformerOnce<T, T>`
820///
821/// Represents a one-time use unary operator that transforms a value of type `T`
822/// to another value of the same type `T`. Equivalent to Java's `UnaryOperator<T>`
823/// with consuming semantics (FnOnce).
824///
825/// # Examples
826///
827/// ```rust
828/// use prism3_function::{BoxUnaryOperatorOnce, TransformerOnce};
829///
830/// let increment: BoxUnaryOperatorOnce<i32> = BoxUnaryOperatorOnce::new(|x| x + 1);
831/// assert_eq!(increment.transform(41), 42);
832/// ```
833///
834/// # Author
835///
836/// Hu Haixing
837pub type BoxUnaryOperatorOnce<T> = BoxTransformerOnce<T, T>;