Skip to main content

qubit_function/tasks/
callable.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//! # Callable Types
11//!
12//! Provides fallible, reusable, zero-argument computations.
13//!
14//! A `Callable<R, E>` is equivalent to `FnMut() -> Result<R, E>`, but uses
15//! task-oriented vocabulary. Use it when the operation is a computation or task
16//! whose success value matters. Use `Runnable<E>` when the operation only needs
17//! to report success or failure.
18//!
19//! The trait itself does not require `Send`; concurrent executors should add
20//! `+ Send + 'static` at their API boundary.
21//!
22
23use std::cell::RefCell;
24use std::rc::Rc;
25use std::sync::Arc;
26
27use parking_lot::Mutex;
28
29use crate::{
30    functions::macros::impl_function_debug_display,
31    macros::{
32        impl_arc_conversions,
33        impl_box_conversions,
34        impl_closure_trait,
35        impl_common_name_methods,
36        impl_common_new_methods,
37        impl_rc_conversions,
38    },
39    suppliers::supplier::Supplier,
40    tasks::callable_once::BoxCallableOnce,
41    tasks::runnable::BoxRunnable,
42};
43
44mod box_callable;
45pub use box_callable::BoxCallable;
46mod rc_callable;
47pub use rc_callable::RcCallable;
48mod arc_callable;
49pub use arc_callable::ArcCallable;
50
51// ============================================================================
52// Callable Trait
53// ============================================================================
54
55/// A fallible, reusable zero-argument computation.
56///
57/// Conceptually this is the same shape as `FnMut() -> Result<R, E>`: `call` takes
58/// `&mut self` and returns `Result<R, E>`, but the API uses task-oriented naming
59/// and helpers. In this crate it aligns with [`Supplier`] of `Result<R, E>`—a
60/// fallible supplier—while emphasizing executable work rather than plain value
61/// production.
62///
63/// Choose **`Callable`** when callers need the success value `R`. When only
64/// success or failure matters, use [`Runnable`](crate::tasks::Runnable), whose
65/// success type is `()`.
66///
67/// # Type Parameters
68///
69/// * `R` - The success value returned by the computation.
70/// * `E` - The error value returned when the computation fails.
71///
72/// # Examples
73///
74/// ```rust
75/// use qubit_function::Callable;
76///
77/// let mut task = || Ok::<i32, String>(21 * 2);
78/// assert_eq!(task.call().expect("call should succeed"), 42);
79/// ```
80///
81pub trait Callable<R, E> {
82    /// Executes the computation, borrowing `self` mutably.
83    ///
84    /// # Returns
85    ///
86    /// Returns `Ok(R)` when the computation succeeds, or `Err(E)` when it
87    /// fails. The exact error meaning is defined by the concrete callable.
88    fn call(&mut self) -> Result<R, E>;
89
90    /// Converts this callable into a boxed callable.
91    ///
92    /// # Returns
93    ///
94    /// A `BoxCallable<R, E>` that executes this callable when `call()` is
95    /// invoked.
96    fn into_box(mut self) -> BoxCallable<R, E>
97    where
98        Self: Sized + 'static,
99    {
100        BoxCallable::new(move || self.call())
101    }
102
103    /// Converts this callable into an `Rc` callable.
104    ///
105    /// # Returns
106    ///
107    /// A `RcCallable<R, E>`.
108    fn into_rc(mut self) -> RcCallable<R, E>
109    where
110        Self: Sized + 'static,
111    {
112        RcCallable::new(move || self.call())
113    }
114
115    /// Converts this callable into an `Arc` callable.
116    ///
117    /// # Returns
118    ///
119    /// An `ArcCallable<R, E>`.
120    fn into_arc(mut self) -> ArcCallable<R, E>
121    where
122        Self: Sized + Send + 'static,
123    {
124        ArcCallable::new(move || self.call())
125    }
126
127    /// Converts this callable into a mutable closure.
128    ///
129    /// # Returns
130    ///
131    /// A closure implementing `FnMut() -> Result<R, E>`.
132    fn into_fn(mut self) -> impl FnMut() -> Result<R, E>
133    where
134        Self: Sized + 'static,
135    {
136        move || self.call()
137    }
138
139    /// Converts this callable into a boxed callable without consuming `self`.
140    ///
141    /// The method clones `self` and boxes the clone. Use this for cloneable
142    /// callable values that need to be reused after boxing.
143    ///
144    /// # Returns
145    ///
146    /// A new `BoxCallable<R, E>` built from a clone of this callable.
147    fn to_box(&self) -> BoxCallable<R, E>
148    where
149        Self: Clone + Sized + 'static,
150    {
151        self.clone().into_box()
152    }
153
154    /// Converts this callable into an `Rc` callable without consuming `self`.
155    ///
156    /// The method clones `self` and wraps the clone.
157    ///
158    /// # Returns
159    ///
160    /// A `RcCallable<R, E>`.
161    fn to_rc(&self) -> RcCallable<R, E>
162    where
163        Self: Clone + Sized + 'static,
164    {
165        self.clone().into_rc()
166    }
167
168    /// Converts this callable into an `Arc` callable without consuming `self`.
169    ///
170    /// The method clones `self` and wraps the clone.
171    ///
172    /// # Returns
173    ///
174    /// An `ArcCallable<R, E>`.
175    fn to_arc(&self) -> ArcCallable<R, E>
176    where
177        Self: Clone + Send + Sized + 'static,
178    {
179        self.clone().into_arc()
180    }
181
182    /// Converts this callable into a mutable closure without consuming `self`.
183    ///
184    /// The method clones `self` and returns a closure that executes the clone
185    /// on each call.
186    ///
187    /// # Returns
188    ///
189    /// A closure implementing `FnMut() -> Result<R, E>`.
190    fn to_fn(&self) -> impl FnMut() -> Result<R, E>
191    where
192        Self: Clone + Sized + 'static,
193    {
194        self.clone().into_fn()
195    }
196
197    /// Converts this callable into a one-time callable.
198    ///
199    /// The returned callable consumes itself on each invocation.
200    ///
201    /// # Returns
202    ///
203    /// A `BoxCallableOnce<R, E>`.
204    fn into_once(mut self) -> BoxCallableOnce<R, E>
205    where
206        Self: Sized + 'static,
207    {
208        BoxCallableOnce::new(move || self.call())
209    }
210
211    /// Converts this callable into a one-time callable without consuming
212    /// `self`.
213    ///
214    /// The method clones `self` and returns a one-time callable.
215    ///
216    /// # Returns
217    ///
218    /// A `BoxCallableOnce<R, E>`.
219    fn to_once(&self) -> BoxCallableOnce<R, E>
220    where
221        Self: Clone + Sized + 'static,
222    {
223        self.clone().into_once()
224    }
225
226    /// Converts this callable into a runnable by discarding the success value.
227    ///
228    /// The returned runnable preserves errors and maps any `Ok(R)` to
229    /// `Ok(())`.
230    ///
231    /// # Returns
232    ///
233    /// A `BoxRunnable<E>` that executes this callable and discards its success
234    /// value.
235    fn into_runnable(mut self) -> BoxRunnable<E>
236    where
237        Self: Sized + 'static,
238    {
239        BoxRunnable::new(move || self.call().map(|_| ()))
240    }
241}