Skip to main content

qubit_function/consumers/bi_consumer/
fn_bi_consumer_ops.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 `FnBiConsumerOps` public type.
12
13#![allow(unused_imports)]
14
15use super::*;
16
17// =======================================================================
18// 6. Provide extension methods for closures
19// =======================================================================
20
21/// Extension trait providing non-mutating bi-consumer composition methods for
22/// closures
23///
24/// Provides `and_then` and other composition methods for all closures
25/// implementing `Fn(&T, &U)`, enabling direct method chaining on closures
26/// without explicit wrapper types.
27///
28/// # Features
29///
30/// - **Natural Syntax**: Chain operations directly on closures
31/// - **Returns BoxBiConsumer**: Composition results can be
32///   further chained
33/// - **Zero Cost**: No overhead when composing closures
34/// - **Automatic Implementation**: All `Fn(&T, &U)` closures get these
35///   methods automatically
36///
37/// # Examples
38///
39/// ```rust
40/// use qubit_function::{BiConsumer, FnBiConsumerOps};
41///
42/// let chained = (|x: &i32, y: &i32| {
43///     println!("First: {}, {}", x, y);
44/// }).and_then(|x: &i32, y: &i32| {
45///     println!("Second: sum = {}", x + y);
46/// });
47/// chained.accept(&5, &3);
48/// ```
49///
50pub trait FnBiConsumerOps<T, U>: Fn(&T, &U) + Sized {
51    /// Chains another non-mutating bi-consumer in sequence
52    ///
53    /// Returns a new consumer executing the current operation first, then
54    /// the next operation. Consumes the current closure and returns
55    /// `BoxBiConsumer<T, U>`.
56    ///
57    /// # Type Parameters
58    ///
59    /// * `C` - The type of the next consumer
60    ///
61    /// # Parameters
62    ///
63    /// * `next` - The consumer to execute after the current operation
64    ///
65    /// # Returns
66    ///
67    /// Returns the composed `BoxBiConsumer<T, U>`
68    ///
69    /// # Examples
70    ///
71    /// ```rust
72    /// use qubit_function::{BiConsumer, FnBiConsumerOps};
73    ///
74    /// let chained = (|x: &i32, y: &i32| {
75    ///     println!("First: {}, {}", x, y);
76    /// }).and_then(|x: &i32, y: &i32| {
77    ///     println!("Second: sum = {}", x + y);
78    /// }).and_then(|x: &i32, y: &i32| {
79    ///     println!("Third: product = {}", x * y);
80    /// });
81    ///
82    /// chained.accept(&5, &3);
83    /// ```
84    fn and_then<C>(self, next: C) -> BoxBiConsumer<T, U>
85    where
86        Self: 'static,
87        C: BiConsumer<T, U> + 'static,
88        T: 'static,
89        U: 'static,
90    {
91        let first = self;
92        let second = next;
93        BoxBiConsumer::new(move |t, u| {
94            first(t, u);
95            second.accept(t, u);
96        })
97    }
98}
99
100/// Implements FnBiConsumerOps for all closure types
101impl<T, U, F> FnBiConsumerOps<T, U> for F where F: Fn(&T, &U) {}