Skip to main content

qubit_function/consumers/bi_consumer/
box_conditional_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 `BoxConditionalBiConsumer` public type.
12
13#![allow(unused_imports)]
14
15use super::*;
16
17// =======================================================================
18// 7. BoxConditionalBiConsumer - Box-based Conditional BiConsumer
19// =======================================================================
20
21/// BoxConditionalBiConsumer struct
22///
23/// A conditional non-mutating bi-consumer that only executes when a predicate is satisfied.
24/// Uses `BoxBiConsumer` and `BoxBiPredicate` for single ownership semantics.
25///
26/// This type is typically created by calling `BoxBiConsumer::when()` and is
27/// designed to work with the `or_else()` method to create if-then-else logic.
28///
29/// # Features
30///
31/// - **Single Ownership**: Not cloneable, consumes `self` on use
32/// - **Conditional Execution**: Only consumes when predicate returns `true`
33/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
34/// - **Implements BiConsumer**: Can be used anywhere a `BiConsumer` is expected
35/// - **Non-mutating**: Neither modifies itself nor input values
36///
37/// # Examples
38///
39/// ## Basic Conditional Execution
40///
41/// ```rust
42/// use qubit_function::{BiConsumer, BoxBiConsumer};
43///
44/// let consumer = BoxBiConsumer::new(|x: &i32, y: &i32| {
45///     println!("Both positive: {} + {} = {}", x, y, x + y);
46/// });
47/// let conditional = consumer.when(|x: &i32, y: &i32| *x > 0 && *y > 0);
48///
49/// conditional.accept(&5, &3);  // Prints: Both positive: 5 + 3 = 8
50/// conditional.accept(&-5, &3); // Does nothing
51/// ```
52///
53/// ## With or_else Branch
54///
55/// ```rust
56/// use qubit_function::{BiConsumer, BoxBiConsumer};
57///
58/// let consumer = BoxBiConsumer::new(|x: &i32, y: &i32| {
59///     println!("Both positive: {} + {} = {}", x, y, x + y);
60/// })
61/// .when(|x: &i32, y: &i32| *x > 0 && *y > 0)
62/// .or_else(|x: &i32, y: &i32| {
63///     println!("Not both positive: {} and {}", x, y);
64/// });
65///
66/// consumer.accept(&5, &3);  // Prints: Both positive: 5 + 3 = 8
67/// consumer.accept(&-5, &3); // Prints: Not both positive: -5 and 3
68/// ```
69///
70pub struct BoxConditionalBiConsumer<T, U> {
71    pub(super) consumer: BoxBiConsumer<T, U>,
72    pub(super) predicate: BoxBiPredicate<T, U>,
73}
74
75// Use macro to generate conditional bi-consumer implementations
76impl_box_conditional_consumer!(
77    BoxConditionalBiConsumer<T, U>,
78    BoxBiConsumer,
79    BiConsumer
80);
81
82// Hand-written BiConsumer trait implementation
83impl<T, U> BiConsumer<T, U> for BoxConditionalBiConsumer<T, U> {
84    fn accept(&self, first: &T, second: &U) {
85        if self.predicate.test(first, second) {
86            self.consumer.accept(first, second);
87        }
88    }
89
90    // Generates: into_box(), into_rc(), into_fn()
91    impl_conditional_consumer_conversions!(
92        BoxBiConsumer<T, U>,
93        RcBiConsumer,
94        Fn
95    );
96}
97
98// Use macro to generate Debug and Display implementations
99impl_conditional_consumer_debug_display!(BoxConditionalBiConsumer<T, U>);