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