qubit_function/consumers/consumer_once.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! # ConsumerOnce Types
10//!
11//! Provides implementations of one-time consumer interfaces for executing one-time operations
12//! that accept a single input parameter but return no result.
13//!
14//! It is similar to the `FnOnce(&T)` trait in the standard library.
15//!
16//! This module provides a unified `ConsumerOnce` trait and one concrete implementation:
17//!
18//! - **`BoxConsumerOnce<T>`**: Box-based single ownership implementation
19//!
20//! # Why No Arc/Rc Variants?
21//!
22//! Unlike reusable [`Consumer`](crate::consumers::Consumer) implementations,
23//! this module does **not** provide `ArcConsumerOnce` or `RcConsumerOnce`
24//! implementations. This is a design decision based on the fact that `FnOnce`
25//! semantics are fundamentally incompatible with shared ownership. See design
26//! docs for details.
27//!
28//! # Design Philosophy
29//!
30//! ConsumerOnce uses `FnOnce(&T)` semantics for truly one-time consumption operations.
31//!
32//! Unlike Consumer, ConsumerOnce consumes itself on first call. Suitable for initialization
33//! callbacks, cleanup callbacks, and similar scenarios.
34//!
35//! # Author
36//!
37//! Haixing Hu
38
39use crate::consumers::macros::{
40 impl_box_conditional_consumer,
41 impl_box_consumer_methods,
42 impl_conditional_consumer_debug_display,
43 impl_consumer_common_methods,
44 impl_consumer_debug_display,
45};
46use crate::macros::{
47 impl_box_once_conversions,
48 impl_closure_once_trait,
49};
50use crate::predicates::predicate::{
51 BoxPredicate,
52 Predicate,
53};
54
55mod box_consumer_once;
56pub use box_consumer_once::BoxConsumerOnce;
57mod fn_consumer_once_ops;
58pub use fn_consumer_once_ops::FnConsumerOnceOps;
59mod box_conditional_consumer_once;
60pub use box_conditional_consumer_once::BoxConditionalConsumerOnce;
61
62// ============================================================================
63// 1. ConsumerOnce Trait - Unified ConsumerOnce Interface
64// ============================================================================
65
66/// ConsumerOnce trait - Unified one-time consumer interface
67///
68/// It is similar to the `FnOnce(&T)` trait in the standard library.
69///
70/// Defines the core behavior of all one-time consumer types. Similar to consumers
71/// implementing `FnOnce(&T)`, executes operations that accept a value reference but
72/// return no result (only side effects), consuming itself in the process.
73///
74/// # Automatic Implementation
75///
76/// - All closures implementing `FnOnce(&T)`
77/// - `BoxConsumerOnce<T>`
78///
79/// # Features
80///
81/// - **Unified Interface**: All consumer types share the same `accept` method signature
82/// - **Automatic Implementation**: Closures automatically implement this trait with zero overhead
83/// - **Type Conversion**: Can be converted to BoxConsumerOnce
84/// - **Generic Programming**: Write functions that work with any one-time consumer type
85///
86/// # Examples
87///
88/// ```rust
89/// use qubit_function::{ConsumerOnce, BoxConsumerOnce};
90/// use std::sync::{Arc, Mutex};
91///
92/// fn apply_consumer<C: ConsumerOnce<i32>>(consumer: C, value: &i32) {
93/// consumer.accept(value);
94/// }
95///
96/// let log = Arc::new(Mutex::new(Vec::new()));
97/// let l = log.clone();
98/// let box_con = BoxConsumerOnce::new(move |x: &i32| {
99/// l.lock().unwrap().push(*x);
100/// });
101/// apply_consumer(box_con, &5);
102/// assert_eq!(*log.lock().unwrap(), vec![5]);
103/// ```
104///
105/// # Author
106///
107/// Haixing Hu
108pub trait ConsumerOnce<T> {
109 /// Execute one-time consumption operation
110 ///
111 /// Executes an operation on the given reference. The operation typically reads
112 /// the input value or produces side effects, but does not modify the input
113 /// value itself. Consumes self.
114 ///
115 /// # Parameters
116 ///
117 /// * `value` - Reference to the value to be consumed
118 ///
119 /// # Examples
120 ///
121 /// ```rust
122 /// use qubit_function::{ConsumerOnce, BoxConsumerOnce};
123 ///
124 /// let consumer = BoxConsumerOnce::new(|x: &i32| println!("{}", x));
125 /// consumer.accept(&5);
126 /// ```
127 fn accept(self, value: &T);
128
129 /// Convert to BoxConsumerOnce
130 ///
131 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
132 ///
133 /// # Default Implementation
134 ///
135 /// The default implementation wraps `self` in a `BoxConsumerOnce` by calling
136 /// `accept` on the consumer. Types can override this method to provide more
137 /// efficient conversions.
138 ///
139 /// # Returns
140 ///
141 /// Returns the wrapped `BoxConsumerOnce<T>`
142 ///
143 /// # Examples
144 ///
145 /// ```rust
146 /// use qubit_function::ConsumerOnce;
147 /// use std::sync::{Arc, Mutex};
148 ///
149 /// let log = Arc::new(Mutex::new(Vec::new()));
150 /// let l = log.clone();
151 /// let closure = move |x: &i32| {
152 /// l.lock().unwrap().push(*x);
153 /// };
154 /// let box_consumer = closure.into_box();
155 /// box_consumer.accept(&5);
156 /// assert_eq!(*log.lock().unwrap(), vec![5]);
157 /// ```
158 fn into_box(self) -> BoxConsumerOnce<T>
159 where
160 Self: Sized + 'static,
161 {
162 BoxConsumerOnce::new(move |t| self.accept(t))
163 }
164
165 /// Convert to closure
166 ///
167 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
168 ///
169 /// Converts a one-time consumer to a closure that can be used directly in places
170 /// where the standard library requires `FnOnce`.
171 ///
172 /// # Default Implementation
173 ///
174 /// The default implementation creates a closure that captures `self` and calls
175 /// its `accept` method. Types can override this method to provide more efficient
176 /// conversions.
177 ///
178 /// # Returns
179 ///
180 /// Returns a closure implementing `FnOnce(&T)`
181 ///
182 /// # Examples
183 ///
184 /// ```rust
185 /// use qubit_function::ConsumerOnce;
186 /// use std::sync::{Arc, Mutex};
187 ///
188 /// let log = Arc::new(Mutex::new(Vec::new()));
189 /// let l = log.clone();
190 /// let closure = move |x: &i32| {
191 /// l.lock().unwrap().push(*x * 2);
192 /// };
193 /// let func = closure.into_fn();
194 /// func(&5);
195 /// assert_eq!(*log.lock().unwrap(), vec![10]);
196 /// ```
197 fn into_fn(self) -> impl FnOnce(&T)
198 where
199 Self: Sized + 'static,
200 {
201 move |t| self.accept(t)
202 }
203
204 /// Convert to BoxConsumerOnce without consuming self
205 ///
206 /// **⚠️ Requires Clone**: This method requires `Self` to implement
207 /// `Clone`. Clones the current consumer and wraps it in a
208 /// `BoxConsumerOnce`.
209 ///
210 /// # Default Implementation
211 ///
212 /// The default implementation clones `self` and then calls
213 /// `into_box()` on the clone. Types can override this method to
214 /// provide more efficient conversions.
215 ///
216 /// # Returns
217 ///
218 /// Returns the wrapped `BoxConsumerOnce<T>`
219 ///
220 /// # Examples
221 ///
222 /// ```rust
223 /// use qubit_function::ConsumerOnce;
224 /// use std::sync::{Arc, Mutex};
225 ///
226 /// let log = Arc::new(Mutex::new(Vec::new()));
227 /// let l = log.clone();
228 /// let closure = move |x: &i32| {
229 /// l.lock().unwrap().push(*x);
230 /// };
231 /// let box_consumer = closure.to_box();
232 /// box_consumer.accept(&5);
233 /// assert_eq!(*log.lock().unwrap(), vec![5]);
234 /// ```
235 fn to_box(&self) -> BoxConsumerOnce<T>
236 where
237 Self: Sized + Clone + 'static,
238 {
239 self.clone().into_box()
240 }
241
242 /// Convert to closure without consuming self
243 ///
244 /// **⚠️ Requires Clone**: This method requires `Self` to implement
245 /// `Clone`. Clones the current consumer and then converts the clone
246 /// to a closure.
247 ///
248 /// # Default Implementation
249 ///
250 /// The default implementation clones `self` and then calls
251 /// `into_fn()` on the clone. Types can override this method to
252 /// provide more efficient conversions.
253 ///
254 /// # Returns
255 ///
256 /// Returns a closure implementing `FnOnce(&T)`
257 ///
258 /// # Examples
259 ///
260 /// ```rust
261 /// use qubit_function::ConsumerOnce;
262 /// use std::sync::{Arc, Mutex};
263 ///
264 /// let log = Arc::new(Mutex::new(Vec::new()));
265 /// let l = log.clone();
266 /// let closure = move |x: &i32| {
267 /// l.lock().unwrap().push(*x * 2);
268 /// };
269 /// let func = closure.to_fn();
270 /// func(&5);
271 /// assert_eq!(*log.lock().unwrap(), vec![10]);
272 /// ```
273 fn to_fn(&self) -> impl FnOnce(&T)
274 where
275 Self: Sized + Clone + 'static,
276 {
277 self.clone().into_fn()
278 }
279}