Skip to main content

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