1 use core::fmt;
2 use log::debug;
3 use serde::{Deserialize, Serialize};
4 use serde_repr::{Deserialize_repr, Serialize_repr};
5 use std::fmt::{Display, Formatter};
6 use strum_macros::{EnumIter, IntoStaticStr};
7 use thiserror::Error;
8
9 #[derive(Error, Serialize, Deserialize, Debug)]
10 #[serde(untagged)]
11 pub enum ErrorResponse {
12 Error {
13 error_code: ErrorCode,
14 message: String,
15 },
16 }
17
18 impl Display for ErrorResponse {
19 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
20 write!(f, "{:?}", self)
21 }
22 }
23
24 #[derive(Error, Serialize_repr, Deserialize_repr, Debug, EnumIter, IntoStaticStr)]
25 #[repr(i32)]
26 pub enum ErrorCode {
27 // Generic errors
28 #[error("Unknown error.")]
29 Unknown = 0,
30 #[error("Parse error.")]
31 ParseError = 1,
32 #[error("Network error. Please check your internet connection and try again.")]
33 NetworkError = 2,
34 #[error("Input error")]
35 InputError = 3,
36 #[error("Missing config file. Please regenerate with 'smb init'.")]
37 MissingConfig = 4,
38 // #[error("Missing id in repository. Please regenerate with 'smb init'.")]
39 // MissingId,
40 #[error("Cancel operation.")]
41 Cancel = 5,
42 // Account
43 #[error("Unauthorized access.")]
44 Unauthorized = 100,
45 // Projects
46 #[error("Project not found.")]
47 ProjectNotFound = 1000,
48 }
49
50 impl ErrorCode {
51 /// Cannot expose the ErrorCode enum directly to Ruby,
52 /// so we need to get it from i32.
53 pub fn from_i32(value: i32) -> Self {
54 match value {
55 // Account
56 100 => ErrorCode::Unauthorized,
57 // Projects
58 1000 => ErrorCode::ProjectNotFound,
59 // Generic errors
60 5 => ErrorCode::Cancel,
61 4 => ErrorCode::MissingConfig,
62 3 => ErrorCode::InputError,
63 2 => ErrorCode::ParseError,
64 1 => ErrorCode::NetworkError,
65 // Fallback
66 _ => ErrorCode::Unknown,
67 }
68 }
69
70 // This could be better.
71 pub fn message(&self, l: Option<String>) -> &str {
72 debug!("Language code: {:?}, {}", l, self);
73 match self {
74 ErrorCode::Unknown => "Unknown error.",
75 ErrorCode::ProjectNotFound => "Project not found.",
76 ErrorCode::ParseError => "Parse error.",
77 ErrorCode::NetworkError => {
78 "Network error. Please check your internet connection and try again."
79 }
80 ErrorCode::Unauthorized => "Unauthorized access.",
81 ErrorCode::InputError => "Input error.",
82 ErrorCode::MissingConfig => "Missing config.",
83 ErrorCode::Cancel => "Cancelled operation.",
84 }
85 }
86
87 pub fn rb_constant_name(&self) -> String {
88 // Using IntoStaticStr to get the variant name directly.
89 // self.into() will return a &'static str representing the variant name.
90 let variant_name_static_str: &'static str = self.into();
91 variant_name_static_str.to_string()
92 }
93 }