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);