prism3_function/
consumer_once.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # ConsumerOnce Types
10//!
11//! Provides implementations of one-time consumer interfaces for executing one-time operations
12//! that accept a single input parameter but return no result.
13//!
14//! This module provides a unified `ConsumerOnce` trait and one concrete implementation:
15//!
16//! - **`BoxConsumerOnce<T>`**: Box-based single ownership implementation
17//!
18//! # Why No Arc/Rc Variants?
19//!
20//! Unlike `Consumer` and `ReadonlyConsumer`, this module does **not** provide `ArcConsumerOnce`
21//! or `RcConsumerOnce` implementations. This is a design decision based on the fact that
22//! `FnOnce` semantics are fundamentally incompatible with shared ownership. See design docs for details.
23//!
24//! # Design Philosophy
25//!
26//! ConsumerOnce uses `FnOnce(&T)` semantics for truly one-time consumption operations.
27//! Unlike Consumer, ConsumerOnce consumes itself on first call. Suitable for initialization
28//! callbacks, cleanup callbacks, and similar scenarios.
29//!
30//! # Author
31//!
32//! Hu Haixing
33
34use std::fmt;
35
36use crate::predicate::{BoxPredicate, Predicate};
37
38// ============================================================================
39// 1. ConsumerOnce Trait - Unified ConsumerOnce Interface
40// ============================================================================
41
42/// ConsumerOnce trait - Unified one-time consumer interface
43///
44/// Defines the core behavior of all one-time consumer types. Similar to consumers
45/// implementing `FnOnce(&T)`, executes operations that accept a value reference but
46/// return no result (only side effects), consuming itself in the process.
47///
48/// # Automatic Implementation
49///
50/// - All closures implementing `FnOnce(&T)`
51/// - `BoxConsumerOnce<T>`
52///
53/// # Features
54///
55/// - **Unified Interface**: All consumer types share the same `accept` method signature
56/// - **Automatic Implementation**: Closures automatically implement this trait with zero overhead
57/// - **Type Conversion**: Can be converted to BoxConsumerOnce
58/// - **Generic Programming**: Write functions that work with any one-time consumer type
59///
60/// # Examples
61///
62/// ```rust
63/// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
64/// use std::sync::{Arc, Mutex};
65///
66/// fn apply_consumer<C: ConsumerOnce<i32>>(consumer: C, value: &i32) {
67///     consumer.accept_once(value);
68/// }
69///
70/// let log = Arc::new(Mutex::new(Vec::new()));
71/// let l = log.clone();
72/// let box_con = BoxConsumerOnce::new(move |x: &i32| {
73///     l.lock().unwrap().push(*x);
74/// });
75/// apply_consumer(box_con, &5);
76/// assert_eq!(*log.lock().unwrap(), vec![5]);
77/// ```
78///
79/// # Author
80///
81/// Hu Haixing
82pub trait ConsumerOnce<T> {
83    /// Execute one-time consumption operation
84    ///
85    /// Executes an operation on the given reference. The operation typically reads
86    /// the input value or produces side effects, but does not modify the input
87    /// value itself. Consumes self.
88    ///
89    /// # Parameters
90    ///
91    /// * `value` - Reference to the value to be consumed
92    ///
93    /// # Examples
94    ///
95    /// ```rust
96    /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
97    ///
98    /// let consumer = BoxConsumerOnce::new(|x: &i32| println!("{}", x));
99    /// consumer.accept_once(&5);
100    /// ```
101    fn accept_once(self, value: &T);
102
103    /// Convert to BoxConsumerOnce
104    ///
105    /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
106    ///
107    /// # Default Implementation
108    ///
109    /// The default implementation wraps `self` in a `BoxConsumerOnce` by calling
110    /// `accept_once` on the consumer. Types can override this method to provide more
111    /// efficient conversions.
112    ///
113    /// # Returns
114    ///
115    /// Returns the wrapped `BoxConsumerOnce<T>`
116    ///
117    /// # Examples
118    ///
119    /// ```rust
120    /// use prism3_function::ConsumerOnce;
121    /// use std::sync::{Arc, Mutex};
122    ///
123    /// let log = Arc::new(Mutex::new(Vec::new()));
124    /// let l = log.clone();
125    /// let closure = move |x: &i32| {
126    ///     l.lock().unwrap().push(*x);
127    /// };
128    /// let box_consumer = closure.into_box_once();
129    /// box_consumer.accept_once(&5);
130    /// assert_eq!(*log.lock().unwrap(), vec![5]);
131    /// ```
132    fn into_box_once(self) -> BoxConsumerOnce<T>
133    where
134        Self: Sized + 'static,
135        T: 'static,
136    {
137        BoxConsumerOnce::new(move |t| self.accept_once(t))
138    }
139
140    /// Convert to closure
141    ///
142    /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
143    ///
144    /// Converts a one-time consumer to a closure that can be used directly in places
145    /// where the standard library requires `FnOnce`.
146    ///
147    /// # Default Implementation
148    ///
149    /// The default implementation creates a closure that captures `self` and calls
150    /// its `accept_once` method. Types can override this method to provide more efficient
151    /// conversions.
152    ///
153    /// # Returns
154    ///
155    /// Returns a closure implementing `FnOnce(&T)`
156    ///
157    /// # Examples
158    ///
159    /// ```rust
160    /// use prism3_function::ConsumerOnce;
161    /// use std::sync::{Arc, Mutex};
162    ///
163    /// let log = Arc::new(Mutex::new(Vec::new()));
164    /// let l = log.clone();
165    /// let closure = move |x: &i32| {
166    ///     l.lock().unwrap().push(*x * 2);
167    /// };
168    /// let func = closure.into_fn_once();
169    /// func(&5);
170    /// assert_eq!(*log.lock().unwrap(), vec![10]);
171    /// ```
172    fn into_fn_once(self) -> impl FnOnce(&T)
173    where
174        Self: Sized + 'static,
175        T: 'static,
176    {
177        move |t| self.accept_once(t)
178    }
179
180    /// Convert to BoxConsumerOnce without consuming self
181    ///
182    /// **⚠️ Requires Clone**: This method requires `Self` to implement
183    /// `Clone`. Clones the current consumer and wraps it in a
184    /// `BoxConsumerOnce`.
185    ///
186    /// # Default Implementation
187    ///
188    /// The default implementation clones `self` and then calls
189    /// `into_box_once()` on the clone. Types can override this method to
190    /// provide more efficient conversions.
191    ///
192    /// # Returns
193    ///
194    /// Returns the wrapped `BoxConsumerOnce<T>`
195    ///
196    /// # Examples
197    ///
198    /// ```rust
199    /// use prism3_function::ConsumerOnce;
200    /// use std::sync::{Arc, Mutex};
201    ///
202    /// let log = Arc::new(Mutex::new(Vec::new()));
203    /// let l = log.clone();
204    /// let closure = move |x: &i32| {
205    ///     l.lock().unwrap().push(*x);
206    /// };
207    /// let box_consumer = closure.to_box_once();
208    /// box_consumer.accept_once(&5);
209    /// assert_eq!(*log.lock().unwrap(), vec![5]);
210    /// ```
211    fn to_box_once(&self) -> BoxConsumerOnce<T>
212    where
213        Self: Sized + Clone + 'static,
214        T: 'static,
215    {
216        self.clone().into_box_once()
217    }
218
219    /// Convert to closure without consuming self
220    ///
221    /// **⚠️ Requires Clone**: This method requires `Self` to implement
222    /// `Clone`. Clones the current consumer and then converts the clone
223    /// to a closure.
224    ///
225    /// # Default Implementation
226    ///
227    /// The default implementation clones `self` and then calls
228    /// `into_fn_once()` on the clone. Types can override this method to
229    /// provide more efficient conversions.
230    ///
231    /// # Returns
232    ///
233    /// Returns a closure implementing `FnOnce(&T)`
234    ///
235    /// # Examples
236    ///
237    /// ```rust
238    /// use prism3_function::ConsumerOnce;
239    /// use std::sync::{Arc, Mutex};
240    ///
241    /// let log = Arc::new(Mutex::new(Vec::new()));
242    /// let l = log.clone();
243    /// let closure = move |x: &i32| {
244    ///     l.lock().unwrap().push(*x * 2);
245    /// };
246    /// let func = closure.to_fn_once();
247    /// func(&5);
248    /// assert_eq!(*log.lock().unwrap(), vec![10]);
249    /// ```
250    fn to_fn_once(&self) -> impl FnOnce(&T)
251    where
252        Self: Sized + Clone + 'static,
253        T: 'static,
254    {
255        self.clone().into_fn_once()
256    }
257}
258
259// ============================================================================
260// 2. BoxConsumerOnce - Single Ownership Implementation
261// ============================================================================
262
263/// BoxConsumerOnce struct
264///
265/// One-time consumer implementation based on `Box<dyn FnOnce(&T)>` for single ownership scenarios.
266/// This is the simplest consumer type for truly one-time use.
267///
268/// # Features
269///
270/// - **Single Ownership**: Not cloneable, transfers ownership on use
271/// - **Zero Overhead**: No reference counting or lock overhead
272/// - **One-time Use**: Consumes self on first call
273/// - **Builder Pattern**: Method chaining naturally consumes `self`
274///
275/// # Use Cases
276///
277/// Choose `BoxConsumerOnce` when:
278/// - Consumer is truly used only once
279/// - Building pipelines where ownership flows naturally
280/// - Consumer captures values that should be consumed
281/// - Performance critical and cannot accept shared overhead
282///
283/// # Performance
284///
285/// `BoxConsumerOnce` has the best performance:
286/// - No reference counting overhead
287/// - No lock acquisition or runtime borrow checking
288/// - Direct function call through vtable
289/// - Minimal memory footprint (single pointer)
290///
291/// # Examples
292///
293/// ```rust
294/// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
295///
296/// let consumer = BoxConsumerOnce::new(|x: &i32| {
297///     println!("Value: {}", x);
298/// });
299/// consumer.accept_once(&5);
300/// ```
301///
302/// # Author
303///
304/// Hu Haixing
305pub struct BoxConsumerOnce<T> {
306    function: Box<dyn FnOnce(&T)>,
307    name: Option<String>,
308}
309
310impl<T> BoxConsumerOnce<T>
311where
312    T: 'static,
313{
314    /// Create a new BoxConsumerOnce
315    ///
316    /// # Type Parameters
317    ///
318    /// * `F` - Closure type
319    ///
320    /// # Parameters
321    ///
322    /// * `f` - Closure to be wrapped
323    ///
324    /// # Returns
325    ///
326    /// Returns a new `BoxConsumerOnce<T>` instance
327    ///
328    /// # Examples
329    ///
330    /// ```rust
331    /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
332    /// use std::sync::{Arc, Mutex};
333    ///
334    /// let log = Arc::new(Mutex::new(Vec::new()));
335    /// let l = log.clone();
336    /// let consumer = BoxConsumerOnce::new(move |x: &i32| {
337    ///     l.lock().unwrap().push(*x + 1);
338    /// });
339    /// consumer.accept_once(&5);
340    /// assert_eq!(*log.lock().unwrap(), vec![6]);
341    /// ```
342    pub fn new<F>(f: F) -> Self
343    where
344        F: FnOnce(&T) + 'static,
345    {
346        BoxConsumerOnce {
347            function: Box::new(f),
348            name: None,
349        }
350    }
351
352    /// Get the consumer's name
353    ///
354    /// Returns the optional name associated with this consumer.
355    /// Used for debugging and logging purposes.
356    ///
357    /// # Returns
358    ///
359    /// Returns `Some(&str)` if a name was set, `None` otherwise
360    ///
361    /// # Examples
362    ///
363    /// ```rust
364    /// use prism3_function::BoxConsumerOnce;
365    ///
366    /// let mut consumer = BoxConsumerOnce::new(|x: &i32| {
367    ///     println!("{}", x);
368    /// });
369    /// assert_eq!(consumer.name(), None);
370    /// consumer.set_name("my_consumer");
371    /// assert_eq!(consumer.name(), Some("my_consumer"));
372    /// ```
373    pub fn name(&self) -> Option<&str> {
374        self.name.as_deref()
375    }
376
377    /// Set the consumer's name
378    ///
379    /// Assigns a name to this consumer for debugging and logging
380    /// purposes. The name can be any type that converts to `String`.
381    ///
382    /// # Parameters
383    ///
384    /// * `name` - The name to set, can be `&str` or `String`
385    ///
386    /// # Examples
387    ///
388    /// ```rust
389    /// use prism3_function::BoxConsumerOnce;
390    ///
391    /// let mut consumer = BoxConsumerOnce::new(|x: &i32| {
392    ///     println!("{}", x);
393    /// });
394    /// consumer.set_name("my_consumer");
395    /// assert_eq!(consumer.name(), Some("my_consumer"));
396    /// ```
397    pub fn set_name(&mut self, name: impl Into<String>) {
398        self.name = Some(name.into());
399    }
400
401    /// Sequentially chain another one-time consumer
402    ///
403    /// Returns a new consumer that executes the current operation first, then the next operation. Consumes self.
404    ///
405    /// # Type Parameters
406    ///
407    /// * `C` - Type of the next consumer
408    ///
409    /// # Parameters
410    ///
411    /// * `next` - Consumer to execute after the current operation. **Note: This
412    ///   parameter is passed by value and will transfer ownership.** Since
413    ///   `BoxConsumerOnce` cannot be cloned, the parameter will be consumed.
414    ///   Can be:
415    ///   - A closure: `|x: &T|`
416    ///   - A `BoxConsumerOnce<T>`
417    ///   - Any type implementing `ConsumerOnce<T>`
418    ///
419    /// # Returns
420    ///
421    /// Returns a new combined `BoxConsumerOnce<T>`
422    ///
423    /// # Examples
424    ///
425    /// ```rust
426    /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
427    /// use std::sync::{Arc, Mutex};
428    ///
429    /// let log = Arc::new(Mutex::new(Vec::new()));
430    /// let l1 = log.clone();
431    /// let l2 = log.clone();
432    /// let first = BoxConsumerOnce::new(move |x: &i32| {
433    ///     l1.lock().unwrap().push(*x * 2);
434    /// });
435    /// let second = BoxConsumerOnce::new(move |x: &i32| {
436    ///     l2.lock().unwrap().push(*x + 10);
437    /// });
438    ///
439    /// // Both first and second are moved and consumed
440    /// let chained = first.and_then(second);
441    /// chained.accept_once(&5);
442    /// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
443    /// // first.accept_once(&3); // Would not compile - moved
444    /// // second.accept_once(&3); // Would not compile - moved
445    /// ```
446    pub fn and_then<C>(self, next: C) -> Self
447    where
448        C: ConsumerOnce<T> + 'static,
449    {
450        let first = self.function;
451        let second = next;
452        BoxConsumerOnce::new(move |t| {
453            first(t);
454            second.accept_once(t);
455        })
456    }
457
458    /// Create a no-op consumer
459    ///
460    /// # Returns
461    ///
462    /// Returns a no-op consumer
463    ///
464    /// # Examples
465    ///
466    /// ```rust
467    /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
468    ///
469    /// let noop = BoxConsumerOnce::<i32>::noop();
470    /// noop.accept_once(&42);
471    /// // Value unchanged
472    /// ```
473    pub fn noop() -> Self {
474        BoxConsumerOnce::new(|_| {})
475    }
476
477    /// Creates a conditional consumer
478    ///
479    /// Returns a consumer that only executes when a predicate is satisfied.
480    ///
481    /// # Parameters
482    ///
483    /// * `predicate` - The condition to check, can be:
484    ///   - Closure: `|x: &T| -> bool`
485    ///   - Function pointer: `fn(&T) -> bool`
486    ///   - `BoxPredicate<T>`
487    ///   - Any type implementing `Predicate<T>`
488    ///
489    /// # Returns
490    ///
491    /// Returns `BoxConditionalConsumerOnce<T>`
492    ///
493    /// # Examples
494    ///
495    /// ```rust
496    /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
497    /// use std::sync::{Arc, Mutex};
498    ///
499    /// let log = Arc::new(Mutex::new(Vec::new()));
500    /// let l = log.clone();
501    /// let consumer = BoxConsumerOnce::new(move |x: &i32| {
502    ///     l.lock().unwrap().push(*x);
503    /// });
504    /// let conditional = consumer.when(|x: &i32| *x > 0);
505    ///
506    /// conditional.accept_once(&5);
507    /// assert_eq!(*log.lock().unwrap(), vec![5]);
508    /// ```
509    pub fn when<P>(self, predicate: P) -> BoxConditionalConsumerOnce<T>
510    where
511        P: Predicate<T> + 'static,
512    {
513        BoxConditionalConsumerOnce {
514            consumer: self,
515            predicate: predicate.into_box(),
516        }
517    }
518}
519
520impl<T> ConsumerOnce<T> for BoxConsumerOnce<T> {
521    fn accept_once(self, value: &T) {
522        (self.function)(value)
523    }
524
525    fn into_box_once(self) -> BoxConsumerOnce<T>
526    where
527        T: 'static,
528    {
529        self
530    }
531
532    fn into_fn_once(self) -> impl FnOnce(&T)
533    where
534        T: 'static,
535    {
536        self.function
537    }
538
539    // do NOT override Consumer::to_xxxx() because BoxConsumerOnce is not Clone
540    // and calling BoxConsumerOnce::to_xxxx() will cause a compile error
541}
542
543impl<T> fmt::Debug for BoxConsumerOnce<T> {
544    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545        f.debug_struct("BoxConsumerOnce")
546            .field("name", &self.name)
547            .field("function", &"<function>")
548            .finish()
549    }
550}
551
552impl<T> fmt::Display for BoxConsumerOnce<T> {
553    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
554        match &self.name {
555            Some(name) => write!(f, "BoxConsumerOnce({})", name),
556            None => write!(f, "BoxConsumerOnce"),
557        }
558    }
559}
560
561// ============================================================================
562// 3. BoxConditionalConsumerOnce - Box-based Conditional Consumer
563// ============================================================================
564
565/// BoxConditionalConsumerOnce struct
566///
567/// A conditional one-time consumer that only executes when a predicate is satisfied.
568/// Uses `BoxConsumerOnce` and `BoxPredicate` for single ownership semantics.
569///
570/// This type is typically created by calling `BoxConsumerOnce::when()` and is
571/// designed to work with the `or_else()` method to create if-then-else logic.
572///
573/// # Features
574///
575/// - **Single Ownership**: Not cloneable, consumes `self` on use
576/// - **Conditional Execution**: Only consumes when predicate returns `true`
577/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
578/// - **Implements ConsumerOnce**: Can be used anywhere a `ConsumerOnce` is expected
579///
580/// # Examples
581///
582/// ## Basic Conditional Execution
583///
584/// ```rust
585/// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
586/// use std::sync::{Arc, Mutex};
587///
588/// let log = Arc::new(Mutex::new(Vec::new()));
589/// let l = log.clone();
590/// let consumer = BoxConsumerOnce::new(move |x: &i32| {
591///     l.lock().unwrap().push(*x);
592/// });
593/// let conditional = consumer.when(|x: &i32| *x > 0);
594///
595/// conditional.accept_once(&5);
596/// assert_eq!(*log.lock().unwrap(), vec![5]); // Executed
597/// ```
598///
599/// ## With or_else Branch
600///
601/// ```rust
602/// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
603/// use std::sync::{Arc, Mutex};
604///
605/// let log = Arc::new(Mutex::new(Vec::new()));
606/// let l1 = log.clone();
607/// let l2 = log.clone();
608/// let consumer = BoxConsumerOnce::new(move |x: &i32| {
609///     l1.lock().unwrap().push(*x);
610/// })
611/// .when(|x: &i32| *x > 0)
612/// .or_else(move |x: &i32| {
613///     l2.lock().unwrap().push(-*x);
614/// });
615///
616/// consumer.accept_once(&5);
617/// assert_eq!(*log.lock().unwrap(), vec![5]); // when branch executed
618/// ```
619///
620/// # Author
621///
622/// Hu Haixing
623pub struct BoxConditionalConsumerOnce<T> {
624    consumer: BoxConsumerOnce<T>,
625    predicate: BoxPredicate<T>,
626}
627
628impl<T> ConsumerOnce<T> for BoxConditionalConsumerOnce<T>
629where
630    T: 'static,
631{
632    fn accept_once(self, value: &T) {
633        if self.predicate.test(value) {
634            self.consumer.accept_once(value);
635        }
636    }
637
638    fn into_box_once(self) -> BoxConsumerOnce<T> {
639        let pred = self.predicate;
640        let consumer = self.consumer;
641        BoxConsumerOnce::new(move |t| {
642            if pred.test(t) {
643                consumer.accept_once(t);
644            }
645        })
646    }
647
648    fn into_fn_once(self) -> impl FnOnce(&T) {
649        let pred = self.predicate;
650        let consumer = self.consumer;
651        move |t: &T| {
652            if pred.test(t) {
653                consumer.accept_once(t);
654            }
655        }
656    }
657
658    // do NOT override ConsumerOnce::to_xxxx() because BoxConditionalConsumerOnce is not Clone
659    // and calling BoxConditionalConsumerOnce::to_xxxx() will cause a compile error
660}
661
662impl<T> BoxConditionalConsumerOnce<T>
663where
664    T: 'static,
665{
666    /// Chains another consumer in sequence
667    ///
668    /// Combines the current conditional consumer with another consumer into a new
669    /// consumer. The current conditional consumer executes first, followed by the
670    /// next consumer.
671    ///
672    /// # Parameters
673    ///
674    /// * `next` - The next consumer to execute. **Note: This parameter is passed
675    ///   by value and will transfer ownership.** Since `BoxConsumerOnce` cannot
676    ///   be cloned, the parameter will be consumed. Can be:
677    ///   - A closure: `|x: &T|`
678    ///   - A `BoxConsumerOnce<T>`
679    ///   - Any type implementing `ConsumerOnce<T>`
680    ///
681    /// # Returns
682    ///
683    /// Returns a new `BoxConsumerOnce<T>`
684    ///
685    /// # Examples
686    ///
687    /// ```rust
688    /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
689    /// use std::sync::{Arc, Mutex};
690    ///
691    /// let log = Arc::new(Mutex::new(Vec::new()));
692    /// let l1 = log.clone();
693    /// let l2 = log.clone();
694    /// let cond1 = BoxConsumerOnce::new(move |x: &i32| {
695    ///     l1.lock().unwrap().push(*x * 2);
696    /// }).when(|x: &i32| *x > 0);
697    /// let cond2 = BoxConsumerOnce::new(move |x: &i32| {
698    ///     l2.lock().unwrap().push(*x + 100);
699    /// }).when(|x: &i32| *x > 10);
700    ///
701    /// // Both cond1 and cond2 are moved and consumed
702    /// let chained = cond1.and_then(cond2);
703    /// chained.accept_once(&6);
704    /// assert_eq!(*log.lock().unwrap(), vec![12, 106]); // First *2 = 12, then +100 = 106
705    /// // cond1.accept_once(&3); // Would not compile - moved
706    /// // cond2.accept_once(&3); // Would not compile - moved
707    /// ```
708    pub fn and_then<C>(self, next: C) -> BoxConsumerOnce<T>
709    where
710        C: ConsumerOnce<T> + 'static,
711    {
712        let first = self;
713        let second = next;
714        BoxConsumerOnce::new(move |t| {
715            first.accept_once(t);
716            second.accept_once(t);
717        })
718    }
719
720    /// Adds an else branch
721    ///
722    /// Executes the original consumer when the condition is satisfied, otherwise
723    /// executes else_consumer.
724    ///
725    /// # Parameters
726    ///
727    /// * `else_consumer` - The consumer for the else branch. **Note: This parameter
728    ///   is passed by value and will transfer ownership.** Since `BoxConsumerOnce`
729    ///   cannot be cloned, the parameter will be consumed. Can be:
730    ///   - A closure: `|x: &T|`
731    ///   - A `BoxConsumerOnce<T>`
732    ///   - Any type implementing `ConsumerOnce<T>`
733    ///
734    /// # Returns
735    ///
736    /// Returns the composed `BoxConsumerOnce<T>`
737    ///
738    /// # Examples
739    ///
740    /// ## Using a closure (recommended)
741    ///
742    /// ```rust
743    /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
744    /// use std::sync::{Arc, Mutex};
745    ///
746    /// let log = Arc::new(Mutex::new(Vec::new()));
747    /// let l1 = log.clone();
748    /// let l2 = log.clone();
749    /// let consumer = BoxConsumerOnce::new(move |x: &i32| {
750    ///     l1.lock().unwrap().push(*x);
751    /// })
752    /// .when(|x: &i32| *x > 0)
753    /// .or_else(move |x: &i32| {
754    ///     l2.lock().unwrap().push(-*x);
755    /// });
756    ///
757    /// consumer.accept_once(&5);
758    /// assert_eq!(*log.lock().unwrap(), vec![5]); // Condition satisfied, execute first
759    /// ```
760    pub fn or_else<C>(self, else_consumer: C) -> BoxConsumerOnce<T>
761    where
762        C: ConsumerOnce<T> + 'static,
763    {
764        let pred = self.predicate;
765        let then_cons = self.consumer;
766        let else_cons = else_consumer;
767        BoxConsumerOnce::new(move |t| {
768            if pred.test(t) {
769                then_cons.accept_once(t);
770            } else {
771                else_cons.accept_once(t);
772            }
773        })
774    }
775}
776
777// ============================================================================
778// 4. Implement ConsumerOnce trait for closures
779// ============================================================================
780
781/// Implement ConsumerOnce for all FnOnce(&T)
782impl<T, F> ConsumerOnce<T> for F
783where
784    F: FnOnce(&T),
785{
786    fn accept_once(self, value: &T) {
787        self(value)
788    }
789
790    fn into_box_once(self) -> BoxConsumerOnce<T>
791    where
792        Self: Sized + 'static,
793        T: 'static,
794    {
795        BoxConsumerOnce::new(self)
796    }
797
798    fn into_fn_once(self) -> impl FnOnce(&T)
799    where
800        Self: Sized + 'static,
801        T: 'static,
802    {
803        self
804    }
805
806    fn to_box_once(&self) -> BoxConsumerOnce<T>
807    where
808        Self: Sized + Clone + 'static,
809        T: 'static,
810    {
811        let cloned = self.clone();
812        BoxConsumerOnce::new(cloned)
813    }
814
815    fn to_fn_once(&self) -> impl FnOnce(&T)
816    where
817        Self: Sized + Clone + 'static,
818        T: 'static,
819    {
820        self.clone()
821    }
822}
823
824// ============================================================================
825// 5. Extension methods for closures
826// ============================================================================
827
828/// Extension trait providing one-time consumer composition methods for closures
829///
830/// Provides `and_then` and other composition methods for all closures implementing `FnOnce(&T)`,
831/// allowing closures to chain methods directly without explicit wrapper types.
832///
833/// # Features
834///
835/// - **Natural Syntax**: Chain operations directly on closures
836/// - **Returns BoxConsumerOnce**: Composed results can continue chaining
837/// - **Zero Cost**: No overhead when composing closures
838/// - **Automatic Implementation**: All `FnOnce(&T)` closures automatically get these methods
839///
840/// # Examples
841///
842/// ```rust
843/// use prism3_function::{ConsumerOnce, FnConsumerOnceOps};
844/// use std::sync::{Arc, Mutex};
845///
846/// let log = Arc::new(Mutex::new(Vec::new()));
847/// let l1 = log.clone();
848/// let l2 = log.clone();
849/// let chained = (move |x: &i32| {
850///     l1.lock().unwrap().push(*x * 2);
851/// }).and_then(move |x: &i32| {
852///     l2.lock().unwrap().push(*x + 10);
853/// });
854/// chained.accept_once(&5);
855/// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
856/// ```
857///
858/// # Author
859///
860/// Hu Haixing
861pub trait FnConsumerOnceOps<T>: FnOnce(&T) + Sized {
862    /// Sequentially chain another one-time consumer
863    ///
864    /// Returns a new consumer that executes the current operation first, then the next operation.
865    /// Consumes the current closure and returns `BoxConsumerOnce<T>`.
866    ///
867    /// # Type Parameters
868    ///
869    /// * `C` - Type of the next consumer
870    ///
871    /// # Parameters
872    ///
873    /// * `next` - Consumer to execute after the current operation. **Note: This
874    ///   parameter is passed by value and will transfer ownership.** Since
875    ///   `BoxConsumerOnce` cannot be cloned, the parameter will be consumed.
876    ///   Can be:
877    ///   - A closure: `|x: &T|`
878    ///   - A `BoxConsumerOnce<T>`
879    ///   - Any type implementing `ConsumerOnce<T>`
880    ///
881    /// # Returns
882    ///
883    /// Returns a combined `BoxConsumerOnce<T>`
884    ///
885    /// # Examples
886    ///
887    /// ```rust
888    /// use prism3_function::{ConsumerOnce, FnConsumerOnceOps};
889    /// use std::sync::{Arc, Mutex};
890    ///
891    /// let log = Arc::new(Mutex::new(Vec::new()));
892    /// let l1 = log.clone();
893    /// let l2 = log.clone();
894    /// let chained = (move |x: &i32| {
895    ///     l1.lock().unwrap().push(*x * 2);
896    /// }).and_then(move |x: &i32| {
897    ///     l2.lock().unwrap().push(*x + 10);
898    /// }).and_then(|x: &i32| println!("Result: {}", x));
899    ///
900    /// chained.accept_once(&5);
901    /// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
902    /// ```
903    fn and_then<C>(self, next: C) -> BoxConsumerOnce<T>
904    where
905        Self: 'static,
906        C: ConsumerOnce<T> + 'static,
907        T: 'static,
908    {
909        let first = self;
910        let second = next;
911        BoxConsumerOnce::new(move |t| {
912            first(t);
913            second.accept_once(t);
914        })
915    }
916}
917
918/// Implement FnConsumerOnceOps for all closure types
919impl<T, F> FnConsumerOnceOps<T> for F where F: FnOnce(&T) {}