Skip to main content

qubit_function/consumers/stateful_bi_consumer/
fn_stateful_bi_consumer_ops.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! Defines the `FnStatefulBiConsumerOps` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// =======================================================================
16// 6. Provide extension methods for closures
17// =======================================================================
18
19/// Extension trait providing bi-consumer composition methods for closures
20///
21/// Provides `and_then` and other composition methods for all closures
22/// implementing `FnMut(&T, &U)`, enabling direct method chaining on
23/// closures without explicit wrapper types.
24///
25/// # Design Rationale
26///
27/// This trait allows closures to be composed naturally using method
28/// syntax, similar to iterator combinators. Composition methods consume
29/// the closure and return `BoxStatefulBiConsumer<T, U>`, which can be further
30/// chained.
31///
32/// # Features
33///
34/// - **Natural Syntax**: Chain operations directly on closures
35/// - **Returns BoxStatefulBiConsumer**: Composition results are
36///   `BoxStatefulBiConsumer<T, U>` for continued chaining
37/// - **Zero Cost**: No overhead when composing closures
38/// - **Automatic Implementation**: All `FnMut(&T, &U)` closures get
39///   these methods automatically
40///
41/// # Examples
42///
43/// ```rust
44/// use qubit_function::{BiConsumer, FnStatefulBiConsumerOps, StatefulBiConsumer};
45/// use std::sync::{Arc, Mutex};
46///
47/// let log = Arc::new(Mutex::new(Vec::new()));
48/// let l1 = log.clone();
49/// let l2 = log.clone();
50/// let mut chained = (move |x: &i32, y: &i32| {
51///     l1.lock().unwrap().push(*x + *y);
52/// }).and_then(move |x: &i32, y: &i32| {
53///     l2.lock().unwrap().push(*x * *y);
54/// });
55/// chained.accept(&5, &3);
56/// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
57/// ```
58///
59/// # Author
60///
61/// Haixing Hu
62pub trait FnStatefulBiConsumerOps<T, U>: FnMut(&T, &U) + Sized {
63    /// Chains another consumer in sequence
64    ///
65    /// Returns a new consumer executing the current operation first, then
66    /// the next operation. Consumes the current closure and returns
67    /// `BoxStatefulBiConsumer<T, U>`.
68    ///
69    /// # Type Parameters
70    ///
71    /// * `C` - The type of the next consumer
72    ///
73    /// # Parameters
74    ///
75    /// * `next` - The consumer to execute after the current operation. **Note:
76    ///   This parameter is passed by value and will transfer ownership.** If you
77    ///   need to preserve the original consumer, clone it first (if it implements
78    ///   `Clone`). Can be:
79    ///   - A closure: `|x: &T, y: &U|`
80    ///   - A `BoxStatefulBiConsumer<T, U>`
81    ///   - An `ArcStatefulBiConsumer<T, U>`
82    ///   - An `RcStatefulBiConsumer<T, U>`
83    ///   - Any type implementing `BiConsumer<T, U>`
84    ///
85    /// # Returns
86    ///
87    /// Returns the composed `BoxStatefulBiConsumer<T, U>`
88    ///
89    /// # Examples
90    ///
91    /// ```rust
92    /// use qubit_function::{BiConsumer, FnStatefulBiConsumerOps, StatefulBiConsumer};
93    /// use std::sync::{Arc, Mutex};
94    ///
95    /// let log = Arc::new(Mutex::new(Vec::new()));
96    /// let l1 = log.clone();
97    /// let l2 = log.clone();
98    /// let mut chained = (move |x: &i32, y: &i32| {
99    ///     l1.lock().unwrap().push(*x + *y);
100    /// }).and_then(move |x: &i32, y: &i32| {
101    ///     l2.lock().unwrap().push(*x * *y);
102    /// }).and_then(|x: &i32, y: &i32| println!("Result: {}, {}", x, y));
103    ///
104    /// chained.accept(&5, &3); // Prints: Result: 5, 3
105    /// assert_eq!(*log.lock().unwrap(), vec![8, 15]);
106    /// ```
107    fn and_then<C>(self, next: C) -> BoxStatefulBiConsumer<T, U>
108    where
109        Self: 'static,
110        C: StatefulBiConsumer<T, U> + 'static,
111        T: 'static,
112        U: 'static,
113    {
114        let mut first = self;
115        let mut second = next;
116        BoxStatefulBiConsumer::new(move |t, u| {
117            first(t, u);
118            second.accept(t, u);
119        })
120    }
121}
122
123/// Implements FnStatefulBiConsumerOps for all closure types
124impl<T, U, F> FnStatefulBiConsumerOps<T, U> for F where F: FnMut(&T, &U) {}