Skip to main content

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}