prism3_function/functions/
mutating_function_once.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # MutatingFunctionOnce Types
10//!
11//! Provides Java-like one-time `MutatingFunction` interface implementations
12//! for performing operations that consume self, accept a mutable reference,
13//! and return a result.
14//!
15//! It is similar to the `FnOnce(&mut T) -> R` trait in the standard library.
16//!
17//! This module provides a unified `MutatingFunctionOnce` trait and a
18//! Box-based single ownership implementation:
19//!
20//! - **`BoxMutatingFunctionOnce<T, R>`**: Box-based single ownership
21//!   implementation for one-time use scenarios
22//!
23//! # Design Philosophy
24//!
25//! The key difference between `MutatingFunctionOnce` and
26//! `MutatingFunction`:
27//!
28//! - **MutatingFunction**: `&self`, can be called multiple times, uses
29//!   `Fn(&mut T) -> R`
30//! - **MutatingFunctionOnce**: `self`, can only be called once, uses
31//!   `FnOnce(&mut T) -> R`
32//!
33//! ## MutatingFunctionOnce vs MutatingFunction
34//!
35//! | Feature | MutatingFunction | MutatingFunctionOnce |
36//! |---------|------------------|----------------------|
37//! | **Self Parameter** | `&self` | `self` |
38//! | **Call Count** | Multiple | Once |
39//! | **Closure Type** | `Fn(&mut T) -> R` | `FnOnce(&mut T) -> R` |
40//! | **Use Cases** | Repeatable operations | One-time resource
41//! transfers |
42//!
43//! # Why MutatingFunctionOnce?
44//!
45//! Core value of MutatingFunctionOnce:
46//!
47//! 1. **Store FnOnce closures**: Allows moving captured variables
48//! 2. **Delayed execution**: Store in data structures, execute later
49//! 3. **Resource transfer**: Suitable for scenarios requiring ownership
50//!    transfer
51//! 4. **Return results**: Unlike MutatorOnce, returns information about the
52//!    operation
53//!
54//! # Why Only Box Variant?
55//!
56//! - **Arc/Rc conflicts with FnOnce semantics**: FnOnce can only be called
57//!   once, while shared ownership implies multiple references
58//! - **Box is perfect match**: Single ownership aligns perfectly with
59//!   one-time call semantics
60//!
61//! # Use Cases
62//!
63//! ## BoxMutatingFunctionOnce
64//!
65//! - Post-initialization callbacks (moving data, returning status)
66//! - Resource transfer with result (moving Vec, returning old value)
67//! - One-time complex operations (requiring moved capture variables)
68//! - Validation with fixes (fix data once, return validation result)
69//!
70//! # Examples
71//!
72//! ## Basic Usage
73//!
74//! ```rust
75//! use prism3_function::{BoxMutatingFunctionOnce, MutatingFunctionOnce};
76//!
77//! let data = vec![1, 2, 3];
78//! let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
79//!     let old_len = x.len();
80//!     x.extend(data); // Move data
81//!     old_len
82//! });
83//!
84//! let mut target = vec![0];
85//! let old_len = func.apply(&mut target);
86//! assert_eq!(old_len, 1);
87//! assert_eq!(target, vec![0, 1, 2, 3]);
88//! ```
89//!
90//! ## Method Chaining
91//!
92//! ```rust
93//! use prism3_function::{BoxMutatingFunctionOnce, MutatingFunctionOnce};
94//!
95//! let data1 = vec![1, 2];
96//! let data2 = vec![3, 4];
97//!
98//! let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
99//!     x.extend(data1);
100//!     x.len()
101//! })
102//! .and_then(move |x: &mut Vec<i32>| {
103//!     x.extend(data2);
104//!     x.len()
105//! });
106//!
107//! let mut target = vec![0];
108//! let final_len = chained.apply(&mut target);
109//! assert_eq!(final_len, 5);
110//! assert_eq!(target, vec![0, 1, 2, 3, 4]);
111//! ```
112//!
113//! ## Validation Pattern
114//!
115//! ```rust
116//! use prism3_function::{BoxMutatingFunctionOnce, MutatingFunctionOnce};
117//!
118//! struct Data {
119//!     value: i32,
120//! }
121//!
122//! let validator = BoxMutatingFunctionOnce::new(|data: &mut Data| {
123//!     if data.value < 0 {
124//!         data.value = 0;
125//!         Err("Fixed negative value")
126//!     } else {
127//!         Ok("Valid")
128//!     }
129//! });
130//!
131//! let mut data = Data { value: -5 };
132//! let result = validator.apply(&mut data);
133//! assert_eq!(data.value, 0);
134//! assert!(result.is_err());
135//! ```
136//!
137//! # Author
138//!
139//! Haixing Hu
140use crate::functions::{
141    function_once::FunctionOnce,
142    macros::{
143        impl_box_conditional_function,
144        impl_box_function_methods,
145        impl_conditional_function_debug_display,
146        impl_fn_ops_trait,
147        impl_function_common_methods,
148        impl_function_debug_display,
149        impl_function_identity_method,
150    },
151};
152use crate::macros::{
153    impl_box_once_conversions,
154    impl_closure_once_trait,
155};
156use crate::predicates::predicate::{
157    BoxPredicate,
158    Predicate,
159};
160
161// =======================================================================
162// 1. MutatingFunctionOnce Trait - One-time Function Interface
163// =======================================================================
164
165/// MutatingFunctionOnce trait - One-time mutating function interface
166///
167/// It is similar to the `FnOnce(&mut T) -> R` trait in the standard library.
168///
169/// Defines the core behavior of all one-time mutating function types.
170/// Performs operations that consume self, accept a mutable reference,
171/// potentially modify it, and return a result.
172///
173/// This trait is automatically implemented by:
174/// - All closures implementing `FnOnce(&mut T) -> R`
175/// - `BoxMutatingFunctionOnce<T, R>`
176///
177/// # Design Rationale
178///
179/// This trait provides a unified abstraction for one-time mutating function
180/// operations. The key difference from `MutatingFunction`:
181/// - `MutatingFunction` uses `&self`, can be called multiple times
182/// - `MutatingFunctionOnce` uses `self`, can only be called once
183///
184/// # Features
185///
186/// - **Unified Interface**: All one-time mutating functions share the same
187///   `apply` method signature
188/// - **Automatic Implementation**: Closures automatically implement this
189///   trait with zero overhead
190/// - **Type Conversions**: Provides `into_box` method for type conversion
191/// - **Generic Programming**: Write functions that work with any one-time
192///   mutating function type
193///
194/// # Examples
195///
196/// ## Generic Function
197///
198/// ```rust
199/// use prism3_function::{MutatingFunctionOnce, BoxMutatingFunctionOnce};
200///
201/// fn apply<F: MutatingFunctionOnce<Vec<i32>, usize>>(
202///     func: F,
203///     initial: Vec<i32>
204/// ) -> (Vec<i32>, usize) {
205///     let mut val = initial;
206///     let result = func.apply(&mut val);
207///     (val, result)
208/// }
209///
210/// let data = vec![1, 2, 3];
211/// let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
212///     let old_len = x.len();
213///     x.extend(data);
214///     old_len
215/// });
216/// let (vec, old_len) = apply(func, vec![0]);
217/// assert_eq!(vec, vec![0, 1, 2, 3]);
218/// assert_eq!(old_len, 1);
219/// ```
220///
221/// ## Type Conversion
222///
223/// ```rust
224/// use prism3_function::MutatingFunctionOnce;
225///
226/// let data = vec![1, 2, 3];
227/// let closure = move |x: &mut Vec<i32>| {
228///     let old_len = x.len();
229///     x.extend(data);
230///     old_len
231/// };
232/// let box_func = closure.into_box();
233/// ```
234///
235/// # Author
236///
237/// Haixing Hu
238pub trait MutatingFunctionOnce<T, R> {
239    /// Performs the one-time mutating function operation
240    ///
241    /// Consumes self and executes an operation on the given mutable
242    /// reference, potentially modifying it, and returns a result. The
243    /// operation can only be called once.
244    ///
245    /// # Parameters
246    ///
247    /// * `t - A mutable reference to the input value
248    ///
249    /// # Returns
250    ///
251    /// The computed result value
252    ///
253    /// # Examples
254    ///
255    /// ```rust
256    /// use prism3_function::{MutatingFunctionOnce,
257    ///                       BoxMutatingFunctionOnce};
258    ///
259    /// let data = vec![1, 2, 3];
260    /// let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
261    ///     let old_len = x.len();
262    ///     x.extend(data);
263    ///     old_len
264    /// });
265    ///
266    /// let mut target = vec![0];
267    /// let old_len = func.apply(&mut target);
268    /// assert_eq!(old_len, 1);
269    /// assert_eq!(target, vec![0, 1, 2, 3]);
270    /// ```
271    fn apply(self, t: &mut T) -> R;
272
273    /// Converts to `BoxMutatingFunctionOnce` (consuming)
274    ///
275    /// Consumes `self` and returns an owned `BoxMutatingFunctionOnce<T, R>`.
276    /// The default implementation simply wraps the consuming
277    /// `apply(self, &mut T)` call in a `Box<dyn FnOnce(&mut T) -> R>`.
278    /// Types that can provide a cheaper or identity conversion (for example
279    /// `BoxMutatingFunctionOnce` itself) should override this method.
280    ///
281    /// # Note
282    ///
283    /// - This method consumes the source value.
284    /// - Implementors may return `self` directly when `Self` is already a
285    ///   `BoxMutatingFunctionOnce<T, R>` to avoid the extra wrapper
286    ///   allocation.
287    fn into_box(self) -> BoxMutatingFunctionOnce<T, R>
288    where
289        Self: Sized + 'static,
290        T: 'static,
291        R: 'static,
292    {
293        BoxMutatingFunctionOnce::new(move |t| self.apply(t))
294    }
295
296    /// Converts to a consuming closure `FnOnce(&mut T) -> R`
297    ///
298    /// Consumes `self` and returns a closure that, when invoked, calls
299    /// `apply(self, &mut T)`. This is the default, straightforward
300    /// implementation; types that can produce a more direct function pointer
301    /// or avoid additional captures may override it.
302    fn into_fn(self) -> impl FnOnce(&mut T) -> R
303    where
304        Self: Sized + 'static,
305        T: 'static,
306        R: 'static,
307    {
308        move |t| self.apply(t)
309    }
310
311    /// Non-consuming adapter to `BoxMutatingFunctionOnce`
312    ///
313    /// Creates a `BoxMutatingFunctionOnce<T, R>` that does not consume
314    /// `self`. The default implementation requires `Self: Clone` and clones
315    /// the receiver for the stored closure; the clone is consumed when the
316    /// boxed function is invoked. Types that can provide a zero-cost adapter
317    /// (for example clonable closures) should override this method to avoid
318    /// unnecessary allocations.
319    fn to_box(&self) -> BoxMutatingFunctionOnce<T, R>
320    where
321        Self: Sized + Clone + 'static,
322        T: 'static,
323        R: 'static,
324    {
325        self.clone().into_box()
326    }
327
328    /// Non-consuming adapter to a callable `FnOnce(&mut T) -> R`
329    ///
330    /// Returns a closure that does not consume `self`. The default requires
331    /// `Self: Clone` and clones `self` for the captured closure; the clone is
332    /// consumed when the returned closure is invoked. Implementors may
333    /// provide more efficient adapters for specific types.
334    fn to_fn(&self) -> impl FnOnce(&mut T) -> R
335    where
336        Self: Sized + Clone + 'static,
337        T: 'static,
338        R: 'static,
339    {
340        self.clone().into_fn()
341    }
342}
343
344// =======================================================================
345// 2. BoxMutatingFunctionOnce - Single Ownership Implementation
346// =======================================================================
347
348/// BoxMutatingFunctionOnce struct
349///
350/// A one-time mutating function implementation based on
351/// `Box<dyn FnOnce(&mut T) -> R>` for single ownership scenarios. This is
352/// the only MutatingFunctionOnce implementation type because FnOnce
353/// conflicts with shared ownership semantics.
354///
355/// # Features
356///
357/// - **Single Ownership**: Not cloneable, consumes self on use
358/// - **Zero Overhead**: No reference counting or locking
359/// - **Move Semantics**: Can capture and move variables
360/// - **Method Chaining**: Compose multiple operations via `and_then`
361/// - **Returns Results**: Unlike MutatorOnce, returns information
362///
363/// # Use Cases
364///
365/// Choose `BoxMutatingFunctionOnce` when:
366/// - Need to store FnOnce closures (with moved captured variables)
367/// - One-time resource transfer operations with results
368/// - Post-initialization callbacks that return status
369/// - Complex operations requiring ownership transfer and results
370///
371/// # Performance
372///
373/// `BoxMutatingFunctionOnce` performance characteristics:
374/// - No reference counting overhead
375/// - No lock acquisition or runtime borrow checking
376/// - Direct function call through vtable
377/// - Minimal memory footprint (single pointer)
378///
379/// # Why No Arc/Rc Variants?
380///
381/// FnOnce can only be called once, which conflicts with Arc/Rc shared
382/// ownership semantics:
383/// - Arc/Rc implies multiple owners might need to call
384/// - FnOnce is consumed after calling, cannot be called again
385/// - This semantic incompatibility makes Arc/Rc variants meaningless
386///
387/// # Examples
388///
389/// ## Basic Usage
390///
391/// ```rust
392/// use prism3_function::{MutatingFunctionOnce, BoxMutatingFunctionOnce};
393///
394/// let data = vec![1, 2, 3];
395/// let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
396///     let old_len = x.len();
397///     x.extend(data); // Move data
398///     old_len
399/// });
400///
401/// let mut target = vec![0];
402/// let old_len = func.apply(&mut target);
403/// assert_eq!(old_len, 1);
404/// assert_eq!(target, vec![0, 1, 2, 3]);
405/// ```
406///
407/// ## Method Chaining
408///
409/// ```rust
410/// use prism3_function::{MutatingFunctionOnce, BoxMutatingFunctionOnce};
411///
412/// let data1 = vec![1, 2];
413/// let data2 = vec![3, 4];
414///
415/// let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
416///     x.extend(data1);
417///     x.len()
418/// })
419/// .and_then(move |x: &mut Vec<i32>| {
420///     x.extend(data2);
421///     x.len()
422/// });
423///
424/// let mut target = vec![0];
425/// let final_len = chained.apply(&mut target);
426/// assert_eq!(final_len, 5);
427/// assert_eq!(target, vec![0, 1, 2, 3, 4]);
428/// ```
429///
430/// # Author
431///
432/// Haixing Hu
433pub struct BoxMutatingFunctionOnce<T, R> {
434    function: Box<dyn FnOnce(&mut T) -> R>,
435    name: Option<String>,
436}
437
438impl<T, R> BoxMutatingFunctionOnce<T, R>
439where
440    T: 'static,
441    R: 'static,
442{
443    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
444    impl_function_common_methods!(
445        BoxMutatingFunctionOnce<T, R>,
446        (FnOnce(&mut T) -> R + 'static),
447        |f| Box::new(f)
448    );
449
450    // Generates: when(), and_then(), compose()
451    impl_box_function_methods!(
452        BoxMutatingFunctionOnce<T, R>,
453        BoxConditionalMutatingFunctionOnce,
454        FunctionOnce    // chains a non-mutating function after this mutating function
455    );
456}
457
458impl<T, R> MutatingFunctionOnce<T, R> for BoxMutatingFunctionOnce<T, R> {
459    fn apply(self, input: &mut T) -> R {
460        (self.function)(input)
461    }
462
463    impl_box_once_conversions!(
464        BoxMutatingFunctionOnce<T, R>,
465        MutatingFunctionOnce,
466        FnOnce(&mut T) -> R
467    );
468}
469
470// Generates: identity() method for BoxMutatingFunctionOnce<T, T>
471impl_function_identity_method!(BoxMutatingFunctionOnce<T, T>, mutating);
472
473// Generates: Debug and Display implementations for BoxMutatingFunctionOnce<T, R>
474impl_function_debug_display!(BoxMutatingFunctionOnce<T, R>);
475
476// =======================================================================
477// 3. Implement MutatingFunctionOnce trait for closures
478// =======================================================================
479
480// Implement MutatingFunctionOnce for all FnOnce(&mut T) -> R using macro
481impl_closure_once_trait!(
482    MutatingFunctionOnce<T, R>,
483    apply,
484    BoxMutatingFunctionOnce,
485    FnOnce(input: &mut T) -> R
486);
487
488// =======================================================================
489// 4. Provide extension methods for closures
490// =======================================================================
491
492// Generates: FnMutatingFunctionOnceOps trait and blanket implementation
493impl_fn_ops_trait!(
494    (FnOnce(&mut T) -> R),
495    FnMutatingFunctionOnceOps,
496    BoxMutatingFunctionOnce,
497    FunctionOnce,
498    BoxConditionalMutatingFunctionOnce
499);
500
501// ============================================================================
502// BoxConditionalMutatingFunctionOnce - Box-based Conditional Mutating Function
503// ============================================================================
504
505/// BoxConditionalMutatingFunctionOnce struct
506///
507/// A conditional consuming transformer that only executes when a predicate is
508/// satisfied. Uses `BoxMutatingFunctionOnce` and `BoxPredicate` for single
509/// ownership semantics.
510///
511/// This type is typically created by calling `BoxMutatingFunctionOnce::when()` and
512/// is designed to work with the `or_else()` method to create if-then-else
513/// logic.
514///
515/// # Features
516///
517/// - **Single Ownership**: Not cloneable, consumes `self` on use
518/// - **One-time Use**: Can only be called once
519/// - **Conditional Execution**: Only transforms when predicate returns `true`
520/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
521///
522/// # Examples
523///
524/// ## With or_else Branch
525///
526/// ```rust
527/// use prism3_function::{MutatingFunctionOnce, BoxMutatingFunctionOnce};
528///
529/// let double = BoxMutatingFunctionOnce::new(|x: &mut i32| x * 2);
530/// let negate = BoxMutatingFunctionOnce::new(|x: &mut i32| -x);
531/// let conditional = double.when(|x: &i32| *x > 0).or_else(negate);
532/// assert_eq!(conditional.apply(5), 10); // when branch executed
533///
534/// let double2 = BoxMutatingFunctionOnce::new(|x: &mut i32| x * 2);
535/// let negate2 = BoxMutatingFunctionOnce::new(|x: &mut i32| -x);
536/// let conditional2 = double2.when(|x: &i32| *x > 0).or_else(negate2);
537/// assert_eq!(conditional2.apply(-5), 5); // or_else branch executed
538/// ```
539///
540/// # Author
541///
542/// Haixing Hu
543pub struct BoxConditionalMutatingFunctionOnce<T, R> {
544    function: BoxMutatingFunctionOnce<T, R>,
545    predicate: BoxPredicate<T>,
546}
547
548// Use macro to generate conditional function implementations
549impl_box_conditional_function!(
550    BoxConditionalMutatingFunctionOnce<T, R>,
551    BoxMutatingFunctionOnce,
552    MutatingFunctionOnce
553);
554
555// Use macro to generate conditional function debug and display implementations
556impl_conditional_function_debug_display!(BoxConditionalMutatingFunctionOnce<T, R>);