qubit_function/consumers/stateful_consumer/fn_stateful_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 `FnStatefulConsumerOps` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// ============================================================================
16// 6. Extension methods for closures
17// ============================================================================
18
19/// Extension trait providing consumer composition methods for closures
20///
21/// Provides `and_then` and other composition methods for all closures
22/// implementing `FnMut(&T)`, allowing direct method chaining on closures
23/// without explicit wrapper types.
24///
25/// # Design Philosophy
26///
27/// This trait allows closures to be naturally composed using method syntax,
28/// similar to iterator combinators. Composition methods consume the closure and
29/// return `BoxStatefulConsumer<T>`, which can continue chaining.
30///
31/// # Features
32///
33/// - **Natural Syntax**: Direct method chaining on closures
34/// - **Returns BoxStatefulConsumer**: Composition results in `BoxStatefulConsumer<T>`, can
35/// continue chaining
36/// - **Zero Cost**: No overhead when composing closures
37/// - **Automatic Implementation**: All `FnMut(&T)` closures automatically get
38/// these methods
39///
40/// # Examples
41///
42/// ```rust
43/// use qubit_function::{Consumer, StatefulConsumer, FnStatefulConsumerOps};
44/// use std::sync::{Arc, Mutex};
45///
46/// let log = Arc::new(Mutex::new(Vec::new()));
47/// let l1 = log.clone();
48/// let l2 = log.clone();
49/// let mut chained = (move |x: &i32| {
50/// l1.lock().unwrap().push(*x * 2);
51/// }).and_then(move |x: &i32| {
52/// l2.lock().unwrap().push(*x + 10);
53/// });
54/// chained.accept(&5);
55/// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
56/// // (5 * 2), (5 + 10)
57/// ```
58///
59/// # Author
60///
61/// Haixing Hu
62pub trait FnStatefulConsumerOps<T>: FnMut(&T) + Sized {
63 /// Sequentially chain another consumer
64 ///
65 /// Returns a new consumer that executes the current operation first, then the
66 /// next operation. Consumes the current closure and returns `BoxStatefulConsumer<T>`.
67 ///
68 /// # Type Parameters
69 ///
70 /// * `C` - Type of the next consumer
71 ///
72 /// # Parameters
73 ///
74 /// * `next` - Consumer to execute after the current operation. **Note: This
75 /// parameter is passed by value and will transfer ownership.** If you need
76 /// to preserve the original consumer, clone it first (if it implements
77 /// `Clone`). Can be:
78 /// - A closure: `|x: &T|`
79 /// - A `BoxStatefulConsumer<T>`
80 /// - An `RcStatefulConsumer<T>`
81 /// - An `ArcStatefulConsumer<T>`
82 /// - Any type implementing `Consumer<T>`
83 ///
84 /// # Return Value
85 ///
86 /// Returns a combined `BoxStatefulConsumer<T>`
87 ///
88 /// # Examples
89 ///
90 /// ## Direct value passing (ownership transfer)
91 ///
92 /// ```rust
93 /// use qubit_function::{Consumer, StatefulConsumer, FnStatefulConsumerOps, BoxStatefulConsumer};
94 /// use std::sync::{Arc, Mutex};
95 ///
96 /// let log = Arc::new(Mutex::new(Vec::new()));
97 /// let l1 = log.clone();
98 /// let l2 = log.clone();
99 /// let second = BoxStatefulConsumer::new(move |x: &i32| {
100 /// l2.lock().unwrap().push(*x + 10);
101 /// });
102 ///
103 /// // second is moved here
104 /// let mut chained = (move |x: &i32| {
105 /// l1.lock().unwrap().push(*x * 2);
106 /// }).and_then(second);
107 ///
108 /// chained.accept(&5);
109 /// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
110 /// // second.accept(&3); // Would not compile - moved
111 /// ```
112 ///
113 /// ## Preserving original with clone
114 ///
115 /// ```rust
116 /// use qubit_function::{Consumer, StatefulConsumer, FnStatefulConsumerOps, RcStatefulConsumer};
117 /// use std::sync::{Arc, Mutex};
118 ///
119 /// let log = Arc::new(Mutex::new(Vec::new()));
120 /// let l1 = log.clone();
121 /// let l2 = log.clone();
122 /// let mut second = RcStatefulConsumer::new(move |x: &i32| {
123 /// l2.lock().unwrap().push(*x + 10);
124 /// });
125 ///
126 /// // Clone to preserve original
127 /// let mut chained = (move |x: &i32| {
128 /// l1.lock().unwrap().push(*x * 2);
129 /// }).and_then(second.clone());
130 ///
131 /// chained.accept(&5);
132 /// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
133 ///
134 /// // Original still usable
135 /// second.accept(&3);
136 /// assert_eq!(*log.lock().unwrap(), vec![10, 15, 13]);
137 /// ```
138 fn and_then<C>(self, next: C) -> BoxStatefulConsumer<T>
139 where
140 Self: 'static,
141 C: StatefulConsumer<T> + 'static,
142 T: 'static,
143 {
144 let mut first = self;
145 let mut second = next;
146 BoxStatefulConsumer::new(move |t| {
147 first(t);
148 second.accept(t);
149 })
150 }
151}
152
153/// Implement FnStatefulConsumerOps for all closure types
154impl<T, F> FnStatefulConsumerOps<T> for F where F: FnMut(&T) {}