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