Skip to content

Commit 11925fc

Browse files
Traits and impls for adding context and exit codes to results.
Co-authored-by: dignifiedquire <[email protected]>
1 parent b7ad2c5 commit 11925fc

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

runtime/src/actor_error.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::fmt::Display;
2+
13
use fvm_shared::error::ExitCode;
24
use thiserror::Error;
35

@@ -108,3 +110,95 @@ macro_rules! actor_error {
108110
$crate::actor_error!($code; $msg $(, $ex)*)
109111
};
110112
}
113+
114+
// Adds context to an actor error's descriptive message.
115+
pub trait ActorContext<T> {
116+
fn context<C>(self, context: C) -> Result<T, ActorError>
117+
where
118+
C: Display + 'static;
119+
120+
fn with_context<C, F>(self, f: F) -> Result<T, ActorError>
121+
where
122+
C: Display + 'static,
123+
F: FnOnce() -> C;
124+
}
125+
126+
impl<T> ActorContext<T> for Result<T, ActorError> {
127+
fn context<C>(self, context: C) -> Result<T, ActorError>
128+
where
129+
C: Display + 'static,
130+
{
131+
self.map_err(|mut err| {
132+
err.msg = format!("{}: {}", context, err.msg);
133+
err
134+
})
135+
}
136+
137+
fn with_context<C, F>(self, f: F) -> Result<T, ActorError>
138+
where
139+
C: Display + 'static,
140+
F: FnOnce() -> C,
141+
{
142+
self.map_err(|mut err| {
143+
err.msg = format!("{}: {}", f(), err.msg);
144+
err
145+
})
146+
}
147+
}
148+
149+
// Adapts a target into an actor error.
150+
pub trait AsActorError<T>: Sized {
151+
fn exit_code(self, code: ExitCode) -> Result<T, ActorError>;
152+
153+
fn context_code<C>(self, code: ExitCode, context: C) -> Result<T, ActorError>
154+
where
155+
C: Display + 'static;
156+
157+
fn with_context_code<C, F>(self, code: ExitCode, f: F) -> Result<T, ActorError>
158+
where
159+
C: Display + 'static,
160+
F: FnOnce() -> C;
161+
}
162+
163+
// Note: E should be std::error::Error, revert to this after anyhow:Error is no longer used.
164+
impl<T, E: Display> AsActorError<T> for Result<T, E> {
165+
fn exit_code(self, code: ExitCode) -> Result<T, ActorError> {
166+
self.map_err(|err| ActorError { exit_code: code, msg: err.to_string() })
167+
}
168+
169+
fn context_code<C>(self, code: ExitCode, context: C) -> Result<T, ActorError>
170+
where
171+
C: Display + 'static,
172+
{
173+
self.map_err(|err| ActorError { exit_code: code, msg: format!("{}: {}", context, err) })
174+
}
175+
176+
fn with_context_code<C, F>(self, code: ExitCode, f: F) -> Result<T, ActorError>
177+
where
178+
C: Display + 'static,
179+
F: FnOnce() -> C,
180+
{
181+
self.map_err(|err| ActorError { exit_code: code, msg: format!("{}: {}", f(), err) })
182+
}
183+
}
184+
185+
impl<T> AsActorError<T> for Option<T> {
186+
fn exit_code(self, code: ExitCode) -> Result<T, ActorError> {
187+
self.ok_or_else(|| ActorError { exit_code: code, msg: "None".to_string() })
188+
}
189+
190+
fn context_code<C>(self, code: ExitCode, context: C) -> Result<T, ActorError>
191+
where
192+
C: Display + 'static,
193+
{
194+
self.ok_or_else(|| ActorError { exit_code: code, msg: context.to_string() })
195+
}
196+
197+
fn with_context_code<C, F>(self, code: ExitCode, f: F) -> Result<T, ActorError>
198+
where
199+
C: Display + 'static,
200+
F: FnOnce() -> C,
201+
{
202+
self.ok_or_else(|| ActorError { exit_code: code, msg: f().to_string() })
203+
}
204+
}

0 commit comments

Comments
 (0)