Skip to main content

qubit_function/functions/stateful_function/
arc_stateful_function.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 `ArcStatefulFunction` public type.
12
13use super::{
14    Arc,
15    ArcConditionalStatefulFunction,
16    BoxFunctionOnce,
17    BoxStatefulFunction,
18    Mutex,
19    Predicate,
20    RcStatefulFunction,
21    StatefulFunction,
22    impl_arc_conversions,
23    impl_function_clone,
24    impl_function_common_methods,
25    impl_function_constant_method,
26    impl_function_debug_display,
27    impl_function_identity_method,
28    impl_shared_function_methods,
29};
30
31// ============================================================================
32// ArcStatefulFunction - Arc<Mutex<dyn FnMut(&T) -> R + Send>>
33// ============================================================================
34
35/// ArcStatefulFunction - thread-safe function wrapper
36///
37/// A thread-safe, clonable function wrapper suitable for multi-threaded
38/// scenarios. Can be called multiple times and shared across threads
39/// while maintaining internal state.
40///
41/// # Features
42///
43/// - **Based on**: `Arc<Mutex<dyn FnMut(&T) -> R + Send>>`
44/// - **Ownership**: Shared ownership via reference counting
45/// - **Reusability**: Can be called multiple times (each call consumes
46///   its input)
47/// - **Thread Safety**: Thread-safe (`Send` required)
48/// - **Clonable**: Cheap cloning via `Arc::clone`
49/// - **Statefulness**: Can modify internal state between calls
50///
51pub struct ArcStatefulFunction<T, R> {
52    pub(super) function: ArcStatefulFn<T, R>,
53    pub(super) name: Option<String>,
54}
55
56type ArcStatefulFn<T, R> = Arc<Mutex<dyn FnMut(&T) -> R + Send + 'static>>;
57
58impl<T, R> ArcStatefulFunction<T, R> {
59    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
60    impl_function_common_methods!(
61        ArcStatefulFunction<T, R>,
62        (FnMut(&T) -> R + Send + 'static),
63        |f| Arc::new(Mutex::new(f))
64    );
65
66    // Generates: when(), and_then(), compose()
67    impl_shared_function_methods!(
68        ArcStatefulFunction<T, R>,
69        ArcConditionalStatefulFunction,
70        into_arc,
71        StatefulFunction,
72        Send + Sync + 'static
73    );
74}
75
76// Generates: constant() method for ArcStatefulFunction<T, R>
77impl_function_constant_method!(ArcStatefulFunction<T, R>, Send + Sync + 'static);
78
79// Generates: identity() method for ArcStatefulFunction<T, T>
80impl_function_identity_method!(ArcStatefulFunction<T, T>);
81
82// Generates: Clone implementation for ArcStatefulFunction<T, R>
83impl_function_clone!(ArcStatefulFunction<T, R>);
84
85// Generates: Debug and Display implementations for ArcStatefulFunction<T, R>
86impl_function_debug_display!(ArcStatefulFunction<T, R>);
87
88// Implement StatefulFunction trait for ArcStatefulFunction<T, R>
89impl<T, R> StatefulFunction<T, R> for ArcStatefulFunction<T, R> {
90    fn apply(&mut self, t: &T) -> R {
91        (self.function.lock())(t)
92    }
93
94    // Use macro to implement conversion methods
95    impl_arc_conversions!(
96        ArcStatefulFunction<T, R>,
97        BoxStatefulFunction,
98        RcStatefulFunction,
99        BoxFunctionOnce,
100        FnMut(t: &T) -> R
101    );
102}
103
104// ============================================================================
105// Blanket implementation for standard FnMut trait
106// ============================================================================
107
108/// Implement StatefulFunction<T, R> for any type that implements FnMut(&T) -> R
109///
110/// This allows closures to be used directly with our StatefulFunction trait
111/// without wrapping.
112///
113/// # Examples
114///
115/// ```rust
116/// use qubit_function::StatefulFunction;
117///
118/// let mut counter = 0;
119/// let mut function = |x: &i32| {
120///     counter += 1;
121///     *x + counter
122/// };
123///
124/// assert_eq!(function.apply(&10), 11);
125/// assert_eq!(function.apply(&10), 12);
126/// ```
127///
128impl<F, T, R> StatefulFunction<T, R> for F
129where
130    F: FnMut(&T) -> R,
131{
132    fn apply(&mut self, t: &T) -> R {
133        self(t)
134    }
135
136    fn into_box(self) -> BoxStatefulFunction<T, R>
137    where
138        Self: Sized + 'static,
139    {
140        BoxStatefulFunction::new(self)
141    }
142
143    fn into_rc(self) -> RcStatefulFunction<T, R>
144    where
145        Self: Sized + 'static,
146    {
147        RcStatefulFunction::new(self)
148    }
149
150    fn into_arc(self) -> ArcStatefulFunction<T, R>
151    where
152        Self: Sized + Send + 'static,
153    {
154        ArcStatefulFunction::new(self)
155    }
156
157    fn into_fn(self) -> impl FnMut(&T) -> R
158    where
159        Self: Sized + 'static,
160    {
161        self
162    }
163
164    fn to_box(&self) -> BoxStatefulFunction<T, R>
165    where
166        Self: Sized + Clone + 'static,
167    {
168        self.clone().into_box()
169    }
170
171    fn to_rc(&self) -> RcStatefulFunction<T, R>
172    where
173        Self: Sized + Clone + 'static,
174    {
175        self.clone().into_rc()
176    }
177
178    fn to_arc(&self) -> ArcStatefulFunction<T, R>
179    where
180        Self: Sized + Clone + Send + 'static,
181    {
182        self.clone().into_arc()
183    }
184
185    fn to_fn(&self) -> impl FnMut(&T) -> R
186    where
187        Self: Sized + Clone + 'static,
188    {
189        self.clone()
190    }
191
192    fn into_once(self) -> BoxFunctionOnce<T, R>
193    where
194        Self: Sized + 'static,
195    {
196        BoxFunctionOnce::new(self)
197    }
198
199    fn to_once(&self) -> BoxFunctionOnce<T, R>
200    where
201        Self: Sized + Clone + 'static,
202    {
203        BoxFunctionOnce::new(self.clone())
204    }
205}