Skip to main content

qubit_function/tasks/
callable_with.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # CallableWith Types
10//!
11//! Provides fallible, reusable computations that operate on a mutable input.
12//!
13//! A `CallableWith<T, R, E>` is equivalent to
14//! `FnMut(&mut T) -> Result<R, E>`, but uses task-oriented vocabulary. Use it
15//! when the operation needs access to protected or caller-provided state and
16//! returns a success value.
17//!
18//! The trait itself does not require `Send`; concurrent executors should add
19//! `+ Send + 'static` at their API boundary.
20//!
21//! # Author
22//!
23//! Haixing Hu
24
25use std::cell::RefCell;
26use std::rc::Rc;
27use std::sync::Arc;
28
29use parking_lot::Mutex;
30
31use crate::{
32    functions::macros::impl_function_debug_display,
33    macros::{
34        impl_arc_conversions,
35        impl_box_conversions,
36        impl_closure_trait,
37        impl_common_name_methods,
38        impl_common_new_methods,
39        impl_rc_conversions,
40    },
41    tasks::runnable_with::BoxRunnableWith,
42};
43
44mod box_callable_with;
45pub use box_callable_with::BoxCallableWith;
46mod rc_callable_with;
47pub use rc_callable_with::RcCallableWith;
48mod arc_callable_with;
49pub use arc_callable_with::ArcCallableWith;
50
51/// A fallible, reusable computation that receives mutable input.
52///
53/// Conceptually this is `FnMut(&mut T) -> Result<R, E>` with task-oriented
54/// naming. It is useful for executor-style APIs that run a task with access to
55/// protected state, such as a value held under a lock.
56///
57/// # Type Parameters
58///
59/// * `T` - The mutable input type.
60/// * `R` - The success value returned by the computation.
61/// * `E` - The error value returned when the computation fails.
62///
63/// # Author
64///
65/// Haixing Hu
66pub trait CallableWith<T, R, E> {
67    /// Executes the computation with mutable input.
68    ///
69    /// # Parameters
70    ///
71    /// * `input` - The mutable input passed to this task.
72    ///
73    /// # Returns
74    ///
75    /// Returns `Ok(R)` when the computation succeeds, or `Err(E)` when it
76    /// fails. The exact error meaning is defined by the concrete callable.
77    fn call_with(&mut self, input: &mut T) -> Result<R, E>;
78
79    /// Converts this callable into a boxed callable.
80    ///
81    /// # Returns
82    ///
83    /// A `BoxCallableWith<T, R, E>`.
84    fn into_box(mut self) -> BoxCallableWith<T, R, E>
85    where
86        Self: Sized + 'static,
87    {
88        BoxCallableWith::new(move |input| self.call_with(input))
89    }
90
91    /// Converts this callable into an `Rc` callable.
92    ///
93    /// # Returns
94    ///
95    /// A `RcCallableWith<T, R, E>`.
96    fn into_rc(mut self) -> RcCallableWith<T, R, E>
97    where
98        Self: Sized + 'static,
99    {
100        RcCallableWith::new(move |input| self.call_with(input))
101    }
102
103    /// Converts this callable into an `Arc` callable.
104    ///
105    /// # Returns
106    ///
107    /// An `ArcCallableWith<T, R, E>`.
108    fn into_arc(mut self) -> ArcCallableWith<T, R, E>
109    where
110        Self: Sized + Send + 'static,
111    {
112        ArcCallableWith::new(move |input| self.call_with(input))
113    }
114
115    /// Converts this callable into a mutable closure.
116    ///
117    /// # Returns
118    ///
119    /// A closure implementing `FnMut(&mut T) -> Result<R, E>`.
120    fn into_fn(mut self) -> impl FnMut(&mut T) -> Result<R, E>
121    where
122        Self: Sized + 'static,
123    {
124        move |input| self.call_with(input)
125    }
126
127    /// Converts this callable into a boxed callable without consuming `self`.
128    ///
129    /// # Returns
130    ///
131    /// A `BoxCallableWith<T, R, E>` built from a clone of this callable.
132    fn to_box(&self) -> BoxCallableWith<T, R, E>
133    where
134        Self: Clone + Sized + 'static,
135    {
136        self.clone().into_box()
137    }
138
139    /// Converts this callable into an `Rc` callable without consuming `self`.
140    ///
141    /// # Returns
142    ///
143    /// A `RcCallableWith<T, R, E>` built from a clone of this callable.
144    fn to_rc(&self) -> RcCallableWith<T, R, E>
145    where
146        Self: Clone + Sized + 'static,
147    {
148        self.clone().into_rc()
149    }
150
151    /// Converts this callable into an `Arc` callable without consuming `self`.
152    ///
153    /// # Returns
154    ///
155    /// An `ArcCallableWith<T, R, E>` built from a clone of this callable.
156    fn to_arc(&self) -> ArcCallableWith<T, R, E>
157    where
158        Self: Clone + Send + Sized + 'static,
159    {
160        self.clone().into_arc()
161    }
162
163    /// Converts this callable into a mutable closure without consuming `self`.
164    ///
165    /// # Returns
166    ///
167    /// A closure implementing `FnMut(&mut T) -> Result<R, E>`.
168    fn to_fn(&self) -> impl FnMut(&mut T) -> Result<R, E>
169    where
170        Self: Clone + Sized + 'static,
171    {
172        self.clone().into_fn()
173    }
174
175    /// Converts this callable into a runnable by discarding the success value.
176    ///
177    /// # Returns
178    ///
179    /// A `BoxRunnableWith<T, E>` preserving errors and mapping success to unit.
180    fn into_runnable_with(mut self) -> BoxRunnableWith<T, E>
181    where
182        Self: Sized + 'static,
183    {
184        BoxRunnableWith::new(move |input| self.call_with(input).map(|_| ()))
185    }
186}