Skip to main content

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