prism3_function/
bi_consumer.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # BiConsumer Types
10//!
11//! Provides bi-consumer interface implementations for operations accepting
12//! two input parameters without returning a result.
13//!
14//! This module provides a unified `BiConsumer` trait and three concrete
15//! implementations based on different ownership models:
16//!
17//! - **`BoxBiConsumer<T, U>`**: Box-based single ownership for one-time use
18//! - **`ArcBiConsumer<T, U>`**: Arc<Mutex<>>-based thread-safe shared
19//!   ownership
20//! - **`RcBiConsumer<T, U>`**: Rc<RefCell<>>-based single-threaded shared
21//!   ownership
22//!
23//! # Design Philosophy
24//!
25//! BiConsumer uses `FnMut(&T, &U)` semantics: can modify its own state but
26//! does NOT modify input values. Suitable for statistics, accumulation, and
27//! event processing scenarios involving two parameters.
28//!
29//! # Author
30//!
31//! Haixing Hu
32
33use std::cell::RefCell;
34use std::fmt;
35use std::rc::Rc;
36use std::sync::{Arc, Mutex};
37
38use crate::bi_predicate::{ArcBiPredicate, BiPredicate, BoxBiPredicate, RcBiPredicate};
39
40/// Type alias for bi-consumer function to simplify complex types.
41///
42/// Represents a mutable function taking two references and returning
43/// nothing. Used to reduce type complexity in struct definitions.
44type BiConsumerFn<T, U> = dyn FnMut(&T, &U);
45
46/// Type alias for thread-safe bi-consumer function.
47///
48/// Represents a mutable function with Send bound for thread-safe usage.
49type SendBiConsumerFn<T, U> = dyn FnMut(&T, &U) + Send;
50
51// =======================================================================
52// 1. BiConsumer Trait - Unified BiConsumer Interface
53// =======================================================================
54
55/// BiConsumer trait - Unified bi-consumer interface
56///
57/// Defines core behavior for all bi-consumer types. Similar to Java's
58/// `BiConsumer<T, U>` interface, performs operations accepting two values
59/// but returning no result (side effects only).
60///
61/// BiConsumer can modify its own state (e.g., accumulate, count) but
62/// should NOT modify the consumed values themselves.
63///
64/// # Automatic Implementations
65///
66/// - All closures implementing `FnMut(&T, &U)`
67/// - `BoxBiConsumer<T, U>`, `ArcBiConsumer<T, U>`, `RcBiConsumer<T, U>`
68///
69/// # Features
70///
71/// - **Unified Interface**: All bi-consumer types share the same `accept`
72///   method signature
73/// - **Automatic Implementation**: Closures automatically implement this
74///   trait with zero overhead
75/// - **Type Conversions**: Easy conversion between ownership models
76/// - **Generic Programming**: Write functions accepting any bi-consumer
77///   type
78///
79/// # Examples
80///
81/// ```rust
82/// use prism3_function::{BiConsumer, BoxBiConsumer, ArcBiConsumer};
83/// use std::sync::{Arc, Mutex};
84///
85/// fn apply_bi_consumer<C: BiConsumer<i32, i32>>(
86///     consumer: &mut C,
87///     a: &i32,
88///     b: &i32
89/// ) {
90///     consumer.accept(a, b);
91/// }
92///
93/// // Works with any bi-consumer type
94/// let log = Arc::new(Mutex::new(Vec::new()));
95/// let l = log.clone();
96/// let mut box_con = BoxBiConsumer::new(move |x: &i32, y: &i32| {
97///     l.lock().unwrap().push(*x + *y);
98/// });
99/// apply_bi_consumer(&mut box_con, &5, &3);
100/// assert_eq!(*log.lock().unwrap(), vec![8]);
101/// ```
102///
103/// # Author
104///
105/// Haixing Hu
106pub trait BiConsumer<T, U> {
107    /// Performs the consumption operation
108    ///
109    /// Executes an operation on the given two references. The operation
110    /// typically reads input values or produces side effects, but does not
111    /// modify the input values themselves. Can modify the consumer's own
112    /// state.
113    ///
114    /// # Parameters
115    ///
116    /// * `first` - Reference to the first value to consume
117    /// * `second` - Reference to the second value to consume
118    ///
119    /// # Examples
120    ///
121    /// ```rust
122    /// use prism3_function::{BiConsumer, BoxBiConsumer};
123    /// use std::sync::{Arc, Mutex};
124    ///
125    /// let log = Arc::new(Mutex::new(Vec::new()));
126    /// let l = log.clone();
127    /// let mut consumer = BoxBiConsumer::new(move |x: &i32, y: &i32| {
128    ///     l.lock().unwrap().push(*x + *y);
129    /// });
130    /// consumer.accept(&5, &3);
131    /// assert_eq!(*log.lock().unwrap(), vec![8]);
132    /// ```
133    fn accept(&mut self, first: &T, second: &U);
134
135    /// Converts to BoxBiConsumer
136    ///
137    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
138    /// calling this method.
139    ///
140    /// Converts the current bi-consumer to `BoxBiConsumer<T, U>`.
141    ///
142    /// # Ownership
143    ///
144    /// This method **consumes** the consumer (takes ownership of `self`).
145    /// After calling, the original consumer is no longer available.
146    ///
147    /// **Tip**: For cloneable consumers ([`ArcBiConsumer`],
148    /// [`RcBiConsumer`]), call `.clone()` first if you need to keep the
149    /// original.
150    ///
151    /// # Returns
152    ///
153    /// Returns the wrapped `BoxBiConsumer<T, U>`
154    ///
155    /// # Examples
156    ///
157    /// ```rust
158    /// use prism3_function::BiConsumer;
159    /// use std::sync::{Arc, Mutex};
160    ///
161    /// let log = Arc::new(Mutex::new(Vec::new()));
162    /// let l = log.clone();
163    /// let closure = move |x: &i32, y: &i32| {
164    ///     l.lock().unwrap().push(*x + *y);
165    /// };
166    /// let mut box_consumer = closure.into_box();
167    /// box_consumer.accept(&5, &3);
168    /// assert_eq!(*log.lock().unwrap(), vec![8]);
169    /// ```
170    fn into_box(self) -> BoxBiConsumer<T, U>
171    where
172        Self: Sized + 'static,
173        T: 'static,
174        U: 'static;
175
176    /// Converts to RcBiConsumer
177    ///
178    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
179    /// calling this method.
180    ///
181    /// # Returns
182    ///
183    /// Returns the wrapped `RcBiConsumer<T, U>`
184    fn into_rc(self) -> RcBiConsumer<T, U>
185    where
186        Self: Sized + 'static,
187        T: 'static,
188        U: 'static;
189
190    /// Converts to ArcBiConsumer
191    ///
192    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
193    /// calling this method.
194    ///
195    /// # Returns
196    ///
197    /// Returns the wrapped `ArcBiConsumer<T, U>`
198    fn into_arc(self) -> ArcBiConsumer<T, U>
199    where
200        Self: Sized + Send + 'static,
201        T: Send + 'static,
202        U: Send + 'static;
203
204    /// Converts bi-consumer to a closure
205    ///
206    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
207    /// calling this method.
208    ///
209    /// Converts the bi-consumer to a closure usable with standard library
210    /// methods requiring `FnMut`.
211    ///
212    /// # Returns
213    ///
214    /// Returns a closure implementing `FnMut(&T, &U)`
215    ///
216    /// # Examples
217    ///
218    /// ```rust
219    /// use prism3_function::{BiConsumer, BoxBiConsumer};
220    /// use std::sync::{Arc, Mutex};
221    ///
222    /// let log = Arc::new(Mutex::new(Vec::new()));
223    /// let l = log.clone();
224    /// let consumer = BoxBiConsumer::new(move |x: &i32, y: &i32| {
225    ///     l.lock().unwrap().push(*x + *y);
226    /// });
227    /// let mut func = consumer.into_fn();
228    /// func(&5, &3);
229    /// assert_eq!(*log.lock().unwrap(), vec![8]);
230    /// ```
231    fn into_fn(self) -> impl FnMut(&T, &U)
232    where
233        Self: Sized + 'static,
234        T: 'static,
235        U: 'static;
236}
237
238// =======================================================================
239// 2. BoxBiConsumer - Single Ownership Implementation
240// =======================================================================
241
242/// BoxBiConsumer struct
243///
244/// A bi-consumer implementation based on `Box<dyn FnMut(&T, &U)>` for
245/// single ownership scenarios. This is the simplest and most efficient
246/// bi-consumer type when sharing is not required.
247///
248/// # Features
249///
250/// - **Single Ownership**: Not cloneable, ownership moves on use
251/// - **Zero Overhead**: No reference counting or locking
252/// - **Mutable State**: Can modify captured environment via `FnMut`
253/// - **Builder Pattern**: Method chaining consumes `self` naturally
254///
255/// # Use Cases
256///
257/// Choose `BoxBiConsumer` when:
258/// - The bi-consumer is used only once or in a linear flow
259/// - Building pipelines where ownership naturally flows
260/// - No need to share the consumer across contexts
261/// - Performance is critical and sharing overhead is unacceptable
262///
263/// # Performance
264///
265/// `BoxBiConsumer` has the best performance among the three bi-consumer
266/// types:
267/// - No reference counting overhead
268/// - No lock acquisition or runtime borrow checking
269/// - Direct function call through vtable
270/// - Minimal memory footprint (single pointer)
271///
272/// # Examples
273///
274/// ```rust
275/// use prism3_function::{BiConsumer, BoxBiConsumer};
276/// use std::sync::{Arc, Mutex};
277///
278/// let log = Arc::new(Mutex::new(Vec::new()));
279/// let l = log.clone();
280/// let mut consumer = BoxBiConsumer::new(move |x: &i32, y: &i32| {
281///     l.lock().unwrap().push(*x + *y);
282/// });
283/// consumer.accept(&5, &3);
284/// assert_eq!(*log.lock().unwrap(), vec![8]);
285/// ```
286///
287/// # Author
288///
289/// Haixing Hu
290pub struct BoxBiConsumer<T, U> {
291    function: Box<BiConsumerFn<T, U>>,
292    name: Option<String>,
293}
294
295impl<T, U> BoxBiConsumer<T, U>
296where
297    T: 'static,
298    U: 'static,
299{
300    /// Creates a new BoxBiConsumer
301    ///
302    /// # Type Parameters
303    ///
304    /// * `F` - The closure type
305    ///
306    /// # Parameters
307    ///
308    /// * `f` - The closure to wrap
309    ///
310    /// # Returns
311    ///
312    /// Returns a new `BoxBiConsumer<T, U>` instance
313    ///
314    /// # Examples
315    ///
316    /// ```rust
317    /// use prism3_function::{BiConsumer, BoxBiConsumer};
318    /// use std::sync::{Arc, Mutex};
319    ///
320    /// let log = Arc::new(Mutex::new(Vec::new()));
321    /// let l = log.clone();
322    /// let mut consumer = BoxBiConsumer::new(move |x: &i32, y: &i32| {
323    ///     l.lock().unwrap().push(*x * 2 + *y);
324    /// });
325    /// consumer.accept(&5, &3);
326    /// assert_eq!(*log.lock().unwrap(), vec![13]);
327    /// ```
328    pub fn new<F>(f: F) -> Self
329    where
330        F: FnMut(&T, &U) + 'static,
331    {
332        BoxBiConsumer {
333            function: Box::new(f),
334            name: None,
335        }
336    }
337
338    /// Creates a new BoxBiConsumer with a name
339    ///
340    /// # Type Parameters
341    ///
342    /// * `F` - The closure type
343    ///
344    /// # Parameters
345    ///
346    /// * `name` - The name of the consumer
347    /// * `f` - The closure to wrap
348    ///
349    /// # Returns
350    ///
351    /// Returns a new `BoxBiConsumer<T, U>` instance with the specified name
352    ///
353    /// # Examples
354    ///
355    /// ```rust
356    /// use prism3_function::{BiConsumer, BoxBiConsumer};
357    /// use std::sync::{Arc, Mutex};
358    ///
359    /// let log = Arc::new(Mutex::new(Vec::new()));
360    /// let l = log.clone();
361    /// let mut consumer = BoxBiConsumer::new_with_name("sum_logger", move |x: &i32, y: &i32| {
362    ///     l.lock().unwrap().push(*x + *y);
363    /// });
364    /// assert_eq!(consumer.name(), Some("sum_logger"));
365    /// consumer.accept(&5, &3);
366    /// assert_eq!(*log.lock().unwrap(), vec![8]);
367    /// ```
368    pub fn new_with_name<F>(name: &str, f: F) -> Self
369    where
370        F: FnMut(&T, &U) + 'static,
371    {
372        BoxBiConsumer {
373            function: Box::new(f),
374            name: Some(name.to_string()),
375        }
376    }
377
378    /// Creates a no-op bi-consumer
379    ///
380    /// Returns a bi-consumer that performs no operation.
381    ///
382    /// # Returns
383    ///
384    /// Returns a no-op bi-consumer
385    ///
386    /// # Examples
387    ///
388    /// ```rust
389    /// use prism3_function::{BiConsumer, BoxBiConsumer};
390    ///
391    /// let mut noop = BoxBiConsumer::<i32, i32>::noop();
392    /// noop.accept(&42, &10);
393    /// // Values unchanged
394    /// ```
395    pub fn noop() -> Self {
396        BoxBiConsumer::new(|_, _| {})
397    }
398
399    /// Gets the name of the consumer
400    ///
401    /// # Returns
402    ///
403    /// Returns the consumer's name, or `None` if not set
404    pub fn name(&self) -> Option<&str> {
405        self.name.as_deref()
406    }
407
408    /// Sets the name of the consumer
409    ///
410    /// # Parameters
411    ///
412    /// * `name` - The name to set
413    pub fn set_name(&mut self, name: impl Into<String>) {
414        self.name = Some(name.into());
415    }
416
417    /// Chains another consumer in sequence
418    ///
419    /// Returns a new consumer executing the current operation first, then
420    /// the next operation. Consumes self.
421    ///
422    /// # Type Parameters
423    ///
424    /// * `C` - The type of the next consumer
425    ///
426    /// # Parameters
427    ///
428    /// * `next` - The consumer to execute after the current operation. **Note:
429    ///   This parameter is passed by value and will transfer ownership.** If you
430    ///   need to preserve the original consumer, clone it first (if it implements
431    ///   `Clone`). Can be:
432    ///   - A closure: `|x: &T, y: &U|`
433    ///   - A `BoxBiConsumer<T, U>`
434    ///   - An `ArcBiConsumer<T, U>`
435    ///   - An `RcBiConsumer<T, U>`
436    ///   - Any type implementing `BiConsumer<T, U>`
437    ///
438    /// # Returns
439    ///
440    /// Returns a new composed `BoxBiConsumer<T, U>`
441    ///
442    /// # Examples
443    ///
444    /// ## Direct value passing (ownership transfer)
445    ///
446    /// ```rust
447    /// use prism3_function::{BiConsumer, BoxBiConsumer};
448    /// use std::sync::{Arc, Mutex};
449    ///
450    /// let log = Arc::new(Mutex::new(Vec::new()));
451    /// let l1 = log.clone();
452    /// let l2 = log.clone();
453    /// let first = BoxBiConsumer::new(move |x: &i32, y: &i32| {
454    ///     l1.lock().unwrap().push(*x + *y);
455    /// });
456    /// let second = BoxBiConsumer::new(move |x: &i32, y: &i32| {
457    ///     l2.lock().unwrap().push(*x * *y);
458    /// });
459    ///
460    /// // second is moved here
461    /// let mut chained = first.and_then(second);
462    /// chained.accept(&5, &3);
463    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
464    /// // second.accept(&2, &3); // Would not compile - moved
465    /// ```
466    ///
467    /// ## Preserving original with clone
468    ///
469    /// ```rust
470    /// use prism3_function::{BiConsumer, BoxBiConsumer};
471    /// use std::sync::{Arc, Mutex};
472    ///
473    /// let log = Arc::new(Mutex::new(Vec::new()));
474    /// let l1 = log.clone();
475    /// let l2 = log.clone();
476    /// let first = BoxBiConsumer::new(move |x: &i32, y: &i32| {
477    ///     l1.lock().unwrap().push(*x + *y);
478    /// });
479    /// let second = BoxBiConsumer::new(move |x: &i32, y: &i32| {
480    ///     l2.lock().unwrap().push(*x * *y);
481    /// });
482    ///
483    /// // Clone to preserve original
484    /// let mut chained = first.and_then(second.clone());
485    /// chained.accept(&5, &3);
486    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
487    ///
488    /// // Original still usable
489    /// second.accept(&2, &3);
490    /// assert_eq!(*log.lock().unwrap(), vec![8, 15, 6]);
491    /// ```
492    pub fn and_then<C>(self, next: C) -> Self
493    where
494        C: BiConsumer<T, U> + 'static,
495    {
496        let mut first = self.function;
497        let mut second = next;
498        BoxBiConsumer::new(move |t, u| {
499            first(t, u);
500            second.accept(t, u);
501        })
502    }
503
504    /// Creates a conditional bi-consumer
505    ///
506    /// Returns a bi-consumer that only executes when a predicate is satisfied.
507    ///
508    /// # Parameters
509    ///
510    /// * `predicate` - The condition to check. **Note: This parameter is passed
511    ///   by value and will transfer ownership.** If you need to preserve the
512    ///   original bi-predicate, clone it first (if it implements `Clone`). Can be:
513    ///   - A closure: `|x: &T, y: &U| -> bool`
514    ///   - A function pointer: `fn(&T, &U) -> bool`
515    ///   - A `BoxBiPredicate<T, U>`
516    ///   - An `RcBiPredicate<T, U>`
517    ///   - An `ArcBiPredicate<T, U>`
518    ///   - Any type implementing `BiPredicate<T, U>`
519    ///
520    /// # Returns
521    ///
522    /// Returns `BoxConditionalBiConsumer<T, U>`
523    pub fn when<P>(self, predicate: P) -> BoxConditionalBiConsumer<T, U>
524    where
525        P: BiPredicate<T, U> + 'static,
526    {
527        BoxConditionalBiConsumer {
528            consumer: self,
529            predicate: predicate.into_box(),
530        }
531    }
532}
533
534impl<T, U> BiConsumer<T, U> for BoxBiConsumer<T, U> {
535    fn accept(&mut self, first: &T, second: &U) {
536        (self.function)(first, second)
537    }
538
539    fn into_box(self) -> BoxBiConsumer<T, U>
540    where
541        T: 'static,
542        U: 'static,
543    {
544        self
545    }
546
547    fn into_rc(self) -> RcBiConsumer<T, U>
548    where
549        T: 'static,
550        U: 'static,
551    {
552        let mut func = self.function;
553        RcBiConsumer::new(move |t, u| func(t, u))
554    }
555
556    fn into_arc(self) -> ArcBiConsumer<T, U>
557    where
558        T: Send + 'static,
559        U: Send + 'static,
560    {
561        panic!(
562            "Cannot convert BoxBiConsumer to ArcBiConsumer: inner \
563                function may not be Send"
564        )
565    }
566
567    fn into_fn(self) -> impl FnMut(&T, &U)
568    where
569        T: 'static,
570        U: 'static,
571    {
572        self.function
573    }
574}
575
576impl<T, U> fmt::Debug for BoxBiConsumer<T, U> {
577    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
578        f.debug_struct("BoxBiConsumer")
579            .field("name", &self.name)
580            .field("function", &"<function>")
581            .finish()
582    }
583}
584
585impl<T, U> fmt::Display for BoxBiConsumer<T, U> {
586    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
587        match &self.name {
588            Some(name) => write!(f, "BoxBiConsumer({})", name),
589            None => write!(f, "BoxBiConsumer"),
590        }
591    }
592}
593
594// =======================================================================
595// 3. BoxConditionalBiConsumer - Box-based Conditional BiConsumer
596// =======================================================================
597
598/// BoxConditionalBiConsumer struct
599///
600/// A conditional bi-consumer that only executes when a predicate is satisfied.
601/// Uses `BoxBiConsumer` and `BoxBiPredicate` for single ownership semantics.
602///
603/// This type is typically created by calling `BoxBiConsumer::when()` and is
604/// designed to work with the `or_else()` method to create if-then-else logic.
605///
606/// # Features
607///
608/// - **Single Ownership**: Not cloneable, consumes `self` on use
609/// - **Conditional Execution**: Only consumes when predicate returns `true`
610/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
611/// - **Implements BiConsumer**: Can be used anywhere a `BiConsumer` is expected
612///
613/// # Examples
614///
615/// ## Basic Conditional Execution
616///
617/// ```rust
618/// use prism3_function::{BiConsumer, BoxBiConsumer};
619/// use std::sync::{Arc, Mutex};
620///
621/// let log = Arc::new(Mutex::new(Vec::new()));
622/// let l = log.clone();
623/// let consumer = BoxBiConsumer::new(move |x: &i32, y: &i32| {
624///     l.lock().unwrap().push(*x + *y);
625/// });
626/// let mut conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
627///
628/// conditional.accept(&5, &3);
629/// assert_eq!(*log.lock().unwrap(), vec![8]); // Executed
630///
631/// conditional.accept(&-5, &3);
632/// assert_eq!(*log.lock().unwrap(), vec![8]); // Not executed
633/// ```
634///
635/// ## With or_else Branch
636///
637/// ```rust
638/// use prism3_function::{BiConsumer, BoxBiConsumer};
639/// use std::sync::{Arc, Mutex};
640///
641/// let log = Arc::new(Mutex::new(Vec::new()));
642/// let l1 = log.clone();
643/// let l2 = log.clone();
644/// let mut consumer = BoxBiConsumer::new(move |x: &i32, y: &i32| {
645///     l1.lock().unwrap().push(*x + *y);
646/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0)
647///   .or_else(move |x: &i32, y: &i32| {
648///     l2.lock().unwrap().push(*x * *y);
649/// });
650///
651/// consumer.accept(&5, &3);
652/// assert_eq!(*log.lock().unwrap(), vec![8]); // when branch executed
653///
654/// consumer.accept(&-5, &3);
655/// assert_eq!(*log.lock().unwrap(), vec![8, -15]); // or_else branch executed
656/// ```
657///
658/// # Author
659///
660/// Haixing Hu
661pub struct BoxConditionalBiConsumer<T, U> {
662    consumer: BoxBiConsumer<T, U>,
663    predicate: BoxBiPredicate<T, U>,
664}
665
666impl<T, U> BiConsumer<T, U> for BoxConditionalBiConsumer<T, U>
667where
668    T: 'static,
669    U: 'static,
670{
671    fn accept(&mut self, first: &T, second: &U) {
672        if self.predicate.test(first, second) {
673            self.consumer.accept(first, second);
674        }
675    }
676
677    fn into_box(self) -> BoxBiConsumer<T, U> {
678        let pred = self.predicate;
679        let mut consumer = self.consumer;
680        BoxBiConsumer::new(move |t, u| {
681            if pred.test(t, u) {
682                consumer.accept(t, u);
683            }
684        })
685    }
686
687    fn into_rc(self) -> RcBiConsumer<T, U> {
688        let pred = self.predicate.into_rc();
689        let consumer = self.consumer.into_rc();
690        let pred_fn = pred.to_fn();
691        let mut consumer_fn = consumer;
692        RcBiConsumer::new(move |t, u| {
693            if pred_fn(t, u) {
694                consumer_fn.accept(t, u);
695            }
696        })
697    }
698
699    fn into_arc(self) -> ArcBiConsumer<T, U>
700    where
701        T: Send + 'static,
702        U: Send + 'static,
703    {
704        panic!(
705            "Cannot convert BoxConditionalBiConsumer to ArcBiConsumer: \
706             predicate and consumer may not be Send + Sync"
707        )
708    }
709
710    fn into_fn(self) -> impl FnMut(&T, &U) {
711        let pred = self.predicate;
712        let mut consumer = self.consumer;
713        move |t: &T, u: &U| {
714            if pred.test(t, u) {
715                consumer.accept(t, u);
716            }
717        }
718    }
719}
720
721impl<T, U> BoxConditionalBiConsumer<T, U>
722where
723    T: 'static,
724    U: 'static,
725{
726    /// Chains another consumer in sequence
727    ///
728    /// Combines the current conditional consumer with another consumer into a new
729    /// consumer. The current conditional consumer executes first, followed by the
730    /// next consumer.
731    ///
732    /// # Parameters
733    ///
734    /// * `next` - The next consumer to execute. **Note: This parameter is passed
735    ///   by value and will transfer ownership.** If you need to preserve the
736    ///   original consumer, clone it first (if it implements `Clone`). Can be:
737    ///   - A closure: `|x: &T, y: &U|`
738    ///   - A `BoxBiConsumer<T, U>`
739    ///   - An `ArcBiConsumer<T, U>`
740    ///   - An `RcBiConsumer<T, U>`
741    ///   - Any type implementing `BiConsumer<T, U>`
742    ///
743    /// # Returns
744    ///
745    /// Returns a new `BoxBiConsumer<T, U>`
746    ///
747    /// # Examples
748    ///
749    /// ## Direct value passing (ownership transfer)
750    ///
751    /// ```rust
752    /// use prism3_function::{BiConsumer, BoxBiConsumer};
753    /// use std::sync::{Arc, Mutex};
754    ///
755    /// let log = Arc::new(Mutex::new(Vec::new()));
756    /// let l1 = log.clone();
757    /// let l2 = log.clone();
758    /// let cond = BoxBiConsumer::new(move |x: &i32, y: &i32| {
759    ///     l1.lock().unwrap().push(*x + *y);
760    /// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0);
761    /// let second = BoxBiConsumer::new(move |x: &i32, y: &i32| {
762    ///     l2.lock().unwrap().push(*x * *y);
763    /// });
764    ///
765    /// // second is moved here
766    /// let mut chained = cond.and_then(second);
767    /// chained.accept(&5, &3);
768    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
769    /// // second.accept(&2, &3); // Would not compile - moved
770    /// ```
771    ///
772    /// ## Preserving original with clone
773    ///
774    /// ```rust
775    /// use prism3_function::{BiConsumer, BoxBiConsumer};
776    /// use std::sync::{Arc, Mutex};
777    ///
778    /// let log = Arc::new(Mutex::new(Vec::new()));
779    /// let l1 = log.clone();
780    /// let l2 = log.clone();
781    /// let cond = BoxBiConsumer::new(move |x: &i32, y: &i32| {
782    ///     l1.lock().unwrap().push(*x + *y);
783    /// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0);
784    /// let second = BoxBiConsumer::new(move |x: &i32, y: &i32| {
785    ///     l2.lock().unwrap().push(*x * *y);
786    /// });
787    ///
788    /// // Clone to preserve original
789    /// let mut chained = cond.and_then(second.clone());
790    /// chained.accept(&5, &3);
791    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
792    ///
793    /// // Original still usable
794    /// second.accept(&2, &3);
795    /// assert_eq!(*log.lock().unwrap(), vec![8, 15, 6]);
796    /// ```
797    pub fn and_then<C>(self, next: C) -> BoxBiConsumer<T, U>
798    where
799        C: BiConsumer<T, U> + 'static,
800    {
801        let mut first = self;
802        let mut second = next;
803        BoxBiConsumer::new(move |t, u| {
804            first.accept(t, u);
805            second.accept(t, u);
806        })
807    }
808
809    /// Adds an else branch
810    ///
811    /// Executes the original consumer when the condition is satisfied, otherwise
812    /// executes else_consumer.
813    ///
814    /// # Parameters
815    ///
816    /// * `else_consumer` - The consumer for the else branch. **Note: This parameter
817    ///   is passed by value and will transfer ownership.** If you need to preserve
818    ///   the original consumer, clone it first (if it implements `Clone`). Can be:
819    ///   - A closure: `|x: &T, y: &U|`
820    ///   - A `BoxBiConsumer<T, U>`
821    ///   - An `RcBiConsumer<T, U>`
822    ///   - An `ArcBiConsumer<T, U>`
823    ///   - Any type implementing `BiConsumer<T, U>`
824    ///
825    /// # Returns
826    ///
827    /// Returns the composed `BoxBiConsumer<T, U>`
828    ///
829    /// # Examples
830    ///
831    /// ## Using a closure (recommended)
832    ///
833    /// ```rust
834    /// use prism3_function::{BiConsumer, BoxBiConsumer};
835    /// use std::sync::{Arc, Mutex};
836    ///
837    /// let log = Arc::new(Mutex::new(Vec::new()));
838    /// let l1 = log.clone();
839    /// let l2 = log.clone();
840    /// let mut consumer = BoxBiConsumer::new(move |x: &i32, y: &i32| {
841    ///     l1.lock().unwrap().push(*x + *y);
842    /// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0)
843    ///   .or_else(move |x: &i32, y: &i32| {
844    ///     l2.lock().unwrap().push(*x * *y);
845    /// });
846    ///
847    /// consumer.accept(&5, &3);
848    /// assert_eq!(*log.lock().unwrap(), vec![8]); // Condition satisfied
849    ///
850    /// consumer.accept(&-5, &3);
851    /// assert_eq!(*log.lock().unwrap(), vec![8, -15]); // Condition not satisfied
852    /// ```
853    pub fn or_else<C>(self, else_consumer: C) -> BoxBiConsumer<T, U>
854    where
855        C: BiConsumer<T, U> + 'static,
856    {
857        let pred = self.predicate;
858        let mut then_cons = self.consumer;
859        let mut else_cons = else_consumer;
860        BoxBiConsumer::new(move |t, u| {
861            if pred.test(t, u) {
862                then_cons.accept(t, u);
863            } else {
864                else_cons.accept(t, u);
865            }
866        })
867    }
868}
869
870// =======================================================================
871// 4. ArcBiConsumer - Thread-Safe Shared Ownership Implementation
872// =======================================================================
873
874/// ArcBiConsumer struct
875///
876/// A bi-consumer implementation based on
877/// `Arc<Mutex<dyn FnMut(&T, &U) + Send>>` for thread-safe shared
878/// ownership scenarios. This consumer can be safely cloned and shared
879/// across multiple threads.
880///
881/// # Features
882///
883/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
884/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
885/// - **Interior Mutability**: Uses `Mutex` for safe mutable access
886/// - **Non-Consuming API**: `and_then` borrows `&self`, original remains
887///   usable
888/// - **Cross-Thread Sharing**: Can be sent to and used by other threads
889///
890/// # Use Cases
891///
892/// Choose `ArcBiConsumer` when:
893/// - Need to share bi-consumer across multiple threads
894/// - Concurrent task processing (e.g., thread pools)
895/// - Using the same consumer in multiple places simultaneously
896/// - Thread safety (Send + Sync) is required
897///
898/// # Performance Considerations
899///
900/// `ArcBiConsumer` has some overhead compared to `BoxBiConsumer`:
901/// - **Reference Counting**: Atomic operations on clone/drop
902/// - **Mutex Locking**: Each `accept` call requires lock acquisition
903/// - **Lock Contention**: High concurrency may cause contention
904///
905/// These overheads are necessary for safe concurrent access. If thread
906/// safety is not needed, consider using `RcBiConsumer` for lower
907/// overhead in single-threaded sharing.
908///
909/// # Examples
910///
911/// ```rust
912/// use prism3_function::{BiConsumer, ArcBiConsumer};
913/// use std::sync::{Arc, Mutex};
914///
915/// let log = Arc::new(Mutex::new(Vec::new()));
916/// let l = log.clone();
917/// let mut consumer = ArcBiConsumer::new(move |x: &i32, y: &i32| {
918///     l.lock().unwrap().push(*x + *y);
919/// });
920/// let mut clone = consumer.clone();
921///
922/// consumer.accept(&5, &3);
923/// assert_eq!(*log.lock().unwrap(), vec![8]);
924/// ```
925///
926/// # Author
927///
928/// Haixing Hu
929pub struct ArcBiConsumer<T, U> {
930    function: Arc<Mutex<SendBiConsumerFn<T, U>>>,
931    name: Option<String>,
932}
933
934impl<T, U> ArcBiConsumer<T, U>
935where
936    T: Send + 'static,
937    U: Send + 'static,
938{
939    /// Creates a new ArcBiConsumer
940    ///
941    /// # Type Parameters
942    ///
943    /// * `F` - The closure type
944    ///
945    /// # Parameters
946    ///
947    /// * `f` - The closure to wrap
948    ///
949    /// # Returns
950    ///
951    /// Returns a new `ArcBiConsumer<T, U>` instance
952    ///
953    /// # Examples
954    ///
955    /// ```rust
956    /// use prism3_function::{BiConsumer, ArcBiConsumer};
957    /// use std::sync::{Arc, Mutex};
958    ///
959    /// let log = Arc::new(Mutex::new(Vec::new()));
960    /// let l = log.clone();
961    /// let mut consumer = ArcBiConsumer::new(move |x: &i32, y: &i32| {
962    ///     l.lock().unwrap().push(*x * 2 + *y);
963    /// });
964    /// consumer.accept(&5, &3);
965    /// assert_eq!(*log.lock().unwrap(), vec![13]);
966    /// ```
967    pub fn new<F>(f: F) -> Self
968    where
969        F: FnMut(&T, &U) + Send + 'static,
970    {
971        ArcBiConsumer {
972            function: Arc::new(Mutex::new(f)),
973            name: None,
974        }
975    }
976
977    /// Creates a new ArcBiConsumer with a name
978    ///
979    /// # Type Parameters
980    ///
981    /// * `F` - The closure type
982    ///
983    /// # Parameters
984    ///
985    /// * `name` - The name of the consumer
986    /// * `f` - The closure to wrap
987    ///
988    /// # Returns
989    ///
990    /// Returns a new `ArcBiConsumer<T, U>` instance with the specified name
991    ///
992    /// # Examples
993    ///
994    /// ```rust
995    /// use prism3_function::{BiConsumer, ArcBiConsumer};
996    /// use std::sync::{Arc, Mutex};
997    ///
998    /// let log = Arc::new(Mutex::new(Vec::new()));
999    /// let l = log.clone();
1000    /// let mut consumer = ArcBiConsumer::new_with_name("sum_logger", move |x: &i32, y: &i32| {
1001    ///     l.lock().unwrap().push(*x + *y);
1002    /// });
1003    /// assert_eq!(consumer.name(), Some("sum_logger"));
1004    /// consumer.accept(&5, &3);
1005    /// assert_eq!(*log.lock().unwrap(), vec![8]);
1006    /// ```
1007    pub fn new_with_name<F>(name: &str, f: F) -> Self
1008    where
1009        F: FnMut(&T, &U) + Send + 'static,
1010    {
1011        ArcBiConsumer {
1012            function: Arc::new(Mutex::new(f)),
1013            name: Some(name.to_string()),
1014        }
1015    }
1016
1017    /// Gets the name of the consumer
1018    ///
1019    /// # Returns
1020    ///
1021    /// Returns the consumer's name, or `None` if not set
1022    pub fn name(&self) -> Option<&str> {
1023        self.name.as_deref()
1024    }
1025
1026    /// Sets the name of the consumer
1027    ///
1028    /// # Parameters
1029    ///
1030    /// * `name` - The name to set
1031    pub fn set_name(&mut self, name: impl Into<String>) {
1032        self.name = Some(name.into());
1033    }
1034
1035    /// Converts to a closure (without consuming self)
1036    ///
1037    /// Creates a new closure that calls the underlying function via Arc.
1038    ///
1039    /// # Returns
1040    ///
1041    /// Returns a closure implementing `FnMut(&T, &U)`
1042    ///
1043    /// # Examples
1044    ///
1045    /// ```rust
1046    /// use prism3_function::{BiConsumer, ArcBiConsumer};
1047    /// use std::sync::{Arc, Mutex};
1048    ///
1049    /// let log = Arc::new(Mutex::new(Vec::new()));
1050    /// let l = log.clone();
1051    /// let consumer = ArcBiConsumer::new(move |x: &i32, y: &i32| {
1052    ///     l.lock().unwrap().push(*x + *y);
1053    /// });
1054    ///
1055    /// let mut func = consumer.to_fn();
1056    /// func(&5, &3);
1057    /// assert_eq!(*log.lock().unwrap(), vec![8]);
1058    /// ```
1059    pub fn to_fn(&self) -> impl FnMut(&T, &U)
1060    where
1061        T: 'static,
1062        U: 'static,
1063    {
1064        let func = Arc::clone(&self.function);
1065        move |t: &T, u: &U| {
1066            func.lock().unwrap()(t, u);
1067        }
1068    }
1069
1070    /// Chains another ArcBiConsumer in sequence
1071    ///
1072    /// Returns a new consumer executing the current operation first, then
1073    /// the next operation. Borrows &self, does not consume the original
1074    /// consumer.
1075    ///
1076    /// # Parameters
1077    ///
1078    /// * `next` - The consumer to execute after the current operation. **Note:
1079    ///   This parameter is passed by reference, so the original consumer remains
1080    ///   usable.** Can be:
1081    ///   - An `ArcBiConsumer<T, U>` (passed by reference)
1082    ///   - Any type implementing `BiConsumer<T, U> + Send + Sync`
1083    ///
1084    /// # Returns
1085    ///
1086    /// Returns a new composed `ArcBiConsumer<T, U>`
1087    ///
1088    /// # Examples
1089    ///
1090    /// ```rust
1091    /// use prism3_function::{BiConsumer, ArcBiConsumer};
1092    /// use std::sync::{Arc, Mutex};
1093    ///
1094    /// let log = Arc::new(Mutex::new(Vec::new()));
1095    /// let l1 = log.clone();
1096    /// let l2 = log.clone();
1097    /// let first = ArcBiConsumer::new(move |x: &i32, y: &i32| {
1098    ///     l1.lock().unwrap().push(*x + *y);
1099    /// });
1100    /// let second = ArcBiConsumer::new(move |x: &i32, y: &i32| {
1101    ///     l2.lock().unwrap().push(*x * *y);
1102    /// });
1103    ///
1104    /// // second is passed by reference, so it remains usable
1105    /// let mut chained = first.and_then(&second);
1106    ///
1107    /// // first and second still usable after chaining
1108    /// chained.accept(&5, &3);
1109    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
1110    /// // second.accept(&2, &3); // Still usable
1111    /// ```
1112    pub fn and_then(&self, next: &ArcBiConsumer<T, U>) -> ArcBiConsumer<T, U> {
1113        let first = Arc::clone(&self.function);
1114        let second = Arc::clone(&next.function);
1115        ArcBiConsumer {
1116            function: Arc::new(Mutex::new(move |t: &T, u: &U| {
1117                first.lock().unwrap()(t, u);
1118                second.lock().unwrap()(t, u);
1119            })),
1120            name: None,
1121        }
1122    }
1123
1124    /// Creates a conditional bi-consumer (thread-safe version)
1125    ///
1126    /// Returns a bi-consumer that only executes when a predicate is satisfied.
1127    ///
1128    /// # Type Parameters
1129    ///
1130    /// * `P` - The predicate type
1131    ///
1132    /// # Parameters
1133    ///
1134    /// * `predicate` - The condition to check. **Note: This parameter is passed
1135    ///   by value and will transfer ownership.** If you need to preserve the
1136    ///   original bi-predicate, clone it first (if it implements `Clone`).
1137    ///   Must be `Send + Sync`, can be:
1138    ///   - A closure: `|x: &T, y: &U| -> bool` (requires `Send + Sync`)
1139    ///   - A function pointer: `fn(&T, &U) -> bool`
1140    ///   - An `ArcBiPredicate<T, U>`
1141    ///   - Any type implementing `BiPredicate<T, U> + Send + Sync`
1142    ///
1143    /// # Returns
1144    ///
1145    /// Returns `ArcConditionalBiConsumer<T, U>`
1146    ///
1147    /// # Examples
1148    ///
1149    /// ```rust
1150    /// use prism3_function::{BiConsumer, ArcBiConsumer};
1151    /// use std::sync::{Arc, Mutex};
1152    ///
1153    /// let log = Arc::new(Mutex::new(Vec::new()));
1154    /// let l = log.clone();
1155    /// let consumer = ArcBiConsumer::new(move |x: &i32, y: &i32| {
1156    ///     l.lock().unwrap().push(*x + *y);
1157    /// });
1158    /// let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
1159    ///
1160    /// let conditional_clone = conditional.clone();
1161    ///
1162    /// let mut positive = 5;
1163    /// let mut m = conditional;
1164    /// m.accept(&positive, &3);
1165    /// assert_eq!(*log.lock().unwrap(), vec![8]);
1166    /// ```
1167    pub fn when<P>(self, predicate: P) -> ArcConditionalBiConsumer<T, U>
1168    where
1169        P: BiPredicate<T, U> + Send + Sync + 'static,
1170        T: Send + Sync,
1171        U: Send + Sync,
1172    {
1173        ArcConditionalBiConsumer {
1174            consumer: self,
1175            predicate: predicate.into_arc(),
1176        }
1177    }
1178}
1179
1180impl<T, U> BiConsumer<T, U> for ArcBiConsumer<T, U> {
1181    fn accept(&mut self, first: &T, second: &U) {
1182        (self.function.lock().unwrap())(first, second)
1183    }
1184
1185    fn into_box(self) -> BoxBiConsumer<T, U>
1186    where
1187        T: 'static,
1188        U: 'static,
1189    {
1190        let func = self.function;
1191        BoxBiConsumer::new(move |t, u| func.lock().unwrap()(t, u))
1192    }
1193
1194    fn into_rc(self) -> RcBiConsumer<T, U>
1195    where
1196        T: 'static,
1197        U: 'static,
1198    {
1199        let func = self.function;
1200        RcBiConsumer::new(move |t, u| func.lock().unwrap()(t, u))
1201    }
1202
1203    fn into_arc(self) -> ArcBiConsumer<T, U>
1204    where
1205        T: Send + 'static,
1206        U: Send + 'static,
1207    {
1208        self
1209    }
1210
1211    fn into_fn(self) -> impl FnMut(&T, &U)
1212    where
1213        T: 'static,
1214        U: 'static,
1215    {
1216        let func = self.function;
1217        move |t: &T, u: &U| {
1218            func.lock().unwrap()(t, u);
1219        }
1220    }
1221}
1222
1223impl<T, U> Clone for ArcBiConsumer<T, U> {
1224    /// Clones the ArcBiConsumer
1225    ///
1226    /// Creates a new ArcBiConsumer sharing the underlying function with
1227    /// the original instance.
1228    fn clone(&self) -> Self {
1229        Self {
1230            function: Arc::clone(&self.function),
1231            name: self.name.clone(),
1232        }
1233    }
1234}
1235
1236impl<T, U> fmt::Debug for ArcBiConsumer<T, U> {
1237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1238        f.debug_struct("ArcBiConsumer")
1239            .field("name", &self.name)
1240            .field("function", &"<function>")
1241            .finish()
1242    }
1243}
1244
1245impl<T, U> fmt::Display for ArcBiConsumer<T, U> {
1246    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1247        match &self.name {
1248            Some(name) => write!(f, "ArcBiConsumer({})", name),
1249            None => write!(f, "ArcBiConsumer"),
1250        }
1251    }
1252}
1253
1254// =======================================================================
1255// 5. ArcConditionalBiConsumer - Arc-based Conditional BiConsumer
1256// =======================================================================
1257
1258/// ArcConditionalBiConsumer struct
1259///
1260/// A thread-safe conditional bi-consumer that only executes when a predicate is
1261/// satisfied. Uses `ArcBiConsumer` and `ArcBiPredicate` for shared ownership across
1262/// threads.
1263///
1264/// This type is typically created by calling `ArcBiConsumer::when()` and is
1265/// designed to work with the `or_else()` method to create if-then-else logic.
1266///
1267/// # Features
1268///
1269/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
1270/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
1271/// - **Conditional Execution**: Only consumes when predicate returns `true`
1272/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
1273///
1274/// # Examples
1275///
1276/// ```rust
1277/// use prism3_function::{BiConsumer, ArcBiConsumer};
1278/// use std::sync::{Arc, Mutex};
1279///
1280/// let log = Arc::new(Mutex::new(Vec::new()));
1281/// let l = log.clone();
1282/// let conditional = ArcBiConsumer::new(move |x: &i32, y: &i32| {
1283///     l.lock().unwrap().push(*x + *y);
1284/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0);
1285///
1286/// let conditional_clone = conditional.clone();
1287///
1288/// let mut value = 5;
1289/// let mut m = conditional;
1290/// m.accept(&value, &3);
1291/// assert_eq!(*log.lock().unwrap(), vec![8]);
1292/// ```
1293///
1294/// # Author
1295///
1296/// Haixing Hu
1297pub struct ArcConditionalBiConsumer<T, U> {
1298    consumer: ArcBiConsumer<T, U>,
1299    predicate: ArcBiPredicate<T, U>,
1300}
1301
1302impl<T, U> BiConsumer<T, U> for ArcConditionalBiConsumer<T, U>
1303where
1304    T: Send + 'static,
1305    U: Send + 'static,
1306{
1307    fn accept(&mut self, first: &T, second: &U) {
1308        if self.predicate.test(first, second) {
1309            self.consumer.accept(first, second);
1310        }
1311    }
1312
1313    fn into_box(self) -> BoxBiConsumer<T, U>
1314    where
1315        T: 'static,
1316        U: 'static,
1317    {
1318        let pred = self.predicate;
1319        let mut consumer = self.consumer;
1320        BoxBiConsumer::new(move |t, u| {
1321            if pred.test(t, u) {
1322                consumer.accept(t, u);
1323            }
1324        })
1325    }
1326
1327    fn into_rc(self) -> RcBiConsumer<T, U>
1328    where
1329        T: 'static,
1330        U: 'static,
1331    {
1332        let pred = self.predicate.to_rc();
1333        let consumer = self.consumer.into_rc();
1334        let pred_fn = pred.to_fn();
1335        let mut consumer_fn = consumer;
1336        RcBiConsumer::new(move |t, u| {
1337            if pred_fn(t, u) {
1338                consumer_fn.accept(t, u);
1339            }
1340        })
1341    }
1342
1343    fn into_arc(self) -> ArcBiConsumer<T, U>
1344    where
1345        T: Send + 'static,
1346        U: Send + 'static,
1347    {
1348        let pred = self.predicate;
1349        let mut consumer = self.consumer;
1350        ArcBiConsumer::new(move |t, u| {
1351            if pred.test(t, u) {
1352                consumer.accept(t, u);
1353            }
1354        })
1355    }
1356
1357    fn into_fn(self) -> impl FnMut(&T, &U)
1358    where
1359        T: 'static,
1360        U: 'static,
1361    {
1362        let pred = self.predicate;
1363        let mut consumer = self.consumer;
1364        move |t: &T, u: &U| {
1365            if pred.test(t, u) {
1366                consumer.accept(t, u);
1367            }
1368        }
1369    }
1370}
1371
1372impl<T, U> ArcConditionalBiConsumer<T, U>
1373where
1374    T: Send + 'static,
1375    U: Send + 'static,
1376{
1377    /// Adds an else branch (thread-safe version)
1378    ///
1379    /// Executes the original consumer when the condition is satisfied, otherwise
1380    /// executes else_consumer.
1381    ///
1382    /// # Parameters
1383    ///
1384    /// * `else_consumer` - The consumer for the else branch. **Note: This parameter
1385    ///   is passed by value and will transfer ownership.** If you need to preserve
1386    ///   the original consumer, clone it first (if it implements `Clone`).
1387    ///   Must be `Send`, can be:
1388    ///   - A closure: `|x: &T, y: &U|` (must be `Send`)
1389    ///   - An `ArcBiConsumer<T, U>`
1390    ///   - A `BoxBiConsumer<T, U>`
1391    ///   - Any type implementing `BiConsumer<T, U> + Send`
1392    ///
1393    /// # Returns
1394    ///
1395    /// Returns the composed `ArcBiConsumer<T, U>`
1396    ///
1397    /// # Examples
1398    ///
1399    /// ## Using a closure (recommended)
1400    ///
1401    /// ```rust
1402    /// use prism3_function::{BiConsumer, ArcBiConsumer};
1403    /// use std::sync::{Arc, Mutex};
1404    ///
1405    /// let log = Arc::new(Mutex::new(Vec::new()));
1406    /// let l1 = log.clone();
1407    /// let l2 = log.clone();
1408    /// let mut consumer = ArcBiConsumer::new(move |x: &i32, y: &i32| {
1409    ///     l1.lock().unwrap().push(*x + *y);
1410    /// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0)
1411    ///   .or_else(move |x: &i32, y: &i32| {
1412    ///     l2.lock().unwrap().push(*x * *y);
1413    /// });
1414    ///
1415    /// consumer.accept(&5, &3);
1416    /// assert_eq!(*log.lock().unwrap(), vec![8]);
1417    ///
1418    /// consumer.accept(&-5, &3);
1419    /// assert_eq!(*log.lock().unwrap(), vec![8, -15]);
1420    /// ```
1421    pub fn or_else<C>(self, else_consumer: C) -> ArcBiConsumer<T, U>
1422    where
1423        C: BiConsumer<T, U> + Send + 'static,
1424        T: Send + Sync,
1425        U: Send + Sync,
1426    {
1427        let pred = self.predicate;
1428        let mut then_cons = self.consumer;
1429        let mut else_cons = else_consumer;
1430
1431        ArcBiConsumer::new(move |t: &T, u: &U| {
1432            if pred.test(t, u) {
1433                then_cons.accept(t, u);
1434            } else {
1435                else_cons.accept(t, u);
1436            }
1437        })
1438    }
1439}
1440
1441impl<T, U> Clone for ArcConditionalBiConsumer<T, U> {
1442    /// Clones the conditional consumer
1443    ///
1444    /// Creates a new instance that shares the underlying consumer and predicate
1445    /// with the original instance.
1446    fn clone(&self) -> Self {
1447        Self {
1448            consumer: self.consumer.clone(),
1449            predicate: self.predicate.clone(),
1450        }
1451    }
1452}
1453
1454// =======================================================================
1455// 6. RcBiConsumer - Single-Threaded Shared Ownership Implementation
1456// =======================================================================
1457
1458/// RcBiConsumer struct
1459///
1460/// A bi-consumer implementation based on `Rc<RefCell<dyn FnMut(&T, &U)>>`
1461/// for single-threaded shared ownership scenarios. This consumer provides
1462/// the benefits of shared ownership without the overhead of thread
1463/// safety.
1464///
1465/// # Features
1466///
1467/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
1468/// - **Single-Threaded**: Not thread-safe, cannot send across threads
1469/// - **Interior Mutability**: Uses `RefCell` for runtime borrow checking
1470/// - **No Lock Overhead**: More efficient than `ArcBiConsumer` for
1471///   single-threaded use
1472/// - **Non-Consuming API**: `and_then` borrows `&self`, original remains
1473///   usable
1474///
1475/// # Use Cases
1476///
1477/// Choose `RcBiConsumer` when:
1478/// - Need to share bi-consumer within a single thread
1479/// - Thread safety is not needed
1480/// - Performance matters (avoiding lock overhead)
1481/// - Single-threaded UI framework event handling
1482/// - Building complex single-threaded state machines
1483///
1484/// # Performance Considerations
1485///
1486/// `RcBiConsumer` performs better than `ArcBiConsumer` in single-threaded
1487/// scenarios:
1488/// - **Non-Atomic Counting**: clone/drop cheaper than `Arc`
1489/// - **No Lock Overhead**: `RefCell` uses runtime checking, no locks
1490/// - **Better Cache Locality**: No atomic operations means better CPU
1491///   cache behavior
1492///
1493/// But still has slight overhead compared to `BoxBiConsumer`:
1494/// - **Reference Counting**: Though non-atomic, still exists
1495/// - **Runtime Borrow Checking**: `RefCell` checks at runtime
1496///
1497/// # Safety
1498///
1499/// `RcBiConsumer` is not thread-safe and does not implement `Send` or
1500/// `Sync`. Attempting to send it to another thread will result in a
1501/// compile error. For thread-safe sharing, use `ArcBiConsumer` instead.
1502///
1503/// # Examples
1504///
1505/// ```rust
1506/// use prism3_function::{BiConsumer, RcBiConsumer};
1507/// use std::rc::Rc;
1508/// use std::cell::RefCell;
1509///
1510/// let log = Rc::new(RefCell::new(Vec::new()));
1511/// let l = log.clone();
1512/// let mut consumer = RcBiConsumer::new(move |x: &i32, y: &i32| {
1513///     l.borrow_mut().push(*x + *y);
1514/// });
1515/// let mut clone = consumer.clone();
1516///
1517/// consumer.accept(&5, &3);
1518/// assert_eq!(*log.borrow(), vec![8]);
1519/// ```
1520///
1521/// # Author
1522///
1523/// Haixing Hu
1524pub struct RcBiConsumer<T, U> {
1525    function: Rc<RefCell<BiConsumerFn<T, U>>>,
1526    name: Option<String>,
1527}
1528
1529impl<T, U> RcBiConsumer<T, U>
1530where
1531    T: 'static,
1532    U: 'static,
1533{
1534    /// Creates a new RcBiConsumer
1535    ///
1536    /// # Type Parameters
1537    ///
1538    /// * `F` - The closure type
1539    ///
1540    /// # Parameters
1541    ///
1542    /// * `f` - The closure to wrap
1543    ///
1544    /// # Returns
1545    ///
1546    /// Returns a new `RcBiConsumer<T, U>` instance
1547    ///
1548    /// # Examples
1549    ///
1550    /// ```rust
1551    /// use prism3_function::{BiConsumer, RcBiConsumer};
1552    /// use std::rc::Rc;
1553    /// use std::cell::RefCell;
1554    ///
1555    /// let log = Rc::new(RefCell::new(Vec::new()));
1556    /// let l = log.clone();
1557    /// let mut consumer = RcBiConsumer::new(move |x: &i32, y: &i32| {
1558    ///     l.borrow_mut().push(*x * 2 + *y);
1559    /// });
1560    /// consumer.accept(&5, &3);
1561    /// assert_eq!(*log.borrow(), vec![13]);
1562    /// ```
1563    pub fn new<F>(f: F) -> Self
1564    where
1565        F: FnMut(&T, &U) + 'static,
1566    {
1567        RcBiConsumer {
1568            function: Rc::new(RefCell::new(f)),
1569            name: None,
1570        }
1571    }
1572
1573    /// Creates a new RcBiConsumer with a name
1574    ///
1575    /// # Type Parameters
1576    ///
1577    /// * `F` - The closure type
1578    ///
1579    /// # Parameters
1580    ///
1581    /// * `name` - The name of the consumer
1582    /// * `f` - The closure to wrap
1583    ///
1584    /// # Returns
1585    ///
1586    /// Returns a new `RcBiConsumer<T, U>` instance with the specified name
1587    ///
1588    /// # Examples
1589    ///
1590    /// ```rust
1591    /// use prism3_function::{BiConsumer, RcBiConsumer};
1592    /// use std::rc::Rc;
1593    /// use std::cell::RefCell;
1594    ///
1595    /// let log = Rc::new(RefCell::new(Vec::new()));
1596    /// let l = log.clone();
1597    /// let mut consumer = RcBiConsumer::new_with_name("sum_logger", move |x: &i32, y: &i32| {
1598    ///     l.borrow_mut().push(*x + *y);
1599    /// });
1600    /// assert_eq!(consumer.name(), Some("sum_logger"));
1601    /// consumer.accept(&5, &3);
1602    /// assert_eq!(*log.borrow(), vec![8]);
1603    /// ```
1604    pub fn new_with_name<F>(name: &str, f: F) -> Self
1605    where
1606        F: FnMut(&T, &U) + 'static,
1607    {
1608        RcBiConsumer {
1609            function: Rc::new(RefCell::new(f)),
1610            name: Some(name.to_string()),
1611        }
1612    }
1613
1614    /// Gets the name of the consumer
1615    ///
1616    /// # Returns
1617    ///
1618    /// Returns the consumer's name, or `None` if not set
1619    pub fn name(&self) -> Option<&str> {
1620        self.name.as_deref()
1621    }
1622
1623    /// Sets the name of the consumer
1624    ///
1625    /// # Parameters
1626    ///
1627    /// * `name` - The name to set
1628    pub fn set_name(&mut self, name: impl Into<String>) {
1629        self.name = Some(name.into());
1630    }
1631
1632    /// Converts to a closure (without consuming self)
1633    ///
1634    /// Creates a new closure that calls the underlying function via Rc.
1635    ///
1636    /// # Returns
1637    ///
1638    /// Returns a closure implementing `FnMut(&T, &U)`
1639    ///
1640    /// # Examples
1641    ///
1642    /// ```rust
1643    /// use prism3_function::{BiConsumer, RcBiConsumer};
1644    /// use std::rc::Rc;
1645    /// use std::cell::RefCell;
1646    ///
1647    /// let log = Rc::new(RefCell::new(Vec::new()));
1648    /// let l = log.clone();
1649    /// let consumer = RcBiConsumer::new(move |x: &i32, y: &i32| {
1650    ///     l.borrow_mut().push(*x + *y);
1651    /// });
1652    ///
1653    /// let mut func = consumer.to_fn();
1654    /// func(&5, &3);
1655    /// assert_eq!(*log.borrow(), vec![8]);
1656    /// ```
1657    pub fn to_fn(&self) -> impl FnMut(&T, &U)
1658    where
1659        T: 'static,
1660        U: 'static,
1661    {
1662        let func = Rc::clone(&self.function);
1663        move |t: &T, u: &U| {
1664            func.borrow_mut()(t, u);
1665        }
1666    }
1667
1668    /// Chains another RcBiConsumer in sequence
1669    ///
1670    /// Returns a new consumer executing the current operation first, then
1671    /// the next operation. Borrows &self, does not consume the original
1672    /// consumer.
1673    ///
1674    /// # Parameters
1675    ///
1676    /// * `next` - The consumer to execute after the current operation
1677    ///
1678    /// # Returns
1679    ///
1680    /// Returns a new composed `RcBiConsumer<T, U>`
1681    ///
1682    /// # Examples
1683    ///
1684    /// ```rust
1685    /// use prism3_function::{BiConsumer, RcBiConsumer};
1686    /// use std::rc::Rc;
1687    /// use std::cell::RefCell;
1688    ///
1689    /// let log = Rc::new(RefCell::new(Vec::new()));
1690    /// let l1 = log.clone();
1691    /// let l2 = log.clone();
1692    /// let first = RcBiConsumer::new(move |x: &i32, y: &i32| {
1693    ///     l1.borrow_mut().push(*x + *y);
1694    /// });
1695    /// let second = RcBiConsumer::new(move |x: &i32, y: &i32| {
1696    ///     l2.borrow_mut().push(*x * *y);
1697    /// });
1698    ///
1699    /// let mut chained = first.and_then(&second);
1700    ///
1701    /// // first and second still usable after chaining
1702    /// chained.accept(&5, &3);
1703    /// assert_eq!(*log.borrow(), vec![8, 15]);
1704    /// ```
1705    pub fn and_then(&self, next: &RcBiConsumer<T, U>) -> RcBiConsumer<T, U> {
1706        let first = Rc::clone(&self.function);
1707        let second = Rc::clone(&next.function);
1708        RcBiConsumer {
1709            function: Rc::new(RefCell::new(move |t: &T, u: &U| {
1710                first.borrow_mut()(t, u);
1711                second.borrow_mut()(t, u);
1712            })),
1713            name: None,
1714        }
1715    }
1716
1717    /// Creates a conditional bi-consumer (single-threaded shared version)
1718    ///
1719    /// Returns a bi-consumer that only executes when a predicate is satisfied.
1720    ///
1721    /// # Type Parameters
1722    ///
1723    /// * `P` - The predicate type
1724    ///
1725    /// # Parameters
1726    ///
1727    /// * `predicate` - The condition to check. **Note: This parameter is passed
1728    ///   by value and will transfer ownership.** If you need to preserve the
1729    ///   original bi-predicate, clone it first (if it implements `Clone`). Can be:
1730    ///   - A closure: `|x: &T, y: &U| -> bool`
1731    ///   - A function pointer: `fn(&T, &U) -> bool`
1732    ///   - An `RcBiPredicate<T, U>`
1733    ///   - A `BoxBiPredicate<T, U>`
1734    ///   - Any type implementing `BiPredicate<T, U>`
1735    ///
1736    /// # Returns
1737    ///
1738    /// Returns `RcConditionalBiConsumer<T, U>`
1739    ///
1740    /// # Examples
1741    ///
1742    /// ```rust
1743    /// use prism3_function::{BiConsumer, RcBiConsumer};
1744    /// use std::rc::Rc;
1745    /// use std::cell::RefCell;
1746    ///
1747    /// let log = Rc::new(RefCell::new(Vec::new()));
1748    /// let l = log.clone();
1749    /// let consumer = RcBiConsumer::new(move |x: &i32, y: &i32| {
1750    ///     l.borrow_mut().push(*x + *y);
1751    /// });
1752    /// let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
1753    ///
1754    /// let conditional_clone = conditional.clone();
1755    ///
1756    /// let mut positive = 5;
1757    /// let mut m = conditional;
1758    /// m.accept(&positive, &3);
1759    /// assert_eq!(*log.borrow(), vec![8]);
1760    /// ```
1761    pub fn when<P>(self, predicate: P) -> RcConditionalBiConsumer<T, U>
1762    where
1763        P: BiPredicate<T, U> + 'static,
1764    {
1765        RcConditionalBiConsumer {
1766            consumer: self,
1767            predicate: predicate.into_rc(),
1768        }
1769    }
1770}
1771
1772impl<T, U> BiConsumer<T, U> for RcBiConsumer<T, U> {
1773    fn accept(&mut self, first: &T, second: &U) {
1774        (self.function.borrow_mut())(first, second)
1775    }
1776
1777    fn into_box(self) -> BoxBiConsumer<T, U>
1778    where
1779        T: 'static,
1780        U: 'static,
1781    {
1782        let func = self.function;
1783        BoxBiConsumer::new(move |t, u| func.borrow_mut()(t, u))
1784    }
1785
1786    fn into_rc(self) -> RcBiConsumer<T, U>
1787    where
1788        T: 'static,
1789        U: 'static,
1790    {
1791        self
1792    }
1793
1794    fn into_arc(self) -> ArcBiConsumer<T, U>
1795    where
1796        T: Send + 'static,
1797        U: Send + 'static,
1798    {
1799        panic!("Cannot convert RcBiConsumer to ArcBiConsumer (not Send)")
1800    }
1801
1802    fn into_fn(self) -> impl FnMut(&T, &U)
1803    where
1804        T: 'static,
1805        U: 'static,
1806    {
1807        let func = self.function;
1808        move |t: &T, u: &U| {
1809            func.borrow_mut()(t, u);
1810        }
1811    }
1812}
1813
1814impl<T, U> Clone for RcBiConsumer<T, U> {
1815    /// Clones the RcBiConsumer
1816    ///
1817    /// Creates a new RcBiConsumer sharing the underlying function with the
1818    /// original instance.
1819    fn clone(&self) -> Self {
1820        Self {
1821            function: Rc::clone(&self.function),
1822            name: self.name.clone(),
1823        }
1824    }
1825}
1826
1827impl<T, U> fmt::Debug for RcBiConsumer<T, U> {
1828    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1829        f.debug_struct("RcBiConsumer")
1830            .field("name", &self.name)
1831            .field("function", &"<function>")
1832            .finish()
1833    }
1834}
1835
1836impl<T, U> fmt::Display for RcBiConsumer<T, U> {
1837    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1838        match &self.name {
1839            Some(name) => write!(f, "RcBiConsumer({})", name),
1840            None => write!(f, "RcBiConsumer"),
1841        }
1842    }
1843}
1844
1845// =======================================================================
1846// 7. RcConditionalBiConsumer - Rc-based Conditional BiConsumer
1847// =======================================================================
1848
1849/// RcConditionalBiConsumer struct
1850///
1851/// A single-threaded conditional bi-consumer that only executes when a predicate is
1852/// satisfied. Uses `RcBiConsumer` and `RcBiPredicate` for shared ownership within a
1853/// single thread.
1854///
1855/// This type is typically created by calling `RcBiConsumer::when()` and is
1856/// designed to work with the `or_else()` method to create if-then-else logic.
1857///
1858/// # Features
1859///
1860/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
1861/// - **Single-Threaded**: Not thread-safe, cannot be sent across threads
1862/// - **Conditional Execution**: Only consumes when predicate returns `true`
1863/// - **No Lock Overhead**: More efficient than `ArcConditionalBiConsumer`
1864///
1865/// # Examples
1866///
1867/// ```rust
1868/// use prism3_function::{BiConsumer, RcBiConsumer};
1869/// use std::rc::Rc;
1870/// use std::cell::RefCell;
1871///
1872/// let log = Rc::new(RefCell::new(Vec::new()));
1873/// let l = log.clone();
1874/// let conditional = RcBiConsumer::new(move |x: &i32, y: &i32| {
1875///     l.borrow_mut().push(*x + *y);
1876/// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0);
1877///
1878/// let conditional_clone = conditional.clone();
1879///
1880/// let mut value = 5;
1881/// let mut m = conditional;
1882/// m.accept(&value, &3);
1883/// assert_eq!(*log.borrow(), vec![8]);
1884/// ```
1885///
1886/// # Author
1887///
1888/// Haixing Hu
1889pub struct RcConditionalBiConsumer<T, U> {
1890    consumer: RcBiConsumer<T, U>,
1891    predicate: RcBiPredicate<T, U>,
1892}
1893
1894impl<T, U> BiConsumer<T, U> for RcConditionalBiConsumer<T, U>
1895where
1896    T: 'static,
1897    U: 'static,
1898{
1899    fn accept(&mut self, first: &T, second: &U) {
1900        if self.predicate.test(first, second) {
1901            self.consumer.accept(first, second);
1902        }
1903    }
1904
1905    fn into_box(self) -> BoxBiConsumer<T, U> {
1906        let pred = self.predicate;
1907        let mut consumer = self.consumer;
1908        BoxBiConsumer::new(move |t, u| {
1909            if pred.test(t, u) {
1910                consumer.accept(t, u);
1911            }
1912        })
1913    }
1914
1915    fn into_rc(self) -> RcBiConsumer<T, U> {
1916        let pred = self.predicate;
1917        let mut consumer = self.consumer;
1918        RcBiConsumer::new(move |t, u| {
1919            if pred.test(t, u) {
1920                consumer.accept(t, u);
1921            }
1922        })
1923    }
1924
1925    fn into_arc(self) -> ArcBiConsumer<T, U>
1926    where
1927        T: Send + 'static,
1928        U: Send + 'static,
1929    {
1930        panic!("Cannot convert RcConditionalBiConsumer to ArcBiConsumer: not Send")
1931    }
1932
1933    fn into_fn(self) -> impl FnMut(&T, &U) {
1934        let pred = self.predicate;
1935        let mut consumer = self.consumer;
1936        move |t: &T, u: &U| {
1937            if pred.test(t, u) {
1938                consumer.accept(t, u);
1939            }
1940        }
1941    }
1942}
1943
1944impl<T, U> RcConditionalBiConsumer<T, U>
1945where
1946    T: 'static,
1947    U: 'static,
1948{
1949    /// Adds an else branch (single-threaded shared version)
1950    ///
1951    /// Executes the original consumer when the condition is satisfied, otherwise
1952    /// executes else_consumer.
1953    ///
1954    /// # Parameters
1955    ///
1956    /// * `else_consumer` - The consumer for the else branch. **Note: This parameter
1957    ///   is passed by value and will transfer ownership.** If you need to preserve
1958    ///   the original consumer, clone it first (if it implements `Clone`). Can be:
1959    ///   - A closure: `|x: &T, y: &U|`
1960    ///   - An `RcBiConsumer<T, U>`
1961    ///   - A `BoxBiConsumer<T, U>`
1962    ///   - Any type implementing `BiConsumer<T, U>`
1963    ///
1964    /// # Returns
1965    ///
1966    /// Returns the composed `RcBiConsumer<T, U>`
1967    ///
1968    /// # Examples
1969    ///
1970    /// ## Using a closure (recommended)
1971    ///
1972    /// ```rust
1973    /// use prism3_function::{BiConsumer, RcBiConsumer};
1974    /// use std::rc::Rc;
1975    /// use std::cell::RefCell;
1976    ///
1977    /// let log = Rc::new(RefCell::new(Vec::new()));
1978    /// let l1 = log.clone();
1979    /// let l2 = log.clone();
1980    /// let mut consumer = RcBiConsumer::new(move |x: &i32, y: &i32| {
1981    ///     l1.borrow_mut().push(*x + *y);
1982    /// }).when(|x: &i32, y: &i32| *x > 0 && *y > 0)
1983    ///   .or_else(move |x: &i32, y: &i32| {
1984    ///     l2.borrow_mut().push(*x * *y);
1985    /// });
1986    ///
1987    /// consumer.accept(&5, &3);
1988    /// assert_eq!(*log.borrow(), vec![8]);
1989    ///
1990    /// consumer.accept(&-5, &3);
1991    /// assert_eq!(*log.borrow(), vec![8, -15]);
1992    /// ```
1993    pub fn or_else<C>(self, else_consumer: C) -> RcBiConsumer<T, U>
1994    where
1995        C: BiConsumer<T, U> + 'static,
1996    {
1997        let pred = self.predicate;
1998        let mut then_cons = self.consumer;
1999        let mut else_cons = else_consumer;
2000
2001        RcBiConsumer::new(move |t: &T, u: &U| {
2002            if pred.test(t, u) {
2003                then_cons.accept(t, u);
2004            } else {
2005                else_cons.accept(t, u);
2006            }
2007        })
2008    }
2009}
2010
2011impl<T, U> Clone for RcConditionalBiConsumer<T, U> {
2012    /// Clones the conditional consumer
2013    ///
2014    /// Creates a new instance that shares the underlying consumer and predicate
2015    /// with the original instance.
2016    fn clone(&self) -> Self {
2017        Self {
2018            consumer: self.consumer.clone(),
2019            predicate: self.predicate.clone(),
2020        }
2021    }
2022}
2023
2024// =======================================================================
2025// 9. Implement BiConsumer trait for closures
2026// =======================================================================
2027
2028/// Implements BiConsumer for all FnMut(&T, &U)
2029impl<T, U, F> BiConsumer<T, U> for F
2030where
2031    F: FnMut(&T, &U),
2032{
2033    fn accept(&mut self, first: &T, second: &U) {
2034        self(first, second)
2035    }
2036
2037    fn into_box(self) -> BoxBiConsumer<T, U>
2038    where
2039        Self: Sized + 'static,
2040        T: 'static,
2041        U: 'static,
2042    {
2043        BoxBiConsumer::new(self)
2044    }
2045
2046    fn into_rc(self) -> RcBiConsumer<T, U>
2047    where
2048        Self: Sized + 'static,
2049        T: 'static,
2050        U: 'static,
2051    {
2052        RcBiConsumer::new(self)
2053    }
2054
2055    fn into_arc(self) -> ArcBiConsumer<T, U>
2056    where
2057        Self: Sized + Send + 'static,
2058        T: Send + 'static,
2059        U: Send + 'static,
2060    {
2061        ArcBiConsumer::new(self)
2062    }
2063
2064    fn into_fn(self) -> impl FnMut(&T, &U)
2065    where
2066        Self: Sized + 'static,
2067        T: 'static,
2068        U: 'static,
2069    {
2070        self
2071    }
2072}
2073
2074// =======================================================================
2075// 10. Provide extension methods for closures
2076// =======================================================================
2077
2078/// Extension trait providing bi-consumer composition methods for closures
2079///
2080/// Provides `and_then` and other composition methods for all closures
2081/// implementing `FnMut(&T, &U)`, enabling direct method chaining on
2082/// closures without explicit wrapper types.
2083///
2084/// # Design Rationale
2085///
2086/// This trait allows closures to be composed naturally using method
2087/// syntax, similar to iterator combinators. Composition methods consume
2088/// the closure and return `BoxBiConsumer<T, U>`, which can be further
2089/// chained.
2090///
2091/// # Features
2092///
2093/// - **Natural Syntax**: Chain operations directly on closures
2094/// - **Returns BoxBiConsumer**: Composition results are
2095///   `BoxBiConsumer<T, U>` for continued chaining
2096/// - **Zero Cost**: No overhead when composing closures
2097/// - **Automatic Implementation**: All `FnMut(&T, &U)` closures get
2098///   these methods automatically
2099///
2100/// # Examples
2101///
2102/// ```rust
2103/// use prism3_function::{BiConsumer, FnBiConsumerOps};
2104/// use std::sync::{Arc, Mutex};
2105///
2106/// let log = Arc::new(Mutex::new(Vec::new()));
2107/// let l1 = log.clone();
2108/// let l2 = log.clone();
2109/// let mut chained = (move |x: &i32, y: &i32| {
2110///     l1.lock().unwrap().push(*x + *y);
2111/// }).and_then(move |x: &i32, y: &i32| {
2112///     l2.lock().unwrap().push(*x * *y);
2113/// });
2114/// chained.accept(&5, &3);
2115/// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
2116/// ```
2117///
2118/// # Author
2119///
2120/// Haixing Hu
2121pub trait FnBiConsumerOps<T, U>: FnMut(&T, &U) + Sized {
2122    /// Chains another consumer in sequence
2123    ///
2124    /// Returns a new consumer executing the current operation first, then
2125    /// the next operation. Consumes the current closure and returns
2126    /// `BoxBiConsumer<T, U>`.
2127    ///
2128    /// # Type Parameters
2129    ///
2130    /// * `C` - The type of the next consumer
2131    ///
2132    /// # Parameters
2133    ///
2134    /// * `next` - The consumer to execute after the current operation. **Note:
2135    ///   This parameter is passed by value and will transfer ownership.** If you
2136    ///   need to preserve the original consumer, clone it first (if it implements
2137    ///   `Clone`). Can be:
2138    ///   - A closure: `|x: &T, y: &U|`
2139    ///   - A `BoxBiConsumer<T, U>`
2140    ///   - An `ArcBiConsumer<T, U>`
2141    ///   - An `RcBiConsumer<T, U>`
2142    ///   - Any type implementing `BiConsumer<T, U>`
2143    ///
2144    /// # Returns
2145    ///
2146    /// Returns the composed `BoxBiConsumer<T, U>`
2147    ///
2148    /// # Examples
2149    ///
2150    /// ```rust
2151    /// use prism3_function::{BiConsumer, FnBiConsumerOps};
2152    /// use std::sync::{Arc, Mutex};
2153    ///
2154    /// let log = Arc::new(Mutex::new(Vec::new()));
2155    /// let l1 = log.clone();
2156    /// let l2 = log.clone();
2157    /// let mut chained = (move |x: &i32, y: &i32| {
2158    ///     l1.lock().unwrap().push(*x + *y);
2159    /// }).and_then(move |x: &i32, y: &i32| {
2160    ///     l2.lock().unwrap().push(*x * *y);
2161    /// }).and_then(|x: &i32, y: &i32| println!("Result: {}, {}", x, y));
2162    ///
2163    /// chained.accept(&5, &3); // Prints: Result: 5, 3
2164    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
2165    /// ```
2166    fn and_then<C>(self, next: C) -> BoxBiConsumer<T, U>
2167    where
2168        Self: 'static,
2169        C: BiConsumer<T, U> + 'static,
2170        T: 'static,
2171        U: 'static,
2172    {
2173        let mut first = self;
2174        let mut second = next;
2175        BoxBiConsumer::new(move |t, u| {
2176            first(t, u);
2177            second.accept(t, u);
2178        })
2179    }
2180}
2181
2182/// Implements FnBiConsumerOps for all closure types
2183impl<T, U, F> FnBiConsumerOps<T, U> for F where F: FnMut(&T, &U) {}