prism3_function/consumers/
consumer.rs

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