1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
6#[serde(rename_all = "snake_case")]
7pub enum ErrorCode {
8 AuthRequired,
9 AuthExpired,
10 AccessDenied,
11 ServerUnavailable,
12 ServerTooOld,
13 ProjectNotFound,
14 BadMetadata,
16 CredentialsUnreadable,
17 NotInProject,
18 InvalidArguments,
19 InvalidConfiguration,
20 NoFilesSelected,
21 IoError,
22 OperationFailed,
24 FileFailed,
26 RevokeFailed,
27 Cancelled,
29}
30
31impl ErrorCode {
32 pub fn as_str(&self) -> &'static str {
33 match self {
34 ErrorCode::AuthRequired => "auth_required",
35 ErrorCode::AuthExpired => "auth_expired",
36 ErrorCode::AccessDenied => "access_denied",
37 ErrorCode::ServerUnavailable => "server_unavailable",
38 ErrorCode::ServerTooOld => "server_too_old",
39 ErrorCode::ProjectNotFound => "project_not_found",
40 ErrorCode::BadMetadata => "bad_metadata",
41 ErrorCode::CredentialsUnreadable => "credentials_unreadable",
42 ErrorCode::NotInProject => "not_in_project",
43 ErrorCode::InvalidArguments => "invalid_arguments",
44 ErrorCode::InvalidConfiguration => "invalid_configuration",
45 ErrorCode::NoFilesSelected => "no_files_selected",
46 ErrorCode::IoError => "io_error",
47 ErrorCode::OperationFailed => "operation_failed",
48 ErrorCode::FileFailed => "file_failed",
49 ErrorCode::RevokeFailed => "revoke_failed",
50 ErrorCode::Cancelled => "cancelled",
51 }
52 }
53}
54
55#[derive(Debug, Clone, Serialize)]
57pub struct Error {
58 pub code: ErrorCode,
59 pub message: String,
60}
61
62impl Error {
63 pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
64 Self {
65 code,
66 message: message.into(),
67 }
68 }
69}
70
71impl std::fmt::Display for Error {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 f.write_str(&self.message)
74 }
75}
76
77impl std::error::Error for Error {}
78
79pub fn backend_error_code(error: &anyhow::Error) -> Option<ErrorCode> {
80 error.downcast_ref::<Error>().map(|e| e.code)
81}