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
157// ============================================================================
158// 1. MutatorOnce Trait - One-time Mutator Interface
159// ============================================================================
160
161/// MutatorOnce trait - One-time mutator interface
162///
163/// Defines the core behavior of all one-time mutator types. Performs operations
164/// that consume self and modify the input value.
165///
166/// This trait is automatically implemented by:
167/// - All closures implementing `FnOnce(&mut T)`
168/// - `BoxMutatorOnce<T>`
169///
170/// # Design Rationale
171///
172/// This trait provides a unified abstraction for one-time mutation operations.
173/// The key difference from `Mutator`:
174/// - `Mutator` uses `&mut self`, can be called multiple times
175/// - `MutatorOnce` uses `self`, can only be called once
176///
177/// # Features
178///
179/// - **Unified Interface**: All one-time mutators share the same `mutate`
180/// method signature
181/// - **Automatic Implementation**: Closures automatically implement this
182/// trait with zero overhead
183/// - **Type Conversions**: Provides `into_box` method for type conversion
184/// - **Generic Programming**: Write functions that work with any one-time
185/// mutator type
186///
187/// # Examples
188///
189/// ## Generic Function
190///
191/// ```rust
192/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
193///
194/// fn apply_once<M: MutatorOnce<Vec<i32>>>(
195/// mutator: M,
196/// initial: Vec<i32>
197/// ) -> Vec<i32> {
198/// let mut val = initial;
199/// mutator.apply(&mut val);
200/// val
201/// }
202///
203/// let data = vec![1, 2, 3];
204/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
205/// x.extend(data);
206/// });
207/// let result = apply_once(mutator, vec![0]);
208/// assert_eq!(result, vec![0, 1, 2, 3]);
209/// ```
210///
211/// ## Type Conversion
212///
213/// ```rust
214/// use qubit_function::MutatorOnce;
215///
216/// let data = vec![1, 2, 3];
217/// let closure = move |x: &mut Vec<i32>| x.extend(data);
218/// let box_mutator = closure.into_box();
219/// ```
220///
221/// # Author
222///
223/// Haixing Hu
224pub trait MutatorOnce<T> {
225 /// Performs the one-time mutation operation
226 ///
227 /// Consumes self and executes an operation on the given mutable reference.
228 /// The operation typically modifies the input value or produces side effects,
229 /// and can only be called once.
230 ///
231 /// # Parameters
232 ///
233 /// * `value` - A mutable reference to the value to be mutated
234 ///
235 /// # Examples
236 ///
237 /// ```rust
238 /// use qubit_function::{MutatorOnce, BoxMutatorOnce};
239 ///
240 /// let data = vec![1, 2, 3];
241 /// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
242 /// x.extend(data);
243 /// });
244 ///
245 /// let mut target = vec![0];
246 /// mutator.apply(&mut target);
247 /// assert_eq!(target, vec![0, 1, 2, 3]);
248 /// ```
249 fn apply(self, value: &mut T);
250
251 /// Converts to `BoxMutatorOnce` (consuming)
252 ///
253 /// Consumes `self` and returns an owned `BoxMutatorOnce<T>`. The default
254 /// implementation simply wraps the consuming `apply(self, &mut T)` call
255 /// in a `Box<dyn FnOnce(&mut T)>`. Types that can provide a cheaper or
256 /// identity conversion (for example `BoxMutatorOnce` itself) should
257 /// override this method.
258 ///
259 /// # Note
260 ///
261 /// - This method consumes the source value.
262 /// - Implementors may return `self` directly when `Self` is already a
263 /// `BoxMutatorOnce<T>` to avoid the extra wrapper allocation.
264 fn into_box(self) -> BoxMutatorOnce<T>
265 where
266 Self: Sized + 'static,
267 {
268 BoxMutatorOnce::new(move |t| self.apply(t))
269 }
270
271 /// Converts to a consuming closure `FnOnce(&mut T)`
272 ///
273 /// Consumes `self` and returns a closure that, when invoked, calls
274 /// `apply(self, &mut T)`. This is the default, straightforward
275 /// implementation; types that can produce a more direct function pointer
276 /// or avoid additional captures may override it.
277 fn into_fn(self) -> impl FnOnce(&mut T)
278 where
279 Self: Sized + 'static,
280 {
281 move |t| self.apply(t)
282 }
283
284 /// Non-consuming adapter to `BoxMutatorOnce`
285 ///
286 /// Creates a `BoxMutatorOnce<T>` that does not consume `self`. The default
287 /// implementation requires `Self: Clone` and clones the receiver for the
288 /// stored closure; the clone is consumed when the boxed mutator is invoked.
289 /// Types that can provide a zero-cost adapter (for example clonable
290 /// closures) should override this method to avoid unnecessary allocations.
291 fn to_box(&self) -> BoxMutatorOnce<T>
292 where
293 Self: Sized + Clone + 'static,
294 {
295 self.clone().into_box()
296 }
297
298 /// Non-consuming adapter to a callable `FnOnce(&mut T)`
299 ///
300 /// Returns a closure that does not consume `self`. The default requires
301 /// `Self: Clone` and clones `self` for the captured closure; the clone is
302 /// consumed when the returned closure is invoked. Implementors may provide
303 /// more efficient adapters for specific types.
304 fn to_fn(&self) -> impl FnOnce(&mut T)
305 where
306 Self: Sized + Clone + 'static,
307 {
308 self.clone().into_fn()
309 }
310}
311
312// ============================================================================
313// 2. BoxMutatorOnce - Single Ownership Implementation
314// ============================================================================
315
316/// BoxMutatorOnce struct
317///
318/// A one-time mutator implementation based on `Box<dyn FnOnce(&mut T)>` for
319/// single ownership scenarios. This is the only MutatorOnce implementation type
320/// because FnOnce conflicts with shared ownership semantics.
321///
322/// # Features
323///
324/// - **Single Ownership**: Not cloneable, consumes self on use
325/// - **Zero Overhead**: No reference counting or locking
326/// - **Move Semantics**: Can capture and move variables
327/// - **Method Chaining**: Compose multiple operations via `and_then`
328///
329/// # Use Cases
330///
331/// Choose `BoxMutatorOnce` when:
332/// - Need to store FnOnce closures (with moved captured variables)
333/// - One-time resource transfer operations
334/// - Post-initialization callbacks
335/// - Complex operations requiring ownership transfer
336///
337/// # Performance
338///
339/// `BoxMutatorOnce` performance characteristics:
340/// - No reference counting overhead
341/// - No lock acquisition or runtime borrow checking
342/// - Direct function call through vtable
343/// - Minimal memory footprint (single pointer)
344///
345/// # Why No Arc/Rc Variants?
346///
347/// FnOnce can only be called once, which conflicts with Arc/Rc shared ownership
348/// semantics:
349/// - Arc/Rc implies multiple owners might need to call
350/// - FnOnce is consumed after calling, cannot be called again
351/// - This semantic incompatibility makes Arc/Rc variants meaningless
352///
353/// # Examples
354///
355/// ## Basic Usage
356///
357/// ```rust
358/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
359///
360/// let data = vec![1, 2, 3];
361/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
362/// x.extend(data); // Move data
363/// });
364///
365/// let mut target = vec![0];
366/// mutator.apply(&mut target);
367/// assert_eq!(target, vec![0, 1, 2, 3]);
368/// ```
369///
370/// ## Method Chaining
371///
372/// ```rust
373/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
374///
375/// let data1 = vec![1, 2];
376/// let data2 = vec![3, 4];
377///
378/// let chained = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
379/// x.extend(data1);
380/// })
381/// .and_then(move |x: &mut Vec<i32>| {
382/// x.extend(data2);
383/// });
384///
385/// let mut target = vec![0];
386/// chained.apply(&mut target);
387/// assert_eq!(target, vec![0, 1, 2, 3, 4]);
388/// ```
389///
390/// # Author
391///
392/// Haixing Hu
393pub struct BoxMutatorOnce<T> {
394 function: Box<dyn FnOnce(&mut T)>,
395 name: Option<String>,
396}
397
398impl<T> BoxMutatorOnce<T> {
399 // Generates: new(), new_with_name(), name(), set_name(), noop()
400 impl_mutator_common_methods!(BoxMutatorOnce<T>, (FnOnce(&mut T) + 'static), |f| Box::new(
401 f
402 ));
403
404 // Generate box mutator methods (when, and_then, or_else, etc.)
405 impl_box_mutator_methods!(BoxMutatorOnce<T>, BoxConditionalMutatorOnce, MutatorOnce);
406}
407
408impl<T> MutatorOnce<T> for BoxMutatorOnce<T> {
409 fn apply(self, value: &mut T) {
410 (self.function)(value)
411 }
412
413 impl_box_once_conversions!(BoxMutatorOnce<T>, MutatorOnce, FnOnce(&mut T));
414}
415
416// Generate Debug and Display trait implementations
417impl_mutator_debug_display!(BoxMutatorOnce<T>);
418
419// ============================================================================
420// 3. Implement MutatorOnce trait for closures
421// ============================================================================
422
423// Implement MutatorOnce for all FnOnce(&mut T) using macro
424impl_closure_once_trait!(
425 MutatorOnce<T>,
426 apply,
427 BoxMutatorOnce,
428 FnOnce(value: &mut T)
429);
430
431// ============================================================================
432// 4. Provide extension methods for closures
433// ============================================================================
434
435/// Extension trait providing one-time mutator composition methods for closures
436///
437/// Provides `and_then` and other composition methods for all closures that
438/// implement `FnOnce(&mut T)`, enabling direct method chaining on closures
439/// without explicit wrapper types.
440///
441/// # Features
442///
443/// - **Natural Syntax**: Chain operations directly on closures
444/// - **Returns BoxMutatorOnce**: Composition results are `BoxMutatorOnce<T>`
445/// for continued chaining
446/// - **Zero Cost**: No overhead when composing closures
447/// - **Automatic Implementation**: All `FnOnce(&mut T)` closures get these
448/// methods automatically
449///
450/// # Examples
451///
452/// ```rust
453/// use qubit_function::{MutatorOnce, FnMutatorOnceOps};
454///
455/// let data1 = vec![1, 2];
456/// let data2 = vec![3, 4];
457///
458/// let chained = (move |x: &mut Vec<i32>| x.extend(data1))
459/// .and_then(move |x: &mut Vec<i32>| x.extend(data2));
460///
461/// let mut target = vec![0];
462/// chained.apply(&mut target);
463/// assert_eq!(target, vec![0, 1, 2, 3, 4]);
464/// ```
465///
466/// # Author
467///
468/// Haixing Hu
469pub trait FnMutatorOnceOps<T>: FnOnce(&mut T) + Sized {
470 /// Chains another mutator in sequence
471 ///
472 /// Returns a new mutator that first executes the current operation, then
473 /// executes the next operation. Consumes the current closure and returns
474 /// `BoxMutatorOnce<T>`.
475 ///
476 /// # Parameters
477 ///
478 /// * `next` - The mutator to execute after the current operation. **Note: This
479 /// parameter is passed by value and will transfer ownership.** Since
480 /// `BoxMutatorOnce` cannot be cloned, the parameter will be consumed.
481 /// Can be:
482 /// - A closure: `|x: &mut T|`
483 /// - A `BoxMutatorOnce<T>`
484 /// - Any type implementing `MutatorOnce<T>`
485 ///
486 /// # Returns
487 ///
488 /// Returns the composed `BoxMutatorOnce<T>`
489 ///
490 /// # Examples
491 ///
492 /// ```rust
493 /// use qubit_function::{MutatorOnce, FnMutatorOnceOps};
494 ///
495 /// let data1 = vec![1, 2];
496 /// let data2 = vec![3, 4];
497 ///
498 /// // Both closures are moved and consumed
499 /// let chained = (move |x: &mut Vec<i32>| x.extend(data1))
500 /// .and_then(move |x: &mut Vec<i32>| x.extend(data2));
501 ///
502 /// let mut target = vec![0];
503 /// chained.apply(&mut target);
504 /// assert_eq!(target, vec![0, 1, 2, 3, 4]);
505 /// // The original closures are consumed and no longer usable
506 /// ```
507 fn and_then<C>(self, next: C) -> BoxMutatorOnce<T>
508 where
509 Self: 'static,
510 C: MutatorOnce<T> + 'static,
511 T: 'static,
512 {
513 BoxMutatorOnce::new(move |t| {
514 self(t);
515 next.apply(t);
516 })
517 }
518}
519
520/// Implements FnMutatorOnceOps for all closure types
521impl<T, F> FnMutatorOnceOps<T> for F where F: FnOnce(&mut T) {}
522
523// ============================================================================
524// 5. BoxConditionalMutatorOnce - Box-based Conditional Mutator
525// ============================================================================
526
527/// BoxConditionalMutatorOnce struct
528///
529/// A conditional one-time mutator that only executes when a predicate is satisfied.
530/// Uses `BoxMutatorOnce` and `BoxPredicate` for single ownership semantics.
531///
532/// This type is typically created by calling `BoxMutatorOnce::when()` and is
533/// designed to work with the `or_else()` method to create if-then-else logic.
534///
535/// # Features
536///
537/// - **Single Ownership**: Not cloneable, consumes `self` on use
538/// - **Conditional Execution**: Only mutates when predicate returns `true`
539/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
540/// - **Implements MutatorOnce**: Can be used anywhere a `MutatorOnce` is expected
541///
542/// # Examples
543///
544/// ## Basic Conditional Execution
545///
546/// ```rust
547/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
548///
549/// let data = vec![1, 2, 3];
550/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
551/// x.extend(data);
552/// });
553/// let conditional = mutator.when(|x: &Vec<i32>| !x.is_empty());
554///
555/// let mut target = vec![0];
556/// conditional.apply(&mut target);
557/// assert_eq!(target, vec![0, 1, 2, 3]); // Executed
558///
559/// let mut empty = Vec::new();
560/// let data2 = vec![4, 5];
561/// let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
562/// x.extend(data2);
563/// });
564/// let conditional2 = mutator2.when(|x: &Vec<i32>| x.len() > 5);
565/// conditional2.apply(&mut empty);
566/// assert_eq!(empty, Vec::<i32>::new()); // Not executed
567/// ```
568///
569/// ## With or_else Branch
570///
571/// ```rust
572/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
573///
574/// let data1 = vec![1, 2, 3];
575/// let data2 = vec![99];
576/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
577/// x.extend(data1);
578/// })
579/// .when(|x: &Vec<i32>| !x.is_empty())
580/// .or_else(move |x: &mut Vec<i32>| {
581/// x.extend(data2);
582/// });
583///
584/// let mut target = vec![0];
585/// mutator.apply(&mut target);
586/// assert_eq!(target, vec![0, 1, 2, 3]); // when branch executed
587///
588/// let data3 = vec![4, 5];
589/// let data4 = vec![99];
590/// let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
591/// x.extend(data3);
592/// })
593/// .when(|x: &Vec<i32>| x.is_empty())
594/// .or_else(move |x: &mut Vec<i32>| {
595/// x.extend(data4);
596/// });
597///
598/// let mut target2 = vec![0];
599/// mutator2.apply(&mut target2);
600/// assert_eq!(target2, vec![0, 99]); // or_else branch executed
601/// ```
602///
603/// # Author
604///
605/// Haixing Hu
606pub struct BoxConditionalMutatorOnce<T> {
607 mutator: BoxMutatorOnce<T>,
608 predicate: BoxPredicate<T>,
609}
610
611// Generate and_then and or_else methods using macro
612impl_box_conditional_mutator!(BoxConditionalMutatorOnce<T>, BoxMutatorOnce, MutatorOnce);
613
614impl<T> MutatorOnce<T> for BoxConditionalMutatorOnce<T> {
615 fn apply(self, value: &mut T) {
616 if self.predicate.test(value) {
617 self.mutator.apply(value);
618 }
619 }
620
621 fn into_fn(self) -> impl FnOnce(&mut T) {
622 let pred = self.predicate;
623 let mutator = self.mutator;
624 move |t: &mut T| {
625 if pred.test(t) {
626 mutator.apply(t);
627 }
628 }
629 }
630}
631
632// Use macro to generate Debug and Display implementations
633impl_conditional_mutator_debug_display!(BoxConditionalMutatorOnce<T>);