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>);