Skip to main content

qubit_function/consumers/
stateful_bi_consumer.rs

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