Skip to main content

qubit_function/suppliers/supplier/
rc_supplier.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 `RcSupplier` public type.
12
13use super::{
14    ArcSupplier,
15    BoxSupplier,
16    BoxSupplierOnce,
17    Predicate,
18    Rc,
19    Supplier,
20    Transformer,
21    impl_closure_trait,
22    impl_rc_conversions,
23    impl_shared_supplier_methods,
24    impl_supplier_clone,
25    impl_supplier_common_methods,
26    impl_supplier_debug_display,
27};
28
29// ======================================================================
30// RcSupplier - Single-threaded Shared Ownership
31// ======================================================================
32
33/// Single-threaded shared ownership stateless supplier.
34///
35/// Uses `Rc<dyn Fn() -> T>` for single-threaded shared ownership.
36/// Can be cloned but not sent across threads.
37///
38/// # Ownership Model
39///
40/// Like `ArcSupplier`, methods borrow `&self` instead of
41/// consuming `self`:
42///
43/// ```rust
44/// use qubit_function::{RcSupplier, Supplier};
45///
46/// let source = RcSupplier::new(|| 10);
47/// let mapped = source.map(|x| x * 2);
48/// // source is still usable here!
49/// ```
50///
51/// # Examples
52///
53/// ## Shared Factory
54///
55/// ```rust
56/// use qubit_function::{RcSupplier, Supplier};
57///
58/// let factory = RcSupplier::new(|| {
59///     String::from("Hello")
60/// });
61///
62/// let f1 = factory.clone();
63/// let f2 = factory.clone();
64/// assert_eq!(f1.get(), "Hello");
65/// assert_eq!(f2.get(), "Hello");
66/// ```
67///
68/// ## Reusable Transformations
69///
70/// ```rust
71/// use qubit_function::{RcSupplier, Supplier};
72///
73/// let base = RcSupplier::new(|| 10);
74/// let doubled = base.map(|x| x * 2);
75/// let tripled = base.map(|x| x * 3);
76///
77/// assert_eq!(base.get(), 10);
78/// assert_eq!(doubled.get(), 20);
79/// assert_eq!(tripled.get(), 30);
80/// ```
81///
82pub struct RcSupplier<T> {
83    pub(super) function: Rc<dyn Fn() -> T>,
84    pub(super) name: Option<String>,
85}
86
87impl<T> RcSupplier<T> {
88    // Generates: new(), new_with_name(), name(), set_name(), constant()
89    impl_supplier_common_methods!(RcSupplier<T>, (Fn() -> T + 'static), |f| Rc::new(f));
90
91    // Generates: map(), filter(), zip()
92    impl_shared_supplier_methods!(
93        RcSupplier<T>,
94        Supplier,
95        ('static)
96    );
97}
98
99// Generates: Debug and Display implementations for RcSupplier<T>
100impl_supplier_debug_display!(RcSupplier<T>);
101
102// Generates: Clone implementation for RcSupplier<T>
103impl_supplier_clone!(RcSupplier<T>);
104
105impl<T> Supplier<T> for RcSupplier<T> {
106    fn get(&self) -> T {
107        (self.function)()
108    }
109
110    // Generate all conversion methods using the unified macro
111    impl_rc_conversions!(
112        RcSupplier<T>,
113        BoxSupplier,
114        BoxSupplierOnce,
115        Fn() -> T
116    );
117}
118
119// ======================================================================
120// Implement Supplier for Closures
121// ======================================================================
122
123// Implement Supplier<T> for any type that implements Fn() -> T
124impl_closure_trait!(
125    Supplier<T>,
126    get,
127    BoxSupplierOnce,
128    Fn() -> T
129);
130
131// ======================================================================
132// Note on Extension Traits for Closures
133// ======================================================================
134//
135// We don't provide `FnSupplierOps` trait for `Fn() -> T` closures
136// because:
137//
138// 1. All `Fn` closures also implement `FnMut`, so they can use `FnSupplierOps`
139//    from the `supplier` module
140// 2. Providing both would cause ambiguity errors due to overlapping trait impls
141// 3. Rust doesn't support negative trait bounds to exclude `FnMut`
142//
143// Users of `Fn` closures should use `FnSupplierOps` from `supplier` module,
144// or explicitly convert to `BoxSupplier` using `.into_box()` first.