redevplugin_worker_sdk/
error.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
7pub enum ErrorCode {
8 InvalidArgument,
9 PermissionDenied,
10 NotFound,
11 AlreadyExists,
12 ResourceClosed,
13 Canceled,
14 Timeout,
15 WouldBlock,
16 IoError,
17 MountUnavailable,
18 NetworkError,
19 ResourceLimit,
20 Internal,
21 RuntimeUnavailable,
22 RedirectRequiresReplay,
23 #[serde(other)]
24 Unknown,
25}
26
27#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28pub struct Error {
29 pub code: ErrorCode,
30 pub message: String,
31 #[serde(default)]
32 pub retryable: bool,
33 #[serde(default)]
34 pub details: Value,
35}
36
37impl Error {
38 pub(crate) fn internal(message: impl Into<String>) -> Self {
39 Self {
40 code: ErrorCode::Internal,
41 message: message.into(),
42 retryable: false,
43 details: Value::Null,
44 }
45 }
46
47 pub(crate) fn from_abi_status(status: i32) -> Self {
48 let code = match status {
49 -1 => ErrorCode::InvalidArgument,
50 -2 => ErrorCode::PermissionDenied,
51 -3 => ErrorCode::NotFound,
52 -4 => ErrorCode::AlreadyExists,
53 -5 => ErrorCode::ResourceClosed,
54 -6 => ErrorCode::Canceled,
55 -7 => ErrorCode::Timeout,
56 -8 => ErrorCode::WouldBlock,
57 -9 => ErrorCode::IoError,
58 -10 => ErrorCode::NetworkError,
59 -11 => ErrorCode::ResourceLimit,
60 -12 => ErrorCode::Internal,
61 -13 => ErrorCode::RuntimeUnavailable,
62 -14 => ErrorCode::RedirectRequiresReplay,
63 -15 => ErrorCode::MountUnavailable,
64 _ => ErrorCode::Unknown,
65 };
66 Self {
67 code,
68 message: format!("Worker API hostcall failed with ABI status {status}"),
69 retryable: false,
70 details: Value::Null,
71 }
72 }
73}
74
75impl fmt::Display for Error {
76 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
77 write!(formatter, "{:?}: {}", self.code, self.message)
78 }
79}
80
81impl std::error::Error for Error {}
82
83pub type Result<T> = std::result::Result<T, Error>;
84
85#[cfg(test)]
86mod tests {
87 use super::{Error, ErrorCode};
88
89 #[test]
90 fn preserves_mount_unavailable_abi_status() {
91 assert_eq!(
92 Error::from_abi_status(-15).code,
93 ErrorCode::MountUnavailable
94 );
95 }
96}