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