Skip to main content

qubit_function/functions/
mutating_function.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! # MutatingFunction Types
11//!
12//! Provides Java-like `MutatingFunction` interface implementations for
13//! performing operations that accept a mutable reference and return a result.
14//!
15//! It is similar to the `Fn(&mut T) -> R` trait in the standard library.
16//!
17//! This module provides a unified `MutatingFunction` trait and three concrete
18//! implementations based on different ownership models:
19//!
20//! - **`BoxMutatingFunction<T, R>`**: Box-based single ownership
21//!   implementation
22//! - **`ArcMutatingFunction<T, R>`**: Arc-based thread-safe shared ownership
23//!   implementation
24//! - **`RcMutatingFunction<T, R>`**: Rc-based single-threaded shared
25//!   ownership implementation
26//!
27//! # Design Philosophy
28//!
29//! `MutatingFunction` bridges the gap between `Function` and `Mutator`:
30//!
31//! - **Function**: `Fn(&T) -> R` - reads input, returns result
32//! - **Mutator**: `Fn(&mut T)` - modifies input, no return
33//! - **MutatingFunction**: `Fn(&mut T) -> R` - modifies input AND returns
34//!   result
35//!
36//! ## Comparison with Related Types
37//!
38//! | Type | Input | Modifies? | Returns? | Use Cases |
39//! |------|-------|-----------|----------|-----------|
40//! | **Function** | `&T` | ❌ | ✅ | Read-only transform |
41//! | **Mutator** | `&mut T` | ✅ | ❌ | In-place modification |
42//! | **MutatingFunction** | `&mut T` | ✅ | ✅ | Modify + return info |
43//! | **Transformer** | `T` | N/A | ✅ | Consume + transform |
44//!
45//! **Key Insight**: Use `MutatingFunction` when you need to both modify the
46//! input and return information about the modification or the previous state.
47//!
48//! # Comparison Table
49//!
50//! | Feature          | Box | Arc | Rc |
51//! |------------------|-----|-----|----|
52//! | Ownership        | Single | Shared | Shared |
53//! | Cloneable        | ❌ | ✅ | ✅ |
54//! | Thread-Safe      | ❌ | ✅ | ❌ |
55//! | Interior Mut.    | N/A | N/A | N/A |
56//! | `and_then` API   | `self` | `&self` | `&self` |
57//! | Lock Overhead    | None | None | None |
58//!
59//! # Use Cases
60//!
61//! ## Common Scenarios
62//!
63//! - **Atomic operations**: Increment counter and return new value
64//! - **Cache updates**: Update cache and return old value
65//! - **Validation**: Validate and fix data, return validation result
66//! - **Event handlers**: Process event and return whether to continue
67//! - **State machines**: Transition state and return transition info
68//!
69//! # Examples
70//!
71//! ## Basic Usage
72//!
73//! ```rust
74//! use qubit_function::{BoxMutatingFunction, MutatingFunction};
75//!
76//! // Increment counter and return new value
77//! let incrementer = BoxMutatingFunction::new(|x: &mut i32| {
78//!     *x += 1;
79//!     *x
80//! });
81//!
82//! let mut value = 5;
83//! let result = incrementer.apply(&mut value);
84//! assert_eq!(value, 6);
85//! assert_eq!(result, 6);
86//! ```
87//!
88//! ## Method Chaining
89//!
90//! ```rust
91//! use qubit_function::{BoxMutatingFunction, MutatingFunction};
92//!
93//! let chained = BoxMutatingFunction::new(|x: &mut i32| {
94//!     *x *= 2;
95//!     *x
96//! })
97//! .and_then(|x: &i32| x + 10);
98//!
99//! let mut value = 5;
100//! let result = chained.apply(&mut value);
101//! assert_eq!(value, 10); // (5 * 2), value is still mutated by the first function
102//! assert_eq!(result, 20);
103//! ```
104//!
105//! ## Cache Update Pattern
106//!
107//! ```rust
108//! use qubit_function::{BoxMutatingFunction, MutatingFunction};
109//! use std::collections::HashMap;
110//!
111//! let updater = BoxMutatingFunction::new(
112//!     |cache: &mut HashMap<String, i32>| {
113//!         cache.insert("key".to_string(), 42)
114//!     }
115//! );
116//!
117//! let mut cache = HashMap::new();
118//! cache.insert("key".to_string(), 10);
119//! let old_value = updater.apply(&mut cache);
120//! assert_eq!(old_value, Some(10));
121//! assert_eq!(cache.get("key"), Some(&42));
122//! ```
123//!
124use std::rc::Rc;
125use std::sync::Arc;
126
127use crate::functions::{
128    function::Function,
129    macros::{
130        impl_box_conditional_function,
131        impl_box_function_methods,
132        impl_conditional_function_clone,
133        impl_conditional_function_debug_display,
134        impl_fn_ops_trait,
135        impl_function_clone,
136        impl_function_common_methods,
137        impl_function_debug_display,
138        impl_function_identity_method,
139        impl_shared_conditional_function,
140        impl_shared_function_methods,
141    },
142    mutating_function_once::BoxMutatingFunctionOnce,
143};
144use crate::macros::{
145    impl_arc_conversions,
146    impl_box_conversions,
147    impl_closure_trait,
148    impl_rc_conversions,
149};
150use crate::predicates::predicate::{
151    ArcPredicate,
152    BoxPredicate,
153    Predicate,
154    RcPredicate,
155};
156
157mod box_mutating_function;
158pub use box_mutating_function::BoxMutatingFunction;
159mod rc_mutating_function;
160pub use rc_mutating_function::RcMutatingFunction;
161mod arc_mutating_function;
162pub use arc_mutating_function::ArcMutatingFunction;
163mod box_conditional_mutating_function;
164pub use box_conditional_mutating_function::BoxConditionalMutatingFunction;
165mod rc_conditional_mutating_function;
166pub use rc_conditional_mutating_function::RcConditionalMutatingFunction;
167mod arc_conditional_mutating_function;
168pub use arc_conditional_mutating_function::ArcConditionalMutatingFunction;
169mod fn_mutating_function_ops;
170pub use fn_mutating_function_ops::FnMutatingFunctionOps;
171
172// =======================================================================
173// 1. MutatingFunction Trait - Unified Interface
174// =======================================================================
175
176/// MutatingFunction trait - Unified mutating function interface
177///
178/// It is similar to the `Fn(&mut T) -> R` trait in the standard library.
179///
180/// Defines the core behavior of all mutating function types. Performs
181/// operations that accept a mutable reference, potentially modify it, and
182/// return a result.
183///
184/// This trait is automatically implemented by:
185/// - All closures implementing `Fn(&mut T) -> R`
186/// - `BoxMutatingFunction<T, R>`, `ArcMutatingFunction<T, R>`, and
187///   `RcMutatingFunction<T, R>`
188///
189/// # Design Rationale
190///
191/// The trait provides a unified abstraction over different ownership models
192/// for operations that both modify input and return results. This is useful
193/// for scenarios where you need to:
194/// - Update state and return information about the update
195/// - Perform atomic-like operations (modify and return)
196/// - Implement event handlers that modify state and signal continuation
197///
198/// # Features
199///
200/// - **Unified Interface**: All mutating function types share the same
201///   `apply` method signature
202/// - **Automatic Implementation**: Closures automatically implement this
203///   trait
204/// - **Type Conversions**: Easy conversion between ownership models
205/// - **Generic Programming**: Write functions that work with any mutating
206///   function type
207///
208/// # Examples
209///
210/// ## Generic Function
211///
212/// ```rust
213/// use qubit_function::{MutatingFunction, BoxMutatingFunction};
214///
215/// fn apply_and_log<F: MutatingFunction<i32, i32>>(
216///     func: &F,
217///     value: i32
218/// ) -> i32 {
219///     let mut val = value;
220///     let result = func.apply(&mut val);
221///     println!("Modified: {} -> {}, returned: {}", value, val, result);
222///     result
223/// }
224///
225/// let incrementer = BoxMutatingFunction::new(|x: &mut i32| {
226///     *x += 1;
227///     *x
228/// });
229/// assert_eq!(apply_and_log(&incrementer, 5), 6);
230/// ```
231///
232/// ## Type Conversion
233///
234/// ```rust
235/// use qubit_function::MutatingFunction;
236///
237/// let closure = |x: &mut i32| {
238///     *x *= 2;
239///     *x
240/// };
241///
242/// // Convert to different ownership models
243/// let box_func = closure.into_box();
244/// // let rc_func = closure.into_rc();  // closure moved
245/// // let arc_func = closure.into_arc(); // closure moved
246/// ```
247///
248pub trait MutatingFunction<T, R> {
249    /// Applies the function to the mutable reference and returns a result
250    ///
251    /// Executes an operation on the given mutable reference, potentially
252    /// modifying it, and returns a result value.
253    ///
254    /// # Parameters
255    ///
256    /// * `t` - A mutable reference to the input value
257    ///
258    /// # Returns
259    ///
260    /// The computed result value
261    ///
262    /// # Examples
263    ///
264    /// ```rust
265    /// use qubit_function::{MutatingFunction, BoxMutatingFunction};
266    ///
267    /// let func = BoxMutatingFunction::new(|x: &mut i32| {
268    ///     let old = *x;
269    ///     *x += 1;
270    ///     old
271    /// });
272    ///
273    /// let mut value = 5;
274    /// let old_value = func.apply(&mut value);
275    /// assert_eq!(old_value, 5);
276    /// assert_eq!(value, 6);
277    /// ```
278    fn apply(&self, t: &mut T) -> R;
279
280    /// Convert this mutating function into a `BoxMutatingFunction<T, R>`.
281    ///
282    /// This consuming conversion takes ownership of `self` and returns a
283    /// boxed implementation that forwards calls to the original function.
284    /// Types that can provide a more efficient conversion may override the
285    /// default implementation.
286    ///
287    /// # Consumption
288    ///
289    /// This method consumes the function: the original value will no longer
290    /// be available after the call. For cloneable functions call `.clone()`
291    /// before converting if you need to retain the original instance.
292    ///
293    /// # Returns
294    ///
295    /// A `BoxMutatingFunction<T, R>` that forwards to the original function.
296    ///
297    /// # Examples
298    ///
299    /// ```rust
300    /// use qubit_function::MutatingFunction;
301    ///
302    /// let closure = |x: &mut i32| {
303    ///     *x *= 2;
304    ///     *x
305    /// };
306    /// let mut boxed = closure.into_box();
307    /// let mut value = 5;
308    /// assert_eq!(boxed.apply(&mut value), 10);
309    /// ```
310    fn into_box(self) -> BoxMutatingFunction<T, R>
311    where
312        Self: Sized + 'static,
313    {
314        BoxMutatingFunction::new(move |t| self.apply(t))
315    }
316
317    /// Convert this mutating function into an `RcMutatingFunction<T, R>`.
318    ///
319    /// This consuming conversion takes ownership of `self` and returns an
320    /// `Rc`-backed function that forwards calls to the original. Override to
321    /// provide a more direct or efficient conversion when available.
322    ///
323    /// # Consumption
324    ///
325    /// This method consumes the function. If you need to keep the original
326    /// instance, clone it prior to calling this method.
327    ///
328    /// # Returns
329    ///
330    /// An `RcMutatingFunction<T, R>` forwarding to the original function.
331    ///
332    /// # Examples
333    ///
334    /// ```rust
335    /// use qubit_function::MutatingFunction;
336    ///
337    /// let closure = |x: &mut i32| {
338    ///     *x *= 2;
339    ///     *x
340    /// };
341    /// let mut rc = closure.into_rc();
342    /// let mut value = 5;
343    /// assert_eq!(rc.apply(&mut value), 10);
344    /// ```
345    fn into_rc(self) -> RcMutatingFunction<T, R>
346    where
347        Self: Sized + 'static,
348    {
349        RcMutatingFunction::new(move |t| self.apply(t))
350    }
351
352    /// Convert this mutating function into an `ArcMutatingFunction<T, R>`.
353    ///
354    /// This consuming conversion takes ownership of `self` and returns an
355    /// `Arc`-wrapped, thread-safe function. Types may override the default
356    /// implementation to provide a more efficient conversion.
357    ///
358    /// # Consumption
359    ///
360    /// This method consumes the function. Clone the instance first if you
361    /// need to retain the original for further use.
362    ///
363    /// # Returns
364    ///
365    /// An `ArcMutatingFunction<T, R>` that forwards to the original
366    /// function.
367    ///
368    /// # Examples
369    ///
370    /// ```rust
371    /// use qubit_function::MutatingFunction;
372    ///
373    /// let closure = |x: &mut i32| {
374    ///     *x *= 2;
375    ///     *x
376    /// };
377    /// let mut arc = closure.into_arc();
378    /// let mut value = 5;
379    /// assert_eq!(arc.apply(&mut value), 10);
380    /// ```
381    fn into_arc(self) -> ArcMutatingFunction<T, R>
382    where
383        Self: Sized + Send + Sync + 'static,
384    {
385        ArcMutatingFunction::new(move |t| self.apply(t))
386    }
387
388    /// Consume the function and return an `Fn(&mut T) -> R` closure.
389    ///
390    /// The returned closure forwards calls to the original function and is
391    /// suitable for use with iterator adapters or other contexts expecting
392    /// closures.
393    ///
394    /// # Consumption
395    ///
396    /// This method consumes the function. The original instance will not be
397    /// available after calling this method.
398    ///
399    /// # Returns
400    ///
401    /// A closure implementing `Fn(&mut T) -> R` which forwards to the
402    /// original function.
403    ///
404    /// # Examples
405    ///
406    /// ```rust
407    /// use qubit_function::{MutatingFunction, BoxMutatingFunction};
408    ///
409    /// let func = BoxMutatingFunction::new(|x: &mut i32| {
410    ///     *x *= 2;
411    ///     *x
412    /// });
413    /// let closure = func.into_fn();
414    /// let mut value = 5;
415    /// assert_eq!(closure(&mut value), 10);
416    /// ```
417    fn into_fn(self) -> impl Fn(&mut T) -> R
418    where
419        Self: Sized + 'static,
420    {
421        move |t| self.apply(t)
422    }
423
424    /// Convert to MutatingFunctionOnce
425    ///
426    /// **⚠️ Consumes `self`**: The original function will be unavailable
427    /// after calling this method.
428    ///
429    /// Converts a reusable mutating function to a one-time function that
430    /// consumes itself on use. This enables passing `MutatingFunction` to
431    /// functions that require `MutatingFunctionOnce`.
432    ///
433    /// # Returns
434    ///
435    /// Returns a `BoxMutatingFunctionOnce<T, R>`
436    ///
437    /// # Examples
438    ///
439    /// ```rust
440    /// use qubit_function::{MutatingFunctionOnce, MutatingFunction,
441    ///                       ArcMutatingFunction, BoxMutatingFunction};
442    ///
443    /// fn takes_once<F: MutatingFunctionOnce<i32, i32>>(func: F, value: &mut i32) {
444    ///     let result = func.apply(value);
445    ///     println!("Result: {}", result);
446    /// }
447    ///
448    /// let func = BoxMutatingFunction::new(|x: &mut i32| {
449    ///     *x *= 2;
450    ///     *x
451    /// });
452    /// let mut value = 5;
453    /// takes_once(func.into_once(), &mut value);
454    /// ```
455    fn into_once(self) -> BoxMutatingFunctionOnce<T, R>
456    where
457        Self: Sized + 'static,
458    {
459        BoxMutatingFunctionOnce::new(move |t| self.apply(t))
460    }
461
462    /// Create a non-consuming `BoxMutatingFunction<T, R>` that forwards to
463    /// `self`.
464    ///
465    /// The default implementation clones `self` (requires `Clone`) and
466    /// returns a boxed function that calls the cloned instance. Override this
467    /// method if a more efficient conversion exists.
468    ///
469    /// # Returns
470    ///
471    /// A `BoxMutatingFunction<T, R>` that forwards to a clone of `self`.
472    fn to_box(&self) -> BoxMutatingFunction<T, R>
473    where
474        Self: Sized + Clone + 'static,
475    {
476        self.clone().into_box()
477    }
478
479    /// Create a non-consuming `RcMutatingFunction<T, R>` that forwards to
480    /// `self`.
481    ///
482    /// The default implementation clones `self` (requires `Clone`) and
483    /// returns an `Rc`-backed function that forwards calls to the clone.
484    /// Override to provide a more direct or efficient conversion if needed.
485    ///
486    /// # Returns
487    ///
488    /// An `RcMutatingFunction<T, R>` that forwards to a clone of `self`.
489    fn to_rc(&self) -> RcMutatingFunction<T, R>
490    where
491        Self: Sized + Clone + 'static,
492    {
493        self.clone().into_rc()
494    }
495
496    /// Create a non-consuming `ArcMutatingFunction<T, R>` that forwards to
497    /// `self`.
498    ///
499    /// The default implementation clones `self` (requires
500    /// `Clone + Send + Sync`) and returns an `Arc`-wrapped function that
501    /// forwards calls to the clone. Override when a more efficient conversion
502    /// is available.
503    ///
504    /// # Returns
505    ///
506    /// An `ArcMutatingFunction<T, R>` that forwards to a clone of `self`.
507    fn to_arc(&self) -> ArcMutatingFunction<T, R>
508    where
509        Self: Sized + Clone + Send + Sync + 'static,
510    {
511        self.clone().into_arc()
512    }
513
514    /// Create a boxed `Fn(&mut T) -> R` closure that forwards to `self`.
515    ///
516    /// The default implementation clones `self` (requires `Clone`) and
517    /// returns a boxed closure that invokes the cloned instance. Override to
518    /// provide a more efficient conversion when possible.
519    ///
520    /// # Returns
521    ///
522    /// A closure implementing `Fn(&mut T) -> R` which forwards to the
523    /// original function.
524    fn to_fn(&self) -> impl Fn(&mut T) -> R
525    where
526        Self: Sized + Clone + 'static,
527    {
528        self.clone().into_fn()
529    }
530
531    /// Convert to MutatingFunctionOnce without consuming self
532    ///
533    /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
534    /// Clones the current function and converts the clone to a one-time function.
535    ///
536    /// # Returns
537    ///
538    /// Returns a `BoxMutatingFunctionOnce<T, R>`
539    ///
540    /// # Examples
541    ///
542    /// ```rust
543    /// use qubit_function::{MutatingFunctionOnce, MutatingFunction,
544    ///                       ArcMutatingFunction};
545    ///
546    /// fn takes_once<F: MutatingFunctionOnce<i32, i32>>(func: F, value: &mut i32) {
547    ///     let result = func.apply(value);
548    ///     println!("Result: {}", result);
549    /// }
550    ///
551    /// let func = ArcMutatingFunction::new(|x: &mut i32| {
552    ///     *x *= 2;
553    ///     *x
554    /// });
555    /// let mut value = 5;
556    /// takes_once(func.to_once(), &mut value);
557    /// ```
558    fn to_once(&self) -> BoxMutatingFunctionOnce<T, R>
559    where
560        Self: Clone + 'static,
561    {
562        self.clone().into_once()
563    }
564}