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