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