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