prism3_function/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//! This module provides a unified `MutatorOnce` trait and a Box-based single
15//! ownership implementation:
16//!
17//! - **`BoxMutatorOnce<T>`**: Box-based single ownership implementation for
18//! one-time use scenarios
19//!
20//! # Design Philosophy
21//!
22//! The key difference between `MutatorOnce` and `Mutator`:
23//!
24//! - **Mutator**: `&mut self`, can be called multiple times, uses `FnMut(&mut T)`
25//! - **MutatorOnce**: `self`, can only be called once, uses `FnOnce(&mut T)`
26//!
27//! ## MutatorOnce vs Mutator
28//!
29//! | Feature | Mutator | MutatorOnce |
30//! |---------|---------|-------------|
31//! | **Self Parameter** | `&mut self` | `self` |
32//! | **Call Count** | Multiple | Once |
33//! | **Closure Type** | `FnMut(&mut T)` | `FnOnce(&mut T)` |
34//! | **Use Cases** | Repeatable modifications | One-time resource transfers, init callbacks |
35//!
36//! # Why MutatorOnce?
37//!
38//! Core value of MutatorOnce:
39//!
40//! 1. **Store FnOnce closures**: Allows moving captured variables
41//! 2. **Delayed execution**: Store in data structures, execute later
42//! 3. **Resource transfer**: Suitable for scenarios requiring ownership transfer
43//!
44//! # Why Only Box Variant?
45//!
46//! - **Arc/Rc conflicts with FnOnce semantics**: FnOnce can only be called once,
47//! while shared ownership implies multiple references
48//! - **Box is perfect match**: Single ownership aligns perfectly with one-time
49//! call semantics
50//!
51//! # Use Cases
52//!
53//! ## BoxMutatorOnce
54//!
55//! - Post-initialization callbacks (moving data)
56//! - Resource transfer (moving Vec, String, etc.)
57//! - One-time complex operations (requiring moved capture variables)
58//!
59//! # Examples
60//!
61//! ## Basic Usage
62//!
63//! ```rust
64//! use prism3_function::{BoxMutatorOnce, MutatorOnce};
65//!
66//! let data = vec![1, 2, 3];
67//! let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
68//! x.extend(data); // Move data
69//! });
70//!
71//! let mut target = vec![0];
72//! mutator.mutate_once(&mut target);
73//! assert_eq!(target, vec![0, 1, 2, 3]);
74//! ```
75//!
76//! ## Method Chaining
77//!
78//! ```rust
79//! use prism3_function::{BoxMutatorOnce, MutatorOnce};
80//!
81//! let data1 = vec![1, 2];
82//! let data2 = vec![3, 4];
83//!
84//! let chained = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
85//! x.extend(data1);
86//! })
87//! .and_then(move |x: &mut Vec<i32>| {
88//! x.extend(data2);
89//! });
90//!
91//! let mut target = vec![0];
92//! chained.mutate_once(&mut target);
93//! assert_eq!(target, vec![0, 1, 2, 3, 4]);
94//! ```
95//!
96//! ## Initialization Callback
97//!
98//! ```rust
99//! use prism3_function::{BoxMutatorOnce, MutatorOnce};
100//!
101//! struct Initializer {
102//! on_complete: Option<BoxMutatorOnce<Vec<i32>>>,
103//! }
104//!
105//! impl Initializer {
106//! fn new<F>(callback: F) -> Self
107//! where
108//! F: FnOnce(&mut Vec<i32>) + 'static
109//! {
110//! Self {
111//! on_complete: Some(BoxMutatorOnce::new(callback))
112//! }
113//! }
114//!
115//! fn run(mut self, data: &mut Vec<i32>) {
116//! // Execute initialization logic
117//! data.push(42);
118//!
119//! // Call callback
120//! if let Some(callback) = self.on_complete.take() {
121//! callback.mutate_once(data);
122//! }
123//! }
124//! }
125//!
126//! let data_to_add = vec![1, 2, 3];
127//! let init = Initializer::new(move |x| {
128//! x.extend(data_to_add); // Move data_to_add
129//! });
130//!
131//! let mut result = Vec::new();
132//! init.run(&mut result);
133//! assert_eq!(result, vec![42, 1, 2, 3]);
134//! ```
135//!
136//! # Author
137//!
138//! Haixing Hu
139
140use crate::predicate::{BoxPredicate, Predicate};
141
142// ============================================================================
143// 1. MutatorOnce Trait - One-time Mutator Interface
144// ============================================================================
145
146/// MutatorOnce trait - One-time mutator interface
147///
148/// Defines the core behavior of all one-time mutator types. Performs operations
149/// that consume self and modify the input value.
150///
151/// This trait is automatically implemented by:
152/// - All closures implementing `FnOnce(&mut T)`
153/// - `BoxMutatorOnce<T>`
154///
155/// # Design Rationale
156///
157/// This trait provides a unified abstraction for one-time mutation operations.
158/// The key difference from `Mutator`:
159/// - `Mutator` uses `&mut self`, can be called multiple times
160/// - `MutatorOnce` uses `self`, can only be called once
161///
162/// # Features
163///
164/// - **Unified Interface**: All one-time mutators share the same `mutate`
165/// method signature
166/// - **Automatic Implementation**: Closures automatically implement this
167/// trait with zero overhead
168/// - **Type Conversions**: Provides `into_box` method for type conversion
169/// - **Generic Programming**: Write functions that work with any one-time
170/// mutator type
171///
172/// # Examples
173///
174/// ## Generic Function
175///
176/// ```rust
177/// use prism3_function::{MutatorOnce, BoxMutatorOnce};
178///
179/// fn apply_once<M: MutatorOnce<Vec<i32>>>(
180/// mutator: M,
181/// initial: Vec<i32>
182/// ) -> Vec<i32> {
183/// let mut val = initial;
184/// mutator.mutate_once(&mut val);
185/// val
186/// }
187///
188/// let data = vec![1, 2, 3];
189/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
190/// x.extend(data);
191/// });
192/// let result = apply_once(mutator, vec![0]);
193/// assert_eq!(result, vec![0, 1, 2, 3]);
194/// ```
195///
196/// ## Type Conversion
197///
198/// ```rust
199/// use prism3_function::MutatorOnce;
200///
201/// let data = vec![1, 2, 3];
202/// let closure = move |x: &mut Vec<i32>| x.extend(data);
203/// let box_mutator = closure.into_box_once();
204/// ```
205///
206/// # Author
207///
208/// Haixing Hu
209pub trait MutatorOnce<T> {
210 /// Performs the one-time mutation operation
211 ///
212 /// Consumes self and executes an operation on the given mutable reference.
213 /// The operation typically modifies the input value or produces side effects,
214 /// and can only be called once.
215 ///
216 /// # Parameters
217 ///
218 /// * `value` - A mutable reference to the value to be mutated
219 ///
220 /// # Examples
221 ///
222 /// ```rust
223 /// use prism3_function::{MutatorOnce, BoxMutatorOnce};
224 ///
225 /// let data = vec![1, 2, 3];
226 /// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
227 /// x.extend(data);
228 /// });
229 ///
230 /// let mut target = vec![0];
231 /// mutator.mutate_once(&mut target);
232 /// assert_eq!(target, vec![0, 1, 2, 3]);
233 /// ```
234 fn mutate_once(self, value: &mut T);
235
236 /// Converts to `BoxMutatorOnce` (consuming)
237 ///
238 /// Consumes `self` and returns an owned `BoxMutatorOnce<T>`. The default
239 /// implementation simply wraps the consuming `mutate_once(self, &mut T)` call
240 /// in a `Box<dyn FnOnce(&mut T)>`. Types that can provide a cheaper or
241 /// identity conversion (for example `BoxMutatorOnce` itself) should
242 /// override this method.
243 ///
244 /// # Note
245 ///
246 /// - This method consumes the source value.
247 /// - Implementors may return `self` directly when `Self` is already a
248 /// `BoxMutatorOnce<T>` to avoid the extra wrapper allocation.
249 fn into_box_once(self) -> BoxMutatorOnce<T>
250 where
251 Self: Sized + 'static,
252 T: 'static,
253 {
254 BoxMutatorOnce::new(move |t| self.mutate_once(t))
255 }
256
257 /// Converts to a consuming closure `FnOnce(&mut T)`
258 ///
259 /// Consumes `self` and returns a closure that, when invoked, calls
260 /// `mutate_once(self, &mut T)`. This is the default, straightforward
261 /// implementation; types that can produce a more direct function pointer
262 /// or avoid additional captures may override it.
263 fn into_fn_once(self) -> impl FnOnce(&mut T)
264 where
265 Self: Sized + 'static,
266 T: 'static,
267 {
268 move |t| self.mutate_once(t)
269 }
270
271 /// Non-consuming adapter to `BoxMutatorOnce`
272 ///
273 /// Creates a `BoxMutatorOnce<T>` that does not consume `self`. The default
274 /// implementation requires `Self: Clone` and clones the receiver for the
275 /// stored closure; the clone is consumed when the boxed mutator is invoked.
276 /// Types that can provide a zero-cost adapter (for example clonable
277 /// closures) should override this method to avoid unnecessary allocations.
278 fn to_box_once(&self) -> BoxMutatorOnce<T>
279 where
280 Self: Sized + Clone + 'static,
281 T: 'static,
282 {
283 self.clone().into_box_once()
284 }
285
286 /// Non-consuming adapter to a callable `FnOnce(&mut T)`
287 ///
288 /// Returns a closure that does not consume `self`. The default requires
289 /// `Self: Clone` and clones `self` for the captured closure; the clone is
290 /// consumed when the returned closure is invoked. Implementors may provide
291 /// more efficient adapters for specific types.
292 fn to_fn_once(&self) -> impl FnOnce(&mut T)
293 where
294 Self: Sized + Clone + 'static,
295 T: 'static,
296 {
297 self.clone().into_fn_once()
298 }
299}
300
301// ============================================================================
302// 2. BoxMutatorOnce - Single Ownership Implementation
303// ============================================================================
304
305/// BoxMutatorOnce struct
306///
307/// A one-time mutator implementation based on `Box<dyn FnOnce(&mut T)>` for
308/// single ownership scenarios. This is the only MutatorOnce implementation type
309/// because FnOnce conflicts with shared ownership semantics.
310///
311/// # Features
312///
313/// - **Single Ownership**: Not cloneable, consumes self on use
314/// - **Zero Overhead**: No reference counting or locking
315/// - **Move Semantics**: Can capture and move variables
316/// - **Method Chaining**: Compose multiple operations via `and_then`
317///
318/// # Use Cases
319///
320/// Choose `BoxMutatorOnce` when:
321/// - Need to store FnOnce closures (with moved captured variables)
322/// - One-time resource transfer operations
323/// - Post-initialization callbacks
324/// - Complex operations requiring ownership transfer
325///
326/// # Performance
327///
328/// `BoxMutatorOnce` performance characteristics:
329/// - No reference counting overhead
330/// - No lock acquisition or runtime borrow checking
331/// - Direct function call through vtable
332/// - Minimal memory footprint (single pointer)
333///
334/// # Why No Arc/Rc Variants?
335///
336/// FnOnce can only be called once, which conflicts with Arc/Rc shared ownership
337/// semantics:
338/// - Arc/Rc implies multiple owners might need to call
339/// - FnOnce is consumed after calling, cannot be called again
340/// - This semantic incompatibility makes Arc/Rc variants meaningless
341///
342/// # Examples
343///
344/// ## Basic Usage
345///
346/// ```rust
347/// use prism3_function::{MutatorOnce, BoxMutatorOnce};
348///
349/// let data = vec![1, 2, 3];
350/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
351/// x.extend(data); // Move data
352/// });
353///
354/// let mut target = vec![0];
355/// mutator.mutate_once(&mut target);
356/// assert_eq!(target, vec![0, 1, 2, 3]);
357/// ```
358///
359/// ## Method Chaining
360///
361/// ```rust
362/// use prism3_function::{MutatorOnce, BoxMutatorOnce};
363///
364/// let data1 = vec![1, 2];
365/// let data2 = vec![3, 4];
366///
367/// let chained = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
368/// x.extend(data1);
369/// })
370/// .and_then(move |x: &mut Vec<i32>| {
371/// x.extend(data2);
372/// });
373///
374/// let mut target = vec![0];
375/// chained.mutate_once(&mut target);
376/// assert_eq!(target, vec![0, 1, 2, 3, 4]);
377/// ```
378///
379/// # Author
380///
381/// Haixing Hu
382pub struct BoxMutatorOnce<T> {
383 function: Box<dyn FnOnce(&mut T)>,
384}
385
386impl<T> BoxMutatorOnce<T>
387where
388 T: 'static,
389{
390 /// Creates a new BoxMutatorOnce
391 ///
392 /// # Parameters
393 ///
394 /// * `f` - The closure to wrap
395 ///
396 /// # Returns
397 ///
398 /// Returns a new `BoxMutatorOnce<T>` instance
399 ///
400 /// # Examples
401 ///
402 /// ```rust
403 /// use prism3_function::{MutatorOnce, BoxMutatorOnce};
404 ///
405 /// let data = String::from("world");
406 /// let mutator = BoxMutatorOnce::new(move |x: &mut String| {
407 /// x.push_str(" ");
408 /// x.push_str(&data); // Move data
409 /// });
410 ///
411 /// let mut target = String::from("hello");
412 /// mutator.mutate_once(&mut target);
413 /// assert_eq!(target, "hello world");
414 /// ```
415 pub fn new<F>(f: F) -> Self
416 where
417 F: FnOnce(&mut T) + 'static,
418 {
419 BoxMutatorOnce {
420 function: Box::new(f),
421 }
422 }
423
424 /// Creates a no-op mutator
425 ///
426 /// Returns a mutator that performs no operation.
427 ///
428 /// # Returns
429 ///
430 /// Returns a no-op mutator
431 ///
432 /// # Examples
433 ///
434 /// ```rust
435 /// use prism3_function::{MutatorOnce, BoxMutatorOnce};
436 ///
437 /// let noop = BoxMutatorOnce::<i32>::noop();
438 /// let mut value = 42;
439 /// noop.mutate_once(&mut value);
440 /// assert_eq!(value, 42); // Value unchanged
441 /// ```
442 pub fn noop() -> Self {
443 BoxMutatorOnce::new(|_| {})
444 }
445
446 /// Chains another mutator in sequence
447 ///
448 /// Returns a new mutator that first executes the current operation, then
449 /// executes the next operation. Consumes self.
450 ///
451 /// # Parameters
452 ///
453 /// * `next` - The mutator to execute after the current operation. **Note:
454 /// This parameter is passed by value and will transfer ownership.** Since
455 /// `BoxMutatorOnce` cannot be cloned, the parameter will be consumed.
456 /// Can be:
457 /// - A closure: `|x: &mut T|`
458 /// - A `BoxMutatorOnce<T>`
459 /// - Any type implementing `MutatorOnce<T>`
460 ///
461 /// # Returns
462 ///
463 /// Returns a new composed `BoxMutatorOnce<T>`
464 ///
465 /// # Examples
466 ///
467 /// ```rust
468 /// use prism3_function::{MutatorOnce, BoxMutatorOnce};
469 ///
470 /// let data1 = vec![1, 2];
471 /// let data2 = vec![3, 4];
472 /// let data3 = vec![5, 6];
473 ///
474 /// let chained = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
475 /// x.extend(data1);
476 /// })
477 /// .and_then(move |x: &mut Vec<i32>| {
478 /// x.extend(data2);
479 /// })
480 /// .and_then(move |x: &mut Vec<i32>| {
481 /// x.extend(data3);
482 /// });
483 ///
484 /// let mut target = vec![0];
485 /// chained.mutate_once(&mut target);
486 /// assert_eq!(target, vec![0, 1, 2, 3, 4, 5, 6]);
487 /// ```
488 pub fn and_then<C>(self, next: C) -> Self
489 where
490 C: MutatorOnce<T> + 'static,
491 {
492 let first = self.function;
493 BoxMutatorOnce::new(move |t| {
494 first(t);
495 next.mutate_once(t);
496 })
497 }
498
499 /// Creates a conditional mutator
500 ///
501 /// Returns a mutator that only executes when a predicate is satisfied.
502 ///
503 /// # Parameters
504 ///
505 /// * `predicate` - The condition to check. **Note: This parameter is passed
506 /// by value and will transfer ownership.** If you need to preserve the
507 /// original predicate, clone it first (if it implements `Clone`). Can be:
508 /// - A closure: `|x: &T| -> bool`
509 /// - A function pointer: `fn(&T) -> bool`
510 /// - A `BoxPredicate<T>`
511 /// - An `RcPredicate<T>`
512 /// - An `ArcPredicate<T>`
513 /// - Any type implementing `Predicate<T>`
514 ///
515 /// # Returns
516 ///
517 /// Returns `BoxConditionalMutatorOnce<T>`
518 ///
519 /// # Examples
520 ///
521 /// ## Using a closure
522 ///
523 /// ```rust
524 /// use prism3_function::{MutatorOnce, BoxMutatorOnce};
525 ///
526 /// let data = vec![1, 2, 3];
527 /// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
528 /// x.extend(data);
529 /// });
530 /// let conditional = mutator.when(|x: &Vec<i32>| !x.is_empty());
531 ///
532 /// let mut target = vec![0];
533 /// conditional.mutate_once(&mut target);
534 /// assert_eq!(target, vec![0, 1, 2, 3]);
535 ///
536 /// let mut empty = Vec::new();
537 /// let data2 = vec![4, 5];
538 /// let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
539 /// x.extend(data2);
540 /// });
541 /// let conditional2 = mutator2.when(|x: &Vec<i32>| x.len() > 5);
542 /// conditional2.mutate_once(&mut empty);
543 /// assert_eq!(empty, Vec::<i32>::new()); // Unchanged
544 /// ```
545 ///
546 /// ## Preserving predicate with clone
547 ///
548 /// ```rust
549 /// use prism3_function::{MutatorOnce, BoxMutatorOnce, RcPredicate};
550 /// use prism3_function::predicate::Predicate;
551 ///
552 /// let data = vec![1, 2, 3];
553 /// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
554 /// x.extend(data);
555 /// });
556 /// let predicate = RcPredicate::new(|x: &Vec<i32>| !x.is_empty());
557 ///
558 /// // Clone to preserve original predicate
559 /// let conditional = mutator.when(predicate.clone());
560 ///
561 /// let mut target = vec![0];
562 /// conditional.mutate_once(&mut target);
563 /// assert_eq!(target, vec![0, 1, 2, 3]);
564 ///
565 /// // Original predicate still usable
566 /// assert!(predicate.test(&vec![1, 2]));
567 /// ```
568 ///
569 /// ## Using composed predicate
570 ///
571 /// ```rust
572 /// use prism3_function::{MutatorOnce, BoxMutatorOnce};
573 /// use prism3_function::predicate::{Predicate, FnPredicateOps};
574 ///
575 /// let pred = (|x: &Vec<i32>| !x.is_empty())
576 /// .and(|x: &Vec<i32>| x.len() < 10);
577 /// let data = vec![1, 2, 3];
578 /// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
579 /// x.extend(data);
580 /// });
581 /// let conditional = mutator.when(pred);
582 ///
583 /// let mut target = vec![0];
584 /// conditional.mutate_once(&mut target);
585 /// assert_eq!(target, vec![0, 1, 2, 3]);
586 /// ```
587 pub fn when<P>(self, predicate: P) -> BoxConditionalMutatorOnce<T>
588 where
589 P: Predicate<T> + 'static,
590 {
591 BoxConditionalMutatorOnce {
592 mutator: self,
593 predicate: predicate.into_box(),
594 }
595 }
596}
597
598impl<T> MutatorOnce<T> for BoxMutatorOnce<T> {
599 fn mutate_once(self, value: &mut T) {
600 (self.function)(value)
601 }
602
603 fn into_box_once(self) -> BoxMutatorOnce<T>
604 where
605 T: 'static,
606 {
607 self
608 }
609
610 fn into_fn_once(self) -> impl FnOnce(&mut T)
611 where
612 T: 'static,
613 {
614 move |t| (self.function)(t)
615 }
616}
617
618// ============================================================================
619// 3. BoxConditionalMutatorOnce - Box-based Conditional Mutator
620// ============================================================================
621
622/// BoxConditionalMutatorOnce struct
623///
624/// A conditional one-time mutator that only executes when a predicate is satisfied.
625/// Uses `BoxMutatorOnce` and `BoxPredicate` for single ownership semantics.
626///
627/// This type is typically created by calling `BoxMutatorOnce::when()` and is
628/// designed to work with the `or_else()` method to create if-then-else logic.
629///
630/// # Features
631///
632/// - **Single Ownership**: Not cloneable, consumes `self` on use
633/// - **Conditional Execution**: Only mutates when predicate returns `true`
634/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
635/// - **Implements MutatorOnce**: Can be used anywhere a `MutatorOnce` is expected
636///
637/// # Examples
638///
639/// ## Basic Conditional Execution
640///
641/// ```rust
642/// use prism3_function::{MutatorOnce, BoxMutatorOnce};
643///
644/// let data = vec![1, 2, 3];
645/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
646/// x.extend(data);
647/// });
648/// let conditional = mutator.when(|x: &Vec<i32>| !x.is_empty());
649///
650/// let mut target = vec![0];
651/// conditional.mutate_once(&mut target);
652/// assert_eq!(target, vec![0, 1, 2, 3]); // Executed
653///
654/// let mut empty = Vec::new();
655/// let data2 = vec![4, 5];
656/// let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
657/// x.extend(data2);
658/// });
659/// let conditional2 = mutator2.when(|x: &Vec<i32>| x.len() > 5);
660/// conditional2.mutate_once(&mut empty);
661/// assert_eq!(empty, Vec::<i32>::new()); // Not executed
662/// ```
663///
664/// ## With or_else Branch
665///
666/// ```rust
667/// use prism3_function::{MutatorOnce, BoxMutatorOnce};
668///
669/// let data1 = vec![1, 2, 3];
670/// let data2 = vec![99];
671/// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
672/// x.extend(data1);
673/// })
674/// .when(|x: &Vec<i32>| !x.is_empty())
675/// .or_else(move |x: &mut Vec<i32>| {
676/// x.extend(data2);
677/// });
678///
679/// let mut target = vec![0];
680/// mutator.mutate_once(&mut target);
681/// assert_eq!(target, vec![0, 1, 2, 3]); // when branch executed
682///
683/// let data3 = vec![4, 5];
684/// let data4 = vec![99];
685/// let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
686/// x.extend(data3);
687/// })
688/// .when(|x: &Vec<i32>| x.is_empty())
689/// .or_else(move |x: &mut Vec<i32>| {
690/// x.extend(data4);
691/// });
692///
693/// let mut target2 = vec![0];
694/// mutator2.mutate_once(&mut target2);
695/// assert_eq!(target2, vec![0, 99]); // or_else branch executed
696/// ```
697///
698/// # Author
699///
700/// Haixing Hu
701pub struct BoxConditionalMutatorOnce<T> {
702 mutator: BoxMutatorOnce<T>,
703 predicate: BoxPredicate<T>,
704}
705
706impl<T> MutatorOnce<T> for BoxConditionalMutatorOnce<T>
707where
708 T: 'static,
709{
710 fn mutate_once(self, value: &mut T) {
711 if self.predicate.test(value) {
712 self.mutator.mutate_once(value);
713 }
714 }
715
716 fn into_box_once(self) -> BoxMutatorOnce<T> {
717 let pred = self.predicate;
718 let mutator = self.mutator;
719 BoxMutatorOnce::new(move |t| {
720 if pred.test(t) {
721 mutator.mutate_once(t);
722 }
723 })
724 }
725
726 fn into_fn_once(self) -> impl FnOnce(&mut T) {
727 let pred = self.predicate;
728 let mutator = self.mutator;
729 move |t: &mut T| {
730 if pred.test(t) {
731 mutator.mutate_once(t);
732 }
733 }
734 }
735}
736
737impl<T> BoxConditionalMutatorOnce<T>
738where
739 T: 'static,
740{
741 /// Chains another mutator in sequence
742 ///
743 /// Combines the current conditional mutator with another mutator into a new
744 /// mutator. The current conditional mutator executes first, followed by the
745 /// next mutator.
746 ///
747 /// # Parameters
748 ///
749 /// * `next` - The next mutator to execute. **Note: This parameter is passed
750 /// by value and will transfer ownership.** Since `BoxMutatorOnce` cannot
751 /// be cloned, the parameter will be consumed. Can be:
752 /// - A closure: `|x: &mut T|`
753 /// - A `BoxMutatorOnce<T>`
754 /// - Any type implementing `MutatorOnce<T>`
755 ///
756 /// # Returns
757 ///
758 /// Returns a new `BoxMutatorOnce<T>`
759 ///
760 /// # Examples
761 ///
762 /// ```rust
763 /// use prism3_function::{MutatorOnce, BoxMutatorOnce};
764 ///
765 /// let data1 = vec![1, 2];
766 /// let cond1 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
767 /// x.extend(data1);
768 /// }).when(|x: &Vec<i32>| !x.is_empty());
769 ///
770 /// let data2 = vec![3, 4];
771 /// let cond2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
772 /// x.extend(data2);
773 /// }).when(|x: &Vec<i32>| x.len() < 10);
774 ///
775 /// // Both cond1 and cond2 are moved and consumed
776 /// let chained = cond1.and_then(cond2);
777 ///
778 /// let mut target = vec![0];
779 /// chained.mutate_once(&mut target);
780 /// assert_eq!(target, vec![0, 1, 2, 3, 4]);
781 /// // cond1.mutate_once(&mut target); // Would not compile - moved
782 /// // cond2.mutate_once(&mut target); // Would not compile - moved
783 /// ```
784 pub fn and_then<C>(self, next: C) -> BoxMutatorOnce<T>
785 where
786 C: MutatorOnce<T> + 'static,
787 {
788 let first = self;
789 BoxMutatorOnce::new(move |t| {
790 first.mutate_once(t);
791 next.mutate_once(t);
792 })
793 }
794
795 /// Adds an else branch
796 ///
797 /// Executes the original mutator when the condition is satisfied, otherwise
798 /// executes else_mutator.
799 ///
800 /// # Parameters
801 ///
802 /// * `else_mutator` - The mutator for the else branch. **Note: This parameter
803 /// is passed by value and will transfer ownership.** Since `BoxMutatorOnce`
804 /// cannot be cloned, the parameter will be consumed. Can be:
805 /// - A closure: `|x: &mut T|`
806 /// - A `BoxMutatorOnce<T>`
807 /// - Any type implementing `MutatorOnce<T>`
808 ///
809 /// # Returns
810 ///
811 /// Returns the composed `BoxMutatorOnce<T>`
812 ///
813 /// # Examples
814 ///
815 /// ## Using a closure (recommended)
816 ///
817 /// ```rust
818 /// use prism3_function::{MutatorOnce, BoxMutatorOnce};
819 ///
820 /// let data1 = vec![1, 2, 3];
821 /// let data2 = vec![99];
822 /// let mutator = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
823 /// x.extend(data1);
824 /// })
825 /// .when(|x: &Vec<i32>| !x.is_empty())
826 /// .or_else(move |x: &mut Vec<i32>| {
827 /// x.extend(data2);
828 /// });
829 ///
830 /// let mut target = vec![0];
831 /// mutator.mutate_once(&mut target);
832 /// assert_eq!(target, vec![0, 1, 2, 3]); // Condition satisfied, execute when branch
833 ///
834 /// let data3 = vec![4, 5];
835 /// let data4 = vec![99];
836 /// let mutator2 = BoxMutatorOnce::new(move |x: &mut Vec<i32>| {
837 /// x.extend(data3);
838 /// })
839 /// .when(|x: &Vec<i32>| x.is_empty())
840 /// .or_else(move |x: &mut Vec<i32>| {
841 /// x.extend(data4);
842 /// });
843 ///
844 /// let mut target2 = vec![0];
845 /// mutator2.mutate_once(&mut target2);
846 /// assert_eq!(target2, vec![0, 99]); // Condition not satisfied, execute or_else branch
847 /// ```
848 pub fn or_else<C>(self, else_mutator: C) -> BoxMutatorOnce<T>
849 where
850 C: MutatorOnce<T> + 'static,
851 {
852 let pred = self.predicate;
853 let then_mut = self.mutator;
854 BoxMutatorOnce::new(move |t| {
855 if pred.test(t) {
856 then_mut.mutate_once(t);
857 } else {
858 else_mutator.mutate_once(t);
859 }
860 })
861 }
862}
863
864// ============================================================================
865// 4. Implement MutatorOnce trait for closures
866// ============================================================================
867
868impl<T, F> MutatorOnce<T> for F
869where
870 F: FnOnce(&mut T),
871{
872 fn mutate_once(self, value: &mut T) {
873 self(value)
874 }
875
876 fn into_box_once(self) -> BoxMutatorOnce<T>
877 where
878 Self: Sized + 'static,
879 T: 'static,
880 {
881 BoxMutatorOnce::new(self)
882 }
883
884 fn into_fn_once(self) -> impl FnOnce(&mut T)
885 where
886 Self: Sized + 'static,
887 T: 'static,
888 {
889 self
890 }
891
892 // Provide specialized non-consuming conversions for closures that
893 // implement `Clone`. Many simple closures are zero-sized and `Clone`,
894 // allowing non-consuming adapters to be cheaply produced.
895 fn to_box_once(&self) -> BoxMutatorOnce<T>
896 where
897 Self: Sized + Clone + 'static,
898 T: 'static,
899 {
900 let cloned = self.clone();
901 BoxMutatorOnce::new(move |t| cloned.mutate_once(t))
902 }
903
904 fn to_fn_once(&self) -> impl FnOnce(&mut T)
905 where
906 Self: Sized + Clone + 'static,
907 T: 'static,
908 {
909 self.clone()
910 }
911}
912
913// ============================================================================
914// 4. Provide extension methods for closures
915// ============================================================================
916
917/// Extension trait providing one-time mutator composition methods for closures
918///
919/// Provides `and_then` and other composition methods for all closures that
920/// implement `FnOnce(&mut T)`, enabling direct method chaining on closures
921/// without explicit wrapper types.
922///
923/// # Features
924///
925/// - **Natural Syntax**: Chain operations directly on closures
926/// - **Returns BoxMutatorOnce**: Composition results are `BoxMutatorOnce<T>`
927/// for continued chaining
928/// - **Zero Cost**: No overhead when composing closures
929/// - **Automatic Implementation**: All `FnOnce(&mut T)` closures get these
930/// methods automatically
931///
932/// # Examples
933///
934/// ```rust
935/// use prism3_function::{MutatorOnce, FnMutatorOnceOps};
936///
937/// let data1 = vec![1, 2];
938/// let data2 = vec![3, 4];
939///
940/// let chained = (move |x: &mut Vec<i32>| x.extend(data1))
941/// .and_then(move |x: &mut Vec<i32>| x.extend(data2));
942///
943/// let mut target = vec![0];
944/// chained.mutate_once(&mut target);
945/// assert_eq!(target, vec![0, 1, 2, 3, 4]);
946/// ```
947///
948/// # Author
949///
950/// Haixing Hu
951pub trait FnMutatorOnceOps<T>: FnOnce(&mut T) + Sized {
952 /// Chains another mutator in sequence
953 ///
954 /// Returns a new mutator that first executes the current operation, then
955 /// executes the next operation. Consumes the current closure and returns
956 /// `BoxMutatorOnce<T>`.
957 ///
958 /// # Parameters
959 ///
960 /// * `next` - The mutator to execute after the current operation. **Note: This
961 /// parameter is passed by value and will transfer ownership.** Since
962 /// `BoxMutatorOnce` cannot be cloned, the parameter will be consumed.
963 /// Can be:
964 /// - A closure: `|x: &mut T|`
965 /// - A `BoxMutatorOnce<T>`
966 /// - Any type implementing `MutatorOnce<T>`
967 ///
968 /// # Returns
969 ///
970 /// Returns the composed `BoxMutatorOnce<T>`
971 ///
972 /// # Examples
973 ///
974 /// ```rust
975 /// use prism3_function::{MutatorOnce, FnMutatorOnceOps};
976 ///
977 /// let data1 = vec![1, 2];
978 /// let data2 = vec![3, 4];
979 ///
980 /// // Both closures are moved and consumed
981 /// let chained = (move |x: &mut Vec<i32>| x.extend(data1))
982 /// .and_then(move |x: &mut Vec<i32>| x.extend(data2));
983 ///
984 /// let mut target = vec![0];
985 /// chained.mutate_once(&mut target);
986 /// assert_eq!(target, vec![0, 1, 2, 3, 4]);
987 /// // The original closures are consumed and no longer usable
988 /// ```
989 fn and_then<C>(self, next: C) -> BoxMutatorOnce<T>
990 where
991 Self: 'static,
992 C: MutatorOnce<T> + 'static,
993 T: 'static,
994 {
995 BoxMutatorOnce::new(move |t| {
996 self(t);
997 next.mutate_once(t);
998 })
999 }
1000}
1001
1002/// Implements FnMutatorOnceOps for all closure types
1003impl<T, F> FnMutatorOnceOps<T> for F where F: FnOnce(&mut T) {}