Skip to main content

qubit_function/consumers/bi_consumer_once/
box_bi_consumer_once.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 `BoxBiConsumerOnce` public type.
12
13#![allow(unused_imports)]
14
15use super::*;
16
17// =======================================================================
18// 2. BoxBiConsumerOnce - Single Ownership Implementation
19// =======================================================================
20
21/// BoxBiConsumerOnce struct
22///
23/// A one-time bi-consumer implementation based on
24/// `Box<dyn FnOnce(&T, &U)>` for single ownership scenarios. This is the
25/// simplest one-time bi-consumer type for truly one-time use.
26///
27/// # Features
28///
29/// - **Single Ownership**: Not cloneable, ownership moves on use
30/// - **Zero Overhead**: No reference counting or locking
31/// - **One-Time Use**: Consumes self on first call
32/// - **Builder Pattern**: Method chaining consumes `self` naturally
33///
34/// # Use Cases
35///
36/// Choose `BoxBiConsumerOnce` when:
37/// - The bi-consumer is truly used only once
38/// - Building pipelines where ownership naturally flows
39/// - The consumer captures values that should be consumed
40/// - Performance is critical and sharing overhead is unacceptable
41///
42/// # Performance
43///
44/// `BoxBiConsumerOnce` has the best performance:
45/// - No reference counting overhead
46/// - No lock acquisition or runtime borrow checking
47/// - Direct function call through vtable
48/// - Minimal memory footprint (single pointer)
49///
50/// # Examples
51///
52/// ```rust
53/// use qubit_function::{BiConsumerOnce, BoxBiConsumerOnce};
54///
55/// let consumer = BoxBiConsumerOnce::new(|x: &i32, y: &i32| {
56///     println!("Sum: {}", x + y);
57/// });
58/// consumer.accept(&5, &3);
59/// ```
60///
61pub struct BoxBiConsumerOnce<T, U> {
62    pub(super) function: Box<BiConsumerOnceFn<T, U>>,
63    pub(super) name: Option<String>,
64}
65
66// All methods require T: 'static and U: 'static because
67// Box<dyn FnOnce(&T, &U)> requires it
68impl<T, U> BoxBiConsumerOnce<T, U> {
69    // Generates: new(), new_with_name(), name(), set_name(), noop()
70    impl_consumer_common_methods!(
71        BoxBiConsumerOnce<T, U>,
72        (FnOnce(&T, &U) + 'static),
73        |f| Box::new(f)
74    );
75
76    // Generates: when() and and_then() methods that consume self
77    impl_box_consumer_methods!(
78        BoxBiConsumerOnce<T, U>,
79        BoxConditionalBiConsumerOnce,
80        BiConsumerOnce
81    );
82}
83
84impl<T, U> BiConsumerOnce<T, U> for BoxBiConsumerOnce<T, U> {
85    fn accept(self, first: &T, second: &U) {
86        (self.function)(first, second)
87    }
88
89    impl_box_once_conversions!(
90        BoxBiConsumerOnce<T, U>,
91        BiConsumerOnce,
92        FnOnce(&T, &U)
93    );
94}
95
96// Use macro to generate Debug and Display implementations
97impl_consumer_debug_display!(BoxBiConsumerOnce<T, U>);
98
99// =======================================================================
100// 3. Implement BiConsumerOnce trait for closures
101// =======================================================================
102
103// Implement BiConsumerOnce for all FnOnce(&T, &U) using macro
104impl_closure_once_trait!(
105    BiConsumerOnce<T, U>,
106    accept,
107    BoxBiConsumerOnce,
108    FnOnce(first: &T, second: &U)
109);