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
13#![allow(unused_imports)]
14
15use super::*;
16
17// ============================================================================
18// 2. BoxMutatorOnce - Single Ownership Implementation
19// ============================================================================
20
21/// BoxMutatorOnce struct
22///
23/// A one-time mutator implementation based on `Box<dyn FnOnce(&mut T)>` for
24/// single ownership scenarios. This is the only MutatorOnce implementation type
25/// because FnOnce conflicts with shared ownership semantics.
26///
27/// # Features
28///
29/// - **Single Ownership**: Not cloneable, consumes self on use
30/// - **Zero Overhead**: No reference counting or locking
31/// - **Move Semantics**: Can capture and move variables
32/// - **Method Chaining**: Compose multiple operations via `and_then`
33///
34/// # Use Cases
35///
36/// Choose `BoxMutatorOnce` when:
37/// - Need to store FnOnce closures (with moved captured variables)
38/// - One-time resource transfer operations
39/// - Post-initialization callbacks
40/// - Complex operations requiring ownership transfer
41///
42/// # Performance
43///
44/// `BoxMutatorOnce` 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 ownership
53/// 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::{MutatorOnce, BoxMutatorOnce};
64///
65/// let data = vec![1, 2, 3];
66/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
67/// x.extend(data); // Move data
68/// });
69///
70/// let mut target = vec![0];
71/// mutator.apply(&mut target);
72/// assert_eq!(target, vec![0, 1, 2, 3]);
73/// ```
74///
75/// ## Method Chaining
76///
77/// ```rust
78/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
79///
80/// let data1 = vec![1, 2];
81/// let data2 = vec![3, 4];
82///
83/// let chained = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
84/// x.extend(data1);
85/// })
86/// .and_then(move |x: &mut Vec<i32>| {
87/// x.extend(data2);
88/// });
89///
90/// let mut target = vec![0];
91/// chained.apply(&mut target);
92/// assert_eq!(target, vec![0, 1, 2, 3, 4]);
93/// ```
94///
95pub struct BoxMutatorOnce<T> {
96 pub(super) function: Box<dyn FnOnce(&mut T)>,
97 pub(super) name: Option<String>,
98}
99
100impl<T> BoxMutatorOnce<T> {
101 // Generates: new(), new_with_name(), name(), set_name(), noop()
102 impl_mutator_common_methods!(BoxMutatorOnce<T>, (FnOnce(&mut T) + 'static), |f| Box::new(
103 f
104 ));
105
106 // Generate box mutator methods (when, and_then, or_else, etc.)
107 impl_box_mutator_methods!(BoxMutatorOnce<T>, BoxConditionalMutatorOnce, MutatorOnce);
108}
109
110impl<T> MutatorOnce<T> for BoxMutatorOnce<T> {
111 fn apply(self, value: &mut T) {
112 (self.function)(value)
113 }
114
115 impl_box_once_conversions!(BoxMutatorOnce<T>, MutatorOnce, FnOnce(&mut T));
116}
117
118// Generate Debug and Display trait implementations
119impl_mutator_debug_display!(BoxMutatorOnce<T>);
120
121// ============================================================================
122// 3. Implement MutatorOnce trait for closures
123// ============================================================================
124
125// Implement MutatorOnce for all FnOnce(&mut T) using macro
126impl_closure_once_trait!(
127 MutatorOnce<T>,
128 apply,
129 BoxMutatorOnce,
130 FnOnce(value: &mut T)
131);