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