Skip to main content

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