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