Skip to main content

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