Skip to main content

qubit_function/consumers/
stateful_bi_consumer.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit 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 qubit_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 qubit_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 qubit_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 qubit_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    {
268        let mut consumer = self;
269        move |t, u| consumer.accept(t, u)
270    }
271
272    /// Convert to BiConsumerOnce
273    ///
274    /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
275    ///
276    /// Converts a reusable stateful bi-consumer to a one-time consumer that consumes itself on use.
277    /// This enables passing `StatefulBiConsumer` to functions that require `BiConsumerOnce`.
278    ///
279    /// # Returns
280    ///
281    /// Returns a `BoxBiConsumerOnce<T, U>`
282    fn into_once(self) -> BoxBiConsumerOnce<T, U>
283    where
284        Self: Sized + 'static,
285        T: 'static,
286        U: 'static,
287    {
288        BoxBiConsumerOnce::new(move |t, u| {
289            let mut consumer = self;
290            consumer.accept(t, u);
291        })
292    }
293
294    /// Converts to BoxStatefulBiConsumer (non-consuming)
295    ///
296    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
297    ///
298    /// Converts the current bi-consumer to `BoxStatefulBiConsumer<T, U>` by cloning
299    /// it first.
300    ///
301    /// # Ownership
302    ///
303    /// This method does **not consume** the consumer. It clones the consumer
304    /// and then converts the clone to `BoxStatefulBiConsumer<T, U>`. The original
305    /// consumer remains available after calling this method.
306    ///
307    /// # Returns
308    ///
309    /// Returns the wrapped `BoxStatefulBiConsumer<T, U>` from the clone
310    ///
311    /// # Examples
312    ///
313    /// ```rust
314    /// use qubit_function::{BiConsumer, ArcStatefulBiConsumer};
315    /// use std::sync::{Arc, Mutex};
316    ///
317    /// let log = Arc::new(Mutex::new(Vec::new()));
318    /// let l = log.clone();
319    /// let consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
320    ///     l.lock().unwrap().push(*x + *y);
321    /// });
322    /// let mut box_consumer = consumer.to_box();
323    /// box_consumer.accept(&5, &3);
324    /// assert_eq!(*log.lock().unwrap(), vec![8]);
325    /// // Original consumer still usable
326    /// consumer.accept(&2, &1);
327    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
328    /// ```
329    fn to_box(&self) -> BoxStatefulBiConsumer<T, U>
330    where
331        Self: Sized + Clone + 'static,
332        T: 'static,
333        U: 'static,
334    {
335        self.clone().into_box()
336    }
337
338    /// Converts to RcStatefulBiConsumer (non-consuming)
339    ///
340    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
341    ///
342    /// Converts the current bi-consumer to `RcStatefulBiConsumer<T, U>` by cloning
343    /// it first.
344    ///
345    /// # Ownership
346    ///
347    /// This method does **not consume** the consumer. It clones the consumer
348    /// and then converts the clone to `RcStatefulBiConsumer<T, U>`. The original
349    /// consumer remains available after calling this method.
350    ///
351    /// # Returns
352    ///
353    /// Returns the wrapped `RcStatefulBiConsumer<T, U>` from the clone
354    ///
355    /// # Examples
356    ///
357    /// ```rust
358    /// use qubit_function::{BiConsumer, ArcStatefulBiConsumer};
359    /// use std::sync::{Arc, Mutex};
360    ///
361    /// let log = Arc::new(Mutex::new(Vec::new()));
362    /// let l = log.clone();
363    /// let consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
364    ///     l.lock().unwrap().push(*x + *y);
365    /// });
366    /// let mut rc_consumer = consumer.to_rc();
367    /// rc_consumer.accept(&5, &3);
368    /// assert_eq!(*log.lock().unwrap(), vec![8]);
369    /// // Original consumer still usable
370    /// consumer.accept(&2, &1);
371    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
372    /// ```
373    fn to_rc(&self) -> RcStatefulBiConsumer<T, U>
374    where
375        Self: Sized + Clone + 'static,
376        T: 'static,
377        U: 'static,
378    {
379        self.clone().into_rc()
380    }
381
382    /// Converts to ArcStatefulBiConsumer (non-consuming)
383    ///
384    /// **⚠️ Requires Clone + Send**: Original consumer must implement Clone +
385    /// Send.
386    ///
387    /// Converts the current bi-consumer to `ArcStatefulBiConsumer<T, U>` by cloning
388    /// it first.
389    ///
390    /// # Ownership
391    ///
392    /// This method does **not consume** the consumer. It clones the consumer
393    /// and then converts the clone to `ArcStatefulBiConsumer<T, U>`. The original
394    /// consumer remains available after calling this method.
395    ///
396    /// # Returns
397    ///
398    /// Returns the wrapped `ArcStatefulBiConsumer<T, U>` from the clone
399    ///
400    /// # Examples
401    ///
402    /// ```rust
403    /// use qubit_function::{BiConsumer, RcStatefulBiConsumer};
404    /// use std::rc::Rc;
405    /// use std::cell::RefCell;
406    ///
407    /// let log = Rc::new(RefCell::new(Vec::new()));
408    /// let l = log.clone();
409    /// let consumer = RcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
410    ///     l.borrow_mut().push(*x + *y);
411    /// });
412    /// let mut arc_consumer = consumer.to_arc();
413    /// arc_consumer.accept(&5, &3);
414    /// assert_eq!(*log.borrow(), vec![8]);
415    /// // Original consumer still usable
416    /// consumer.accept(&2, &1);
417    /// assert_eq!(*log.borrow(), vec![8, 3]);
418    /// ```
419    fn to_arc(&self) -> ArcStatefulBiConsumer<T, U>
420    where
421        Self: Sized + Clone + Send + 'static,
422        T: 'static,
423        U: 'static,
424    {
425        self.clone().into_arc()
426    }
427
428    /// Converts to closure (non-consuming)
429    ///
430    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
431    ///
432    /// Converts the consumer to a closure that can be used directly in
433    /// standard library functions requiring `FnMut`.
434    ///
435    /// # Ownership
436    ///
437    /// This method does **not consume** the consumer. It clones the consumer
438    /// and then converts the clone to a closure. The original consumer
439    /// remains available after calling this method.
440    ///
441    /// # Returns
442    ///
443    /// Returns a closure implementing `FnMut(&T, &U)` from the clone
444    ///
445    /// # Examples
446    ///
447    /// ```rust
448    /// use qubit_function::{BiConsumer, BoxStatefulBiConsumer};
449    /// use std::sync::{Arc, Mutex};
450    ///
451    /// let log = Arc::new(Mutex::new(Vec::new()));
452    /// let l = log.clone();
453    /// let consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
454    ///     l.lock().unwrap().push(*x + *y);
455    /// });
456    /// let mut func = consumer.to_fn();
457    /// func(&5, &3);
458    /// assert_eq!(*log.lock().unwrap(), vec![8]);
459    /// // Original consumer still usable
460    /// consumer.accept(&2, &1);
461    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
462    /// ```
463    fn to_fn(&self) -> impl FnMut(&T, &U)
464    where
465        Self: Sized + Clone + 'static,
466    {
467        self.clone().into_fn()
468    }
469
470    /// Convert to BiConsumerOnce without consuming self
471    ///
472    /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
473    /// Clones the current consumer and converts the clone to a one-time consumer.
474    ///
475    /// # Returns
476    ///
477    /// Returns a `BoxBiConsumerOnce<T, U>`
478    fn to_once(&self) -> BoxBiConsumerOnce<T, U>
479    where
480        Self: Clone + 'static,
481        T: 'static,
482        U: 'static,
483    {
484        self.clone().into_once()
485    }
486}
487
488// =======================================================================
489// 2. BoxStatefulBiConsumer - Single Ownership Implementation
490// =======================================================================
491
492/// BoxStatefulBiConsumer struct
493///
494/// A bi-consumer implementation based on `Box<dyn FnMut(&T, &U)>` for
495/// single ownership scenarios. This is the simplest and most efficient
496/// bi-consumer type when sharing is not required.
497///
498/// # Features
499///
500/// - **Single Ownership**: Not cloneable, ownership moves on use
501/// - **Zero Overhead**: No reference counting or locking
502/// - **Mutable State**: Can modify captured environment via `FnMut`
503/// - **Builder Pattern**: Method chaining consumes `self` naturally
504///
505/// # Use Cases
506///
507/// Choose `BoxStatefulBiConsumer` when:
508/// - The bi-consumer is used only once or in a linear flow
509/// - Building pipelines where ownership naturally flows
510/// - No need to share the consumer across contexts
511/// - Performance is critical and sharing overhead is unacceptable
512///
513/// # Performance
514///
515/// `BoxStatefulBiConsumer` has the best performance among the three bi-consumer
516/// types:
517/// - No reference counting overhead
518/// - No lock acquisition or runtime borrow checking
519/// - Direct function call through vtable
520/// - Minimal memory footprint (single pointer)
521///
522/// # Examples
523///
524/// ```rust
525/// use qubit_function::{BiConsumer, BoxStatefulBiConsumer};
526/// use std::sync::{Arc, Mutex};
527///
528/// let log = Arc::new(Mutex::new(Vec::new()));
529/// let l = log.clone();
530/// let mut consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
531///     l.lock().unwrap().push(*x + *y);
532/// });
533/// consumer.accept(&5, &3);
534/// assert_eq!(*log.lock().unwrap(), vec![8]);
535/// ```
536///
537/// # Author
538///
539/// Haixing Hu
540pub struct BoxStatefulBiConsumer<T, U> {
541    function: Box<dyn FnMut(&T, &U)>,
542    name: Option<String>,
543}
544
545impl<T, U> BoxStatefulBiConsumer<T, U> {
546    // Generates: new(), new_with_name(), name(), set_name(), noop()
547    impl_consumer_common_methods!(
548        BoxStatefulBiConsumer<T, U>,
549        (FnMut(&T, &U) + 'static),
550        |f| Box::new(f)
551    );
552
553    // Generates: when() and and_then() methods that consume self
554    impl_box_consumer_methods!(
555        BoxStatefulBiConsumer<T, U>,
556        BoxConditionalStatefulBiConsumer,
557        StatefulBiConsumer
558    );
559}
560
561impl<T, U> StatefulBiConsumer<T, U> for BoxStatefulBiConsumer<T, U> {
562    fn accept(&mut self, first: &T, second: &U) {
563        (self.function)(first, second)
564    }
565
566    // Generates: into_box(), into_rc(), into_fn(), into_once()
567    impl_box_conversions!(
568        BoxStatefulBiConsumer<T, U>,
569        RcStatefulBiConsumer,
570        FnMut(&T, &U),
571        BoxBiConsumerOnce
572    );
573}
574
575// Use macro to generate Debug and Display implementations
576impl_consumer_debug_display!(BoxStatefulBiConsumer<T, U>);
577
578// =======================================================================
579// 3. RcStatefulBiConsumer - Single-Threaded Shared Ownership Implementation
580// =======================================================================
581
582/// RcStatefulBiConsumer struct
583///
584/// A bi-consumer implementation based on `Rc<RefCell<dyn FnMut(&T, &U)>>`
585/// for single-threaded shared ownership scenarios. This consumer provides
586/// the benefits of shared ownership without the overhead of thread
587/// safety.
588///
589/// # Features
590///
591/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
592/// - **Single-Threaded**: Not thread-safe, cannot send across threads
593/// - **Interior Mutability**: Uses `RefCell` for runtime borrow checking
594/// - **No Lock Overhead**: More efficient than `ArcStatefulBiConsumer` for
595///   single-threaded use
596/// - **Non-Consuming API**: `and_then` borrows `&self`, original remains
597///   usable
598///
599/// # Use Cases
600///
601/// Choose `RcStatefulBiConsumer` when:
602/// - Need to share bi-consumer within a single thread
603/// - Thread safety is not needed
604/// - Performance matters (avoiding lock overhead)
605/// - Single-threaded UI framework event handling
606/// - Building complex single-threaded state machines
607///
608/// # Performance Considerations
609///
610/// `RcStatefulBiConsumer` performs better than `ArcStatefulBiConsumer` in single-threaded
611/// scenarios:
612/// - **Non-Atomic Counting**: clone/drop cheaper than `Arc`
613/// - **No Lock Overhead**: `RefCell` uses runtime checking, no locks
614/// - **Better Cache Locality**: No atomic operations means better CPU
615///   cache behavior
616///
617/// But still has slight overhead compared to `BoxStatefulBiConsumer`:
618/// - **Reference Counting**: Though non-atomic, still exists
619/// - **Runtime Borrow Checking**: `RefCell` checks at runtime
620///
621/// # Safety
622///
623/// `RcStatefulBiConsumer` is not thread-safe and does not implement `Send` or
624/// `Sync`. Attempting to send it to another thread will result in a
625/// compile error. For thread-safe sharing, use `ArcStatefulBiConsumer` instead.
626///
627/// # Examples
628///
629/// ```rust
630/// use qubit_function::{BiConsumer, RcStatefulBiConsumer};
631/// use std::rc::Rc;
632/// use std::cell::RefCell;
633///
634/// let log = Rc::new(RefCell::new(Vec::new()));
635/// let l = log.clone();
636/// let mut consumer = RcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
637///     l.borrow_mut().push(*x + *y);
638/// });
639/// let mut clone = consumer.clone();
640///
641/// consumer.accept(&5, &3);
642/// assert_eq!(*log.borrow(), vec![8]);
643/// ```
644///
645/// # Author
646///
647/// Haixing Hu
648pub struct RcStatefulBiConsumer<T, U> {
649    function: Rc<RefCell<dyn FnMut(&T, &U)>>,
650    name: Option<String>,
651}
652
653impl<T, U> RcStatefulBiConsumer<T, U> {
654    // Generates: new(), new_with_name(), name(), set_name(), noop()
655    impl_consumer_common_methods!(
656        RcStatefulBiConsumer<T, U>,
657        (FnMut(&T, &U) + 'static),
658        |f| Rc::new(RefCell::new(f))
659    );
660
661    // Generates: when() and and_then() methods that borrow &self (Rc can clone)
662    impl_shared_consumer_methods!(
663        RcStatefulBiConsumer<T, U>,
664        RcConditionalStatefulBiConsumer,
665        into_rc,
666        StatefulBiConsumer,
667        'static
668    );
669}
670
671impl<T, U> StatefulBiConsumer<T, U> for RcStatefulBiConsumer<T, U> {
672    fn accept(&mut self, first: &T, second: &U) {
673        (self.function.borrow_mut())(first, second)
674    }
675
676    // Use macro to implement conversion methods
677    impl_rc_conversions!(
678        RcStatefulBiConsumer<T, U>,
679        BoxStatefulBiConsumer,
680        BoxBiConsumerOnce,
681        FnMut(t: &T, u: &U)
682    );
683}
684
685// Use macro to generate Clone implementation
686impl_consumer_clone!(RcStatefulBiConsumer<T, U>);
687
688// Use macro to generate Debug and Display implementations
689impl_consumer_debug_display!(RcStatefulBiConsumer<T, U>);
690
691// =======================================================================
692// 4. ArcStatefulBiConsumer - Thread-Safe Shared Ownership Implementation
693// =======================================================================
694
695/// ArcStatefulBiConsumer struct
696///
697/// A bi-consumer implementation based on
698/// `Arc<Mutex<dyn FnMut(&T, &U) + Send>>` for thread-safe shared
699/// ownership scenarios. This consumer can be safely cloned and shared
700/// across multiple threads.
701///
702/// # Features
703///
704/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
705/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
706/// - **Interior Mutability**: Uses `Mutex` for safe mutable access
707/// - **Non-Consuming API**: `and_then` borrows `&self`, original remains
708///   usable
709/// - **Cross-Thread Sharing**: Can be sent to and used by other threads
710///
711/// # Use Cases
712///
713/// Choose `ArcStatefulBiConsumer` when:
714/// - Need to share bi-consumer across multiple threads
715/// - Concurrent task processing (e.g., thread pools)
716/// - Using the same consumer in multiple places simultaneously
717/// - Thread safety (Send + Sync) is required
718///
719/// # Performance Considerations
720///
721/// `ArcStatefulBiConsumer` has some overhead compared to `BoxStatefulBiConsumer`:
722/// - **Reference Counting**: Atomic operations on clone/drop
723/// - **Mutex Locking**: Each `accept` call requires lock acquisition
724/// - **Lock Contention**: High concurrency may cause contention
725///
726/// These overheads are necessary for safe concurrent access. If thread
727/// safety is not needed, consider using `RcStatefulBiConsumer` for lower
728/// overhead in single-threaded sharing.
729///
730/// # Examples
731///
732/// ```rust
733/// use qubit_function::{BiConsumer, ArcStatefulBiConsumer};
734/// use std::sync::{Arc, Mutex};
735///
736/// let log = Arc::new(Mutex::new(Vec::new()));
737/// let l = log.clone();
738/// let mut consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
739///     l.lock().unwrap().push(*x + *y);
740/// });
741/// let mut clone = consumer.clone();
742///
743/// consumer.accept(&5, &3);
744/// assert_eq!(*log.lock().unwrap(), vec![8]);
745/// ```
746///
747/// # Author
748///
749/// Haixing Hu
750pub struct ArcStatefulBiConsumer<T, U> {
751    function: Arc<Mutex<dyn FnMut(&T, &U) + Send>>,
752    name: Option<String>,
753}
754
755impl<T, U> ArcStatefulBiConsumer<T, U> {
756    // Generates: new(), new_with_name(), name(), set_name(), noop()
757    impl_consumer_common_methods!(
758        ArcStatefulBiConsumer<T, U>,
759        (FnMut(&T, &U) + Send + 'static),
760        |f| Arc::new(Mutex::new(f))
761    );
762
763    // Generates: when() and and_then() methods that borrow &self (Arc can clone)
764    impl_shared_consumer_methods!(
765        ArcStatefulBiConsumer<T, U>,
766        ArcConditionalStatefulBiConsumer,
767        into_arc,
768        StatefulBiConsumer,
769        Send + Sync + 'static
770    );
771}
772
773impl<T, U> StatefulBiConsumer<T, U> for ArcStatefulBiConsumer<T, U> {
774    fn accept(&mut self, first: &T, second: &U) {
775        (self.function.lock())(first, second)
776    }
777
778    // Use macro to implement conversion methods
779    impl_arc_conversions!(
780        ArcStatefulBiConsumer<T, U>,
781        BoxStatefulBiConsumer,
782        RcStatefulBiConsumer,
783        BoxBiConsumerOnce,
784        FnMut(t: &T, u: &U)
785    );
786}
787
788// Use macro to generate Clone implementation
789impl_consumer_clone!(ArcStatefulBiConsumer<T, U>);
790
791// Use macro to generate Debug and Display implementations
792impl_consumer_debug_display!(ArcStatefulBiConsumer<T, U>);
793
794// =======================================================================
795// 5. Implement BiConsumer trait for closures
796// =======================================================================
797
798// Implements BiConsumer for all FnMut(&T, &U)
799impl_closure_trait!(
800    StatefulBiConsumer<T, U>,
801    accept,
802    BoxBiConsumerOnce,
803    FnMut(first: &T, second: &U)
804);
805
806// =======================================================================
807// 6. Provide extension methods for closures
808// =======================================================================
809
810/// Extension trait providing bi-consumer composition methods for closures
811///
812/// Provides `and_then` and other composition methods for all closures
813/// implementing `FnMut(&T, &U)`, enabling direct method chaining on
814/// closures without explicit wrapper types.
815///
816/// # Design Rationale
817///
818/// This trait allows closures to be composed naturally using method
819/// syntax, similar to iterator combinators. Composition methods consume
820/// the closure and return `BoxStatefulBiConsumer<T, U>`, which can be further
821/// chained.
822///
823/// # Features
824///
825/// - **Natural Syntax**: Chain operations directly on closures
826/// - **Returns BoxStatefulBiConsumer**: Composition results are
827///   `BoxStatefulBiConsumer<T, U>` for continued chaining
828/// - **Zero Cost**: No overhead when composing closures
829/// - **Automatic Implementation**: All `FnMut(&T, &U)` closures get
830///   these methods automatically
831///
832/// # Examples
833///
834/// ```rust
835/// use qubit_function::{BiConsumer, FnStatefulBiConsumerOps};
836/// use std::sync::{Arc, Mutex};
837///
838/// let log = Arc::new(Mutex::new(Vec::new()));
839/// let l1 = log.clone();
840/// let l2 = log.clone();
841/// let mut chained = (move |x: &i32, y: &i32| {
842///     l1.lock().unwrap().push(*x + *y);
843/// }).and_then(move |x: &i32, y: &i32| {
844///     l2.lock().unwrap().push(*x * *y);
845/// });
846/// chained.accept(&5, &3);
847/// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
848/// ```
849///
850/// # Author
851///
852/// Haixing Hu
853pub trait FnStatefulBiConsumerOps<T, U>: FnMut(&T, &U) + Sized {
854    /// Chains another consumer in sequence
855    ///
856    /// Returns a new consumer executing the current operation first, then
857    /// the next operation. Consumes the current closure and returns
858    /// `BoxStatefulBiConsumer<T, U>`.
859    ///
860    /// # Type Parameters
861    ///
862    /// * `C` - The type of the next consumer
863    ///
864    /// # Parameters
865    ///
866    /// * `next` - The consumer to execute after the current operation. **Note:
867    ///   This parameter is passed by value and will transfer ownership.** If you
868    ///   need to preserve the original consumer, clone it first (if it implements
869    ///   `Clone`). Can be:
870    ///   - A closure: `|x: &T, y: &U|`
871    ///   - A `BoxStatefulBiConsumer<T, U>`
872    ///   - An `ArcStatefulBiConsumer<T, U>`
873    ///   - An `RcStatefulBiConsumer<T, U>`
874    ///   - Any type implementing `BiConsumer<T, U>`
875    ///
876    /// # Returns
877    ///
878    /// Returns the composed `BoxStatefulBiConsumer<T, U>`
879    ///
880    /// # Examples
881    ///
882    /// ```rust
883    /// use qubit_function::{BiConsumer, FnStatefulBiConsumerOps};
884    /// use std::sync::{Arc, Mutex};
885    ///
886    /// let log = Arc::new(Mutex::new(Vec::new()));
887    /// let l1 = log.clone();
888    /// let l2 = log.clone();
889    /// let mut chained = (move |x: &i32, y: &i32| {
890    ///     l1.lock().unwrap().push(*x + *y);
891    /// }).and_then(move |x: &i32, y: &i32| {
892    ///     l2.lock().unwrap().push(*x * *y);
893    /// }).and_then(|x: &i32, y: &i32| println!("Result: {}, {}", x, y));
894    ///
895    /// chained.accept(&5, &3); // Prints: Result: 5, 3
896    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
897    /// ```
898    fn and_then<C>(self, next: C) -> BoxStatefulBiConsumer<T, U>
899    where
900        Self: 'static,
901        C: StatefulBiConsumer<T, U> + 'static,
902        T: 'static,
903        U: 'static,
904    {
905        let mut first = self;
906        let mut second = next;
907        BoxStatefulBiConsumer::new(move |t, u| {
908            first(t, u);
909            second.accept(t, u);
910        })
911    }
912}
913
914/// Implements FnStatefulBiConsumerOps for all closure types
915impl<T, U, F> FnStatefulBiConsumerOps<T, U> for F where F: FnMut(&T, &U) {}
916
917// =======================================================================
918// 7. BoxConditionalBiConsumer - Box-based Conditional BiConsumer
919// =======================================================================
920
921/// BoxConditionalBiConsumer struct
922///
923/// A conditional bi-consumer that only executes when a predicate is satisfied.
924/// Uses `BoxStatefulBiConsumer` and `BoxBiPredicate` for single ownership semantics.
925///
926/// This type is typically created by calling `BoxStatefulBiConsumer::when()` and is
927/// designed to work with the `or_else()` method to create if-then-else logic.
928///
929/// # Features
930///
931/// - **Single Ownership**: Not cloneable, consumes `self` on use
932/// - **Conditional Execution**: Only consumes when predicate returns `true`
933/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
934/// - **Implements BiConsumer**: Can be used anywhere a `BiConsumer` is expected
935///
936/// # Examples
937///
938/// ## Basic Conditional Execution
939///
940/// ```rust
941/// use qubit_function::{BiConsumer, BoxStatefulBiConsumer};
942/// use std::sync::{Arc, Mutex};
943///
944/// let log = Arc::new(Mutex::new(Vec::new()));
945/// let l = log.clone();
946/// let consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
947///     l.lock().unwrap().push(*x + *y);
948/// });
949/// let mut conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
950///
951/// conditional.accept(&5, &3);
952/// assert_eq!(*log.lock().unwrap(), vec![8]); // Executed
953///
954/// conditional.accept(&-5, &3);
955/// assert_eq!(*log.lock().unwrap(), vec![8]); // Not executed
956/// ```
957///
958/// ## With or_else Branch
959///
960/// ```rust
961/// use qubit_function::{BiConsumer, BoxStatefulBiConsumer};
962/// use std::sync::{Arc, Mutex};
963///
964/// let log = Arc::new(Mutex::new(Vec::new()));
965/// let l1 = log.clone();
966/// let l2 = log.clone();
967/// let mut consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
968///     l1.lock().unwrap().push(*x + *y);
969/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0)
970///   .or_else(move |x: &i32, y: &i32| {
971///     l2.lock().unwrap().push(*x * *y);
972/// });
973///
974/// consumer.accept(&5, &3);
975/// assert_eq!(*log.lock().unwrap(), vec![8]); // when branch executed
976///
977/// consumer.accept(&-5, &3);
978/// assert_eq!(*log.lock().unwrap(), vec![8, -15]); // or_else branch executed
979/// ```
980///
981/// # Author
982///
983/// Haixing Hu
984pub struct BoxConditionalStatefulBiConsumer<T, U> {
985    consumer: BoxStatefulBiConsumer<T, U>,
986    predicate: BoxBiPredicate<T, U>,
987}
988
989// Use macro to generate conditional bi-consumer implementations
990impl_box_conditional_consumer!(
991    BoxConditionalStatefulBiConsumer<T, U>,
992    BoxStatefulBiConsumer,
993    StatefulBiConsumer
994);
995
996impl<T, U> StatefulBiConsumer<T, U> for BoxConditionalStatefulBiConsumer<T, U> {
997    fn accept(&mut self, first: &T, second: &U) {
998        if self.predicate.test(first, second) {
999            self.consumer.accept(first, second);
1000        }
1001    }
1002
1003    // Generates: into_box(), into_rc(), into_fn()
1004    impl_conditional_consumer_conversions!(
1005        BoxStatefulBiConsumer<T, U>,
1006        RcStatefulBiConsumer,
1007        FnMut
1008    );
1009}
1010
1011// Use macro to generate Debug and Display implementations
1012impl_conditional_consumer_debug_display!(BoxConditionalStatefulBiConsumer<T, U>);
1013
1014// =======================================================================
1015// 8. ArcConditionalStatefulBiConsumer - Arc-based Conditional BiConsumer
1016// =======================================================================
1017
1018/// ArcConditionalStatefulBiConsumer struct
1019///
1020/// A thread-safe conditional bi-consumer that only executes when a predicate is
1021/// satisfied. Uses `ArcStatefulBiConsumer` and `ArcBiPredicate` for shared ownership across
1022/// threads.
1023///
1024/// This type is typically created by calling `ArcStatefulBiConsumer::when()` and is
1025/// designed to work with the `or_else()` method to create if-then-else logic.
1026///
1027/// # Features
1028///
1029/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
1030/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
1031/// - **Conditional Execution**: Only consumes when predicate returns `true`
1032/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
1033///
1034/// # Examples
1035///
1036/// ```rust
1037/// use qubit_function::{BiConsumer, ArcStatefulBiConsumer};
1038/// use std::sync::{Arc, Mutex};
1039///
1040/// let log = Arc::new(Mutex::new(Vec::new()));
1041/// let l = log.clone();
1042/// let conditional = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
1043///     l.lock().unwrap().push(*x + *y);
1044/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0);
1045///
1046/// let conditional_clone = conditional.clone();
1047///
1048/// let mut value = 5;
1049/// let mut m = conditional;
1050/// m.accept(&value, &3);
1051/// assert_eq!(*log.lock().unwrap(), vec![8]);
1052/// ```
1053///
1054/// # Author
1055///
1056/// Haixing Hu
1057pub struct ArcConditionalStatefulBiConsumer<T, U> {
1058    consumer: ArcStatefulBiConsumer<T, U>,
1059    predicate: ArcBiPredicate<T, U>,
1060}
1061
1062// Use macro to generate and_then and or_else methods
1063impl_shared_conditional_consumer!(
1064    ArcConditionalStatefulBiConsumer<T, U>,
1065    ArcStatefulBiConsumer,
1066    StatefulBiConsumer,
1067    into_arc,
1068    Send + Sync + 'static
1069);
1070
1071impl<T, U> StatefulBiConsumer<T, U> for ArcConditionalStatefulBiConsumer<T, U> {
1072    fn accept(&mut self, first: &T, second: &U) {
1073        if self.predicate.test(first, second) {
1074            self.consumer.accept(first, second);
1075        }
1076    }
1077
1078    // Generates: into_box(), into_rc(), into_fn()
1079    impl_conditional_consumer_conversions!(
1080        BoxStatefulBiConsumer<T, U>,
1081        RcStatefulBiConsumer,
1082        FnMut
1083    );
1084}
1085
1086// Use macro to generate Clone implementation
1087impl_conditional_consumer_clone!(ArcConditionalStatefulBiConsumer<T, U>);
1088
1089// Use macro to generate Debug and Display implementations
1090impl_conditional_consumer_debug_display!(ArcConditionalStatefulBiConsumer<T, U>);
1091
1092// =======================================================================
1093// 9. RcConditionalStatefulBiConsumer - Rc-based Conditional BiConsumer
1094// =======================================================================
1095
1096/// RcConditionalStatefulBiConsumer struct
1097///
1098/// A single-threaded conditional bi-consumer that only executes when a predicate is
1099/// satisfied. Uses `RcStatefulBiConsumer` and `RcBiPredicate` for shared ownership within a
1100/// single thread.
1101///
1102/// This type is typically created by calling `RcStatefulBiConsumer::when()` and is
1103/// designed to work with the `or_else()` method to create if-then-else logic.
1104///
1105/// # Features
1106///
1107/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
1108/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
1109/// - **Conditional Execution**: Only consumes when predicate returns `true`
1110/// - **No Lock Overhead**: More efficient than `ArcConditionalStatefulBiConsumer`
1111///
1112/// # Examples
1113///
1114/// ```rust
1115/// use qubit_function::{BiConsumer, RcStatefulBiConsumer};
1116/// use std::rc::Rc;
1117/// use std::cell::RefCell;
1118///
1119/// let log = Rc::new(RefCell::new(Vec::new()));
1120/// let l = log.clone();
1121/// let conditional = RcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
1122///     l.borrow_mut().push(*x + *y);
1123/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0);
1124///
1125/// let conditional_clone = conditional.clone();
1126///
1127/// let mut value = 5;
1128/// let mut m = conditional;
1129/// m.accept(&value, &3);
1130/// assert_eq!(*log.borrow(), vec![8]);
1131/// ```
1132///
1133/// # Author
1134///
1135/// Haixing Hu
1136pub struct RcConditionalStatefulBiConsumer<T, U> {
1137    consumer: RcStatefulBiConsumer<T, U>,
1138    predicate: RcBiPredicate<T, U>,
1139}
1140
1141// Use macro to generate and_then and or_else methods
1142impl_shared_conditional_consumer!(
1143    RcConditionalStatefulBiConsumer<T, U>,
1144    RcStatefulBiConsumer,
1145    StatefulBiConsumer,
1146    into_rc,
1147    'static
1148);
1149
1150impl<T, U> StatefulBiConsumer<T, U> for RcConditionalStatefulBiConsumer<T, U> {
1151    fn accept(&mut self, first: &T, second: &U) {
1152        if self.predicate.test(first, second) {
1153            self.consumer.accept(first, second);
1154        }
1155    }
1156
1157    // Generates: into_box(), into_rc(), into_fn()
1158    impl_conditional_consumer_conversions!(
1159        BoxStatefulBiConsumer<T, U>,
1160        RcStatefulBiConsumer,
1161        FnMut
1162    );
1163}
1164
1165// Use macro to generate Clone implementation
1166impl_conditional_consumer_clone!(RcConditionalStatefulBiConsumer<T, U>);
1167
1168// Use macro to generate Debug and Display implementations
1169impl_conditional_consumer_debug_display!(RcConditionalStatefulBiConsumer<T, U>);