Skip to main content

qubit_function/consumers/bi_consumer/
box_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 `BoxBiConsumer` public type.
12
13use super::{
14    BiConsumer,
15    BiConsumerFn,
16    BiPredicate,
17    BoxBiConsumerOnce,
18    BoxConditionalBiConsumer,
19    RcBiConsumer,
20    impl_box_consumer_methods,
21    impl_box_conversions,
22    impl_consumer_common_methods,
23    impl_consumer_debug_display,
24};
25
26// =======================================================================
27// 2. BoxBiConsumer - Single Ownership Implementation
28// =======================================================================
29
30/// BoxBiConsumer struct
31///
32/// A non-mutating bi-consumer implementation based on `Box<dyn Fn(&T, &U)>`
33/// for single ownership scenarios.
34///
35/// # Features
36///
37/// - **Single Ownership**: Not cloneable, ownership moves on use
38/// - **Zero Overhead**: No reference counting or locking
39/// - **Shared-reference API**: Invoked through `&self` and shared input
40///   references
41/// - **No Wrapper Interior Mutability**: No need for Mutex or RefCell in the
42///   wrapper
43///
44/// # Use Cases
45///
46/// Choose `BoxBiConsumer` when:
47/// - The non-mutating bi-consumer is used only once or in a linear flow
48/// - No need to share the consumer across contexts
49/// - Pure observation operations like logging
50///
51/// # Examples
52///
53/// ```rust
54/// use qubit_function::{BiConsumer, BoxBiConsumer};
55///
56/// let consumer = BoxBiConsumer::new(|x: &i32, y: &i32| {
57///     println!("Sum: {}", x + y);
58/// });
59/// consumer.accept(&5, &3);
60/// ```
61///
62pub struct BoxBiConsumer<T, U> {
63    pub(super) function: Box<BiConsumerFn<T, U>>,
64    pub(super) name: Option<String>,
65}
66
67impl<T, U> BoxBiConsumer<T, U> {
68    // Generates: new(), new_with_name(), name(), set_name(), noop()
69    impl_consumer_common_methods!(
70        BoxBiConsumer<T, U>,
71        (Fn(&T, &U) + 'static),
72        |f| Box::new(f)
73    );
74
75    // Generates: when() and and_then() methods that consume self
76    impl_box_consumer_methods!(
77        BoxBiConsumer<T, U>,
78        BoxConditionalBiConsumer,
79        BiConsumer
80    );
81}
82
83impl<T, U> BiConsumer<T, U> for BoxBiConsumer<T, U> {
84    fn accept(&self, first: &T, second: &U) {
85        (self.function)(first, second)
86    }
87
88    // Generates: into_box(), into_rc(), into_fn(), into_once()
89    impl_box_conversions!(
90        BoxBiConsumer<T, U>,
91        RcBiConsumer,
92        Fn(&T, &U),
93        BoxBiConsumerOnce
94    );
95}
96
97// Use macro to generate Debug and Display implementations
98impl_consumer_debug_display!(BoxBiConsumer<T, U>);