Skip to main content

qubit_function/functions/
mutating_function_once.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit 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 qubit_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 qubit_function::{BoxMutatingFunctionOnce, MutatingFunctionOnce};
94//!
95//! let data1 = vec![1, 2];
96//!
97//! let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
98//!     x.extend(data1);
99//!     x.len()
100//! })
101//! .and_then(|len: &usize| len + 2);
102//!
103//! let mut target = vec![0];
104//! let final_len = chained.apply(&mut target);
105//! assert_eq!(final_len, 5);
106//! assert_eq!(target, vec![0, 1, 2]);
107//! ```
108//!
109//! ## Validation Pattern
110//!
111//! ```rust
112//! use qubit_function::{BoxMutatingFunctionOnce, MutatingFunctionOnce};
113//!
114//! struct Data {
115//!     value: i32,
116//! }
117//!
118//! let validator = BoxMutatingFunctionOnce::new(|data: &mut Data| {
119//!     if data.value < 0 {
120//!         data.value = 0;
121//!         Err("Fixed negative value")
122//!     } else {
123//!         Ok("Valid")
124//!     }
125//! });
126//!
127//! let mut data = Data { value: -5 };
128//! let result = validator.apply(&mut data);
129//! assert_eq!(data.value, 0);
130//! assert!(result.is_err());
131//! ```
132//!
133//! # Author
134//!
135//! Haixing Hu
136use crate::functions::{
137    function_once::FunctionOnce,
138    macros::{
139        impl_box_conditional_function,
140        impl_box_function_methods,
141        impl_conditional_function_debug_display,
142        impl_fn_ops_trait,
143        impl_function_common_methods,
144        impl_function_debug_display,
145        impl_function_identity_method,
146    },
147};
148use crate::macros::{
149    impl_box_once_conversions,
150    impl_closure_once_trait,
151};
152use crate::predicates::predicate::{
153    BoxPredicate,
154    Predicate,
155};
156
157mod box_mutating_function_once;
158pub use box_mutating_function_once::BoxMutatingFunctionOnce;
159mod box_conditional_mutating_function_once;
160pub use box_conditional_mutating_function_once::BoxConditionalMutatingFunctionOnce;
161mod fn_mutating_function_once_ops;
162pub use fn_mutating_function_once_ops::FnMutatingFunctionOnceOps;
163
164// =======================================================================
165// 1. MutatingFunctionOnce Trait - One-time Function Interface
166// =======================================================================
167
168/// MutatingFunctionOnce trait - One-time mutating function interface
169///
170/// It is similar to the `FnOnce(&mut T) -> R` trait in the standard library.
171///
172/// Defines the core behavior of all one-time mutating function types.
173/// Performs operations that consume self, accept a mutable reference,
174/// potentially modify it, and return a result.
175///
176/// This trait is automatically implemented by:
177/// - All closures implementing `FnOnce(&mut T) -> R`
178/// - `BoxMutatingFunctionOnce<T, R>`
179///
180/// # Design Rationale
181///
182/// This trait provides a unified abstraction for one-time mutating function
183/// operations. The key difference from `MutatingFunction`:
184/// - `MutatingFunction` uses `&self`, can be called multiple times
185/// - `MutatingFunctionOnce` uses `self`, can only be called once
186///
187/// # Features
188///
189/// - **Unified Interface**: All one-time mutating functions share the same
190///   `apply` method signature
191/// - **Automatic Implementation**: Closures automatically implement this
192///   trait with zero overhead
193/// - **Type Conversions**: Provides `into_box` method for type conversion
194/// - **Generic Programming**: Write functions that work with any one-time
195///   mutating function type
196///
197/// # Examples
198///
199/// ## Generic Function
200///
201/// ```rust
202/// use qubit_function::{MutatingFunctionOnce, BoxMutatingFunctionOnce};
203///
204/// fn apply<F: MutatingFunctionOnce<Vec<i32>, usize>>(
205///     func: F,
206///     initial: Vec<i32>
207/// ) -> (Vec<i32>, usize) {
208///     let mut val = initial;
209///     let result = func.apply(&mut val);
210///     (val, result)
211/// }
212///
213/// let data = vec![1, 2, 3];
214/// let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
215///     let old_len = x.len();
216///     x.extend(data);
217///     old_len
218/// });
219/// let (vec, old_len) = apply(func, vec![0]);
220/// assert_eq!(vec, vec![0, 1, 2, 3]);
221/// assert_eq!(old_len, 1);
222/// ```
223///
224/// ## Type Conversion
225///
226/// ```rust
227/// use qubit_function::MutatingFunctionOnce;
228///
229/// let data = vec![1, 2, 3];
230/// let closure = move |x: &mut Vec<i32>| {
231///     let old_len = x.len();
232///     x.extend(data);
233///     old_len
234/// };
235/// let box_func = closure.into_box();
236/// ```
237///
238/// # Author
239///
240/// Haixing Hu
241pub trait MutatingFunctionOnce<T, R> {
242    /// Performs the one-time mutating function operation
243    ///
244    /// Consumes self and executes an operation on the given mutable
245    /// reference, potentially modifying it, and returns a result. The
246    /// operation can only be called once.
247    ///
248    /// # Parameters
249    ///
250    /// * `t - A mutable reference to the input value
251    ///
252    /// # Returns
253    ///
254    /// The computed result value
255    ///
256    /// # Examples
257    ///
258    /// ```rust
259    /// use qubit_function::{MutatingFunctionOnce,
260    ///                       BoxMutatingFunctionOnce};
261    ///
262    /// let data = vec![1, 2, 3];
263    /// let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
264    ///     let old_len = x.len();
265    ///     x.extend(data);
266    ///     old_len
267    /// });
268    ///
269    /// let mut target = vec![0];
270    /// let old_len = func.apply(&mut target);
271    /// assert_eq!(old_len, 1);
272    /// assert_eq!(target, vec![0, 1, 2, 3]);
273    /// ```
274    fn apply(self, t: &mut T) -> R;
275
276    /// Converts to `BoxMutatingFunctionOnce` (consuming)
277    ///
278    /// Consumes `self` and returns an owned `BoxMutatingFunctionOnce<T, R>`.
279    /// The default implementation simply wraps the consuming
280    /// `apply(self, &mut T)` call in a `Box<dyn FnOnce(&mut T) -> R>`.
281    /// Types that can provide a cheaper or identity conversion (for example
282    /// `BoxMutatingFunctionOnce` itself) should override this method.
283    ///
284    /// # Note
285    ///
286    /// - This method consumes the source value.
287    /// - Implementors may return `self` directly when `Self` is already a
288    ///   `BoxMutatingFunctionOnce<T, R>` to avoid the extra wrapper
289    ///   allocation.
290    fn into_box(self) -> BoxMutatingFunctionOnce<T, R>
291    where
292        Self: Sized + 'static,
293    {
294        BoxMutatingFunctionOnce::new(move |t| self.apply(t))
295    }
296
297    /// Converts to a consuming closure `FnOnce(&mut T) -> R`
298    ///
299    /// Consumes `self` and returns a closure that, when invoked, calls
300    /// `apply(self, &mut T)`. This is the default, straightforward
301    /// implementation; types that can produce a more direct function pointer
302    /// or avoid additional captures may override it.
303    fn into_fn(self) -> impl FnOnce(&mut T) -> R
304    where
305        Self: Sized + 'static,
306    {
307        move |t| self.apply(t)
308    }
309
310    /// Non-consuming adapter to `BoxMutatingFunctionOnce`
311    ///
312    /// Creates a `BoxMutatingFunctionOnce<T, R>` that does not consume
313    /// `self`. The default implementation requires `Self: Clone` and clones
314    /// the receiver for the stored closure; the clone is consumed when the
315    /// boxed function is invoked. Types that can provide a zero-cost adapter
316    /// (for example clonable closures) should override this method to avoid
317    /// unnecessary allocations.
318    fn to_box(&self) -> BoxMutatingFunctionOnce<T, R>
319    where
320        Self: Sized + Clone + 'static,
321    {
322        self.clone().into_box()
323    }
324
325    /// Non-consuming adapter to a callable `FnOnce(&mut T) -> R`
326    ///
327    /// Returns a closure that does not consume `self`. The default requires
328    /// `Self: Clone` and clones `self` for the captured closure; the clone is
329    /// consumed when the returned closure is invoked. Implementors may
330    /// provide more efficient adapters for specific types.
331    fn to_fn(&self) -> impl FnOnce(&mut T) -> R
332    where
333        Self: Sized + Clone + 'static,
334    {
335        self.clone().into_fn()
336    }
337}