qubit_function/tasks/runnable/box_runnable.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! Defines the `BoxRunnable` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// ============================================================================
16// BoxRunnable
17// ============================================================================
18
19/// Box-based reusable runnable.
20///
21/// `BoxRunnable<E>` stores a `Box<dyn FnMut() -> Result<(), E>>` and can be
22/// executed repeatedly. It is the boxed concrete implementation of
23/// [`Runnable`].
24///
25/// # Type Parameters
26///
27/// * `E` - The error value returned when the action fails.
28///
29/// # Examples
30///
31/// ```rust
32/// use qubit_function::{BoxRunnable, Runnable};
33///
34/// let mut task = BoxRunnable::new(|| Ok::<(), String>(()));
35/// assert_eq!(task.run(), Ok(()));
36/// ```
37///
38/// # Author
39///
40/// Haixing Hu
41pub struct BoxRunnable<E> {
42 /// The stateful closure executed by this runnable.
43 pub(super) function: Box<dyn FnMut() -> Result<(), E>>,
44 /// The optional name of this runnable.
45 pub(super) name: Option<String>,
46}
47
48impl<E> BoxRunnable<E> {
49 impl_common_new_methods!(
50 (FnMut() -> Result<(), E> + 'static),
51 |function| Box::new(function),
52 "runnable"
53 );
54
55 /// Creates a boxed runnable from a reusable supplier.
56 ///
57 /// This is an explicit bridge from `Supplier<Result<(), E>>` to
58 /// `Runnable<E>`.
59 ///
60 /// # Parameters
61 ///
62 /// * `supplier` - The supplier that produces the runnable result.
63 ///
64 /// # Returns
65 ///
66 /// A new `BoxRunnable<E>`.
67 #[inline]
68 pub fn from_supplier<S>(supplier: S) -> Self
69 where
70 S: Supplier<Result<(), E>> + 'static,
71 {
72 Self::new(move || supplier.get())
73 }
74
75 impl_common_name_methods!("runnable");
76
77 /// Chains another runnable after this runnable succeeds.
78 ///
79 /// The second runnable is not executed if this runnable returns `Err`.
80 ///
81 /// # Parameters
82 ///
83 /// * `next` - The runnable to execute after this runnable succeeds.
84 ///
85 /// # Returns
86 ///
87 /// A runnable executing both actions in sequence.
88 #[inline]
89 pub fn and_then<N>(self, next: N) -> BoxRunnable<E>
90 where
91 N: Runnable<E> + 'static,
92 E: 'static,
93 {
94 let name = self.name;
95 let mut function = self.function;
96 let mut next = next;
97 BoxRunnable::new_with_optional_name(
98 move || {
99 function()?;
100 next.run()
101 },
102 name,
103 )
104 }
105
106 /// Runs this runnable before a callable.
107 ///
108 /// The callable is not executed if this runnable returns `Err`.
109 ///
110 /// # Parameters
111 ///
112 /// * `callable` - The callable to execute after this runnable succeeds.
113 ///
114 /// # Returns
115 ///
116 /// A callable producing the second computation's result.
117 #[inline]
118 pub fn then_callable<R, C>(self, callable: C) -> BoxCallable<R, E>
119 where
120 C: crate::tasks::callable::Callable<R, E> + 'static,
121 R: 'static,
122 E: 'static,
123 {
124 let name = self.name;
125 let mut function = self.function;
126 let mut callable = callable;
127 BoxCallable::new_with_optional_name(
128 move || {
129 function()?;
130 callable.call()
131 },
132 name,
133 )
134 }
135}
136
137impl<E> Runnable<E> for BoxRunnable<E> {
138 /// Executes the boxed runnable.
139 #[inline]
140 fn run(&mut self) -> Result<(), E> {
141 (self.function)()
142 }
143
144 impl_box_conversions!(
145 BoxRunnable<E>,
146 RcRunnable,
147 FnMut() -> Result<(), E>
148 );
149
150 /// Converts this boxed runnable into a boxed callable while preserving its
151 /// name.
152 #[inline]
153 fn into_callable(self) -> BoxCallable<(), E>
154 where
155 Self: Sized + 'static,
156 {
157 let name = self.name;
158 let mut function = self.function;
159 BoxCallable::new_with_optional_name(
160 move || {
161 function()?;
162 Ok(())
163 },
164 name,
165 )
166 }
167}