1use std::any::Any;
16use std::io::Error as IoError;
17use std::sync::Arc;
18
19use common_error::ext::{BoxedError, ErrorExt};
20use common_error::status_code::StatusCode;
21use common_macro::stack_trace_debug;
22use snafu::{Location, Snafu};
23
24#[derive(Snafu)]
25#[snafu(visibility(pub))]
26#[stack_trace_debug]
27pub enum Error {
28 #[snafu(display("Failed to read"))]
29 Read {
30 #[snafu(source)]
31 error: IoError,
32 #[snafu(implicit)]
33 location: Location,
34 },
35
36 #[snafu(display("Failed to write"))]
37 Write {
38 #[snafu(source)]
39 error: IoError,
40 #[snafu(implicit)]
41 location: Location,
42 },
43
44 #[snafu(display("Failed to flush"))]
45 Flush {
46 #[snafu(source)]
47 error: IoError,
48 #[snafu(implicit)]
49 location: Location,
50 },
51
52 #[snafu(display("Failed to close"))]
53 Close {
54 #[snafu(source)]
55 error: IoError,
56 #[snafu(implicit)]
57 location: Location,
58 },
59
60 #[snafu(display("Failed to open"))]
61 Open {
62 #[snafu(source)]
63 error: IoError,
64 #[snafu(implicit)]
65 location: Location,
66 },
67
68 #[snafu(display("Failed to read metadata"))]
69 Metadata {
70 #[snafu(source)]
71 error: IoError,
72 #[snafu(implicit)]
73 location: Location,
74 },
75
76 #[snafu(display("Failed to create"))]
77 Create {
78 #[snafu(source)]
79 error: IoError,
80 #[snafu(implicit)]
81 location: Location,
82 },
83
84 #[snafu(display("Failed to rename"))]
85 Rename {
86 #[snafu(source)]
87 error: IoError,
88 #[snafu(implicit)]
89 location: Location,
90 },
91
92 #[snafu(display("Failed to remove"))]
93 Remove {
94 #[snafu(source)]
95 error: IoError,
96 #[snafu(implicit)]
97 location: Location,
98 },
99
100 #[snafu(display("Error while walking directory"))]
101 WalkDir {
102 #[snafu(source)]
103 error: async_walkdir::Error,
104 #[snafu(implicit)]
105 location: Location,
106 },
107
108 #[snafu(display("Magic not matched"))]
109 MagicNotMatched {
110 #[snafu(implicit)]
111 location: Location,
112 },
113
114 #[snafu(display("Unsupported decompression: {}", decompression))]
115 UnsupportedDecompression {
116 decompression: String,
117 #[snafu(implicit)]
118 location: Location,
119 },
120
121 #[snafu(display("Failed to serialize json"))]
122 SerializeJson {
123 #[snafu(source)]
124 error: serde_json::Error,
125 #[snafu(implicit)]
126 location: Location,
127 },
128
129 #[snafu(display("Failed to deserialize json"))]
130 DeserializeJson {
131 #[snafu(source)]
132 error: serde_json::Error,
133 #[snafu(implicit)]
134 location: Location,
135 },
136
137 #[snafu(display("Unexpected footer payload size: {}", size))]
138 UnexpectedFooterPayloadSize {
139 size: i32,
140 #[snafu(implicit)]
141 location: Location,
142 },
143
144 #[snafu(display("Invalid puffin footer"))]
145 InvalidPuffinFooter {
146 #[snafu(implicit)]
147 location: Location,
148 },
149
150 #[snafu(display(
151 "Unexpected puffin file size, min: {}, actual: {}",
152 min_file_size,
153 actual_file_size
154 ))]
155 UnexpectedPuffinFileSize {
156 min_file_size: u64,
157 actual_file_size: u64,
158 #[snafu(implicit)]
159 location: Location,
160 },
161
162 #[snafu(display("Failed to compress lz4"))]
163 Lz4Compression {
164 #[snafu(source)]
165 error: std::io::Error,
166
167 #[snafu(implicit)]
168 location: Location,
169 },
170
171 #[snafu(display("Failed to decompress lz4"))]
172 Lz4Decompression {
173 #[snafu(source)]
174 error: serde_json::Error,
175
176 #[snafu(implicit)]
177 location: Location,
178 },
179
180 #[snafu(display("Unsupported compression: {codec}"))]
181 UnsupportedCompression {
182 codec: String,
183 #[snafu(implicit)]
184 location: Location,
185 },
186
187 #[snafu(display("Write to the same blob twice: {blob}"))]
188 DuplicateBlob {
189 blob: String,
190 #[snafu(implicit)]
191 location: Location,
192 },
193
194 #[snafu(display("Blob not found: {blob}"))]
195 BlobNotFound {
196 blob: String,
197 #[snafu(implicit)]
198 location: Location,
199 },
200
201 #[snafu(display("Blob index out of bound, index: {}, max index: {}", index, max_index))]
202 BlobIndexOutOfBound {
203 index: usize,
204 max_index: usize,
205 #[snafu(implicit)]
206 location: Location,
207 },
208
209 #[snafu(display("File key not match, expected: {}, actual: {}", expected, actual))]
210 FileKeyNotMatch {
211 expected: String,
212 actual: String,
213 #[snafu(implicit)]
214 location: Location,
215 },
216
217 #[snafu(display("Get value from cache"))]
218 CacheGet { source: Arc<Error> },
219
220 #[snafu(display("External error"))]
221 External {
222 #[snafu(source)]
223 error: BoxedError,
224 #[snafu(implicit)]
225 location: Location,
226 },
227}
228
229impl Error {
230 pub fn is_blob_not_found(&self) -> bool {
231 match self {
232 Error::BlobNotFound { .. } => true,
233 Error::CacheGet { source } => source.is_blob_not_found(),
234 _ => false,
235 }
236 }
237}
238
239impl ErrorExt for Error {
240 fn status_code(&self) -> StatusCode {
241 use Error::*;
242 match self {
243 Read { .. }
244 | MagicNotMatched { .. }
245 | DeserializeJson { .. }
246 | Write { .. }
247 | Flush { .. }
248 | Close { .. }
249 | Open { .. }
250 | Metadata { .. }
251 | Create { .. }
252 | Remove { .. }
253 | Rename { .. }
254 | SerializeJson { .. }
255 | UnexpectedFooterPayloadSize { .. }
256 | UnexpectedPuffinFileSize { .. }
257 | Lz4Compression { .. }
258 | Lz4Decompression { .. }
259 | BlobNotFound { .. }
260 | BlobIndexOutOfBound { .. }
261 | FileKeyNotMatch { .. }
262 | WalkDir { .. }
263 | InvalidPuffinFooter { .. } => StatusCode::Unexpected,
264
265 UnsupportedCompression { .. } | UnsupportedDecompression { .. } => {
266 StatusCode::Unsupported
267 }
268
269 DuplicateBlob { .. } => StatusCode::InvalidArguments,
270
271 CacheGet { source } => source.status_code(),
272
273 External { error, .. } => error.status_code(),
274 }
275 }
276
277 fn as_any(&self) -> &dyn Any {
278 self
279 }
280}
281
282pub type Result<T> = std::result::Result<T, Error>;