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