Skip to main content

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        T: 'static,
268    {
269        BoxMutatorOnce::new(move |t| self.apply(t))
270    }
271
272    /// Converts to a consuming closure `FnOnce(&mut T)`
273    ///
274    /// Consumes `self` and returns a closure that, when invoked, calls
275    /// `apply(self, &mut T)`. This is the default, straightforward
276    /// implementation; types that can produce a more direct function pointer
277    /// or avoid additional captures may override it.
278    fn into_fn(self) -> impl FnOnce(&mut T)
279    where
280        Self: Sized + 'static,
281    {
282        move |t| self.apply(t)
283    }
284
285    /// Non-consuming adapter to `BoxMutatorOnce`
286    ///
287    /// Creates a `BoxMutatorOnce<T>` that does not consume `self`. The default
288    /// implementation requires `Self: Clone` and clones the receiver for the
289    /// stored closure; the clone is consumed when the boxed mutator is invoked.
290    /// Types that can provide a zero-cost adapter (for example clonable
291    /// closures) should override this method to avoid unnecessary allocations.
292    fn to_box(&self) -> BoxMutatorOnce<T>
293    where
294        Self: Sized + Clone + 'static,
295        T: '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}
313
314// ============================================================================
315// 2. BoxMutatorOnce - Single Ownership Implementation
316// ============================================================================
317
318/// BoxMutatorOnce struct
319///
320/// A one-time mutator implementation based on `Box<dyn FnOnce(&mut T)>` for
321/// single ownership scenarios. This is the only MutatorOnce implementation type
322/// because FnOnce conflicts with shared ownership semantics.
323///
324/// # Features
325///
326/// - **Single Ownership**: Not cloneable, consumes self on use
327/// - **Zero Overhead**: No reference counting or locking
328/// - **Move Semantics**: Can capture and move variables
329/// - **Method Chaining**: Compose multiple operations via `and_then`
330///
331/// # Use Cases
332///
333/// Choose `BoxMutatorOnce` when:
334/// - Need to store FnOnce closures (with moved captured variables)
335/// - One-time resource transfer operations
336/// - Post-initialization callbacks
337/// - Complex operations requiring ownership transfer
338///
339/// # Performance
340///
341/// `BoxMutatorOnce` performance characteristics:
342/// - No reference counting overhead
343/// - No lock acquisition or runtime borrow checking
344/// - Direct function call through vtable
345/// - Minimal memory footprint (single pointer)
346///
347/// # Why No Arc/Rc Variants?
348///
349/// FnOnce can only be called once, which conflicts with Arc/Rc shared ownership
350/// semantics:
351/// - Arc/Rc implies multiple owners might need to call
352/// - FnOnce is consumed after calling, cannot be called again
353/// - This semantic incompatibility makes Arc/Rc variants meaningless
354///
355/// # Examples
356///
357/// ## Basic Usage
358///
359/// ```rust
360/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
361///
362/// let data = vec![1, 2, 3];
363/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
364///     x.extend(data); // Move data
365/// });
366///
367/// let mut target = vec![0];
368/// mutator.apply(&mut target);
369/// assert_eq!(target, vec![0, 1, 2, 3]);
370/// ```
371///
372/// ## Method Chaining
373///
374/// ```rust
375/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
376///
377/// let data1 = vec![1, 2];
378/// let data2 = vec![3, 4];
379///
380/// let chained = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
381///     x.extend(data1);
382/// })
383/// .and_then(move |x: &mut Vec<i32>| {
384///     x.extend(data2);
385/// });
386///
387/// let mut target = vec![0];
388/// chained.apply(&mut target);
389/// assert_eq!(target, vec![0, 1, 2, 3, 4]);
390/// ```
391///
392/// # Author
393///
394/// Haixing Hu
395pub struct BoxMutatorOnce<T> {
396    function: Box<dyn FnOnce(&mut T)>,
397    name: Option<String>,
398}
399
400impl<T> BoxMutatorOnce<T> {
401    // Generates: new(), new_with_name(), name(), set_name(), noop()
402    impl_mutator_common_methods!(BoxMutatorOnce<T>, (FnOnce(&mut T) + 'static), |f| Box::new(
403        f
404    ));
405
406    // Generate box mutator methods (when, and_then, or_else, etc.)
407    impl_box_mutator_methods!(BoxMutatorOnce<T>, BoxConditionalMutatorOnce, MutatorOnce);
408}
409
410impl<T> MutatorOnce<T> for BoxMutatorOnce<T> {
411    fn apply(self, value: &mut T) {
412        (self.function)(value)
413    }
414
415    impl_box_once_conversions!(BoxMutatorOnce<T>, MutatorOnce, FnOnce(&mut T));
416}
417
418// Generate Debug and Display trait implementations
419impl_mutator_debug_display!(BoxMutatorOnce<T>);
420
421// ============================================================================
422// 3. Implement MutatorOnce trait for closures
423// ============================================================================
424
425// Implement MutatorOnce for all FnOnce(&mut T) using macro
426impl_closure_once_trait!(
427    MutatorOnce<T>,
428    apply,
429    BoxMutatorOnce,
430    FnOnce(value: &mut T)
431);
432
433// ============================================================================
434// 4. Provide extension methods for closures
435// ============================================================================
436
437/// Extension trait providing one-time mutator composition methods for closures
438///
439/// Provides `and_then` and other composition methods for all closures that
440/// implement `FnOnce(&mut T)`, enabling direct method chaining on closures
441/// without explicit wrapper types.
442///
443/// # Features
444///
445/// - **Natural Syntax**: Chain operations directly on closures
446/// - **Returns BoxMutatorOnce**: Composition results are `BoxMutatorOnce<T>`
447///   for continued chaining
448/// - **Zero Cost**: No overhead when composing closures
449/// - **Automatic Implementation**: All `FnOnce(&mut T)` closures get these
450///   methods automatically
451///
452/// # Examples
453///
454/// ```rust
455/// use qubit_function::{MutatorOnce, FnMutatorOnceOps};
456///
457/// let data1 = vec![1, 2];
458/// let data2 = vec![3, 4];
459///
460/// let chained = (move |x: &mut Vec<i32>| x.extend(data1))
461///     .and_then(move |x: &mut Vec<i32>| x.extend(data2));
462///
463/// let mut target = vec![0];
464/// chained.apply(&mut target);
465/// assert_eq!(target, vec![0, 1, 2, 3, 4]);
466/// ```
467///
468/// # Author
469///
470/// Haixing Hu
471pub trait FnMutatorOnceOps<T>: FnOnce(&mut T) + Sized {
472    /// Chains another mutator in sequence
473    ///
474    /// Returns a new mutator that first executes the current operation, then
475    /// executes the next operation. Consumes the current closure and returns
476    /// `BoxMutatorOnce<T>`.
477    ///
478    /// # Parameters
479    ///
480    /// * `next` - The mutator to execute after the current operation. **Note: This
481    ///   parameter is passed by value and will transfer ownership.** Since
482    ///   `BoxMutatorOnce` cannot be cloned, the parameter will be consumed.
483    ///   Can be:
484    ///   - A closure: `|x: &mut T|`
485    ///   - A `BoxMutatorOnce<T>`
486    ///   - Any type implementing `MutatorOnce<T>`
487    ///
488    /// # Returns
489    ///
490    /// Returns the composed `BoxMutatorOnce<T>`
491    ///
492    /// # Examples
493    ///
494    /// ```rust
495    /// use qubit_function::{MutatorOnce, FnMutatorOnceOps};
496    ///
497    /// let data1 = vec![1, 2];
498    /// let data2 = vec![3, 4];
499    ///
500    /// // Both closures are moved and consumed
501    /// let chained = (move |x: &mut Vec<i32>| x.extend(data1))
502    ///     .and_then(move |x: &mut Vec<i32>| x.extend(data2));
503    ///
504    /// let mut target = vec![0];
505    /// chained.apply(&mut target);
506    /// assert_eq!(target, vec![0, 1, 2, 3, 4]);
507    /// // The original closures are consumed and no longer usable
508    /// ```
509    fn and_then<C>(self, next: C) -> BoxMutatorOnce<T>
510    where
511        Self: 'static,
512        C: MutatorOnce<T> + 'static,
513        T: 'static,
514    {
515        BoxMutatorOnce::new(move |t| {
516            self(t);
517            next.apply(t);
518        })
519    }
520}
521
522/// Implements FnMutatorOnceOps for all closure types
523impl<T, F> FnMutatorOnceOps<T> for F where F: FnOnce(&mut T) {}
524
525// ============================================================================
526// 5. BoxConditionalMutatorOnce - Box-based Conditional Mutator
527// ============================================================================
528
529/// BoxConditionalMutatorOnce struct
530///
531/// A conditional one-time mutator that only executes when a predicate is satisfied.
532/// Uses `BoxMutatorOnce` and `BoxPredicate` for single ownership semantics.
533///
534/// This type is typically created by calling `BoxMutatorOnce::when()` and is
535/// designed to work with the `or_else()` method to create if-then-else logic.
536///
537/// # Features
538///
539/// - **Single Ownership**: Not cloneable, consumes `self` on use
540/// - **Conditional Execution**: Only mutates when predicate returns `true`
541/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
542/// - **Implements MutatorOnce**: Can be used anywhere a `MutatorOnce` is expected
543///
544/// # Examples
545///
546/// ## Basic Conditional Execution
547///
548/// ```rust
549/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
550///
551/// let data = vec![1, 2, 3];
552/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
553///     x.extend(data);
554/// });
555/// let conditional = mutator.when(|x: &Vec<i32>| !x.is_empty());
556///
557/// let mut target = vec![0];
558/// conditional.apply(&mut target);
559/// assert_eq!(target, vec![0, 1, 2, 3]); // Executed
560///
561/// let mut empty = Vec::new();
562/// let data2 = vec![4, 5];
563/// let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
564///     x.extend(data2);
565/// });
566/// let conditional2 = mutator2.when(|x: &Vec<i32>| x.len() > 5);
567/// conditional2.apply(&mut empty);
568/// assert_eq!(empty, Vec::<i32>::new()); // Not executed
569/// ```
570///
571/// ## With or_else Branch
572///
573/// ```rust
574/// use qubit_function::{MutatorOnce, BoxMutatorOnce};
575///
576/// let data1 = vec![1, 2, 3];
577/// let data2 = vec![99];
578/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
579///     x.extend(data1);
580/// })
581/// .when(|x: &Vec<i32>| !x.is_empty())
582/// .or_else(move |x: &mut Vec<i32>| {
583///     x.extend(data2);
584/// });
585///
586/// let mut target = vec![0];
587/// mutator.apply(&mut target);
588/// assert_eq!(target, vec![0, 1, 2, 3]); // when branch executed
589///
590/// let data3 = vec![4, 5];
591/// let data4 = vec![99];
592/// let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
593///     x.extend(data3);
594/// })
595/// .when(|x: &Vec<i32>| x.is_empty())
596/// .or_else(move |x: &mut Vec<i32>| {
597///     x.extend(data4);
598/// });
599///
600/// let mut target2 = vec![0];
601/// mutator2.apply(&mut target2);
602/// assert_eq!(target2, vec![0, 99]); // or_else branch executed
603/// ```
604///
605/// # Author
606///
607/// Haixing Hu
608pub struct BoxConditionalMutatorOnce<T> {
609    mutator: BoxMutatorOnce<T>,
610    predicate: BoxPredicate<T>,
611}
612
613// Generate and_then and or_else methods using macro
614impl_box_conditional_mutator!(BoxConditionalMutatorOnce<T>, BoxMutatorOnce, MutatorOnce);
615
616impl<T> MutatorOnce<T> for BoxConditionalMutatorOnce<T> {
617    fn apply(self, value: &mut T) {
618        if self.predicate.test(value) {
619            self.mutator.apply(value);
620        }
621    }
622
623    fn into_box(self) -> BoxMutatorOnce<T>
624    where
625        T: 'static,
626    {
627        let pred = self.predicate;
628        let mutator = self.mutator;
629        BoxMutatorOnce::new(move |t| {
630            if pred.test(t) {
631                mutator.apply(t);
632            }
633        })
634    }
635
636    fn into_fn(self) -> impl FnOnce(&mut T) {
637        let pred = self.predicate;
638        let mutator = self.mutator;
639        move |t: &mut T| {
640            if pred.test(t) {
641                mutator.apply(t);
642            }
643        }
644    }
645}
646
647// Use macro to generate Debug and Display implementations
648impl_conditional_mutator_debug_display!(BoxConditionalMutatorOnce<T>);