prism3_function/consumer_once.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025.
4 * 3-Prism 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//! This module provides a unified `ConsumerOnce` trait and one concrete implementation:
15//!
16//! - **`BoxConsumerOnce<T>`**: Box-based single ownership implementation
17//!
18//! # Why No Arc/Rc Variants?
19//!
20//! Unlike `Consumer` and `ReadonlyConsumer`, this module does **not** provide `ArcConsumerOnce`
21//! or `RcConsumerOnce` implementations. This is a design decision based on the fact that
22//! `FnOnce` semantics are fundamentally incompatible with shared ownership. See design docs for details.
23//!
24//! # Design Philosophy
25//!
26//! ConsumerOnce uses `FnOnce(&T)` semantics for truly one-time consumption operations.
27//! Unlike Consumer, ConsumerOnce consumes itself on first call. Suitable for initialization
28//! callbacks, cleanup callbacks, and similar scenarios.
29//!
30//! # Author
31//!
32//! Hu Haixing
33
34use std::fmt;
35
36use crate::predicate::{BoxPredicate, Predicate};
37
38// ============================================================================
39// 1. ConsumerOnce Trait - Unified ConsumerOnce Interface
40// ============================================================================
41
42/// ConsumerOnce trait - Unified one-time consumer interface
43///
44/// Defines the core behavior of all one-time consumer types. Similar to consumers
45/// implementing `FnOnce(&T)`, executes operations that accept a value reference but
46/// return no result (only side effects), consuming itself in the process.
47///
48/// # Automatic Implementation
49///
50/// - All closures implementing `FnOnce(&T)`
51/// - `BoxConsumerOnce<T>`
52///
53/// # Features
54///
55/// - **Unified Interface**: All consumer types share the same `accept` method signature
56/// - **Automatic Implementation**: Closures automatically implement this trait with zero overhead
57/// - **Type Conversion**: Can be converted to BoxConsumerOnce
58/// - **Generic Programming**: Write functions that work with any one-time consumer type
59///
60/// # Examples
61///
62/// ```rust
63/// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
64/// use std::sync::{Arc, Mutex};
65///
66/// fn apply_consumer<C: ConsumerOnce<i32>>(consumer: C, value: &i32) {
67/// consumer.accept_once(value);
68/// }
69///
70/// let log = Arc::new(Mutex::new(Vec::new()));
71/// let l = log.clone();
72/// let box_con = BoxConsumerOnce::new(move |x: &i32| {
73/// l.lock().unwrap().push(*x);
74/// });
75/// apply_consumer(box_con, &5);
76/// assert_eq!(*log.lock().unwrap(), vec![5]);
77/// ```
78///
79/// # Author
80///
81/// Hu Haixing
82pub trait ConsumerOnce<T> {
83 /// Execute one-time consumption operation
84 ///
85 /// Executes an operation on the given reference. The operation typically reads
86 /// the input value or produces side effects, but does not modify the input
87 /// value itself. Consumes self.
88 ///
89 /// # Parameters
90 ///
91 /// * `value` - Reference to the value to be consumed
92 ///
93 /// # Examples
94 ///
95 /// ```rust
96 /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
97 ///
98 /// let consumer = BoxConsumerOnce::new(|x: &i32| println!("{}", x));
99 /// consumer.accept_once(&5);
100 /// ```
101 fn accept_once(self, value: &T);
102
103 /// Convert to BoxConsumerOnce
104 ///
105 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
106 ///
107 /// # Default Implementation
108 ///
109 /// The default implementation wraps `self` in a `BoxConsumerOnce` by calling
110 /// `accept_once` on the consumer. Types can override this method to provide more
111 /// efficient conversions.
112 ///
113 /// # Returns
114 ///
115 /// Returns the wrapped `BoxConsumerOnce<T>`
116 ///
117 /// # Examples
118 ///
119 /// ```rust
120 /// use prism3_function::ConsumerOnce;
121 /// use std::sync::{Arc, Mutex};
122 ///
123 /// let log = Arc::new(Mutex::new(Vec::new()));
124 /// let l = log.clone();
125 /// let closure = move |x: &i32| {
126 /// l.lock().unwrap().push(*x);
127 /// };
128 /// let box_consumer = closure.into_box_once();
129 /// box_consumer.accept_once(&5);
130 /// assert_eq!(*log.lock().unwrap(), vec![5]);
131 /// ```
132 fn into_box_once(self) -> BoxConsumerOnce<T>
133 where
134 Self: Sized + 'static,
135 T: 'static,
136 {
137 BoxConsumerOnce::new(move |t| self.accept_once(t))
138 }
139
140 /// Convert to closure
141 ///
142 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
143 ///
144 /// Converts a one-time consumer to a closure that can be used directly in places
145 /// where the standard library requires `FnOnce`.
146 ///
147 /// # Default Implementation
148 ///
149 /// The default implementation creates a closure that captures `self` and calls
150 /// its `accept_once` method. Types can override this method to provide more efficient
151 /// conversions.
152 ///
153 /// # Returns
154 ///
155 /// Returns a closure implementing `FnOnce(&T)`
156 ///
157 /// # Examples
158 ///
159 /// ```rust
160 /// use prism3_function::ConsumerOnce;
161 /// use std::sync::{Arc, Mutex};
162 ///
163 /// let log = Arc::new(Mutex::new(Vec::new()));
164 /// let l = log.clone();
165 /// let closure = move |x: &i32| {
166 /// l.lock().unwrap().push(*x * 2);
167 /// };
168 /// let func = closure.into_fn_once();
169 /// func(&5);
170 /// assert_eq!(*log.lock().unwrap(), vec![10]);
171 /// ```
172 fn into_fn_once(self) -> impl FnOnce(&T)
173 where
174 Self: Sized + 'static,
175 T: 'static,
176 {
177 move |t| self.accept_once(t)
178 }
179
180 /// Convert to BoxConsumerOnce without consuming self
181 ///
182 /// **⚠️ Requires Clone**: This method requires `Self` to implement
183 /// `Clone`. Clones the current consumer and wraps it in a
184 /// `BoxConsumerOnce`.
185 ///
186 /// # Default Implementation
187 ///
188 /// The default implementation clones `self` and then calls
189 /// `into_box_once()` on the clone. Types can override this method to
190 /// provide more efficient conversions.
191 ///
192 /// # Returns
193 ///
194 /// Returns the wrapped `BoxConsumerOnce<T>`
195 ///
196 /// # Examples
197 ///
198 /// ```rust
199 /// use prism3_function::ConsumerOnce;
200 /// use std::sync::{Arc, Mutex};
201 ///
202 /// let log = Arc::new(Mutex::new(Vec::new()));
203 /// let l = log.clone();
204 /// let closure = move |x: &i32| {
205 /// l.lock().unwrap().push(*x);
206 /// };
207 /// let box_consumer = closure.to_box_once();
208 /// box_consumer.accept_once(&5);
209 /// assert_eq!(*log.lock().unwrap(), vec![5]);
210 /// ```
211 fn to_box_once(&self) -> BoxConsumerOnce<T>
212 where
213 Self: Sized + Clone + 'static,
214 T: 'static,
215 {
216 self.clone().into_box_once()
217 }
218
219 /// Convert to closure without consuming self
220 ///
221 /// **⚠️ Requires Clone**: This method requires `Self` to implement
222 /// `Clone`. Clones the current consumer and then converts the clone
223 /// to a closure.
224 ///
225 /// # Default Implementation
226 ///
227 /// The default implementation clones `self` and then calls
228 /// `into_fn_once()` on the clone. Types can override this method to
229 /// provide more efficient conversions.
230 ///
231 /// # Returns
232 ///
233 /// Returns a closure implementing `FnOnce(&T)`
234 ///
235 /// # Examples
236 ///
237 /// ```rust
238 /// use prism3_function::ConsumerOnce;
239 /// use std::sync::{Arc, Mutex};
240 ///
241 /// let log = Arc::new(Mutex::new(Vec::new()));
242 /// let l = log.clone();
243 /// let closure = move |x: &i32| {
244 /// l.lock().unwrap().push(*x * 2);
245 /// };
246 /// let func = closure.to_fn_once();
247 /// func(&5);
248 /// assert_eq!(*log.lock().unwrap(), vec![10]);
249 /// ```
250 fn to_fn_once(&self) -> impl FnOnce(&T)
251 where
252 Self: Sized + Clone + 'static,
253 T: 'static,
254 {
255 self.clone().into_fn_once()
256 }
257}
258
259// ============================================================================
260// 2. BoxConsumerOnce - Single Ownership Implementation
261// ============================================================================
262
263/// BoxConsumerOnce struct
264///
265/// One-time consumer implementation based on `Box<dyn FnOnce(&T)>` for single ownership scenarios.
266/// This is the simplest consumer type for truly one-time use.
267///
268/// # Features
269///
270/// - **Single Ownership**: Not cloneable, transfers ownership on use
271/// - **Zero Overhead**: No reference counting or lock overhead
272/// - **One-time Use**: Consumes self on first call
273/// - **Builder Pattern**: Method chaining naturally consumes `self`
274///
275/// # Use Cases
276///
277/// Choose `BoxConsumerOnce` when:
278/// - Consumer is truly used only once
279/// - Building pipelines where ownership flows naturally
280/// - Consumer captures values that should be consumed
281/// - Performance critical and cannot accept shared overhead
282///
283/// # Performance
284///
285/// `BoxConsumerOnce` has the best performance:
286/// - No reference counting overhead
287/// - No lock acquisition or runtime borrow checking
288/// - Direct function call through vtable
289/// - Minimal memory footprint (single pointer)
290///
291/// # Examples
292///
293/// ```rust
294/// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
295///
296/// let consumer = BoxConsumerOnce::new(|x: &i32| {
297/// println!("Value: {}", x);
298/// });
299/// consumer.accept_once(&5);
300/// ```
301///
302/// # Author
303///
304/// Hu Haixing
305pub struct BoxConsumerOnce<T> {
306 function: Box<dyn FnOnce(&T)>,
307 name: Option<String>,
308}
309
310impl<T> BoxConsumerOnce<T>
311where
312 T: 'static,
313{
314 /// Create a new BoxConsumerOnce
315 ///
316 /// # Type Parameters
317 ///
318 /// * `F` - Closure type
319 ///
320 /// # Parameters
321 ///
322 /// * `f` - Closure to be wrapped
323 ///
324 /// # Returns
325 ///
326 /// Returns a new `BoxConsumerOnce<T>` instance
327 ///
328 /// # Examples
329 ///
330 /// ```rust
331 /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
332 /// use std::sync::{Arc, Mutex};
333 ///
334 /// let log = Arc::new(Mutex::new(Vec::new()));
335 /// let l = log.clone();
336 /// let consumer = BoxConsumerOnce::new(move |x: &i32| {
337 /// l.lock().unwrap().push(*x + 1);
338 /// });
339 /// consumer.accept_once(&5);
340 /// assert_eq!(*log.lock().unwrap(), vec![6]);
341 /// ```
342 pub fn new<F>(f: F) -> Self
343 where
344 F: FnOnce(&T) + 'static,
345 {
346 BoxConsumerOnce {
347 function: Box::new(f),
348 name: None,
349 }
350 }
351
352 /// Get the consumer's name
353 ///
354 /// Returns the optional name associated with this consumer.
355 /// Used for debugging and logging purposes.
356 ///
357 /// # Returns
358 ///
359 /// Returns `Some(&str)` if a name was set, `None` otherwise
360 ///
361 /// # Examples
362 ///
363 /// ```rust
364 /// use prism3_function::BoxConsumerOnce;
365 ///
366 /// let mut consumer = BoxConsumerOnce::new(|x: &i32| {
367 /// println!("{}", x);
368 /// });
369 /// assert_eq!(consumer.name(), None);
370 /// consumer.set_name("my_consumer");
371 /// assert_eq!(consumer.name(), Some("my_consumer"));
372 /// ```
373 pub fn name(&self) -> Option<&str> {
374 self.name.as_deref()
375 }
376
377 /// Set the consumer's name
378 ///
379 /// Assigns a name to this consumer for debugging and logging
380 /// purposes. The name can be any type that converts to `String`.
381 ///
382 /// # Parameters
383 ///
384 /// * `name` - The name to set, can be `&str` or `String`
385 ///
386 /// # Examples
387 ///
388 /// ```rust
389 /// use prism3_function::BoxConsumerOnce;
390 ///
391 /// let mut consumer = BoxConsumerOnce::new(|x: &i32| {
392 /// println!("{}", x);
393 /// });
394 /// consumer.set_name("my_consumer");
395 /// assert_eq!(consumer.name(), Some("my_consumer"));
396 /// ```
397 pub fn set_name(&mut self, name: impl Into<String>) {
398 self.name = Some(name.into());
399 }
400
401 /// Sequentially chain another one-time consumer
402 ///
403 /// Returns a new consumer that executes the current operation first, then the next operation. Consumes self.
404 ///
405 /// # Type Parameters
406 ///
407 /// * `C` - Type of the next consumer
408 ///
409 /// # Parameters
410 ///
411 /// * `next` - Consumer to execute after the current operation. **Note: This
412 /// parameter is passed by value and will transfer ownership.** Since
413 /// `BoxConsumerOnce` cannot be cloned, the parameter will be consumed.
414 /// Can be:
415 /// - A closure: `|x: &T|`
416 /// - A `BoxConsumerOnce<T>`
417 /// - Any type implementing `ConsumerOnce<T>`
418 ///
419 /// # Returns
420 ///
421 /// Returns a new combined `BoxConsumerOnce<T>`
422 ///
423 /// # Examples
424 ///
425 /// ```rust
426 /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
427 /// use std::sync::{Arc, Mutex};
428 ///
429 /// let log = Arc::new(Mutex::new(Vec::new()));
430 /// let l1 = log.clone();
431 /// let l2 = log.clone();
432 /// let first = BoxConsumerOnce::new(move |x: &i32| {
433 /// l1.lock().unwrap().push(*x * 2);
434 /// });
435 /// let second = BoxConsumerOnce::new(move |x: &i32| {
436 /// l2.lock().unwrap().push(*x + 10);
437 /// });
438 ///
439 /// // Both first and second are moved and consumed
440 /// let chained = first.and_then(second);
441 /// chained.accept_once(&5);
442 /// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
443 /// // first.accept_once(&3); // Would not compile - moved
444 /// // second.accept_once(&3); // Would not compile - moved
445 /// ```
446 pub fn and_then<C>(self, next: C) -> Self
447 where
448 C: ConsumerOnce<T> + 'static,
449 {
450 let first = self.function;
451 let second = next;
452 BoxConsumerOnce::new(move |t| {
453 first(t);
454 second.accept_once(t);
455 })
456 }
457
458 /// Create a no-op consumer
459 ///
460 /// # Returns
461 ///
462 /// Returns a no-op consumer
463 ///
464 /// # Examples
465 ///
466 /// ```rust
467 /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
468 ///
469 /// let noop = BoxConsumerOnce::<i32>::noop();
470 /// noop.accept_once(&42);
471 /// // Value unchanged
472 /// ```
473 pub fn noop() -> Self {
474 BoxConsumerOnce::new(|_| {})
475 }
476
477 /// Creates a conditional consumer
478 ///
479 /// Returns a consumer that only executes when a predicate is satisfied.
480 ///
481 /// # Parameters
482 ///
483 /// * `predicate` - The condition to check, can be:
484 /// - Closure: `|x: &T| -> bool`
485 /// - Function pointer: `fn(&T) -> bool`
486 /// - `BoxPredicate<T>`
487 /// - Any type implementing `Predicate<T>`
488 ///
489 /// # Returns
490 ///
491 /// Returns `BoxConditionalConsumerOnce<T>`
492 ///
493 /// # Examples
494 ///
495 /// ```rust
496 /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
497 /// use std::sync::{Arc, Mutex};
498 ///
499 /// let log = Arc::new(Mutex::new(Vec::new()));
500 /// let l = log.clone();
501 /// let consumer = BoxConsumerOnce::new(move |x: &i32| {
502 /// l.lock().unwrap().push(*x);
503 /// });
504 /// let conditional = consumer.when(|x: &i32| *x > 0);
505 ///
506 /// conditional.accept_once(&5);
507 /// assert_eq!(*log.lock().unwrap(), vec![5]);
508 /// ```
509 pub fn when<P>(self, predicate: P) -> BoxConditionalConsumerOnce<T>
510 where
511 P: Predicate<T> + 'static,
512 {
513 BoxConditionalConsumerOnce {
514 consumer: self,
515 predicate: predicate.into_box(),
516 }
517 }
518}
519
520impl<T> ConsumerOnce<T> for BoxConsumerOnce<T> {
521 fn accept_once(self, value: &T) {
522 (self.function)(value)
523 }
524
525 fn into_box_once(self) -> BoxConsumerOnce<T>
526 where
527 T: 'static,
528 {
529 self
530 }
531
532 fn into_fn_once(self) -> impl FnOnce(&T)
533 where
534 T: 'static,
535 {
536 self.function
537 }
538
539 // do NOT override Consumer::to_xxxx() because BoxConsumerOnce is not Clone
540 // and calling BoxConsumerOnce::to_xxxx() will cause a compile error
541}
542
543impl<T> fmt::Debug for BoxConsumerOnce<T> {
544 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545 f.debug_struct("BoxConsumerOnce")
546 .field("name", &self.name)
547 .field("function", &"<function>")
548 .finish()
549 }
550}
551
552impl<T> fmt::Display for BoxConsumerOnce<T> {
553 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
554 match &self.name {
555 Some(name) => write!(f, "BoxConsumerOnce({})", name),
556 None => write!(f, "BoxConsumerOnce"),
557 }
558 }
559}
560
561// ============================================================================
562// 3. BoxConditionalConsumerOnce - Box-based Conditional Consumer
563// ============================================================================
564
565/// BoxConditionalConsumerOnce struct
566///
567/// A conditional one-time consumer that only executes when a predicate is satisfied.
568/// Uses `BoxConsumerOnce` and `BoxPredicate` for single ownership semantics.
569///
570/// This type is typically created by calling `BoxConsumerOnce::when()` and is
571/// designed to work with the `or_else()` method to create if-then-else logic.
572///
573/// # Features
574///
575/// - **Single Ownership**: Not cloneable, consumes `self` on use
576/// - **Conditional Execution**: Only consumes when predicate returns `true`
577/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
578/// - **Implements ConsumerOnce**: Can be used anywhere a `ConsumerOnce` is expected
579///
580/// # Examples
581///
582/// ## Basic Conditional Execution
583///
584/// ```rust
585/// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
586/// use std::sync::{Arc, Mutex};
587///
588/// let log = Arc::new(Mutex::new(Vec::new()));
589/// let l = log.clone();
590/// let consumer = BoxConsumerOnce::new(move |x: &i32| {
591/// l.lock().unwrap().push(*x);
592/// });
593/// let conditional = consumer.when(|x: &i32| *x > 0);
594///
595/// conditional.accept_once(&5);
596/// assert_eq!(*log.lock().unwrap(), vec![5]); // Executed
597/// ```
598///
599/// ## With or_else Branch
600///
601/// ```rust
602/// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
603/// use std::sync::{Arc, Mutex};
604///
605/// let log = Arc::new(Mutex::new(Vec::new()));
606/// let l1 = log.clone();
607/// let l2 = log.clone();
608/// let consumer = BoxConsumerOnce::new(move |x: &i32| {
609/// l1.lock().unwrap().push(*x);
610/// })
611/// .when(|x: &i32| *x > 0)
612/// .or_else(move |x: &i32| {
613/// l2.lock().unwrap().push(-*x);
614/// });
615///
616/// consumer.accept_once(&5);
617/// assert_eq!(*log.lock().unwrap(), vec![5]); // when branch executed
618/// ```
619///
620/// # Author
621///
622/// Hu Haixing
623pub struct BoxConditionalConsumerOnce<T> {
624 consumer: BoxConsumerOnce<T>,
625 predicate: BoxPredicate<T>,
626}
627
628impl<T> ConsumerOnce<T> for BoxConditionalConsumerOnce<T>
629where
630 T: 'static,
631{
632 fn accept_once(self, value: &T) {
633 if self.predicate.test(value) {
634 self.consumer.accept_once(value);
635 }
636 }
637
638 fn into_box_once(self) -> BoxConsumerOnce<T> {
639 let pred = self.predicate;
640 let consumer = self.consumer;
641 BoxConsumerOnce::new(move |t| {
642 if pred.test(t) {
643 consumer.accept_once(t);
644 }
645 })
646 }
647
648 fn into_fn_once(self) -> impl FnOnce(&T) {
649 let pred = self.predicate;
650 let consumer = self.consumer;
651 move |t: &T| {
652 if pred.test(t) {
653 consumer.accept_once(t);
654 }
655 }
656 }
657
658 // do NOT override ConsumerOnce::to_xxxx() because BoxConditionalConsumerOnce is not Clone
659 // and calling BoxConditionalConsumerOnce::to_xxxx() will cause a compile error
660}
661
662impl<T> BoxConditionalConsumerOnce<T>
663where
664 T: 'static,
665{
666 /// Chains another consumer in sequence
667 ///
668 /// Combines the current conditional consumer with another consumer into a new
669 /// consumer. The current conditional consumer executes first, followed by the
670 /// next consumer.
671 ///
672 /// # Parameters
673 ///
674 /// * `next` - The next consumer to execute. **Note: This parameter is passed
675 /// by value and will transfer ownership.** Since `BoxConsumerOnce` cannot
676 /// be cloned, the parameter will be consumed. Can be:
677 /// - A closure: `|x: &T|`
678 /// - A `BoxConsumerOnce<T>`
679 /// - Any type implementing `ConsumerOnce<T>`
680 ///
681 /// # Returns
682 ///
683 /// Returns a new `BoxConsumerOnce<T>`
684 ///
685 /// # Examples
686 ///
687 /// ```rust
688 /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
689 /// use std::sync::{Arc, Mutex};
690 ///
691 /// let log = Arc::new(Mutex::new(Vec::new()));
692 /// let l1 = log.clone();
693 /// let l2 = log.clone();
694 /// let cond1 = BoxConsumerOnce::new(move |x: &i32| {
695 /// l1.lock().unwrap().push(*x * 2);
696 /// }).when(|x: &i32| *x > 0);
697 /// let cond2 = BoxConsumerOnce::new(move |x: &i32| {
698 /// l2.lock().unwrap().push(*x + 100);
699 /// }).when(|x: &i32| *x > 10);
700 ///
701 /// // Both cond1 and cond2 are moved and consumed
702 /// let chained = cond1.and_then(cond2);
703 /// chained.accept_once(&6);
704 /// assert_eq!(*log.lock().unwrap(), vec![12, 106]); // First *2 = 12, then +100 = 106
705 /// // cond1.accept_once(&3); // Would not compile - moved
706 /// // cond2.accept_once(&3); // Would not compile - moved
707 /// ```
708 pub fn and_then<C>(self, next: C) -> BoxConsumerOnce<T>
709 where
710 C: ConsumerOnce<T> + 'static,
711 {
712 let first = self;
713 let second = next;
714 BoxConsumerOnce::new(move |t| {
715 first.accept_once(t);
716 second.accept_once(t);
717 })
718 }
719
720 /// Adds an else branch
721 ///
722 /// Executes the original consumer when the condition is satisfied, otherwise
723 /// executes else_consumer.
724 ///
725 /// # Parameters
726 ///
727 /// * `else_consumer` - The consumer for the else branch. **Note: This parameter
728 /// is passed by value and will transfer ownership.** Since `BoxConsumerOnce`
729 /// cannot be cloned, the parameter will be consumed. Can be:
730 /// - A closure: `|x: &T|`
731 /// - A `BoxConsumerOnce<T>`
732 /// - Any type implementing `ConsumerOnce<T>`
733 ///
734 /// # Returns
735 ///
736 /// Returns the composed `BoxConsumerOnce<T>`
737 ///
738 /// # Examples
739 ///
740 /// ## Using a closure (recommended)
741 ///
742 /// ```rust
743 /// use prism3_function::{ConsumerOnce, BoxConsumerOnce};
744 /// use std::sync::{Arc, Mutex};
745 ///
746 /// let log = Arc::new(Mutex::new(Vec::new()));
747 /// let l1 = log.clone();
748 /// let l2 = log.clone();
749 /// let consumer = BoxConsumerOnce::new(move |x: &i32| {
750 /// l1.lock().unwrap().push(*x);
751 /// })
752 /// .when(|x: &i32| *x > 0)
753 /// .or_else(move |x: &i32| {
754 /// l2.lock().unwrap().push(-*x);
755 /// });
756 ///
757 /// consumer.accept_once(&5);
758 /// assert_eq!(*log.lock().unwrap(), vec![5]); // Condition satisfied, execute first
759 /// ```
760 pub fn or_else<C>(self, else_consumer: C) -> BoxConsumerOnce<T>
761 where
762 C: ConsumerOnce<T> + 'static,
763 {
764 let pred = self.predicate;
765 let then_cons = self.consumer;
766 let else_cons = else_consumer;
767 BoxConsumerOnce::new(move |t| {
768 if pred.test(t) {
769 then_cons.accept_once(t);
770 } else {
771 else_cons.accept_once(t);
772 }
773 })
774 }
775}
776
777// ============================================================================
778// 4. Implement ConsumerOnce trait for closures
779// ============================================================================
780
781/// Implement ConsumerOnce for all FnOnce(&T)
782impl<T, F> ConsumerOnce<T> for F
783where
784 F: FnOnce(&T),
785{
786 fn accept_once(self, value: &T) {
787 self(value)
788 }
789
790 fn into_box_once(self) -> BoxConsumerOnce<T>
791 where
792 Self: Sized + 'static,
793 T: 'static,
794 {
795 BoxConsumerOnce::new(self)
796 }
797
798 fn into_fn_once(self) -> impl FnOnce(&T)
799 where
800 Self: Sized + 'static,
801 T: 'static,
802 {
803 self
804 }
805
806 fn to_box_once(&self) -> BoxConsumerOnce<T>
807 where
808 Self: Sized + Clone + 'static,
809 T: 'static,
810 {
811 let cloned = self.clone();
812 BoxConsumerOnce::new(cloned)
813 }
814
815 fn to_fn_once(&self) -> impl FnOnce(&T)
816 where
817 Self: Sized + Clone + 'static,
818 T: 'static,
819 {
820 self.clone()
821 }
822}
823
824// ============================================================================
825// 5. Extension methods for closures
826// ============================================================================
827
828/// Extension trait providing one-time consumer composition methods for closures
829///
830/// Provides `and_then` and other composition methods for all closures implementing `FnOnce(&T)`,
831/// allowing closures to chain methods directly without explicit wrapper types.
832///
833/// # Features
834///
835/// - **Natural Syntax**: Chain operations directly on closures
836/// - **Returns BoxConsumerOnce**: Composed results can continue chaining
837/// - **Zero Cost**: No overhead when composing closures
838/// - **Automatic Implementation**: All `FnOnce(&T)` closures automatically get these methods
839///
840/// # Examples
841///
842/// ```rust
843/// use prism3_function::{ConsumerOnce, FnConsumerOnceOps};
844/// use std::sync::{Arc, Mutex};
845///
846/// let log = Arc::new(Mutex::new(Vec::new()));
847/// let l1 = log.clone();
848/// let l2 = log.clone();
849/// let chained = (move |x: &i32| {
850/// l1.lock().unwrap().push(*x * 2);
851/// }).and_then(move |x: &i32| {
852/// l2.lock().unwrap().push(*x + 10);
853/// });
854/// chained.accept_once(&5);
855/// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
856/// ```
857///
858/// # Author
859///
860/// Hu Haixing
861pub trait FnConsumerOnceOps<T>: FnOnce(&T) + Sized {
862 /// Sequentially chain another one-time consumer
863 ///
864 /// Returns a new consumer that executes the current operation first, then the next operation.
865 /// Consumes the current closure and returns `BoxConsumerOnce<T>`.
866 ///
867 /// # Type Parameters
868 ///
869 /// * `C` - Type of the next consumer
870 ///
871 /// # Parameters
872 ///
873 /// * `next` - Consumer to execute after the current operation. **Note: This
874 /// parameter is passed by value and will transfer ownership.** Since
875 /// `BoxConsumerOnce` cannot be cloned, the parameter will be consumed.
876 /// Can be:
877 /// - A closure: `|x: &T|`
878 /// - A `BoxConsumerOnce<T>`
879 /// - Any type implementing `ConsumerOnce<T>`
880 ///
881 /// # Returns
882 ///
883 /// Returns a combined `BoxConsumerOnce<T>`
884 ///
885 /// # Examples
886 ///
887 /// ```rust
888 /// use prism3_function::{ConsumerOnce, FnConsumerOnceOps};
889 /// use std::sync::{Arc, Mutex};
890 ///
891 /// let log = Arc::new(Mutex::new(Vec::new()));
892 /// let l1 = log.clone();
893 /// let l2 = log.clone();
894 /// let chained = (move |x: &i32| {
895 /// l1.lock().unwrap().push(*x * 2);
896 /// }).and_then(move |x: &i32| {
897 /// l2.lock().unwrap().push(*x + 10);
898 /// }).and_then(|x: &i32| println!("Result: {}", x));
899 ///
900 /// chained.accept_once(&5);
901 /// assert_eq!(*log.lock().unwrap(), vec![10, 15]);
902 /// ```
903 fn and_then<C>(self, next: C) -> BoxConsumerOnce<T>
904 where
905 Self: 'static,
906 C: ConsumerOnce<T> + 'static,
907 T: 'static,
908 {
909 let first = self;
910 let second = next;
911 BoxConsumerOnce::new(move |t| {
912 first(t);
913 second.accept_once(t);
914 })
915 }
916}
917
918/// Implement FnConsumerOnceOps for all closure types
919impl<T, F> FnConsumerOnceOps<T> for F where F: FnOnce(&T) {}