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