zrx_scheduler/scheduler/step/error/convert.rs
1// Copyright (c) 2025-2026 Zensical and contributors
2
3// SPDX-License-Identifier: MIT
4// Third-party contributions licensed under DCO
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to
8// deal in the Software without restriction, including without limitation the
9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10// sell copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22// IN THE SOFTWARE.
23
24// ----------------------------------------------------------------------------
25
26//! Step error conversions.
27
28use std::error;
29
30use crate::scheduler::signal::Value;
31
32use super::Error;
33
34// ----------------------------------------------------------------------------
35// Traits
36// ----------------------------------------------------------------------------
37
38/// Conversion into [`Error`].
39pub trait IntoError {
40 /// Converts into a step error.
41 ///
42 /// This method is intended to be used within [`Action::execute`][], to make
43 /// it convenient to convert an arbitrary error into a step error.
44 ///
45 /// [`Action::execute`]: crate::scheduler::action::Action::execute
46 fn into_error(self) -> Error;
47}
48
49// ----------------------------------------------------------------------------
50
51/// Conversion into [`Result`].
52pub trait IntoResult<T = ()>: Sized {
53 /// Converts into a step result.
54 ///
55 /// # Errors
56 ///
57 /// In case conversion fails, an error should be returned.
58 fn into_result(self) -> Result<T, Error>;
59}
60
61// ----------------------------------------------------------------------------
62// Blanket implementations
63// ----------------------------------------------------------------------------
64
65impl<E> IntoError for E
66where
67 E: error::Error + Send + 'static,
68{
69 /// Converts any error into a step error.
70 ///
71 /// This implementation attempts to downcast the error into one of the known
72 /// variants, and falls back to the [`Error::Other`] variant in other cases.
73 /// It also ensures that the error is not double-boxed, returning unknown
74 /// errors captured by the [`Error::Other`] variant unchanged.
75 #[inline]
76 fn into_error(self) -> Error {
77 let mut err: Box<dyn error::Error + Send> = Box::new(self);
78 err = match err.downcast() {
79 Ok(err) => return *err,
80 Err(err) => err,
81 };
82
83 // Implements downcast attempt of error
84 macro_rules! downcast {
85 ($variant:path) => {
86 err = match err.downcast() {
87 Ok(err) => return $variant(*err),
88 Err(err) => err,
89 }
90 };
91 }
92
93 // Downcast known error variants
94 downcast!(Error::Session);
95 downcast!(Error::Key);
96
97 // Handle unknown error variants
98 Error::Other(err)
99 }
100}
101
102// ----------------------------------------------------------------------------
103
104impl<T, E> IntoResult<T> for Result<T, E>
105where
106 T: Value,
107 E: IntoError,
108{
109 /// Converts any result into a step result.
110 #[inline]
111 fn into_result(self) -> Result<T, Error> {
112 self.map_err(IntoError::into_error)
113 }
114}
115
116impl<T> IntoResult<T> for T
117where
118 T: Value,
119{
120 /// Converts any value into a step result.
121 #[inline]
122 fn into_result(self) -> Result<T, Error> {
123 Ok(self)
124 }
125}