prism3_function/consumers/
stateful_bi_consumer.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # BiConsumer Types
10//!
11//! Provides bi-consumer interface implementations for operations accepting
12//! two input parameters without returning a result.
13//!
14//! It is similar to the `FnMut(&T, &U)` trait in the standard library.
15//!
16//! This module provides a unified `BiConsumer` trait and three concrete
17//! implementations based on different ownership models:
18//!
19//! - **`BoxStatefulBiConsumer<T, U>`**: Box-based single ownership for one-time use
20//! - **`ArcStatefulBiConsumer<T, U>`**: Arc<Mutex<>>-based thread-safe shared
21//!   ownership
22//! - **`RcStatefulBiConsumer<T, U>`**: Rc<RefCell<>>-based single-threaded shared
23//!   ownership
24//!
25//! # Design Philosophy
26//!
27//! BiConsumer uses `FnMut(&T, &U)` semantics: can modify its own state but
28//! does NOT modify input values.
29//!
30//! Suitable for statistics, accumulation, and event processing scenarios
31//! involving two parameters.
32//!
33//! # Author
34//!
35//! Haixing Hu
36use std::cell::RefCell;
37use std::rc::Rc;
38use std::sync::Arc;
39
40use parking_lot::Mutex;
41
42use crate::consumers::{
43    bi_consumer_once::BoxBiConsumerOnce,
44    macros::{
45        impl_box_conditional_consumer,
46        impl_box_consumer_methods,
47        impl_conditional_consumer_clone,
48        impl_conditional_consumer_conversions,
49        impl_conditional_consumer_debug_display,
50        impl_consumer_clone,
51        impl_consumer_common_methods,
52        impl_consumer_debug_display,
53        impl_shared_conditional_consumer,
54        impl_shared_consumer_methods,
55    },
56};
57use crate::macros::{
58    impl_arc_conversions,
59    impl_box_conversions,
60    impl_closure_trait,
61    impl_rc_conversions,
62};
63use crate::predicates::bi_predicate::{
64    ArcBiPredicate,
65    BiPredicate,
66    BoxBiPredicate,
67    RcBiPredicate,
68};
69
70// =======================================================================
71// 1. BiConsumer Trait - Unified BiConsumer Interface
72// =======================================================================
73
74/// BiConsumer trait - Unified bi-consumer interface
75///
76/// Defines core behavior for all bi-consumer types. Similar to Java's
77/// `BiConsumer<T, U>` interface, performs operations accepting two values
78/// but returning no result (side effects only).
79///
80/// It is similar to the `FnMut(&T, &U)` trait in the standard library.
81///
82/// BiConsumer can modify its own state (e.g., accumulate, count) but
83/// should NOT modify the consumed values themselves.
84///
85/// # Automatic Implementations
86///
87/// - All closures implementing `FnMut(&T, &U)`
88/// - `BoxStatefulBiConsumer<T, U>`, `ArcStatefulBiConsumer<T, U>`, `RcStatefulBiConsumer<T, U>`
89///
90/// # Features
91///
92/// - **Unified Interface**: All bi-consumer types share the same `accept`
93///   method signature
94/// - **Automatic Implementation**: Closures automatically implement this
95///   trait with zero overhead
96/// - **Type Conversions**: Easy conversion between ownership models
97/// - **Generic Programming**: Write functions accepting any bi-consumer
98///   type
99///
100/// # Examples
101///
102/// ```rust
103/// use prism3_function::{BiConsumer, BoxStatefulBiConsumer, ArcStatefulBiConsumer};
104/// use std::sync::{Arc, Mutex};
105///
106/// fn apply_bi_consumer<C: StatefulBiConsumer<i32, i32>>(
107///     consumer: &mut C,
108///     a: &i32,
109///     b: &i32
110/// ) {
111///     consumer.accept(a, b);
112/// }
113///
114/// // Works with any bi-consumer type
115/// let log = Arc::new(Mutex::new(Vec::new()));
116/// let l = log.clone();
117/// let mut box_con = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
118///     l.lock().unwrap().push(*x + *y);
119/// });
120/// apply_bi_consumer(&mut box_con, &5, &3);
121/// assert_eq!(*log.lock().unwrap(), vec![8]);
122/// ```
123///
124/// # Author
125///
126/// Haixing Hu
127pub trait StatefulBiConsumer<T, U> {
128    /// Performs the consumption operation
129    ///
130    /// Executes an operation on the given two references. The operation
131    /// typically reads input values or produces side effects, but does not
132    /// modify the input values themselves. Can modify the consumer's own
133    /// state.
134    ///
135    /// # Parameters
136    ///
137    /// * `first` - Reference to the first value to consume
138    /// * `second` - Reference to the second value to consume
139    ///
140    /// # Examples
141    ///
142    /// ```rust
143    /// use prism3_function::{BiConsumer, BoxStatefulBiConsumer};
144    /// use std::sync::{Arc, Mutex};
145    ///
146    /// let log = Arc::new(Mutex::new(Vec::new()));
147    /// let l = log.clone();
148    /// let mut consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
149    ///     l.lock().unwrap().push(*x + *y);
150    /// });
151    /// consumer.accept(&5, &3);
152    /// assert_eq!(*log.lock().unwrap(), vec![8]);
153    /// ```
154    fn accept(&mut self, first: &T, second: &U);
155
156    /// Converts to BoxStatefulBiConsumer
157    ///
158    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
159    /// calling this method.
160    ///
161    /// Converts the current bi-consumer to `BoxStatefulBiConsumer<T, U>`.
162    ///
163    /// # Ownership
164    ///
165    /// This method **consumes** the consumer (takes ownership of `self`).
166    /// After calling, the original consumer is no longer available.
167    ///
168    /// **Tip**: For cloneable consumers ([`ArcStatefulBiConsumer`],
169    /// [`RcStatefulBiConsumer`]), call `.clone()` first if you need to keep the
170    /// original.
171    ///
172    /// # Returns
173    ///
174    /// Returns the wrapped `BoxStatefulBiConsumer<T, U>`
175    ///
176    /// # Examples
177    ///
178    /// ```rust
179    /// use prism3_function::BiConsumer;
180    /// use std::sync::{Arc, Mutex};
181    ///
182    /// let log = Arc::new(Mutex::new(Vec::new()));
183    /// let l = log.clone();
184    /// let closure = move |x: &i32, y: &i32| {
185    ///     l.lock().unwrap().push(*x + *y);
186    /// };
187    /// let mut box_consumer = closure.into_box();
188    /// box_consumer.accept(&5, &3);
189    /// assert_eq!(*log.lock().unwrap(), vec![8]);
190    /// ```
191    fn into_box(self) -> BoxStatefulBiConsumer<T, U>
192    where
193        Self: Sized + 'static,
194        T: 'static,
195        U: 'static,
196    {
197        let mut consumer = self;
198        BoxStatefulBiConsumer::new(move |t, u| consumer.accept(t, u))
199    }
200
201    /// Converts to RcStatefulBiConsumer
202    ///
203    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
204    /// calling this method.
205    ///
206    /// # Returns
207    ///
208    /// Returns the wrapped `RcStatefulBiConsumer<T, U>`
209    fn into_rc(self) -> RcStatefulBiConsumer<T, U>
210    where
211        Self: Sized + 'static,
212        T: 'static,
213        U: 'static,
214    {
215        let mut consumer = self;
216        RcStatefulBiConsumer::new(move |t, u| consumer.accept(t, u))
217    }
218
219    /// Converts to ArcStatefulBiConsumer
220    ///
221    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
222    /// calling this method.
223    ///
224    /// # Returns
225    ///
226    /// Returns the wrapped `ArcStatefulBiConsumer<T, U>`
227    fn into_arc(self) -> ArcStatefulBiConsumer<T, U>
228    where
229        Self: Sized + Send + 'static,
230        T: 'static,
231        U: 'static,
232    {
233        let mut consumer = self;
234        ArcStatefulBiConsumer::new(move |t, u| consumer.accept(t, u))
235    }
236
237    /// Converts bi-consumer to a closure
238    ///
239    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
240    /// calling this method.
241    ///
242    /// Converts the bi-consumer to a closure usable with standard library
243    /// methods requiring `FnMut`.
244    ///
245    /// # Returns
246    ///
247    /// Returns a closure implementing `FnMut(&T, &U)`
248    ///
249    /// # Examples
250    ///
251    /// ```rust
252    /// use prism3_function::{BiConsumer, BoxStatefulBiConsumer};
253    /// use std::sync::{Arc, Mutex};
254    ///
255    /// let log = Arc::new(Mutex::new(Vec::new()));
256    /// let l = log.clone();
257    /// let consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
258    ///     l.lock().unwrap().push(*x + *y);
259    /// });
260    /// let mut func = consumer.into_fn();
261    /// func(&5, &3);
262    /// assert_eq!(*log.lock().unwrap(), vec![8]);
263    /// ```
264    fn into_fn(self) -> impl FnMut(&T, &U)
265    where
266        Self: Sized + 'static,
267        T: 'static,
268        U: 'static,
269    {
270        let mut consumer = self;
271        move |t, u| consumer.accept(t, u)
272    }
273
274    /// Convert to BiConsumerOnce
275    ///
276    /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
277    ///
278    /// Converts a reusable stateful bi-consumer to a one-time consumer that consumes itself on use.
279    /// This enables passing `StatefulBiConsumer` to functions that require `BiConsumerOnce`.
280    ///
281    /// # Returns
282    ///
283    /// Returns a `BoxBiConsumerOnce<T, U>`
284    fn into_once(self) -> BoxBiConsumerOnce<T, U>
285    where
286        Self: Sized + 'static,
287        T: 'static,
288        U: 'static,
289    {
290        BoxBiConsumerOnce::new(move |t, u| {
291            let mut consumer = self;
292            consumer.accept(t, u);
293        })
294    }
295
296    /// Converts to BoxStatefulBiConsumer (non-consuming)
297    ///
298    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
299    ///
300    /// Converts the current bi-consumer to `BoxStatefulBiConsumer<T, U>` by cloning
301    /// it first.
302    ///
303    /// # Ownership
304    ///
305    /// This method does **not consume** the consumer. It clones the consumer
306    /// and then converts the clone to `BoxStatefulBiConsumer<T, U>`. The original
307    /// consumer remains available after calling this method.
308    ///
309    /// # Returns
310    ///
311    /// Returns the wrapped `BoxStatefulBiConsumer<T, U>` from the clone
312    ///
313    /// # Examples
314    ///
315    /// ```rust
316    /// use prism3_function::{BiConsumer, ArcStatefulBiConsumer};
317    /// use std::sync::{Arc, Mutex};
318    ///
319    /// let log = Arc::new(Mutex::new(Vec::new()));
320    /// let l = log.clone();
321    /// let consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
322    ///     l.lock().unwrap().push(*x + *y);
323    /// });
324    /// let mut box_consumer = consumer.to_box();
325    /// box_consumer.accept(&5, &3);
326    /// assert_eq!(*log.lock().unwrap(), vec![8]);
327    /// // Original consumer still usable
328    /// consumer.accept(&2, &1);
329    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
330    /// ```
331    fn to_box(&self) -> BoxStatefulBiConsumer<T, U>
332    where
333        Self: Sized + Clone + 'static,
334        T: 'static,
335        U: 'static,
336    {
337        self.clone().into_box()
338    }
339
340    /// Converts to RcStatefulBiConsumer (non-consuming)
341    ///
342    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
343    ///
344    /// Converts the current bi-consumer to `RcStatefulBiConsumer<T, U>` by cloning
345    /// it first.
346    ///
347    /// # Ownership
348    ///
349    /// This method does **not consume** the consumer. It clones the consumer
350    /// and then converts the clone to `RcStatefulBiConsumer<T, U>`. The original
351    /// consumer remains available after calling this method.
352    ///
353    /// # Returns
354    ///
355    /// Returns the wrapped `RcStatefulBiConsumer<T, U>` from the clone
356    ///
357    /// # Examples
358    ///
359    /// ```rust
360    /// use prism3_function::{BiConsumer, ArcStatefulBiConsumer};
361    /// use std::sync::{Arc, Mutex};
362    ///
363    /// let log = Arc::new(Mutex::new(Vec::new()));
364    /// let l = log.clone();
365    /// let consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
366    ///     l.lock().unwrap().push(*x + *y);
367    /// });
368    /// let mut rc_consumer = consumer.to_rc();
369    /// rc_consumer.accept(&5, &3);
370    /// assert_eq!(*log.lock().unwrap(), vec![8]);
371    /// // Original consumer still usable
372    /// consumer.accept(&2, &1);
373    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
374    /// ```
375    fn to_rc(&self) -> RcStatefulBiConsumer<T, U>
376    where
377        Self: Sized + Clone + 'static,
378        T: 'static,
379        U: 'static,
380    {
381        self.clone().into_rc()
382    }
383
384    /// Converts to ArcStatefulBiConsumer (non-consuming)
385    ///
386    /// **⚠️ Requires Clone + Send**: Original consumer must implement Clone +
387    /// Send.
388    ///
389    /// Converts the current bi-consumer to `ArcStatefulBiConsumer<T, U>` by cloning
390    /// it first.
391    ///
392    /// # Ownership
393    ///
394    /// This method does **not consume** the consumer. It clones the consumer
395    /// and then converts the clone to `ArcStatefulBiConsumer<T, U>`. The original
396    /// consumer remains available after calling this method.
397    ///
398    /// # Returns
399    ///
400    /// Returns the wrapped `ArcStatefulBiConsumer<T, U>` from the clone
401    ///
402    /// # Examples
403    ///
404    /// ```rust
405    /// use prism3_function::{BiConsumer, RcStatefulBiConsumer};
406    /// use std::rc::Rc;
407    /// use std::cell::RefCell;
408    ///
409    /// let log = Rc::new(RefCell::new(Vec::new()));
410    /// let l = log.clone();
411    /// let consumer = RcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
412    ///     l.borrow_mut().push(*x + *y);
413    /// });
414    /// let mut arc_consumer = consumer.to_arc();
415    /// arc_consumer.accept(&5, &3);
416    /// assert_eq!(*log.borrow(), vec![8]);
417    /// // Original consumer still usable
418    /// consumer.accept(&2, &1);
419    /// assert_eq!(*log.borrow(), vec![8, 3]);
420    /// ```
421    fn to_arc(&self) -> ArcStatefulBiConsumer<T, U>
422    where
423        Self: Sized + Clone + Send + 'static,
424        T: 'static,
425        U: 'static,
426    {
427        self.clone().into_arc()
428    }
429
430    /// Converts to closure (non-consuming)
431    ///
432    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
433    ///
434    /// Converts the consumer to a closure that can be used directly in
435    /// standard library functions requiring `FnMut`.
436    ///
437    /// # Ownership
438    ///
439    /// This method does **not consume** the consumer. It clones the consumer
440    /// and then converts the clone to a closure. The original consumer
441    /// remains available after calling this method.
442    ///
443    /// # Returns
444    ///
445    /// Returns a closure implementing `FnMut(&T, &U)` from the clone
446    ///
447    /// # Examples
448    ///
449    /// ```rust
450    /// use prism3_function::{BiConsumer, BoxStatefulBiConsumer};
451    /// use std::sync::{Arc, Mutex};
452    ///
453    /// let log = Arc::new(Mutex::new(Vec::new()));
454    /// let l = log.clone();
455    /// let consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
456    ///     l.lock().unwrap().push(*x + *y);
457    /// });
458    /// let mut func = consumer.to_fn();
459    /// func(&5, &3);
460    /// assert_eq!(*log.lock().unwrap(), vec![8]);
461    /// // Original consumer still usable
462    /// consumer.accept(&2, &1);
463    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
464    /// ```
465    fn to_fn(&self) -> impl FnMut(&T, &U)
466    where
467        Self: Sized + Clone + 'static,
468        T: 'static,
469        U: 'static,
470    {
471        self.clone().into_fn()
472    }
473
474    /// Convert to BiConsumerOnce without consuming self
475    ///
476    /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
477    /// Clones the current consumer and converts the clone to a one-time consumer.
478    ///
479    /// # Returns
480    ///
481    /// Returns a `BoxBiConsumerOnce<T, U>`
482    fn to_once(&self) -> BoxBiConsumerOnce<T, U>
483    where
484        Self: Clone + 'static,
485        T: 'static,
486        U: 'static,
487    {
488        self.clone().into_once()
489    }
490}
491
492// =======================================================================
493// 2. BoxStatefulBiConsumer - Single Ownership Implementation
494// =======================================================================
495
496/// BoxStatefulBiConsumer struct
497///
498/// A bi-consumer implementation based on `Box<dyn FnMut(&T, &U)>` for
499/// single ownership scenarios. This is the simplest and most efficient
500/// bi-consumer type when sharing is not required.
501///
502/// # Features
503///
504/// - **Single Ownership**: Not cloneable, ownership moves on use
505/// - **Zero Overhead**: No reference counting or locking
506/// - **Mutable State**: Can modify captured environment via `FnMut`
507/// - **Builder Pattern**: Method chaining consumes `self` naturally
508///
509/// # Use Cases
510///
511/// Choose `BoxStatefulBiConsumer` when:
512/// - The bi-consumer is used only once or in a linear flow
513/// - Building pipelines where ownership naturally flows
514/// - No need to share the consumer across contexts
515/// - Performance is critical and sharing overhead is unacceptable
516///
517/// # Performance
518///
519/// `BoxStatefulBiConsumer` has the best performance among the three bi-consumer
520/// types:
521/// - No reference counting overhead
522/// - No lock acquisition or runtime borrow checking
523/// - Direct function call through vtable
524/// - Minimal memory footprint (single pointer)
525///
526/// # Examples
527///
528/// ```rust
529/// use prism3_function::{BiConsumer, BoxStatefulBiConsumer};
530/// use std::sync::{Arc, Mutex};
531///
532/// let log = Arc::new(Mutex::new(Vec::new()));
533/// let l = log.clone();
534/// let mut consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
535///     l.lock().unwrap().push(*x + *y);
536/// });
537/// consumer.accept(&5, &3);
538/// assert_eq!(*log.lock().unwrap(), vec![8]);
539/// ```
540///
541/// # Author
542///
543/// Haixing Hu
544pub struct BoxStatefulBiConsumer<T, U> {
545    function: Box<dyn FnMut(&T, &U)>,
546    name: Option<String>,
547}
548
549impl<T, U> BoxStatefulBiConsumer<T, U>
550where
551    T: 'static,
552    U: 'static,
553{
554    // Generates: new(), new_with_name(), name(), set_name(), noop()
555    impl_consumer_common_methods!(
556        BoxStatefulBiConsumer<T, U>,
557        (FnMut(&T, &U) + 'static),
558        |f| Box::new(f)
559    );
560
561    // Generates: when() and and_then() methods that consume self
562    impl_box_consumer_methods!(
563        BoxStatefulBiConsumer<T, U>,
564        BoxConditionalStatefulBiConsumer,
565        StatefulBiConsumer
566    );
567}
568
569impl<T, U> StatefulBiConsumer<T, U> for BoxStatefulBiConsumer<T, U> {
570    fn accept(&mut self, first: &T, second: &U) {
571        (self.function)(first, second)
572    }
573
574    // Generates: into_box(), into_rc(), into_fn(), into_once()
575    impl_box_conversions!(
576        BoxStatefulBiConsumer<T, U>,
577        RcStatefulBiConsumer,
578        FnMut(&T, &U),
579        BoxBiConsumerOnce
580    );
581}
582
583// Use macro to generate Debug and Display implementations
584impl_consumer_debug_display!(BoxStatefulBiConsumer<T, U>);
585
586// =======================================================================
587// 3. RcStatefulBiConsumer - Single-Threaded Shared Ownership Implementation
588// =======================================================================
589
590/// RcStatefulBiConsumer struct
591///
592/// A bi-consumer implementation based on `Rc<RefCell<dyn FnMut(&T, &U)>>`
593/// for single-threaded shared ownership scenarios. This consumer provides
594/// the benefits of shared ownership without the overhead of thread
595/// safety.
596///
597/// # Features
598///
599/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
600/// - **Single-Threaded**: Not thread-safe, cannot send across threads
601/// - **Interior Mutability**: Uses `RefCell` for runtime borrow checking
602/// - **No Lock Overhead**: More efficient than `ArcStatefulBiConsumer` for
603///   single-threaded use
604/// - **Non-Consuming API**: `and_then` borrows `&self`, original remains
605///   usable
606///
607/// # Use Cases
608///
609/// Choose `RcStatefulBiConsumer` when:
610/// - Need to share bi-consumer within a single thread
611/// - Thread safety is not needed
612/// - Performance matters (avoiding lock overhead)
613/// - Single-threaded UI framework event handling
614/// - Building complex single-threaded state machines
615///
616/// # Performance Considerations
617///
618/// `RcStatefulBiConsumer` performs better than `ArcStatefulBiConsumer` in single-threaded
619/// scenarios:
620/// - **Non-Atomic Counting**: clone/drop cheaper than `Arc`
621/// - **No Lock Overhead**: `RefCell` uses runtime checking, no locks
622/// - **Better Cache Locality**: No atomic operations means better CPU
623///   cache behavior
624///
625/// But still has slight overhead compared to `BoxStatefulBiConsumer`:
626/// - **Reference Counting**: Though non-atomic, still exists
627/// - **Runtime Borrow Checking**: `RefCell` checks at runtime
628///
629/// # Safety
630///
631/// `RcStatefulBiConsumer` is not thread-safe and does not implement `Send` or
632/// `Sync`. Attempting to send it to another thread will result in a
633/// compile error. For thread-safe sharing, use `ArcStatefulBiConsumer` instead.
634///
635/// # Examples
636///
637/// ```rust
638/// use prism3_function::{BiConsumer, RcStatefulBiConsumer};
639/// use std::rc::Rc;
640/// use std::cell::RefCell;
641///
642/// let log = Rc::new(RefCell::new(Vec::new()));
643/// let l = log.clone();
644/// let mut consumer = RcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
645///     l.borrow_mut().push(*x + *y);
646/// });
647/// let mut clone = consumer.clone();
648///
649/// consumer.accept(&5, &3);
650/// assert_eq!(*log.borrow(), vec![8]);
651/// ```
652///
653/// # Author
654///
655/// Haixing Hu
656pub struct RcStatefulBiConsumer<T, U> {
657    function: Rc<RefCell<dyn FnMut(&T, &U)>>,
658    name: Option<String>,
659}
660
661impl<T, U> RcStatefulBiConsumer<T, U>
662where
663    T: 'static,
664    U: 'static,
665{
666    // Generates: new(), new_with_name(), name(), set_name(), noop()
667    impl_consumer_common_methods!(
668        RcStatefulBiConsumer<T, U>,
669        (FnMut(&T, &U) + 'static),
670        |f| Rc::new(RefCell::new(f))
671    );
672
673    // Generates: when() and and_then() methods that borrow &self (Rc can clone)
674    impl_shared_consumer_methods!(
675        RcStatefulBiConsumer<T, U>,
676        RcConditionalStatefulBiConsumer,
677        into_rc,
678        StatefulBiConsumer,
679        'static
680    );
681}
682
683impl<T, U> StatefulBiConsumer<T, U> for RcStatefulBiConsumer<T, U> {
684    fn accept(&mut self, first: &T, second: &U) {
685        (self.function.borrow_mut())(first, second)
686    }
687
688    // Use macro to implement conversion methods
689    impl_rc_conversions!(
690        RcStatefulBiConsumer<T, U>,
691        BoxStatefulBiConsumer,
692        BoxBiConsumerOnce,
693        FnMut(t: &T, u: &U)
694    );
695}
696
697// Use macro to generate Clone implementation
698impl_consumer_clone!(RcStatefulBiConsumer<T, U>);
699
700// Use macro to generate Debug and Display implementations
701impl_consumer_debug_display!(RcStatefulBiConsumer<T, U>);
702
703// =======================================================================
704// 4. ArcStatefulBiConsumer - Thread-Safe Shared Ownership Implementation
705// =======================================================================
706
707/// ArcStatefulBiConsumer struct
708///
709/// A bi-consumer implementation based on
710/// `Arc<Mutex<dyn FnMut(&T, &U) + Send>>` for thread-safe shared
711/// ownership scenarios. This consumer can be safely cloned and shared
712/// across multiple threads.
713///
714/// # Features
715///
716/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
717/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
718/// - **Interior Mutability**: Uses `Mutex` for safe mutable access
719/// - **Non-Consuming API**: `and_then` borrows `&self`, original remains
720///   usable
721/// - **Cross-Thread Sharing**: Can be sent to and used by other threads
722///
723/// # Use Cases
724///
725/// Choose `ArcStatefulBiConsumer` when:
726/// - Need to share bi-consumer across multiple threads
727/// - Concurrent task processing (e.g., thread pools)
728/// - Using the same consumer in multiple places simultaneously
729/// - Thread safety (Send + Sync) is required
730///
731/// # Performance Considerations
732///
733/// `ArcStatefulBiConsumer` has some overhead compared to `BoxStatefulBiConsumer`:
734/// - **Reference Counting**: Atomic operations on clone/drop
735/// - **Mutex Locking**: Each `accept` call requires lock acquisition
736/// - **Lock Contention**: High concurrency may cause contention
737///
738/// These overheads are necessary for safe concurrent access. If thread
739/// safety is not needed, consider using `RcStatefulBiConsumer` for lower
740/// overhead in single-threaded sharing.
741///
742/// # Examples
743///
744/// ```rust
745/// use prism3_function::{BiConsumer, ArcStatefulBiConsumer};
746/// use std::sync::{Arc, Mutex};
747///
748/// let log = Arc::new(Mutex::new(Vec::new()));
749/// let l = log.clone();
750/// let mut consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
751///     l.lock().unwrap().push(*x + *y);
752/// });
753/// let mut clone = consumer.clone();
754///
755/// consumer.accept(&5, &3);
756/// assert_eq!(*log.lock().unwrap(), vec![8]);
757/// ```
758///
759/// # Author
760///
761/// Haixing Hu
762pub struct ArcStatefulBiConsumer<T, U> {
763    function: Arc<Mutex<dyn FnMut(&T, &U) + Send>>,
764    name: Option<String>,
765}
766
767impl<T, U> ArcStatefulBiConsumer<T, U>
768where
769    T: 'static,
770    U: 'static,
771{
772    // Generates: new(), new_with_name(), name(), set_name(), noop()
773    impl_consumer_common_methods!(
774        ArcStatefulBiConsumer<T, U>,
775        (FnMut(&T, &U) + Send + 'static),
776        |f| Arc::new(Mutex::new(f))
777    );
778
779    // Generates: when() and and_then() methods that borrow &self (Arc can clone)
780    impl_shared_consumer_methods!(
781        ArcStatefulBiConsumer<T, U>,
782        ArcConditionalStatefulBiConsumer,
783        into_arc,
784        StatefulBiConsumer,
785        Send + Sync + 'static
786    );
787}
788
789impl<T, U> StatefulBiConsumer<T, U> for ArcStatefulBiConsumer<T, U> {
790    fn accept(&mut self, first: &T, second: &U) {
791        (self.function.lock())(first, second)
792    }
793
794    // Use macro to implement conversion methods
795    impl_arc_conversions!(
796        ArcStatefulBiConsumer<T, U>,
797        BoxStatefulBiConsumer,
798        RcStatefulBiConsumer,
799        BoxBiConsumerOnce,
800        FnMut(t: &T, u: &U)
801    );
802}
803
804// Use macro to generate Clone implementation
805impl_consumer_clone!(ArcStatefulBiConsumer<T, U>);
806
807// Use macro to generate Debug and Display implementations
808impl_consumer_debug_display!(ArcStatefulBiConsumer<T, U>);
809
810// =======================================================================
811// 5. Implement BiConsumer trait for closures
812// =======================================================================
813
814// Implements BiConsumer for all FnMut(&T, &U)
815impl_closure_trait!(
816    StatefulBiConsumer<T, U>,
817    accept,
818    BoxBiConsumerOnce,
819    FnMut(first: &T, second: &U)
820);
821
822// =======================================================================
823// 6. Provide extension methods for closures
824// =======================================================================
825
826/// Extension trait providing bi-consumer composition methods for closures
827///
828/// Provides `and_then` and other composition methods for all closures
829/// implementing `FnMut(&T, &U)`, enabling direct method chaining on
830/// closures without explicit wrapper types.
831///
832/// # Design Rationale
833///
834/// This trait allows closures to be composed naturally using method
835/// syntax, similar to iterator combinators. Composition methods consume
836/// the closure and return `BoxStatefulBiConsumer<T, U>`, which can be further
837/// chained.
838///
839/// # Features
840///
841/// - **Natural Syntax**: Chain operations directly on closures
842/// - **Returns BoxStatefulBiConsumer**: Composition results are
843///   `BoxStatefulBiConsumer<T, U>` for continued chaining
844/// - **Zero Cost**: No overhead when composing closures
845/// - **Automatic Implementation**: All `FnMut(&T, &U)` closures get
846///   these methods automatically
847///
848/// # Examples
849///
850/// ```rust
851/// use prism3_function::{BiConsumer, FnStatefulBiConsumerOps};
852/// use std::sync::{Arc, Mutex};
853///
854/// let log = Arc::new(Mutex::new(Vec::new()));
855/// let l1 = log.clone();
856/// let l2 = log.clone();
857/// let mut chained = (move |x: &i32, y: &i32| {
858///     l1.lock().unwrap().push(*x + *y);
859/// }).and_then(move |x: &i32, y: &i32| {
860///     l2.lock().unwrap().push(*x * *y);
861/// });
862/// chained.accept(&5, &3);
863/// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
864/// ```
865///
866/// # Author
867///
868/// Haixing Hu
869pub trait FnStatefulBiConsumerOps<T, U>: FnMut(&T, &U) + Sized {
870    /// Chains another consumer in sequence
871    ///
872    /// Returns a new consumer executing the current operation first, then
873    /// the next operation. Consumes the current closure and returns
874    /// `BoxStatefulBiConsumer<T, U>`.
875    ///
876    /// # Type Parameters
877    ///
878    /// * `C` - The type of the next consumer
879    ///
880    /// # Parameters
881    ///
882    /// * `next` - The consumer to execute after the current operation. **Note:
883    ///   This parameter is passed by value and will transfer ownership.** If you
884    ///   need to preserve the original consumer, clone it first (if it implements
885    ///   `Clone`). Can be:
886    ///   - A closure: `|x: &T, y: &U|`
887    ///   - A `BoxStatefulBiConsumer<T, U>`
888    ///   - An `ArcStatefulBiConsumer<T, U>`
889    ///   - An `RcStatefulBiConsumer<T, U>`
890    ///   - Any type implementing `BiConsumer<T, U>`
891    ///
892    /// # Returns
893    ///
894    /// Returns the composed `BoxStatefulBiConsumer<T, U>`
895    ///
896    /// # Examples
897    ///
898    /// ```rust
899    /// use prism3_function::{BiConsumer, FnStatefulBiConsumerOps};
900    /// use std::sync::{Arc, Mutex};
901    ///
902    /// let log = Arc::new(Mutex::new(Vec::new()));
903    /// let l1 = log.clone();
904    /// let l2 = log.clone();
905    /// let mut chained = (move |x: &i32, y: &i32| {
906    ///     l1.lock().unwrap().push(*x + *y);
907    /// }).and_then(move |x: &i32, y: &i32| {
908    ///     l2.lock().unwrap().push(*x * *y);
909    /// }).and_then(|x: &i32, y: &i32| println!("Result: {}, {}", x, y));
910    ///
911    /// chained.accept(&5, &3); // Prints: Result: 5, 3
912    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
913    /// ```
914    fn and_then<C>(self, next: C) -> BoxStatefulBiConsumer<T, U>
915    where
916        Self: 'static,
917        C: StatefulBiConsumer<T, U> + 'static,
918        T: 'static,
919        U: 'static,
920    {
921        let mut first = self;
922        let mut second = next;
923        BoxStatefulBiConsumer::new(move |t, u| {
924            first(t, u);
925            second.accept(t, u);
926        })
927    }
928}
929
930/// Implements FnStatefulBiConsumerOps for all closure types
931impl<T, U, F> FnStatefulBiConsumerOps<T, U> for F where F: FnMut(&T, &U) {}
932
933// =======================================================================
934// 7. BoxConditionalBiConsumer - Box-based Conditional BiConsumer
935// =======================================================================
936
937/// BoxConditionalBiConsumer struct
938///
939/// A conditional bi-consumer that only executes when a predicate is satisfied.
940/// Uses `BoxStatefulBiConsumer` and `BoxBiPredicate` for single ownership semantics.
941///
942/// This type is typically created by calling `BoxStatefulBiConsumer::when()` and is
943/// designed to work with the `or_else()` method to create if-then-else logic.
944///
945/// # Features
946///
947/// - **Single Ownership**: Not cloneable, consumes `self` on use
948/// - **Conditional Execution**: Only consumes when predicate returns `true`
949/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
950/// - **Implements BiConsumer**: Can be used anywhere a `BiConsumer` is expected
951///
952/// # Examples
953///
954/// ## Basic Conditional Execution
955///
956/// ```rust
957/// use prism3_function::{BiConsumer, BoxStatefulBiConsumer};
958/// use std::sync::{Arc, Mutex};
959///
960/// let log = Arc::new(Mutex::new(Vec::new()));
961/// let l = log.clone();
962/// let consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
963///     l.lock().unwrap().push(*x + *y);
964/// });
965/// let mut conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
966///
967/// conditional.accept(&5, &3);
968/// assert_eq!(*log.lock().unwrap(), vec![8]); // Executed
969///
970/// conditional.accept(&-5, &3);
971/// assert_eq!(*log.lock().unwrap(), vec![8]); // Not executed
972/// ```
973///
974/// ## With or_else Branch
975///
976/// ```rust
977/// use prism3_function::{BiConsumer, BoxStatefulBiConsumer};
978/// use std::sync::{Arc, Mutex};
979///
980/// let log = Arc::new(Mutex::new(Vec::new()));
981/// let l1 = log.clone();
982/// let l2 = log.clone();
983/// let mut consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
984///     l1.lock().unwrap().push(*x + *y);
985/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0)
986///   .or_else(move |x: &i32, y: &i32| {
987///     l2.lock().unwrap().push(*x * *y);
988/// });
989///
990/// consumer.accept(&5, &3);
991/// assert_eq!(*log.lock().unwrap(), vec![8]); // when branch executed
992///
993/// consumer.accept(&-5, &3);
994/// assert_eq!(*log.lock().unwrap(), vec![8, -15]); // or_else branch executed
995/// ```
996///
997/// # Author
998///
999/// Haixing Hu
1000pub struct BoxConditionalStatefulBiConsumer<T, U> {
1001    consumer: BoxStatefulBiConsumer<T, U>,
1002    predicate: BoxBiPredicate<T, U>,
1003}
1004
1005// Use macro to generate conditional bi-consumer implementations
1006impl_box_conditional_consumer!(
1007    BoxConditionalStatefulBiConsumer<T, U>,
1008    BoxStatefulBiConsumer,
1009    StatefulBiConsumer
1010);
1011
1012impl<T, U> StatefulBiConsumer<T, U> for BoxConditionalStatefulBiConsumer<T, U>
1013where
1014    T: 'static,
1015    U: 'static,
1016{
1017    fn accept(&mut self, first: &T, second: &U) {
1018        if self.predicate.test(first, second) {
1019            self.consumer.accept(first, second);
1020        }
1021    }
1022
1023    // Generates: into_box(), into_rc(), into_fn()
1024    impl_conditional_consumer_conversions!(
1025        BoxStatefulBiConsumer<T, U>,
1026        RcStatefulBiConsumer,
1027        FnMut
1028    );
1029}
1030
1031// Use macro to generate Debug and Display implementations
1032impl_conditional_consumer_debug_display!(BoxConditionalStatefulBiConsumer<T, U>);
1033
1034// =======================================================================
1035// 8. ArcConditionalStatefulBiConsumer - Arc-based Conditional BiConsumer
1036// =======================================================================
1037
1038/// ArcConditionalStatefulBiConsumer struct
1039///
1040/// A thread-safe conditional bi-consumer that only executes when a predicate is
1041/// satisfied. Uses `ArcStatefulBiConsumer` and `ArcBiPredicate` for shared ownership across
1042/// threads.
1043///
1044/// This type is typically created by calling `ArcStatefulBiConsumer::when()` and is
1045/// designed to work with the `or_else()` method to create if-then-else logic.
1046///
1047/// # Features
1048///
1049/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
1050/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
1051/// - **Conditional Execution**: Only consumes when predicate returns `true`
1052/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
1053///
1054/// # Examples
1055///
1056/// ```rust
1057/// use prism3_function::{BiConsumer, ArcStatefulBiConsumer};
1058/// use std::sync::{Arc, Mutex};
1059///
1060/// let log = Arc::new(Mutex::new(Vec::new()));
1061/// let l = log.clone();
1062/// let conditional = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
1063///     l.lock().unwrap().push(*x + *y);
1064/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0);
1065///
1066/// let conditional_clone = conditional.clone();
1067///
1068/// let mut value = 5;
1069/// let mut m = conditional;
1070/// m.accept(&value, &3);
1071/// assert_eq!(*log.lock().unwrap(), vec![8]);
1072/// ```
1073///
1074/// # Author
1075///
1076/// Haixing Hu
1077pub struct ArcConditionalStatefulBiConsumer<T, U> {
1078    consumer: ArcStatefulBiConsumer<T, U>,
1079    predicate: ArcBiPredicate<T, U>,
1080}
1081
1082// Use macro to generate and_then and or_else methods
1083impl_shared_conditional_consumer!(
1084    ArcConditionalStatefulBiConsumer<T, U>,
1085    ArcStatefulBiConsumer,
1086    StatefulBiConsumer,
1087    into_arc,
1088    Send + Sync + 'static
1089);
1090
1091impl<T, U> StatefulBiConsumer<T, U> for ArcConditionalStatefulBiConsumer<T, U>
1092where
1093    T: Send + 'static,
1094    U: Send + 'static,
1095{
1096    fn accept(&mut self, first: &T, second: &U) {
1097        if self.predicate.test(first, second) {
1098            self.consumer.accept(first, second);
1099        }
1100    }
1101
1102    // Generates: into_box(), into_rc(), into_fn()
1103    impl_conditional_consumer_conversions!(
1104        BoxStatefulBiConsumer<T, U>,
1105        RcStatefulBiConsumer,
1106        FnMut
1107    );
1108}
1109
1110// Use macro to generate Clone implementation
1111impl_conditional_consumer_clone!(ArcConditionalStatefulBiConsumer<T, U>);
1112
1113// Use macro to generate Debug and Display implementations
1114impl_conditional_consumer_debug_display!(ArcConditionalStatefulBiConsumer<T, U>);
1115
1116// =======================================================================
1117// 9. RcConditionalStatefulBiConsumer - Rc-based Conditional BiConsumer
1118// =======================================================================
1119
1120/// RcConditionalStatefulBiConsumer struct
1121///
1122/// A single-threaded conditional bi-consumer that only executes when a predicate is
1123/// satisfied. Uses `RcStatefulBiConsumer` and `RcBiPredicate` for shared ownership within a
1124/// single thread.
1125///
1126/// This type is typically created by calling `RcStatefulBiConsumer::when()` and is
1127/// designed to work with the `or_else()` method to create if-then-else logic.
1128///
1129/// # Features
1130///
1131/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
1132/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
1133/// - **Conditional Execution**: Only consumes when predicate returns `true`
1134/// - **No Lock Overhead**: More efficient than `ArcConditionalStatefulBiConsumer`
1135///
1136/// # Examples
1137///
1138/// ```rust
1139/// use prism3_function::{BiConsumer, RcStatefulBiConsumer};
1140/// use std::rc::Rc;
1141/// use std::cell::RefCell;
1142///
1143/// let log = Rc::new(RefCell::new(Vec::new()));
1144/// let l = log.clone();
1145/// let conditional = RcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
1146///     l.borrow_mut().push(*x + *y);
1147/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0);
1148///
1149/// let conditional_clone = conditional.clone();
1150///
1151/// let mut value = 5;
1152/// let mut m = conditional;
1153/// m.accept(&value, &3);
1154/// assert_eq!(*log.borrow(), vec![8]);
1155/// ```
1156///
1157/// # Author
1158///
1159/// Haixing Hu
1160pub struct RcConditionalStatefulBiConsumer<T, U> {
1161    consumer: RcStatefulBiConsumer<T, U>,
1162    predicate: RcBiPredicate<T, U>,
1163}
1164
1165// Use macro to generate and_then and or_else methods
1166impl_shared_conditional_consumer!(
1167    RcConditionalStatefulBiConsumer<T, U>,
1168    RcStatefulBiConsumer,
1169    StatefulBiConsumer,
1170    into_rc,
1171    'static
1172);
1173
1174impl<T, U> StatefulBiConsumer<T, U> for RcConditionalStatefulBiConsumer<T, U>
1175where
1176    T: 'static,
1177    U: 'static,
1178{
1179    fn accept(&mut self, first: &T, second: &U) {
1180        if self.predicate.test(first, second) {
1181            self.consumer.accept(first, second);
1182        }
1183    }
1184
1185    // Generates: into_box(), into_rc(), into_fn()
1186    impl_conditional_consumer_conversions!(
1187        BoxStatefulBiConsumer<T, U>,
1188        RcStatefulBiConsumer,
1189        FnMut
1190    );
1191}
1192
1193// Use macro to generate Clone implementation
1194impl_conditional_consumer_clone!(RcConditionalStatefulBiConsumer<T, U>);
1195
1196// Use macro to generate Debug and Display implementations
1197impl_conditional_consumer_debug_display!(RcConditionalStatefulBiConsumer<T, U>);