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