prism3_function/
mapper_once.rs

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