Skip to main content

qubit_function/functions/mutating_function/
rc_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// qubit-style: allow explicit-imports
11//! Defines the `RcMutatingFunction` public type.
12
13use super::{
14    BoxMutatingFunction,
15    BoxMutatingFunctionOnce,
16    Function,
17    MutatingFunction,
18    Predicate,
19    Rc,
20    RcConditionalMutatingFunction,
21    impl_function_clone,
22    impl_function_common_methods,
23    impl_function_debug_display,
24    impl_function_identity_method,
25    impl_rc_conversions,
26    impl_shared_function_methods,
27};
28
29// =======================================================================
30// 4. RcMutatingFunction - Single-Threaded Shared Ownership
31// =======================================================================
32
33/// RcMutatingFunction struct
34///
35/// A mutating function implementation based on `Rc<dyn Fn(&mut T) -> R>` for
36/// single-threaded shared ownership scenarios. This type allows multiple
37/// references to the same function without the overhead of thread safety.
38///
39/// # Features
40///
41/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
42/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
43/// - **Stateless**: Cannot modify captured environment (uses `Fn` not
44///   `FnMut`)
45/// - **Chainable**: Method chaining via `&self` (non-consuming)
46/// - **Performance**: More efficient than `ArcMutatingFunction` (no locking)
47///
48/// # Use Cases
49///
50/// Choose `RcMutatingFunction` when:
51/// - The function needs to be shared within a single thread for stateless
52///   operations
53/// - Thread safety is not required
54/// - Performance is important (avoiding lock overhead)
55///
56/// # Examples
57///
58/// ```rust
59/// use qubit_function::{MutatingFunction, RcMutatingFunction};
60///
61/// let func = RcMutatingFunction::new(|x: &mut i32| {
62///     *x *= 2;
63///     *x
64/// });
65/// let clone = func.clone();
66///
67/// let mut value = 5;
68/// assert_eq!(func.apply(&mut value), 10);
69/// ```
70///
71pub struct RcMutatingFunction<T, R> {
72    pub(super) function: Rc<dyn Fn(&mut T) -> R>,
73    pub(super) name: Option<String>,
74}
75
76impl<T, R> RcMutatingFunction<T, R> {
77    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
78    impl_function_common_methods!(
79        RcMutatingFunction<T, R>,
80        (Fn(&mut T) -> R + 'static),
81        |f| Rc::new(f)
82    );
83
84    // Generates: when(), and_then(), compose()
85    impl_shared_function_methods!(
86        RcMutatingFunction<T, R>,
87        RcConditionalMutatingFunction,
88        into_rc,
89        Function,  // chains a non-mutating function after this mutating function
90        'static
91    );
92}
93
94// Generates: Clone implementation for RcMutatingFunction<T, R>
95impl_function_clone!(RcMutatingFunction<T, R>);
96
97// Generates: Debug and Display implementations for RcMutatingFunction<T, R>
98impl_function_debug_display!(RcMutatingFunction<T, R>);
99
100// Generates: identity() method for RcMutatingFunction<T, T>
101impl_function_identity_method!(RcMutatingFunction<T, T>, mutating);
102
103impl<T, R> MutatingFunction<T, R> for RcMutatingFunction<T, R> {
104    fn apply(&self, input: &mut T) -> R {
105        (self.function)(input)
106    }
107
108    // Use macro to implement conversion methods
109    impl_rc_conversions!(
110        RcMutatingFunction<T, R>,
111        BoxMutatingFunction,
112        BoxMutatingFunctionOnce,
113        Fn(input: &mut T) -> R
114    );
115}