qubit_function/mutators/mutator_once.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # MutatorOnce Types
10//!
11//! Provides Java-style one-time `Mutator` interface implementations for performing
12//! operations that consume self and modify the input value.
13//!
14//! It is similar to the `FnOnce(&mut T)` trait in the standard library.
15//!
16//! This module provides a unified `MutatorOnce` trait and a Box-based single
17//! ownership implementation:
18//!
19//! - **`BoxMutatorOnce<T>`**: Box-based single ownership implementation for
20//! one-time use scenarios
21//!
22//! # Design Philosophy
23//!
24//! The key difference between `MutatorOnce` and `Mutator`:
25//!
26//! - **Mutator**: `&mut self`, can be called multiple times, uses `FnMut(&mut T)`
27//! - **MutatorOnce**: `self`, can only be called once, uses `FnOnce(&mut T)`
28//!
29//! ## MutatorOnce vs Mutator
30//!
31//! | Feature | Mutator | MutatorOnce |
32//! |---------|---------|-------------|
33//! | **Self Parameter** | `&mut self` | `self` |
34//! | **Call Count** | Multiple | Once |
35//! | **Closure Type** | `FnMut(&mut T)` | `FnOnce(&mut T)` |
36//! | **Use Cases** | Repeatable modifications | One-time resource transfers, init callbacks |
37//!
38//! # Why MutatorOnce?
39//!
40//! Core value of MutatorOnce:
41//!
42//! 1. **Store FnOnce closures**: Allows moving captured variables
43//! 2. **Delayed execution**: Store in data structures, execute later
44//! 3. **Resource transfer**: Suitable for scenarios requiring ownership transfer
45//!
46//! # Why Only Box Variant?
47//!
48//! - **Arc/Rc conflicts with FnOnce semantics**: FnOnce can only be called once,
49//! while shared ownership implies multiple references
50//! - **Box is perfect match**: Single ownership aligns perfectly with one-time
51//! call semantics
52//!
53//! # Use Cases
54//!
55//! ## BoxMutatorOnce
56//!
57//! - Post-initialization callbacks (moving data)
58//! - Resource transfer (moving Vec, String, etc.)
59//! - One-time complex operations (requiring moved capture variables)
60//!
61//! # Examples
62//!
63//! ## Basic Usage
64//!
65//! ```rust
66//! use qubit_function::{BoxMutatorOnce, MutatorOnce};
67//!
68//! let data = vec![1, 2, 3];
69//! let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
70//! x.extend(data); // Move data
71//! });
72//!
73//! let mut target = vec![0];
74//! mutator.apply(&mut target);
75//! assert_eq!(target, vec![0, 1, 2, 3]);
76//! ```
77//!
78//! ## Method Chaining
79//!
80//! ```rust
81//! use qubit_function::{BoxMutatorOnce, MutatorOnce};
82//!
83//! let data1 = vec![1, 2];
84//! let data2 = vec![3, 4];
85//!
86//! let chained = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
87//! x.extend(data1);
88//! })
89//! .and_then(move |x: &mut Vec<i32>| {
90//! x.extend(data2);
91//! });
92//!
93//! let mut target = vec![0];
94//! chained.apply(&mut target);
95//! assert_eq!(target, vec![0, 1, 2, 3, 4]);
96//! ```
97//!
98//! ## Initialization Callback
99//!
100//! ```rust
101//! use qubit_function::{BoxMutatorOnce, MutatorOnce};
102//!
103//! struct Initializer {
104//! on_complete: Option<BoxMutatorOnce<Vec<i32>>>,
105//! }
106//!
107//! impl Initializer {
108//! fn new<F>(callback: F) -> Self
109//! where
110//! F: FnOnce(&mut Vec<i32>) + 'static
111//! {
112//! Self {
113//! on_complete: Some(BoxMutatorOnce::new(callback))
114//! }
115//! }
116//!
117//! fn run(mut self, data: &mut Vec<i32>) {
118//! // Execute initialization logic
119//! data.push(42);
120//!
121//! // Call callback
122//! if let Some(callback) = self.on_complete.take() {
123//! callback.apply(data);
124//! }
125//! }
126//! }
127//!
128//! let data_to_add = vec![1, 2, 3];
129//! let init = Initializer::new(move |x| {
130//! x.extend(data_to_add); // Move data_to_add
131//! });
132//!
133//! let mut result = Vec::new();
134//! init.run(&mut result);
135//! assert_eq!(result, vec![42, 1, 2, 3]);
136//! ```
137//!
138//! # Author
139//!
140//! Haixing Hu
141use crate::macros::{
142 impl_box_once_conversions,
143 impl_closure_once_trait,
144};
145use crate::mutators::macros::{
146 impl_box_conditional_mutator,
147 impl_box_mutator_methods,
148 impl_conditional_mutator_debug_display,
149 impl_mutator_common_methods,
150 impl_mutator_debug_display,
151};
152use crate::predicates::predicate::{
153 BoxPredicate,
154 Predicate,
155};
156
157mod box_mutator_once;
158pub use box_mutator_once::BoxMutatorOnce;
159mod fn_mutator_once_ops;
160pub use fn_mutator_once_ops::FnMutatorOnceOps;
161mod box_conditional_mutator_once;
162pub use box_conditional_mutator_once::BoxConditionalMutatorOnce;
163
164// ============================================================================
165// 1. MutatorOnce Trait - One-time Mutator Interface
166// ============================================================================
167
168/// MutatorOnce trait - One-time mutator interface
169///
170/// Defines the core behavior of all one-time mutator types. Performs operations
171/// that consume self and modify the input value.
172///
173/// This trait is automatically implemented by:
174/// - All closures implementing `FnOnce(&mut T)`
175/// - `BoxMutatorOnce<T>`
176///
177/// # Design Rationale
178///
179/// This trait provides a unified abstraction for one-time mutation operations.
180/// The key difference from `Mutator`:
181/// - `Mutator` uses `&mut self`, can be called multiple times
182/// - `MutatorOnce` uses `self`, can only be called once
183///
184/// # Features
185///
186/// - **Unified Interface**: All one-time mutators share the same `mutate`
187/// method signature
188/// - **Automatic Implementation**: Closures automatically implement this
189/// trait with zero overhead
190/// - **Type Conversions**: Provides `into_box` method for type conversion
191/// - **Generic Programming**: Write functions that work with any one-time
192/// mutator type
193///
194/// # Examples
195///
196/// ## Generic Function
197///
198/// ```rust
199/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
200///
201/// fn apply_once<M: MutatorOnce<Vec<i32>>>(
202/// mutator: M,
203/// initial: Vec<i32>
204/// ) -> Vec<i32> {
205/// let mut val = initial;
206/// mutator.apply(&mut val);
207/// val
208/// }
209///
210/// let data = vec![1, 2, 3];
211/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
212/// x.extend(data);
213/// });
214/// let result = apply_once(mutator, vec![0]);
215/// assert_eq!(result, vec![0, 1, 2, 3]);
216/// ```
217///
218/// ## Type Conversion
219///
220/// ```rust
221/// use qubit_function::MutatorOnce;
222///
223/// let data = vec![1, 2, 3];
224/// let closure = move |x: &mut Vec<i32>| x.extend(data);
225/// let box_mutator = closure.into_box();
226/// ```
227///
228/// # Author
229///
230/// Haixing Hu
231pub trait MutatorOnce<T> {
232 /// Performs the one-time mutation operation
233 ///
234 /// Consumes self and executes an operation on the given mutable reference.
235 /// The operation typically modifies the input value or produces side effects,
236 /// and can only be called once.
237 ///
238 /// # Parameters
239 ///
240 /// * `value` - A mutable reference to the value to be mutated
241 ///
242 /// # Examples
243 ///
244 /// ```rust
245 /// use qubit_function::{MutatorOnce, BoxMutatorOnce};
246 ///
247 /// let data = vec![1, 2, 3];
248 /// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
249 /// x.extend(data);
250 /// });
251 ///
252 /// let mut target = vec![0];
253 /// mutator.apply(&mut target);
254 /// assert_eq!(target, vec![0, 1, 2, 3]);
255 /// ```
256 fn apply(self, value: &mut T);
257
258 /// Converts to `BoxMutatorOnce` (consuming)
259 ///
260 /// Consumes `self` and returns an owned `BoxMutatorOnce<T>`. The default
261 /// implementation simply wraps the consuming `apply(self, &mut T)` call
262 /// in a `Box<dyn FnOnce(&mut T)>`. Types that can provide a cheaper or
263 /// identity conversion (for example `BoxMutatorOnce` itself) should
264 /// override this method.
265 ///
266 /// # Note
267 ///
268 /// - This method consumes the source value.
269 /// - Implementors may return `self` directly when `Self` is already a
270 /// `BoxMutatorOnce<T>` to avoid the extra wrapper allocation.
271 fn into_box(self) -> BoxMutatorOnce<T>
272 where
273 Self: Sized + 'static,
274 {
275 BoxMutatorOnce::new(move |t| self.apply(t))
276 }
277
278 /// Converts to a consuming closure `FnOnce(&mut T)`
279 ///
280 /// Consumes `self` and returns a closure that, when invoked, calls
281 /// `apply(self, &mut T)`. This is the default, straightforward
282 /// implementation; types that can produce a more direct function pointer
283 /// or avoid additional captures may override it.
284 fn into_fn(self) -> impl FnOnce(&mut T)
285 where
286 Self: Sized + 'static,
287 {
288 move |t| self.apply(t)
289 }
290
291 /// Non-consuming adapter to `BoxMutatorOnce`
292 ///
293 /// Creates a `BoxMutatorOnce<T>` that does not consume `self`. The default
294 /// implementation requires `Self: Clone` and clones the receiver for the
295 /// stored closure; the clone is consumed when the boxed mutator is invoked.
296 /// Types that can provide a zero-cost adapter (for example clonable
297 /// closures) should override this method to avoid unnecessary allocations.
298 fn to_box(&self) -> BoxMutatorOnce<T>
299 where
300 Self: Sized + Clone + 'static,
301 {
302 self.clone().into_box()
303 }
304
305 /// Non-consuming adapter to a callable `FnOnce(&mut T)`
306 ///
307 /// Returns a closure that does not consume `self`. The default requires
308 /// `Self: Clone` and clones `self` for the captured closure; the clone is
309 /// consumed when the returned closure is invoked. Implementors may provide
310 /// more efficient adapters for specific types.
311 fn to_fn(&self) -> impl FnOnce(&mut T)
312 where
313 Self: Sized + Clone + 'static,
314 {
315 self.clone().into_fn()
316 }
317}