qubit_function/consumers/consumer.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # Consumer Types
10//!
11//! Provides implementations of non-mutating consumer interfaces for executing
12//! operations that neither modify their own state nor modify input values.
13//!
14//! It is similar to the `Fn(&T)` trait in the standard library.
15//!
16//! This module provides a unified `Consumer` trait and three concrete
17//! implementations based on different ownership models:
18//!
19//! - **`BoxConsumer<T>`**: Box-based single ownership implementation
20//! - **`ArcConsumer<T>`**: Arc-based thread-safe shared ownership
21//! implementation
22//! - **`RcConsumer<T>`**: Rc-based single-threaded shared ownership
23//! implementation
24//!
25//! # Design Philosophy
26//!
27//! Consumer uses `Fn(&T)` semantics: it is invoked through `&self` and receives
28//! shared references to input values.
29//!
30//! Suitable for pure observation, logging, notification and other scenarios.
31//! Compared to `StatefulConsumer`, `Consumer` does not require wrapper-level
32//! interior mutability (`Mutex`/`RefCell`), making it more efficient and easier
33//! to share.
34//!
35//! # Author
36//!
37//! Haixing Hu
38
39use std::rc::Rc;
40use std::sync::Arc;
41
42use crate::consumers::consumer_once::BoxConsumerOnce;
43use crate::consumers::macros::{
44 impl_box_conditional_consumer,
45 impl_box_consumer_methods,
46 impl_conditional_consumer_clone,
47 impl_conditional_consumer_conversions,
48 impl_conditional_consumer_debug_display,
49 impl_consumer_clone,
50 impl_consumer_common_methods,
51 impl_consumer_debug_display,
52 impl_shared_conditional_consumer,
53 impl_shared_consumer_methods,
54};
55use crate::macros::{
56 impl_arc_conversions,
57 impl_box_conversions,
58 impl_closure_trait,
59 impl_rc_conversions,
60};
61use crate::predicates::predicate::{
62 ArcPredicate,
63 BoxPredicate,
64 Predicate,
65 RcPredicate,
66};
67
68mod box_consumer;
69pub use box_consumer::BoxConsumer;
70mod rc_consumer;
71pub use rc_consumer::RcConsumer;
72mod arc_consumer;
73pub use arc_consumer::ArcConsumer;
74mod fn_consumer_ops;
75pub use fn_consumer_ops::FnConsumerOps;
76mod box_conditional_consumer;
77pub use box_conditional_consumer::BoxConditionalConsumer;
78mod rc_conditional_consumer;
79pub use rc_conditional_consumer::RcConditionalConsumer;
80mod arc_conditional_consumer;
81pub use arc_conditional_consumer::ArcConditionalConsumer;
82
83// ============================================================================
84// 1. Consumer Trait - Unified Consumer Interface
85// ============================================================================
86
87/// Consumer trait - Unified non-mutating consumer interface
88///
89/// It is similar to the `Fn(&T)` trait in the standard library.
90///
91/// Defines the core behavior of all non-mutating consumer types. The API uses
92/// `&self` and shared input references, so callers can use a consumer without
93/// granting mutable access to the consumer wrapper or input value.
94///
95/// # Auto-implementation
96///
97/// - All closures implementing `Fn(&T)`
98/// - `BoxConsumer<T>`, `ArcConsumer<T>`,
99/// `RcConsumer<T>`
100///
101/// # Features
102///
103/// - **Unified Interface**: All non-mutating consumer types share the same `accept`
104/// method signature
105/// - **Auto-implementation**: Closures automatically implement this trait with
106/// zero overhead
107/// - **Type Conversion**: Easy conversion between different ownership models
108/// - **Generic Programming**: Write functions that work with any non-mutating
109/// consumer type
110/// - **No Wrapper Interior Mutability**: No need for Mutex or RefCell in the
111/// wrapper, making shared ownership more efficient
112///
113/// # Examples
114///
115/// ```rust
116/// use qubit_function::{Consumer, BoxConsumer};
117///
118/// fn apply_consumer<C: Consumer<i32>>(consumer: &C, value: &i32) {
119/// consumer.accept(value);
120/// }
121///
122/// let box_con = BoxConsumer::new(|x: &i32| {
123/// println!("Value: {}", x);
124/// });
125/// apply_consumer(&box_con, &5);
126/// ```
127///
128/// # Author
129///
130/// Haixing Hu
131pub trait Consumer<T> {
132 /// Execute non-mutating consumption operation
133 ///
134 /// Performs an operation on the given reference. The operation typically
135 /// reads input values or produces side effects, but neither modifies the
136 /// input value nor the consumer's own state.
137 ///
138 /// # Parameters
139 ///
140 /// * `value` - Reference to the value to consume
141 ///
142 /// # Examples
143 ///
144 /// ```rust
145 /// use qubit_function::{Consumer, BoxConsumer};
146 ///
147 /// let consumer = BoxConsumer::new(|x: &i32| println!("{}", x));
148 /// consumer.accept(&5);
149 /// ```
150 fn accept(&self, value: &T);
151
152 /// Convert to BoxConsumer
153 ///
154 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after
155 /// calling this method.
156 ///
157 /// # Returns
158 ///
159 /// Returns the wrapped `BoxConsumer<T>`
160 fn into_box(self) -> BoxConsumer<T>
161 where
162 Self: Sized + 'static,
163 {
164 BoxConsumer::new(move |t| self.accept(t))
165 }
166
167 /// Convert to RcConsumer
168 ///
169 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after
170 /// calling this method.
171 ///
172 /// # Returns
173 ///
174 /// Returns the wrapped `RcConsumer<T>`
175 fn into_rc(self) -> RcConsumer<T>
176 where
177 Self: Sized + 'static,
178 {
179 RcConsumer::new(move |t| self.accept(t))
180 }
181
182 /// Convert to ArcConsumer
183 ///
184 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after
185 /// calling this method.
186 ///
187 /// # Returns
188 ///
189 /// Returns the wrapped `ArcConsumer<T>`
190 fn into_arc(self) -> ArcConsumer<T>
191 where
192 Self: Sized + Send + Sync + 'static,
193 {
194 ArcConsumer::new(move |t| self.accept(t))
195 }
196
197 /// Convert to closure
198 ///
199 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after
200 /// calling this method.
201 ///
202 /// Converts a non-mutating consumer to a closure that can be used directly in
203 /// places where the standard library requires `Fn`.
204 ///
205 /// # Returns
206 ///
207 /// Returns a closure implementing `Fn(&T)`
208 ///
209 /// # Examples
210 ///
211 /// ```rust
212 /// use qubit_function::{Consumer, BoxConsumer};
213 ///
214 /// let consumer = BoxConsumer::new(|x: &i32| {
215 /// println!("Value: {}", x);
216 /// });
217 /// let func = consumer.into_fn();
218 /// func(&5);
219 /// ```
220 fn into_fn(self) -> impl Fn(&T)
221 where
222 Self: Sized + 'static,
223 {
224 move |t| self.accept(t)
225 }
226
227 /// Convert to ConsumerOnce
228 ///
229 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
230 ///
231 /// Converts a reusable non-mutating consumer to a one-time consumer that consumes itself on use.
232 /// This enables passing `Consumer` to functions that require `ConsumerOnce`.
233 ///
234 /// # Returns
235 ///
236 /// Returns a `BoxConsumerOnce<T>`
237 ///
238 /// # Examples
239 ///
240 /// ```rust
241 /// use qubit_function::{Consumer, ConsumerOnce, BoxConsumer};
242 ///
243 /// fn takes_once<C: ConsumerOnce<i32>>(consumer: C, value: &i32) {
244 /// consumer.accept(value);
245 /// }
246 ///
247 /// let consumer = BoxConsumer::new(|x: &i32| println!("{}", x));
248 /// takes_once(consumer.into_once(), &5);
249 /// ```
250 fn into_once(self) -> BoxConsumerOnce<T>
251 where
252 Self: Sized + 'static,
253 {
254 BoxConsumerOnce::new(move |t| self.accept(t))
255 }
256
257 /// Non-consuming conversion to `BoxConsumer`
258 ///
259 /// **⚠️ Does NOT consume `self`**: This method clones `self` and returns a
260 /// boxed non-mutating consumer that calls the cloned consumer. Requires
261 /// `Self: Clone` so it can be called through an immutable reference.
262 ///
263 /// # Returns
264 ///
265 /// Returns the wrapped `BoxConsumer<T>`
266 fn to_box(&self) -> BoxConsumer<T>
267 where
268 Self: Clone + 'static,
269 {
270 self.clone().into_box()
271 }
272
273 /// Non-consuming conversion to `RcConsumer`
274 ///
275 /// **⚠️ Does NOT consume `self`**: Clones `self` and returns an
276 /// `RcConsumer` that forwards to the cloned consumer. Requires
277 /// `Self: Clone`.
278 ///
279 /// # Returns
280 ///
281 /// Returns the wrapped `RcConsumer<T>`
282 fn to_rc(&self) -> RcConsumer<T>
283 where
284 Self: Clone + 'static,
285 {
286 self.clone().into_rc()
287 }
288
289 /// Non-consuming conversion to `ArcConsumer`
290 ///
291 /// **⚠️ Does NOT consume `self`**: Clones `self` and returns an
292 /// `ArcConsumer`. Requires `Self: Clone + Send + Sync` so the result
293 /// is thread-safe.
294 ///
295 /// # Returns
296 ///
297 /// Returns the wrapped `ArcConsumer<T>`
298 fn to_arc(&self) -> ArcConsumer<T>
299 where
300 Self: Clone + Send + Sync + 'static,
301 {
302 self.clone().into_arc()
303 }
304
305 /// Non-consuming conversion to a boxed closure
306 ///
307 /// **⚠️ Does NOT consume `self`**: Returns a closure which calls a cloned
308 /// copy of the consumer. Requires `Self: Clone`.
309 ///
310 /// # Returns
311 ///
312 /// Returns a closure implementing `Fn(&T)` which forwards to the cloned
313 /// consumer.
314 fn to_fn(&self) -> impl Fn(&T)
315 where
316 Self: Clone + 'static,
317 {
318 self.clone().into_fn()
319 }
320
321 /// Convert to ConsumerOnce without consuming self
322 ///
323 /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
324 /// Clones the current consumer and converts the clone to a one-time consumer.
325 ///
326 /// # Returns
327 ///
328 /// Returns a `BoxConsumerOnce<T>`
329 ///
330 /// # Examples
331 ///
332 /// ```rust
333 /// use qubit_function::{Consumer, ConsumerOnce, ArcConsumer};
334 ///
335 /// fn takes_once<C: ConsumerOnce<i32>>(consumer: C, value: &i32) {
336 /// consumer.accept(value);
337 /// }
338 ///
339 /// let consumer = ArcConsumer::new(|x: &i32| println!("{}", x));
340 /// takes_once(consumer.to_once(), &5);
341 /// ```
342 fn to_once(&self) -> BoxConsumerOnce<T>
343 where
344 Self: Clone + 'static,
345 {
346 self.clone().into_once()
347 }
348}