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