Skip to main content

qubit_function/consumers/stateful_bi_consumer/
box_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// qubit-style: allow explicit-imports
11//! Defines the `BoxStatefulBiConsumer` public type.
12
13use super::{
14    BiPredicate,
15    BoxBiConsumerOnce,
16    BoxConditionalStatefulBiConsumer,
17    RcStatefulBiConsumer,
18    StatefulBiConsumer,
19    impl_box_consumer_methods,
20    impl_box_conversions,
21    impl_consumer_common_methods,
22    impl_consumer_debug_display,
23};
24
25type BoxStatefulBiConsumerFn<T, U> = Box<dyn FnMut(&T, &U)>;
26
27// =======================================================================
28// 2. BoxStatefulBiConsumer - Single Ownership Implementation
29// =======================================================================
30
31/// BoxStatefulBiConsumer struct
32///
33/// A bi-consumer implementation based on `Box<dyn FnMut(&T, &U)>` for
34/// single ownership scenarios. This is the simplest and most efficient
35/// bi-consumer type when sharing is not required.
36///
37/// # Features
38///
39/// - **Single Ownership**: Not cloneable, ownership moves on use
40/// - **Zero Overhead**: No reference counting or locking
41/// - **Mutable State**: Can modify captured environment via `FnMut`
42/// - **Builder Pattern**: Method chaining consumes `self` naturally
43///
44/// # Use Cases
45///
46/// Choose `BoxStatefulBiConsumer` when:
47/// - The bi-consumer is used only once or in a linear flow
48/// - Building pipelines where ownership naturally flows
49/// - No need to share the consumer across contexts
50/// - Performance is critical and sharing overhead is unacceptable
51///
52/// # Performance
53///
54/// `BoxStatefulBiConsumer` has the best performance among the three bi-consumer
55/// types:
56/// - No reference counting overhead
57/// - No lock acquisition or runtime borrow checking
58/// - Direct function call through vtable
59/// - Minimal memory footprint (single pointer)
60///
61/// # Examples
62///
63/// ```rust
64/// use qubit_function::{BiConsumer, BoxStatefulBiConsumer, StatefulBiConsumer};
65/// use std::sync::{Arc, Mutex};
66///
67/// let log = Arc::new(Mutex::new(Vec::new()));
68/// let l = log.clone();
69/// let mut consumer = BoxStatefulBiConsumer::new(move |x: &i32, y: &i32| {
70///     l.lock().expect("mutex should not be poisoned").push(*x + *y);
71/// });
72/// consumer.accept(&5, &3);
73/// assert_eq!(*log.lock().expect("mutex should not be poisoned"), vec![8]);
74/// ```
75///
76pub struct BoxStatefulBiConsumer<T, U> {
77    pub(super) function: BoxStatefulBiConsumerFn<T, U>,
78    pub(super) name: Option<String>,
79}
80
81impl<T, U> BoxStatefulBiConsumer<T, U> {
82    // Generates: new(), new_with_name(), name(), set_name(), noop()
83    impl_consumer_common_methods!(
84        BoxStatefulBiConsumer<T, U>,
85        (FnMut(&T, &U) + 'static),
86        |f| Box::new(f)
87    );
88
89    // Generates: when() and and_then() methods that consume self
90    impl_box_consumer_methods!(
91        BoxStatefulBiConsumer<T, U>,
92        BoxConditionalStatefulBiConsumer,
93        StatefulBiConsumer
94    );
95}
96
97impl<T, U> StatefulBiConsumer<T, U> for BoxStatefulBiConsumer<T, U> {
98    fn accept(&mut self, first: &T, second: &U) {
99        (self.function)(first, second)
100    }
101
102    // Generates: into_box(), into_rc(), into_fn(), into_once()
103    impl_box_conversions!(
104        BoxStatefulBiConsumer<T, U>,
105        RcStatefulBiConsumer,
106        FnMut(&T, &U),
107        BoxBiConsumerOnce
108    );
109}
110
111// Use macro to generate Debug and Display implementations
112impl_consumer_debug_display!(BoxStatefulBiConsumer<T, U>);