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