Skip to main content

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}