crab_vault_engine/
error.rs1use axum::{
2 http::StatusCode,
3 response::{IntoResponse, Response},
4};
5use serde::Serialize;
6use thiserror::Error;
7
8pub type EngineResult<T> = Result<T, EngineError>;
9
10#[derive(Debug, Serialize, Error)]
11#[serde(rename_all = "camelCase", tag = "code")]
12pub enum EngineError {
13 #[error("io error: {error} while manipulating {path}")]
14 Io {
15 #[serde(skip)]
16 error: std::io::Error,
17 path: String,
18 },
19
20 #[error("ser/de error: {error} at line{line}, column {column}")]
21 Serde {
22 error: &'static str,
23 line: usize,
24 column: usize,
25 },
26
27 #[error("bucket not found: {bucket}")]
28 BucketNotFound { bucket: String },
29
30 #[error("bucket meta not found: {bucket}")]
31 BucketMetaNotFound { bucket: String },
32
33 #[error("bucket not empty, possibly while deleting, details {bucket}")]
34 BucketNotEmpty { bucket: String },
35
36 #[error("object not found: {bucket}/{object}")]
37 ObjectNotFound { bucket: String, object: String },
38
39 #[error("object meta not found: {bucket}/{object}")]
40 ObjectMetaNotFound { bucket: String, object: String },
41
42 #[allow(dead_code)]
43 #[error("some other errors: {0}")]
44 Other(String),
45
46 #[allow(dead_code)]
47 #[error("backend error: {0}")]
48 BackendError(String),
49
50 #[error("invalid argument: {0}")]
51 InvalidArgument(String),
52}
53
54impl From<serde_json::error::Error> for EngineError {
55 fn from(value: serde_json::error::Error) -> Self {
56 use serde_json::error::Category;
57 let kind = match value.classify() {
58 Category::Io => "io",
59 Category::Syntax => "syntax",
60 Category::Data => "data",
61 Category::Eof => "eof",
62 };
63
64 EngineError::Serde {
65 error: kind,
66 line: value.line(),
67 column: value.column(),
68 }
69 }
70}
71
72impl IntoResponse for EngineError {
73 fn into_response(self) -> Response {
74 use EngineError::*;
75 let code = match &self {
76 Serde {
77 error: _,
78 line: _,
79 column: _,
80 }
81 | Io { error: _, path: _ }
82 | BackendError(_)
83 | Other(_) => StatusCode::INTERNAL_SERVER_ERROR,
84
85 ObjectNotFound {
86 bucket: _,
87 object: _,
88 }
89 | BucketNotFound { bucket: _ } => StatusCode::NOT_FOUND,
90
91 ObjectMetaNotFound {
92 bucket: _,
93 object: _,
94 }
95 | BucketMetaNotFound { bucket: _ } => StatusCode::NOT_FOUND,
96
97 BucketNotEmpty { bucket: _ } => StatusCode::CONFLICT,
98 InvalidArgument(_) => StatusCode::UNPROCESSABLE_ENTITY,
99 };
100
101 #[derive(Serialize)]
102 struct Msg {
103 #[serde(flatten)]
104 error: EngineError,
105 msg: String,
106 }
107
108 (
109 code,
110 axum::Json(Msg {
111 msg: self.to_string(),
112 error: self,
113 }),
114 )
115 .into_response()
116 }
117}
118
119impl From<EngineError> for Response {
120 fn from(value: EngineError) -> Self {
121 value.into_response()
122 }
123}