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