qubit_function/consumers/consumer/rc_consumer.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10// qubit-style: allow explicit-imports
11//! Defines the `RcConsumer` public type.
12
13#![allow(unused_imports)]
14
15use super::*;
16
17// ============================================================================
18// 3. RcConsumer - Single-threaded Shared Ownership Implementation
19// ============================================================================
20
21/// RcConsumer struct
22///
23/// Non-mutating consumer implementation based on `Rc<dyn Fn(&T)>` for
24/// single-threaded shared ownership scenarios. The wrapper does not need
25/// `RefCell` because it only invokes a shared `Fn`.
26///
27/// # Features
28///
29/// - **Shared Ownership**: Cloneable through `Rc`, allows multiple owners
30/// - **Single-threaded**: Not thread-safe, cannot be sent across threads
31/// - **No Wrapper Interior Mutability Overhead**: No RefCell needed by the
32/// wrapper
33/// - **Non-consuming API**: `and_then` borrows `&self`, original object remains
34/// usable
35///
36/// # Use Cases
37///
38/// Choose `RcConsumer` when:
39/// - Need to share non-mutating consumer within a single thread
40/// - Pure observation operations, performance critical
41/// - Event handling in single-threaded UI frameworks
42///
43/// # Performance Advantages
44///
45/// `RcConsumer` has neither Arc's atomic operation overhead nor
46/// RefCell's runtime borrow checking overhead, making it the most performant of
47/// the three non-mutating consumers.
48///
49/// # Examples
50///
51/// ```rust
52/// use qubit_function::{Consumer, RcConsumer};
53///
54/// let consumer = RcConsumer::new(|x: &i32| {
55/// println!("Observed: {}", x);
56/// });
57/// let clone = consumer.clone();
58///
59/// consumer.accept(&5);
60/// clone.accept(&10);
61/// ```
62///
63pub struct RcConsumer<T> {
64 pub(super) function: Rc<dyn Fn(&T)>,
65 pub(super) name: Option<String>,
66}
67
68impl<T> RcConsumer<T> {
69 // Generates: new(), new_with_name(), name(), set_name(), noop()
70 impl_consumer_common_methods!(RcConsumer<T>, (Fn(&T) + 'static), |f| Rc::new(f));
71
72 // Generates: when() and and_then() methods that borrow &self (Rc can clone)
73 impl_shared_consumer_methods!(
74 RcConsumer<T>,
75 RcConditionalConsumer,
76 into_rc,
77 Consumer,
78 'static
79 );
80}
81
82impl<T> Consumer<T> for RcConsumer<T> {
83 fn accept(&self, value: &T) {
84 (self.function)(value)
85 }
86
87 // Use macro to implement conversion methods
88 impl_rc_conversions!(
89 RcConsumer<T>,
90 BoxConsumer,
91 BoxConsumerOnce,
92 Fn(t: &T)
93 );
94}
95
96// Use macro to generate Clone implementation
97impl_consumer_clone!(RcConsumer<T>);
98
99// Use macro to generate Debug and Display implementations
100impl_consumer_debug_display!(RcConsumer<T>);