Skip to main content

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}