prism3_function/
bi_consumer.rs

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