Skip to main content

qubit_function/functions/mutating_function_once/
box_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//! Defines the `BoxMutatingFunctionOnce` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// =======================================================================
16// 2. BoxMutatingFunctionOnce - Single Ownership Implementation
17// =======================================================================
18
19/// BoxMutatingFunctionOnce struct
20///
21/// A one-time mutating function implementation based on
22/// `Box<dyn FnOnce(&mut T) -> R>` for single ownership scenarios. This is
23/// the only MutatingFunctionOnce implementation type because FnOnce
24/// conflicts with shared ownership semantics.
25///
26/// # Features
27///
28/// - **Single Ownership**: Not cloneable, consumes self on use
29/// - **Zero Overhead**: No reference counting or locking
30/// - **Move Semantics**: Can capture and move variables
31/// - **Method Chaining**: Compose multiple operations via `and_then`
32/// - **Returns Results**: Unlike MutatorOnce, returns information
33///
34/// # Use Cases
35///
36/// Choose `BoxMutatingFunctionOnce` when:
37/// - Need to store FnOnce closures (with moved captured variables)
38/// - One-time resource transfer operations with results
39/// - Post-initialization callbacks that return status
40/// - Complex operations requiring ownership transfer and results
41///
42/// # Performance
43///
44/// `BoxMutatingFunctionOnce` performance characteristics:
45/// - No reference counting overhead
46/// - No lock acquisition or runtime borrow checking
47/// - Direct function call through vtable
48/// - Minimal memory footprint (single pointer)
49///
50/// # Why No Arc/Rc Variants?
51///
52/// FnOnce can only be called once, which conflicts with Arc/Rc shared
53/// ownership semantics:
54/// - Arc/Rc implies multiple owners might need to call
55/// - FnOnce is consumed after calling, cannot be called again
56/// - This semantic incompatibility makes Arc/Rc variants meaningless
57///
58/// # Examples
59///
60/// ## Basic Usage
61///
62/// ```rust
63/// use qubit_function::{MutatingFunctionOnce, BoxMutatingFunctionOnce};
64///
65/// let data = vec![1, 2, 3];
66/// let func = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
67///     let old_len = x.len();
68///     x.extend(data); // Move data
69///     old_len
70/// });
71///
72/// let mut target = vec![0];
73/// let old_len = func.apply(&mut target);
74/// assert_eq!(old_len, 1);
75/// assert_eq!(target, vec![0, 1, 2, 3]);
76/// ```
77///
78/// ## Method Chaining
79///
80/// ```rust
81/// use qubit_function::{MutatingFunctionOnce, BoxMutatingFunctionOnce};
82///
83/// let data1 = vec![1, 2];
84/// let additional_len = 2;
85///
86/// let chained = BoxMutatingFunctionOnce::new(move |x: &mut Vec<i32>| {
87///     x.extend(data1);
88///     x.len()
89/// })
90/// .and_then(move |len: &usize| len + additional_len);
91///
92/// let mut target = vec![0];
93/// let final_len = chained.apply(&mut target);
94/// assert_eq!(final_len, 5);
95/// assert_eq!(target, vec![0, 1, 2]);
96/// ```
97///
98/// # Author
99///
100/// Haixing Hu
101pub struct BoxMutatingFunctionOnce<T, R> {
102    pub(super) function: Box<dyn FnOnce(&mut T) -> R>,
103    pub(super) name: Option<String>,
104}
105
106impl<T, R> BoxMutatingFunctionOnce<T, R> {
107    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
108    impl_function_common_methods!(
109        BoxMutatingFunctionOnce<T, R>,
110        (FnOnce(&mut T) -> R + 'static),
111        |f| Box::new(f)
112    );
113
114    // Generates: when(), and_then(), compose()
115    impl_box_function_methods!(
116        BoxMutatingFunctionOnce<T, R>,
117        BoxConditionalMutatingFunctionOnce,
118        FunctionOnce    // chains a non-mutating function after this mutating function
119    );
120}
121
122impl<T, R> MutatingFunctionOnce<T, R> for BoxMutatingFunctionOnce<T, R> {
123    fn apply(self, input: &mut T) -> R {
124        (self.function)(input)
125    }
126
127    impl_box_once_conversions!(
128        BoxMutatingFunctionOnce<T, R>,
129        MutatingFunctionOnce,
130        FnOnce(&mut T) -> R
131    );
132}
133
134// Generates: identity() method for BoxMutatingFunctionOnce<T, T>
135impl_function_identity_method!(BoxMutatingFunctionOnce<T, T>, mutating);
136
137// Generates: Debug and Display implementations for BoxMutatingFunctionOnce<T, R>
138impl_function_debug_display!(BoxMutatingFunctionOnce<T, R>);
139
140// =======================================================================
141// 3. Implement MutatingFunctionOnce trait for closures
142// =======================================================================
143
144// Implement MutatingFunctionOnce for all FnOnce(&mut T) -> R using macro
145impl_closure_once_trait!(
146    MutatingFunctionOnce<T, R>,
147    apply,
148    BoxMutatingFunctionOnce,
149    FnOnce(input: &mut T) -> R
150);