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