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