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    {
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>);