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 readonly 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, neither modifying its own state nor
28//! modifying input values.
29//!
30//! Suitable for pure observation, logging, notification and other scenarios.
31//! Compared to Consumer, Consumer does not require interior mutability
32//! (Mutex/RefCell), making it more efficient and easier to share.
33//!
34//! # Author
35//!
36//! Haixing Hu
37
38use std::rc::Rc;
39use std::sync::Arc;
40
41use crate::consumers::consumer_once::BoxConsumerOnce;
42use crate::consumers::macros::{
43 impl_box_conditional_consumer,
44 impl_box_consumer_methods,
45 impl_conditional_consumer_clone,
46 impl_conditional_consumer_conversions,
47 impl_conditional_consumer_debug_display,
48 impl_consumer_clone,
49 impl_consumer_common_methods,
50 impl_consumer_debug_display,
51 impl_shared_conditional_consumer,
52 impl_shared_consumer_methods,
53};
54use crate::macros::{
55 impl_arc_conversions,
56 impl_box_conversions,
57 impl_closure_trait,
58 impl_rc_conversions,
59};
60use crate::predicates::predicate::{
61 ArcPredicate,
62 BoxPredicate,
63 Predicate,
64 RcPredicate,
65};
66
67// ============================================================================
68// 1. Consumer Trait - Unified Consumer Interface
69// ============================================================================
70
71/// Consumer trait - Unified readonly consumer interface
72///
73/// It is similar to the `Fn(&T)` trait in the standard library.
74///
75/// Defines the core behavior of all readonly consumer types. Unlike `Consumer`,
76/// `Consumer` neither modifies its own state nor modifies input values,
77/// making it a completely immutable operation.
78///
79/// # Auto-implementation
80///
81/// - All closures implementing `Fn(&T)`
82/// - `BoxConsumer<T>`, `ArcConsumer<T>`,
83/// `RcConsumer<T>`
84///
85/// # Features
86///
87/// - **Unified Interface**: All readonly consumer types share the same `accept`
88/// method signature
89/// - **Auto-implementation**: Closures automatically implement this trait with
90/// zero overhead
91/// - **Type Conversion**: Easy conversion between different ownership models
92/// - **Generic Programming**: Write functions that work with any readonly
93/// consumer type
94/// - **No Interior Mutability**: No need for Mutex or RefCell, more efficient
95///
96/// # Examples
97///
98/// ```rust
99/// use qubit_function::{Consumer, BoxConsumer};
100///
101/// fn apply_consumer<C: Consumer<i32>>(consumer: &C, value: &i32) {
102/// consumer.accept(value);
103/// }
104///
105/// let box_con = BoxConsumer::new(|x: &i32| {
106/// println!("Value: {}", x);
107/// });
108/// apply_consumer(&box_con, &5);
109/// ```
110///
111/// # Author
112///
113/// Haixing Hu
114pub trait Consumer<T> {
115 /// Execute readonly consumption operation
116 ///
117 /// Performs an operation on the given reference. The operation typically
118 /// reads input values or produces side effects, but neither modifies the
119 /// input value nor the consumer's own state.
120 ///
121 /// # Parameters
122 ///
123 /// * `value` - Reference to the value to consume
124 ///
125 /// # Examples
126 ///
127 /// ```rust
128 /// use qubit_function::{Consumer, BoxConsumer};
129 ///
130 /// let consumer = BoxConsumer::new(|x: &i32| println!("{}", x));
131 /// consumer.accept(&5);
132 /// ```
133 fn accept(&self, value: &T);
134
135 /// Convert to BoxConsumer
136 ///
137 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after
138 /// calling this method.
139 ///
140 /// # Returns
141 ///
142 /// Returns the wrapped `BoxConsumer<T>`
143 fn into_box(self) -> BoxConsumer<T>
144 where
145 Self: Sized + 'static,
146 {
147 BoxConsumer::new(move |t| self.accept(t))
148 }
149
150 /// Convert to RcConsumer
151 ///
152 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after
153 /// calling this method.
154 ///
155 /// # Returns
156 ///
157 /// Returns the wrapped `RcConsumer<T>`
158 fn into_rc(self) -> RcConsumer<T>
159 where
160 Self: Sized + 'static,
161 {
162 RcConsumer::new(move |t| self.accept(t))
163 }
164
165 /// Convert to ArcConsumer
166 ///
167 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after
168 /// calling this method.
169 ///
170 /// # Returns
171 ///
172 /// Returns the wrapped `ArcConsumer<T>`
173 fn into_arc(self) -> ArcConsumer<T>
174 where
175 Self: Sized + Send + Sync + 'static,
176 {
177 ArcConsumer::new(move |t| self.accept(t))
178 }
179
180 /// Convert to closure
181 ///
182 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after
183 /// calling this method.
184 ///
185 /// Converts a readonly consumer to a closure that can be used directly in
186 /// places where the standard library requires `Fn`.
187 ///
188 /// # Returns
189 ///
190 /// Returns a closure implementing `Fn(&T)`
191 ///
192 /// # Examples
193 ///
194 /// ```rust
195 /// use qubit_function::{Consumer, BoxConsumer};
196 ///
197 /// let consumer = BoxConsumer::new(|x: &i32| {
198 /// println!("Value: {}", x);
199 /// });
200 /// let func = consumer.into_fn();
201 /// func(&5);
202 /// ```
203 fn into_fn(self) -> impl Fn(&T)
204 where
205 Self: Sized + 'static,
206 {
207 move |t| self.accept(t)
208 }
209
210 /// Convert to ConsumerOnce
211 ///
212 /// **⚠️ Consumes `self`**: The original consumer will be unavailable after calling this method.
213 ///
214 /// Converts a reusable readonly consumer to a one-time consumer that consumes itself on use.
215 /// This enables passing `Consumer` to functions that require `ConsumerOnce`.
216 ///
217 /// # Returns
218 ///
219 /// Returns a `BoxConsumerOnce<T>`
220 ///
221 /// # Examples
222 ///
223 /// ```rust
224 ///
225 /// fn takes_once<C: ConsumerOnce<i32>>(consumer: C, value: &i32) {
226 /// consumer.accept(value);
227 /// }
228 ///
229 /// let consumer = BoxConsumer::new(|x: &i32| println!("{}", x));
230 /// takes_once(consumer.into_once(), &5);
231 /// ```
232 fn into_once(self) -> BoxConsumerOnce<T>
233 where
234 Self: Sized + 'static,
235 {
236 BoxConsumerOnce::new(move |t| self.accept(t))
237 }
238
239 /// Non-consuming conversion to `BoxConsumer`
240 ///
241 /// **⚠️ Does NOT consume `self`**: This method clones `self` and returns a
242 /// boxed readonly consumer that calls the cloned consumer. Requires
243 /// `Self: Clone` so it can be called through an immutable reference.
244 ///
245 /// # Returns
246 ///
247 /// Returns the wrapped `BoxConsumer<T>`
248 fn to_box(&self) -> BoxConsumer<T>
249 where
250 Self: Clone + 'static,
251 {
252 self.clone().into_box()
253 }
254
255 /// Non-consuming conversion to `RcConsumer`
256 ///
257 /// **⚠️ Does NOT consume `self`**: Clones `self` and returns an
258 /// `RcConsumer` that forwards to the cloned consumer. Requires
259 /// `Self: Clone`.
260 ///
261 /// # Returns
262 ///
263 /// Returns the wrapped `RcConsumer<T>`
264 fn to_rc(&self) -> RcConsumer<T>
265 where
266 Self: Clone + 'static,
267 {
268 self.clone().into_rc()
269 }
270
271 /// Non-consuming conversion to `ArcConsumer`
272 ///
273 /// **⚠️ Does NOT consume `self`**: Clones `self` and returns an
274 /// `ArcConsumer`. Requires `Self: Clone + Send + Sync` so the result
275 /// is thread-safe.
276 ///
277 /// # Returns
278 ///
279 /// Returns the wrapped `ArcConsumer<T>`
280 fn to_arc(&self) -> ArcConsumer<T>
281 where
282 Self: Clone + Send + Sync + 'static,
283 {
284 self.clone().into_arc()
285 }
286
287 /// Non-consuming conversion to a boxed closure
288 ///
289 /// **⚠️ Does NOT consume `self`**: Returns a closure which calls a cloned
290 /// copy of the consumer. Requires `Self: Clone`.
291 ///
292 /// # Returns
293 ///
294 /// Returns a closure implementing `Fn(&T)` which forwards to the cloned
295 /// consumer.
296 fn to_fn(&self) -> impl Fn(&T)
297 where
298 Self: Clone + 'static,
299 {
300 self.clone().into_fn()
301 }
302
303 /// Convert to ConsumerOnce without consuming self
304 ///
305 /// **⚠️ Requires Clone**: This method requires `Self` to implement `Clone`.
306 /// Clones the current consumer and converts the clone to a one-time consumer.
307 ///
308 /// # Returns
309 ///
310 /// Returns a `BoxConsumerOnce<T>`
311 ///
312 /// # Examples
313 ///
314 /// ```rust
315 ///
316 /// fn takes_once<C: ConsumerOnce<i32>>(consumer: C, value: &i32) {
317 /// consumer.accept(value);
318 /// }
319 ///
320 /// let consumer = BoxConsumer::new(|x: &i32| println!("{}", x));
321 /// takes_once(consumer.to_once(), &5);
322 /// ```
323 fn to_once(&self) -> BoxConsumerOnce<T>
324 where
325 Self: Clone + 'static,
326 {
327 self.clone().into_once()
328 }
329}
330
331// ============================================================================
332// 2. BoxConsumer - Single Ownership Implementation
333// ============================================================================
334
335/// BoxConsumer struct
336///
337/// Readonly consumer implementation based on `Box<dyn Fn(&T)>` for single
338/// ownership scenarios.
339///
340/// # Features
341///
342/// - **Single Ownership**: Not cloneable, transfers ownership when used
343/// - **Zero Overhead**: No reference counting or lock overhead
344/// - **Completely Immutable**: Neither modifies itself nor input
345/// - **No Interior Mutability**: No need for Mutex or RefCell
346///
347/// # Use Cases
348///
349/// Choose `BoxConsumer` when:
350/// - Readonly consumer is used once or in a linear flow
351/// - No need to share consumer across contexts
352/// - Pure observation operations, such as logging
353///
354/// # Examples
355///
356/// ```rust
357/// use qubit_function::{Consumer, BoxConsumer};
358///
359/// let consumer = BoxConsumer::new(|x: &i32| {
360/// println!("Observed value: {}", x);
361/// });
362/// consumer.accept(&5);
363/// ```
364///
365/// # Author
366///
367/// Haixing Hu
368pub struct BoxConsumer<T> {
369 function: Box<dyn Fn(&T)>,
370 name: Option<String>,
371}
372
373impl<T> BoxConsumer<T> {
374 // Generates: new(), new_with_name(), name(), set_name(), noop()
375 impl_consumer_common_methods!(BoxConsumer<T>, (Fn(&T) + 'static), |f| Box::new(f));
376
377 // Generates: when() and and_then() methods that consume self
378 impl_box_consumer_methods!(BoxConsumer<T>, BoxConditionalConsumer, Consumer);
379}
380
381impl<T> Consumer<T> for BoxConsumer<T> {
382 fn accept(&self, value: &T) {
383 (self.function)(value)
384 }
385
386 // Generates: into_box(), into_rc(), into_fn(), into_once()
387 impl_box_conversions!(BoxConsumer<T>, RcConsumer, Fn(&T), BoxConsumerOnce);
388}
389
390// Use macro to generate Debug and Display implementations
391impl_consumer_debug_display!(BoxConsumer<T>);
392
393// ============================================================================
394// 3. RcConsumer - Single-threaded Shared Ownership Implementation
395// ============================================================================
396
397/// RcConsumer struct
398///
399/// Readonly consumer implementation based on `Rc<dyn Fn(&T)>` for
400/// single-threaded shared ownership scenarios. No RefCell needed because
401/// operations are readonly.
402///
403/// # Features
404///
405/// - **Shared Ownership**: Cloneable through `Rc`, allows multiple owners
406/// - **Single-threaded**: Not thread-safe, cannot be sent across threads
407/// - **No Interior Mutability Overhead**: No RefCell needed because it's readonly
408/// - **Non-consuming API**: `and_then` borrows `&self`, original object remains
409/// usable
410///
411/// # Use Cases
412///
413/// Choose `RcConsumer` when:
414/// - Need to share readonly consumer within a single thread
415/// - Pure observation operations, performance critical
416/// - Event handling in single-threaded UI frameworks
417///
418/// # Performance Advantages
419///
420/// `RcConsumer` has neither Arc's atomic operation overhead nor
421/// RefCell's runtime borrow checking overhead, making it the most performant of
422/// the three readonly consumers.
423///
424/// # Examples
425///
426/// ```rust
427/// use qubit_function::{Consumer, RcConsumer};
428///
429/// let consumer = RcConsumer::new(|x: &i32| {
430/// println!("Observed: {}", x);
431/// });
432/// let clone = consumer.clone();
433///
434/// consumer.accept(&5);
435/// clone.accept(&10);
436/// ```
437///
438/// # Author
439///
440/// Haixing Hu
441pub struct RcConsumer<T> {
442 function: Rc<dyn Fn(&T)>,
443 name: Option<String>,
444}
445
446impl<T> RcConsumer<T> {
447 // Generates: new(), new_with_name(), name(), set_name(), noop()
448 impl_consumer_common_methods!(RcConsumer<T>, (Fn(&T) + 'static), |f| Rc::new(f));
449
450 // Generates: when() and and_then() methods that borrow &self (Rc can clone)
451 impl_shared_consumer_methods!(
452 RcConsumer<T>,
453 RcConditionalConsumer,
454 into_rc,
455 Consumer,
456 'static
457 );
458}
459
460impl<T> Consumer<T> for RcConsumer<T> {
461 fn accept(&self, value: &T) {
462 (self.function)(value)
463 }
464
465 // Use macro to implement conversion methods
466 impl_rc_conversions!(
467 RcConsumer<T>,
468 BoxConsumer,
469 BoxConsumerOnce,
470 Fn(t: &T)
471 );
472}
473
474// Use macro to generate Clone implementation
475impl_consumer_clone!(RcConsumer<T>);
476
477// Use macro to generate Debug and Display implementations
478impl_consumer_debug_display!(RcConsumer<T>);
479
480// ============================================================================
481// 4. ArcConsumer - Thread-safe Shared Ownership Implementation
482// ============================================================================
483
484/// ArcConsumer struct
485///
486/// Readonly consumer implementation based on `Arc<dyn Fn(&T) + Send + Sync>`,
487/// for thread-safe shared ownership scenarios. No Mutex needed because
488/// operations are readonly.
489///
490/// # Features
491///
492/// - **Shared Ownership**: Cloneable through `Arc`, allows multiple owners
493/// - **Thread Safe**: Implements `Send + Sync`, can be safely used concurrently
494/// - **Lock-free**: No Mutex protection needed because it's readonly
495/// - **Non-consuming API**: `and_then` borrows `&self`, original object remains
496/// usable
497///
498/// # Use Cases
499///
500/// Choose `ArcConsumer` when:
501/// - Need to share readonly consumer across multiple threads
502/// - Pure observation operations, such as logging, monitoring, notifications
503/// - Need high-concurrency reads with no lock overhead
504///
505/// # Performance Advantages
506///
507/// Compared to `ArcConsumer`, `ArcConsumer` has no Mutex lock overhead,
508/// performing better in high-concurrency scenarios.
509///
510/// # Examples
511///
512/// ```rust
513/// use qubit_function::{Consumer, ArcConsumer};
514///
515/// let consumer = ArcConsumer::new(|x: &i32| {
516/// println!("Observed: {}", x);
517/// });
518/// let clone = consumer.clone();
519///
520/// consumer.accept(&5);
521/// clone.accept(&10);
522/// ```
523///
524/// # Author
525///
526/// Haixing Hu
527pub struct ArcConsumer<T> {
528 function: Arc<dyn Fn(&T) + Send + Sync>,
529 name: Option<String>,
530}
531
532impl<T> ArcConsumer<T> {
533 // Generates: new(), new_with_name(), name(), set_name(), noop()
534 impl_consumer_common_methods!(ArcConsumer<T>, (Fn(&T) + Send + Sync + 'static), |f| {
535 Arc::new(f)
536 });
537
538 // Generates: when() and and_then() methods that borrow &self (Arc can clone)
539 impl_shared_consumer_methods!(
540 ArcConsumer<T>,
541 ArcConditionalConsumer,
542 into_arc,
543 Consumer,
544 Send + Sync + 'static
545 );
546}
547
548impl<T> Consumer<T> for ArcConsumer<T> {
549 fn accept(&self, value: &T) {
550 (self.function)(value)
551 }
552
553 // Use macro to implement conversion methods
554 impl_arc_conversions!(
555 ArcConsumer<T>,
556 BoxConsumer,
557 RcConsumer,
558 BoxConsumerOnce,
559 Fn(t: &T)
560 );
561}
562
563// Use macro to generate Clone implementation
564impl_consumer_clone!(ArcConsumer<T>);
565
566// Use macro to generate Debug and Display implementations
567impl_consumer_debug_display!(ArcConsumer<T>);
568
569// ============================================================================
570// 5. Implement Consumer trait for closures
571// ============================================================================
572
573// Implement Consumer for all Fn(&T)
574impl_closure_trait!(
575 Consumer<T>,
576 accept,
577 BoxConsumerOnce,
578 Fn(value: &T)
579);
580
581// ============================================================================
582// 6. Provide extension methods for closures
583// ============================================================================
584
585/// Extension trait providing readonly consumer composition methods for closures
586///
587/// Provides `and_then` and other composition methods for all closures
588/// implementing `Fn(&T)`, allowing closures to directly chain methods without
589/// explicit wrapper types.
590///
591/// # Features
592///
593/// - **Natural Syntax**: Chain operations directly on closures
594/// - **Returns BoxConsumer**: Combined results can continue chaining
595/// - **Zero Cost**: No overhead when composing closures
596/// - **Auto-implementation**: All `Fn(&T)` closures automatically get these
597/// methods
598///
599/// # Examples
600///
601/// ```rust
602/// use qubit_function::{Consumer, FnConsumerOps};
603///
604/// let chained = (|x: &i32| {
605/// println!("First: {}", x);
606/// }).and_then(|x: &i32| {
607/// println!("Second: {}", x);
608/// });
609/// chained.accept(&5);
610/// ```
611///
612/// # Author
613///
614/// Haixing Hu
615pub trait FnConsumerOps<T>: Fn(&T) + Sized {
616 /// Sequentially chain another readonly consumer
617 ///
618 /// Returns a new consumer that executes the current operation first, then the
619 /// next operation. Consumes the current closure and returns
620 /// `BoxConsumer<T>`.
621 ///
622 /// # Type Parameters
623 ///
624 /// * `C` - Type of the next consumer
625 ///
626 /// # Parameters
627 ///
628 /// * `next` - Consumer to execute after the current operation
629 ///
630 /// # Returns
631 ///
632 /// Returns a combined `BoxConsumer<T>`
633 ///
634 /// # Examples
635 ///
636 /// ```rust
637 /// use qubit_function::{Consumer, FnConsumerOps};
638 ///
639 /// let chained = (|x: &i32| {
640 /// println!("First: {}", x);
641 /// }).and_then(|x: &i32| {
642 /// println!("Second: {}", x);
643 /// }).and_then(|x: &i32| println!("Third: {}", x));
644 ///
645 /// chained.accept(&5);
646 /// ```
647 fn and_then<C>(self, next: C) -> BoxConsumer<T>
648 where
649 Self: 'static,
650 C: Consumer<T> + 'static,
651 T: 'static,
652 {
653 let first = self;
654 let second = next;
655 BoxConsumer::new(move |t| {
656 first(t);
657 second.accept(t);
658 })
659 }
660}
661
662/// Implement FnConsumerOps for all closure types
663impl<T, F> FnConsumerOps<T> for F where F: Fn(&T) {}
664
665// ============================================================================
666// 7. BoxConditionalConsumer - Box-based Conditional Consumer
667// ============================================================================
668
669/// BoxConditionalConsumer struct
670///
671/// A conditional readonly consumer that only executes when a predicate is satisfied.
672/// Uses `BoxConsumer` and `BoxPredicate` for single ownership semantics.
673///
674/// This type is typically created by calling `BoxConsumer::when()` and is
675/// designed to work with the `or_else()` method to create if-then-else logic.
676///
677/// # Features
678///
679/// - **Single Ownership**: Not cloneable, consumes `self` on use
680/// - **Conditional Execution**: Only consumes when predicate returns `true`
681/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
682/// - **Implements Consumer**: Can be used anywhere a `Consumer` is expected
683/// - **Readonly**: Neither modifies itself nor input values
684///
685/// # Examples
686///
687/// ## Basic Conditional Execution
688///
689/// ```rust
690/// use qubit_function::{Consumer, BoxConsumer};
691///
692/// let consumer = BoxConsumer::new(|x: &i32| {
693/// println!("Positive: {}", x);
694/// });
695/// let conditional = consumer.when(|x: &i32| *x > 0);
696///
697/// conditional.accept(&5); // Prints: Positive: 5
698/// conditional.accept(&-5); // Does nothing
699/// ```
700///
701/// ## With or_else Branch
702///
703/// ```rust
704/// use qubit_function::{Consumer, BoxConsumer};
705///
706/// let consumer = BoxConsumer::new(|x: &i32| {
707/// println!("Positive: {}", x);
708/// })
709/// .when(|x: &i32| *x > 0)
710/// .or_else(|x: &i32| {
711/// println!("Non-positive: {}", x);
712/// });
713///
714/// consumer.accept(&5); // Prints: Positive: 5
715/// consumer.accept(&-5); // Prints: Non-positive: -5
716/// ```
717///
718/// # Author
719///
720/// Haixing Hu
721pub struct BoxConditionalConsumer<T> {
722 consumer: BoxConsumer<T>,
723 predicate: BoxPredicate<T>,
724}
725
726// Use macro to generate conditional consumer implementations
727impl_box_conditional_consumer!(BoxConditionalConsumer<T>, BoxConsumer, Consumer);
728
729// Consumer trait implementation
730impl<T> Consumer<T> for BoxConditionalConsumer<T> {
731 fn accept(&self, value: &T) {
732 if self.predicate.test(value) {
733 self.consumer.accept(value);
734 }
735 }
736
737 // Generates: into_box(), into_rc(), into_fn()
738 impl_conditional_consumer_conversions!(BoxConsumer<T>, RcConsumer, Fn);
739}
740
741// Use macro to generate Debug and Display implementations
742impl_conditional_consumer_debug_display!(BoxConditionalConsumer<T>);
743
744// ============================================================================
745// 8. RcConditionalConsumer - Rc-based Conditional Consumer
746// ============================================================================
747
748/// RcConditionalConsumer struct
749///
750/// A conditional readonly consumer that only executes when a predicate is satisfied.
751/// Uses `RcConsumer` and `RcPredicate` for single-threaded shared ownership semantics.
752///
753/// This type is typically created by calling `RcConsumer::when()` and is
754/// designed to work with the `or_else()` method to create if-then-else logic.
755///
756/// # Features
757///
758/// - **Shared Ownership**: Cloneable through `Rc`, allows multiple owners
759/// - **Single-threaded**: Not thread-safe, cannot be sent across threads
760/// - **Conditional Execution**: Only consumes when predicate returns `true`
761/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
762/// - **Implements Consumer**: Can be used anywhere a `Consumer` is expected
763/// - **Readonly**: Neither modifies itself nor input values
764///
765/// # Examples
766///
767/// ## Basic Conditional Execution
768///
769/// ```rust
770/// use qubit_function::{Consumer, RcConsumer};
771///
772/// let consumer = RcConsumer::new(|x: &i32| {
773/// println!("Positive: {}", x);
774/// });
775/// let conditional = consumer.when(|x: &i32| *x > 0);
776///
777/// conditional.accept(&5); // Prints: Positive: 5
778/// conditional.accept(&-5); // Does nothing
779/// ```
780///
781/// ## With or_else Branch
782///
783/// ```rust
784/// use qubit_function::{Consumer, RcConsumer};
785///
786/// let consumer = RcConsumer::new(|x: &i32| {
787/// println!("Positive: {}", x);
788/// })
789/// .when(|x: &i32| *x > 0)
790/// .or_else(|x: &i32| {
791/// println!("Non-positive: {}", x);
792/// });
793///
794/// consumer.accept(&5); // Prints: Positive: 5
795/// consumer.accept(&-5); // Prints: Non-positive: -5
796/// ```
797///
798/// # Author
799///
800/// Haixing Hu
801pub struct RcConditionalConsumer<T> {
802 consumer: RcConsumer<T>,
803 predicate: RcPredicate<T>,
804}
805
806// Use macro to generate conditional consumer implementations
807impl_shared_conditional_consumer!(
808 RcConditionalConsumer<T>,
809 RcConsumer,
810 Consumer,
811 into_rc,
812 'static
813);
814
815// Hand-written Consumer trait implementation
816impl<T> Consumer<T> for RcConditionalConsumer<T> {
817 fn accept(&self, value: &T) {
818 if self.predicate.test(value) {
819 self.consumer.accept(value);
820 }
821 }
822
823 // Generates: into_box(), into_rc(), into_fn()
824 impl_conditional_consumer_conversions!(BoxConsumer<T>, RcConsumer, Fn);
825}
826
827// Use macro to generate Clone implementation
828impl_conditional_consumer_clone!(RcConditionalConsumer<T>);
829
830// Use macro to generate Debug and Display implementations
831impl_conditional_consumer_debug_display!(RcConditionalConsumer<T>);
832
833// ============================================================================
834// 9. ArcConditionalConsumer - Arc-based Conditional Consumer
835// ============================================================================
836
837/// ArcConditionalConsumer struct
838///
839/// A conditional readonly consumer that only executes when a predicate is satisfied.
840/// Uses `ArcConsumer` and `ArcPredicate` for thread-safe shared ownership semantics.
841///
842/// This type is typically created by calling `ArcConsumer::when()` and is
843/// designed to work with the `or_else()` method to create if-then-else logic.
844///
845/// # Features
846///
847/// - **Shared Ownership**: Cloneable through `Arc`, allows multiple owners
848/// - **Thread Safe**: Implements `Send + Sync`, can be safely used concurrently
849/// - **Conditional Execution**: Only consumes when predicate returns `true`
850/// - **Chainable**: Can add `or_else` branch to create if-then-else logic
851/// - **Implements Consumer**: Can be used anywhere a `Consumer` is expected
852/// - **Readonly**: Neither modifies itself nor input values
853///
854/// # Examples
855///
856/// ## Basic Conditional Execution
857///
858/// ```rust
859/// use qubit_function::{Consumer, ArcConsumer};
860///
861/// let consumer = ArcConsumer::new(|x: &i32| {
862/// println!("Positive: {}", x);
863/// });
864/// let conditional = consumer.when(|x: &i32| *x > 0);
865///
866/// conditional.accept(&5); // Prints: Positive: 5
867/// conditional.accept(&-5); // Does nothing
868/// ```
869///
870/// ## With or_else Branch
871///
872/// ```rust
873/// use qubit_function::{Consumer, ArcConsumer};
874///
875/// let consumer = ArcConsumer::new(|x: &i32| {
876/// println!("Positive: {}", x);
877/// })
878/// .when(|x: &i32| *x > 0)
879/// .or_else(|x: &i32| {
880/// println!("Non-positive: {}", x);
881/// });
882///
883/// consumer.accept(&5); // Prints: Positive: 5
884/// consumer.accept(&-5); // Prints: Non-positive: -5
885/// ```
886///
887/// # Author
888///
889/// Haixing Hu
890pub struct ArcConditionalConsumer<T> {
891 consumer: ArcConsumer<T>,
892 predicate: ArcPredicate<T>,
893}
894
895// Use macro to generate conditional consumer implementations
896impl_shared_conditional_consumer!(
897 ArcConditionalConsumer<T>,
898 ArcConsumer,
899 Consumer,
900 into_arc,
901 Send + Sync + 'static
902);
903
904// Hand-written Consumer trait implementation
905impl<T> Consumer<T> for ArcConditionalConsumer<T> {
906 fn accept(&self, value: &T) {
907 if self.predicate.test(value) {
908 self.consumer.accept(value);
909 }
910 }
911
912 // Generates: into_box(), into_rc(), into_fn()
913 impl_conditional_consumer_conversions!(BoxConsumer<T>, RcConsumer, Fn);
914}
915
916// Use macro to generate Clone implementation
917impl_conditional_consumer_clone!(ArcConditionalConsumer<T>);
918
919// Use macro to generate Debug and Display implementations
920impl_conditional_consumer_debug_display!(ArcConditionalConsumer<T>);