Skip to main content

qubit_function/tasks/runnable_once/
local_box_runnable_once.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// qubit-style: allow explicit-imports
11//! Defines the `LocalBoxRunnableOnce` public type.
12
13#![allow(unused_imports)]
14
15use super::*;
16
17// ============================================================================
18// LocalBoxRunnableOnce
19// ============================================================================
20
21/// Local box-based one-time runnable.
22///
23/// `LocalBoxRunnableOnce<E>` stores a `Box<dyn FnOnce() -> Result<(), E>>` and
24/// can be executed only once on the local thread. Use [`BoxRunnableOnce`] when
25/// the runnable must be movable across threads.
26///
27/// # Type Parameters
28///
29/// * `E` - The error value returned when the action fails.
30///
31pub struct LocalBoxRunnableOnce<E> {
32    /// The one-time closure executed by this runnable.
33    pub(super) function: Box<dyn FnOnce() -> Result<(), E>>,
34    /// The optional name of this runnable.
35    pub(super) name: Option<String>,
36}
37
38impl<E> LocalBoxRunnableOnce<E> {
39    impl_common_new_methods!(
40        (FnOnce() -> Result<(), E> + 'static),
41        |function| Box::new(function),
42        "local runnable"
43    );
44
45    /// Creates a local boxed runnable from a one-time supplier.
46    ///
47    /// This is an explicit bridge from `SupplierOnce<Result<(), E>>` to
48    /// `RunnableOnce<E>` without requiring `Send`.
49    ///
50    /// # Parameters
51    ///
52    /// * `supplier` - The supplier that produces the runnable result.
53    ///
54    /// # Returns
55    ///
56    /// A new `LocalBoxRunnableOnce<E>`.
57    #[inline]
58    pub fn from_supplier<S>(supplier: S) -> Self
59    where
60        S: SupplierOnce<Result<(), E>> + 'static,
61    {
62        Self::new(move || supplier.get())
63    }
64
65    impl_common_name_methods!("local runnable");
66
67    /// Chains another runnable after this runnable succeeds.
68    ///
69    /// The second runnable is not executed if this runnable returns `Err`.
70    ///
71    /// # Parameters
72    ///
73    /// * `next` - The runnable to execute after this runnable succeeds.
74    ///
75    /// # Returns
76    ///
77    /// A new local runnable executing both actions in sequence.
78    #[inline]
79    pub fn and_then<N>(self, next: N) -> LocalBoxRunnableOnce<E>
80    where
81        N: RunnableOnce<E> + 'static,
82        E: 'static,
83    {
84        let name = self.name;
85        let function = self.function;
86        LocalBoxRunnableOnce::new_with_optional_name(
87            move || {
88                function()?;
89                next.run()
90            },
91            name,
92        )
93    }
94
95    /// Runs this runnable before a local callable.
96    ///
97    /// The callable is not executed if this runnable returns `Err`.
98    ///
99    /// # Parameters
100    ///
101    /// * `callable` - The callable to execute after this runnable succeeds.
102    ///
103    /// # Returns
104    ///
105    /// A local callable producing the second computation's result.
106    #[inline]
107    pub fn then_callable<R, C>(self, callable: C) -> LocalBoxCallableOnce<R, E>
108    where
109        C: CallableOnce<R, E> + 'static,
110        R: 'static,
111        E: 'static,
112    {
113        let name = self.name;
114        let function = self.function;
115        LocalBoxCallableOnce::new_with_optional_name(
116            move || {
117                function()?;
118                callable.call()
119            },
120            name,
121        )
122    }
123}
124
125impl<E> RunnableOnce<E> for LocalBoxRunnableOnce<E> {
126    /// Executes the local boxed runnable.
127    #[inline]
128    fn run(self) -> Result<(), E> {
129        (self.function)()
130    }
131
132    /// Converts this local boxed runnable into itself.
133    #[inline]
134    fn into_local_box(self) -> LocalBoxRunnableOnce<E>
135    where
136        Self: Sized + 'static,
137    {
138        self
139    }
140
141    /// Extracts the underlying local one-time closure.
142    #[inline]
143    fn into_fn(self) -> impl FnOnce() -> Result<(), E>
144    where
145        Self: Sized + 'static,
146    {
147        self.function
148    }
149
150    /// Converts this local boxed runnable into a local boxed callable while
151    /// preserving its name.
152    #[inline]
153    fn into_local_callable(self) -> LocalBoxCallableOnce<(), E>
154    where
155        Self: Sized + 'static,
156    {
157        let name = self.name;
158        let function = self.function;
159        LocalBoxCallableOnce::new_with_optional_name(function, name)
160    }
161}
162
163impl<E> SupplierOnce<Result<(), E>> for LocalBoxRunnableOnce<E> {
164    /// Executes the local boxed runnable as a one-time supplier of
165    /// `Result<(), E>`.
166    #[inline]
167    fn get(self) -> Result<(), E> {
168        self.run()
169    }
170}
171
172impl_supplier_debug_display!(LocalBoxRunnableOnce<E>);