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}