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