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}