Skip to main content

qubit_function/consumers/
stateful_bi_consumer.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # BiConsumer Types
10//!
11//! Provides bi-consumer interface implementations for operations accepting
12//! two input parameters without returning a result.
13//!
14//! It is similar to the `FnMut(&T, &U)` trait in the standard library.
15//!
16//! This module provides a unified `BiConsumer` trait and three concrete
17//! implementations based on different ownership models:
18//!
19//! - **`BoxStatefulBiConsumer<T, U>`**: Box-based single ownership for one-time use
20//! - **`ArcStatefulBiConsumer<T, U>`**: Arc<Mutex<>>-based thread-safe shared
21//!   ownership
22//! - **`RcStatefulBiConsumer<T, U>`**: Rc<RefCell<>>-based single-threaded shared
23//!   ownership
24//!
25//! # Design Philosophy
26//!
27//! BiConsumer uses `FnMut(&T, &U)` semantics: can modify its own state but
28//! does NOT modify input values.
29//!
30//! Suitable for statistics, accumulation, and event processing scenarios
31//! involving two parameters.
32//!
33//! # Author
34//!
35//! Haixing Hu
36use std::cell::RefCell;
37use std::rc::Rc;
38use std::sync::Arc;
39
40use parking_lot::Mutex;
41
42use crate::consumers::{
43    bi_consumer_once::BoxBiConsumerOnce,
44    macros::{
45        impl_box_conditional_consumer,
46        impl_box_consumer_methods,
47        impl_conditional_consumer_clone,
48        impl_conditional_consumer_conversions,
49        impl_conditional_consumer_debug_display,
50        impl_consumer_clone,
51        impl_consumer_common_methods,
52        impl_consumer_debug_display,
53        impl_shared_conditional_consumer,
54        impl_shared_consumer_methods,
55    },
56};
57use crate::macros::{
58    impl_arc_conversions,
59    impl_box_conversions,
60    impl_closure_trait,
61    impl_rc_conversions,
62};
63use crate::predicates::bi_predicate::{
64    ArcBiPredicate,
65    BiPredicate,
66    BoxBiPredicate,
67    RcBiPredicate,
68};
69
70mod box_stateful_bi_consumer;
71pub use box_stateful_bi_consumer::BoxStatefulBiConsumer;
72mod rc_stateful_bi_consumer;
73pub use rc_stateful_bi_consumer::RcStatefulBiConsumer;
74mod arc_stateful_bi_consumer;
75pub use arc_stateful_bi_consumer::ArcStatefulBiConsumer;
76mod fn_stateful_bi_consumer_ops;
77pub use fn_stateful_bi_consumer_ops::FnStatefulBiConsumerOps;
78mod box_conditional_stateful_bi_consumer;
79pub use box_conditional_stateful_bi_consumer::BoxConditionalStatefulBiConsumer;
80mod arc_conditional_stateful_bi_consumer;
81pub use arc_conditional_stateful_bi_consumer::ArcConditionalStatefulBiConsumer;
82mod rc_conditional_stateful_bi_consumer;
83pub use rc_conditional_stateful_bi_consumer::RcConditionalStatefulBiConsumer;
84
85// =======================================================================
86// 1. BiConsumer Trait - Unified BiConsumer Interface
87// =======================================================================
88
89/// BiConsumer trait - Unified bi-consumer interface
90///
91/// Defines core behavior for all bi-consumer types. Similar to Java's
92/// `BiConsumer<T, U>` interface, performs operations accepting two values
93/// but returning no result (side effects only).
94///
95/// It is similar to the `FnMut(&T, &U)` trait in the standard library.
96///
97/// BiConsumer can modify its own state (e.g., accumulate, count) but
98/// should NOT modify the consumed values themselves.
99///
100/// # Automatic Implementations
101///
102/// - All closures implementing `FnMut(&T, &U)`
103/// - `BoxStatefulBiConsumer<T, U>`, `ArcStatefulBiConsumer<T, U>`, `RcStatefulBiConsumer<T, U>`
104///
105/// # Features
106///
107/// - **Unified Interface**: All bi-consumer types share the same `accept`
108///   method signature
109/// - **Automatic Implementation**: Closures automatically implement this
110///   trait with zero overhead
111/// - **Type Conversions**: Easy conversion between ownership models
112/// - **Generic Programming**: Write functions accepting any bi-consumer
113///   type
114///
115/// # Examples
116///
117/// ```rust
118/// use qubit_function::{BiConsumer, BoxStatefulBiConsumer, StatefulBiConsumer};
119/// use std::cell::RefCell;
120/// use std::rc::Rc;
121///
122/// fn apply_bi_consumer<C: StatefulBiConsumer<i32, i32>>(
123///     consumer: &mut C,
124///     a: &i32,
125///     b: &i32
126/// ) {
127///     consumer.accept(a, b);
128/// }
129///
130/// // Works with any bi-consumer type
131/// let log = Rc::new(RefCell::new(Vec::new()));
132/// let l = log.clone();
133/// let mut box_con = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
134///     l.borrow_mut().push(*x + *y);
135/// });
136/// apply_bi_consumer(&mut box_con, &5, &3);
137/// assert_eq!(*log.borrow(), vec![8]);
138/// ```
139///
140/// # Author
141///
142/// Haixing Hu
143pub trait StatefulBiConsumer<T, U> {
144    /// Performs the consumption operation
145    ///
146    /// Executes an operation on the given two references. The operation
147    /// typically reads input values or produces side effects, but does not
148    /// modify the input values themselves. Can modify the consumer's own
149    /// state.
150    ///
151    /// # Parameters
152    ///
153    /// * `first` - Reference to the first value to consume
154    /// * `second` - Reference to the second value to consume
155    ///
156    /// # Examples
157    ///
158    /// ```rust
159    /// use qubit_function::{BiConsumer, BoxStatefulBiConsumer, StatefulBiConsumer};
160    /// use std::sync::{Arc, Mutex};
161    ///
162    /// let log = Arc::new(Mutex::new(Vec::new()));
163    /// let l = log.clone();
164    /// let mut consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
165    ///     l.lock().unwrap().push(*x + *y);
166    /// });
167    /// consumer.accept(&5, &3);
168    /// assert_eq!(*log.lock().unwrap(), vec![8]);
169    /// ```
170    fn accept(&mut self, first: &T, second: &U);
171
172    /// Converts to BoxStatefulBiConsumer
173    ///
174    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
175    /// calling this method.
176    ///
177    /// Converts the current bi-consumer to `BoxStatefulBiConsumer<T, U>`.
178    ///
179    /// # Ownership
180    ///
181    /// This method **consumes** the consumer (takes ownership of `self`).
182    /// After calling, the original consumer is no longer available.
183    ///
184    /// **Tip**: For cloneable consumers ([`ArcStatefulBiConsumer`],
185    /// [`RcStatefulBiConsumer`]), call `.clone()` first if you need to keep the
186    /// original.
187    ///
188    /// # Returns
189    ///
190    /// Returns the wrapped `BoxStatefulBiConsumer<T, U>`
191    ///
192    /// # Examples
193    ///
194    /// ```rust
195    /// use qubit_function::{BiConsumer, StatefulBiConsumer};
196    /// use std::sync::{Arc, Mutex};
197    ///
198    /// let log = Arc::new(Mutex::new(Vec::new()));
199    /// let l = log.clone();
200    /// let closure = move |x: &i32, y: &i32| {
201    ///     l.lock().unwrap().push(*x + *y);
202    /// };
203    /// let mut box_consumer = StatefulBiConsumer::into_box(closure);
204    /// box_consumer.accept(&5, &3);
205    /// assert_eq!(*log.lock().unwrap(), vec![8]);
206    /// ```
207    fn into_box(self) -> BoxStatefulBiConsumer<T, U>
208    where
209        Self: Sized + 'static,
210    {
211        let mut consumer = self;
212        BoxStatefulBiConsumer::new(move |t, u| consumer.accept(t, u))
213    }
214
215    /// Converts to RcStatefulBiConsumer
216    ///
217    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
218    /// calling this method.
219    ///
220    /// # Returns
221    ///
222    /// Returns the wrapped `RcStatefulBiConsumer<T, U>`
223    fn into_rc(self) -> RcStatefulBiConsumer<T, U>
224    where
225        Self: Sized + 'static,
226    {
227        let mut consumer = self;
228        RcStatefulBiConsumer::new(move |t, u| consumer.accept(t, u))
229    }
230
231    /// Converts to ArcStatefulBiConsumer
232    ///
233    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
234    /// calling this method.
235    ///
236    /// # Returns
237    ///
238    /// Returns the wrapped `ArcStatefulBiConsumer<T, U>`
239    fn into_arc(self) -> ArcStatefulBiConsumer<T, U>
240    where
241        Self: Sized + Send + 'static,
242    {
243        let mut consumer = self;
244        ArcStatefulBiConsumer::new(move |t, u| consumer.accept(t, u))
245    }
246
247    /// Converts bi-consumer to a closure
248    ///
249    /// **⚠️ Consumes `self`**: Original consumer becomes unavailable after
250    /// calling this method.
251    ///
252    /// Converts the bi-consumer to a closure usable with standard library
253    /// methods requiring `FnMut`.
254    ///
255    /// # Returns
256    ///
257    /// Returns a closure implementing `FnMut(&T, &U)`
258    ///
259    /// # Examples
260    ///
261    /// ```rust
262    /// use qubit_function::{BiConsumer, ArcStatefulBiConsumer, StatefulBiConsumer};
263    /// use std::sync::{Arc, Mutex};
264    ///
265    /// let log = Arc::new(Mutex::new(Vec::new()));
266    /// let l = log.clone();
267    /// let mut consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
268    ///     l.lock().unwrap().push(*x + *y);
269    /// });
270    /// let mut func = consumer.into_fn();
271    /// func(&5, &3);
272    /// assert_eq!(*log.lock().unwrap(), vec![8]);
273    /// ```
274    fn into_fn(self) -> impl FnMut(&T, &U)
275    where
276        Self: Sized + 'static,
277    {
278        let mut consumer = self;
279        move |t, u| consumer.accept(t, u)
280    }
281
282    /// Convert to BiConsumerOnce
283    ///
284    /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
285    ///
286    /// Converts a reusable stateful bi-consumer to a one-time consumer that consumes itself on use.
287    /// This enables passing `StatefulBiConsumer` to functions that require `BiConsumerOnce`.
288    ///
289    /// # Returns
290    ///
291    /// Returns a `BoxBiConsumerOnce<T, U>`
292    fn into_once(self) -> BoxBiConsumerOnce<T, U>
293    where
294        Self: Sized + 'static,
295    {
296        BoxBiConsumerOnce::new(move |t, u| {
297            let mut consumer = self;
298            consumer.accept(t, u);
299        })
300    }
301
302    /// Converts to BoxStatefulBiConsumer (non-consuming)
303    ///
304    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
305    ///
306    /// Converts the current bi-consumer to `BoxStatefulBiConsumer<T, U>` by cloning
307    /// it first.
308    ///
309    /// # Ownership
310    ///
311    /// This method does **not consume** the consumer. It clones the consumer
312    /// and then converts the clone to `BoxStatefulBiConsumer<T, U>`. The original
313    /// consumer remains available after calling this method.
314    ///
315    /// # Returns
316    ///
317    /// Returns the wrapped `BoxStatefulBiConsumer<T, U>` from the clone
318    ///
319    /// # Examples
320    ///
321    /// ```rust
322    /// use qubit_function::{BiConsumer, ArcStatefulBiConsumer, StatefulBiConsumer};
323    /// use std::sync::{Arc, Mutex};
324    ///
325    /// let log = Arc::new(Mutex::new(Vec::new()));
326    /// let l = log.clone();
327    /// let mut consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
328    ///     l.lock().unwrap().push(*x + *y);
329    /// });
330    /// let mut box_consumer = consumer.to_box();
331    /// box_consumer.accept(&5, &3);
332    /// assert_eq!(*log.lock().unwrap(), vec![8]);
333    /// // Original consumer still usable
334    /// consumer.accept(&2, &1);
335    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
336    /// ```
337    fn to_box(&self) -> BoxStatefulBiConsumer<T, U>
338    where
339        Self: Sized + Clone + 'static,
340    {
341        self.clone().into_box()
342    }
343
344    /// Converts to RcStatefulBiConsumer (non-consuming)
345    ///
346    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
347    ///
348    /// Converts the current bi-consumer to `RcStatefulBiConsumer<T, U>` by cloning
349    /// it first.
350    ///
351    /// # Ownership
352    ///
353    /// This method does **not consume** the consumer. It clones the consumer
354    /// and then converts the clone to `RcStatefulBiConsumer<T, U>`. The original
355    /// consumer remains available after calling this method.
356    ///
357    /// # Returns
358    ///
359    /// Returns the wrapped `RcStatefulBiConsumer<T, U>` from the clone
360    ///
361    /// # Examples
362    ///
363    /// ```rust
364    /// use qubit_function::{BiConsumer, ArcStatefulBiConsumer, StatefulBiConsumer};
365    /// use std::sync::{Arc, Mutex};
366    ///
367    /// let log = Arc::new(Mutex::new(Vec::new()));
368    /// let l = log.clone();
369    /// let mut consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
370    ///     l.lock().unwrap().push(*x + *y);
371    /// });
372    /// let mut rc_consumer = consumer.to_rc();
373    /// rc_consumer.accept(&5, &3);
374    /// assert_eq!(*log.lock().unwrap(), vec![8]);
375    /// // Original consumer still usable
376    /// consumer.accept(&2, &1);
377    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
378    /// ```
379    fn to_rc(&self) -> RcStatefulBiConsumer<T, U>
380    where
381        Self: Sized + Clone + 'static,
382    {
383        self.clone().into_rc()
384    }
385
386    /// Converts to ArcStatefulBiConsumer (non-consuming)
387    ///
388    /// **⚠️ Requires Clone + Send**: Original consumer must implement Clone +
389    /// Send.
390    ///
391    /// Converts the current bi-consumer to `ArcStatefulBiConsumer<T, U>` by cloning
392    /// it first.
393    ///
394    /// # Ownership
395    ///
396    /// This method does **not consume** the consumer. It clones the consumer
397    /// and then converts the clone to `ArcStatefulBiConsumer<T, U>`. The original
398    /// consumer remains available after calling this method.
399    ///
400    /// # Returns
401    ///
402    /// Returns the wrapped `ArcStatefulBiConsumer<T, U>` from the clone
403    ///
404    /// # Examples
405    ///
406    /// ```rust
407    /// use qubit_function::{BiConsumer, ArcStatefulBiConsumer, StatefulBiConsumer};
408    /// use std::sync::{Arc, Mutex};
409    ///
410    /// let log = Arc::new(Mutex::new(Vec::new()));
411    /// let l = log.clone();
412    /// let mut consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
413    ///     l.lock().unwrap().push(*x + *y);
414    /// });
415    /// let mut arc_consumer = consumer.to_arc();
416    /// arc_consumer.accept(&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_arc(&self) -> ArcStatefulBiConsumer<T, U>
423    where
424        Self: Sized + Clone + Send + 'static,
425    {
426        self.clone().into_arc()
427    }
428
429    /// Converts to closure (non-consuming)
430    ///
431    /// **⚠️ Requires Clone**: Original consumer must implement Clone.
432    ///
433    /// Converts the consumer to a closure that can be used directly in
434    /// standard library functions requiring `FnMut`.
435    ///
436    /// # Ownership
437    ///
438    /// This method does **not consume** the consumer. It clones the consumer
439    /// and then converts the clone to a closure. The original consumer
440    /// remains available after calling this method.
441    ///
442    /// # Returns
443    ///
444    /// Returns a closure implementing `FnMut(&T, &U)` from the clone
445    ///
446    /// # Examples
447    ///
448    /// ```rust
449    /// use qubit_function::{BiConsumer, ArcStatefulBiConsumer, StatefulBiConsumer};
450    /// use std::sync::{Arc, Mutex};
451    ///
452    /// let log = Arc::new(Mutex::new(Vec::new()));
453    /// let l = log.clone();
454    /// let mut consumer = ArcStatefulBiConsumer::new(move |x: &i32, y: &i32| {
455    ///     l.lock().unwrap().push(*x + *y);
456    /// });
457    /// {
458    ///     let mut func = consumer.to_fn();
459    ///     func(&5, &3);
460    ///     assert_eq!(*log.lock().unwrap(), vec![8]);
461    /// }
462    /// // Original consumer still usable
463    /// consumer.accept(&2, &1);
464    /// assert_eq!(*log.lock().unwrap(), vec![8, 3]);
465    /// ```
466    fn to_fn(&self) -> impl FnMut(&T, &U)
467    where
468        Self: Sized + Clone + 'static,
469    {
470        self.clone().into_fn()
471    }
472
473    /// Convert to BiConsumerOnce without consuming self
474    ///
475    /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
476    /// Clones the current consumer and converts the clone to a one-time consumer.
477    ///
478    /// # Returns
479    ///
480    /// Returns a `BoxBiConsumerOnce<T, U>`
481    fn to_once(&self) -> BoxBiConsumerOnce<T, U>
482    where
483        Self: Clone + 'static,
484    {
485        self.clone().into_once()
486    }
487}