eversal_lib/
error.rs

1use core::fmt;
2
3#[derive(Debug, Clone)]
4pub struct Error {
5  status: u16,
6  details: String,
7}
8
9impl Error {
10  pub fn new(status: u16, details: String) -> Self {
11    Self { status, details }
12  }
13
14  pub fn status(&self) -> u16 {
15    self.status
16  }
17
18  pub fn details(&self) -> &str {
19    &self.details
20  }
21}
22
23impl fmt::Display for Error {
24  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25    write!(f, "{}", self.details)
26  }
27}
28
29impl std::error::Error for Error {
30  fn description(&self) -> &str {
31    &self.details
32  }
33}
34
35impl From<oauth2::url::ParseError> for Error {
36  fn from(error: oauth2::url::ParseError) -> Self {
37    Self::new(500, error.to_string())
38  }
39}
40
41impl From<jsonwebtoken::errors::Error> for Error {
42  fn from(error: jsonwebtoken::errors::Error) -> Self {
43    Self::new(500, error.to_string())
44  }
45}
46
47impl From<reqwest::Error> for Error {
48  fn from(error: reqwest::Error) -> Self {
49    let status = error.status().unwrap_or(reqwest::StatusCode::INTERNAL_SERVER_ERROR);
50    Self::new(status.as_u16(), error.to_string())
51  }
52}
53
54impl From<sqlx::Error> for Error {
55  fn from(error: sqlx::Error) -> Self {
56    match error {
57      sqlx::Error::RowNotFound => Error::new(404, "Not found".to_string()),
58      sqlx::Error::ColumnIndexOutOfBounds { .. } => Error::new(422, error.to_string()),
59      sqlx::Error::ColumnNotFound { .. } => Error::new(422, error.to_string()),
60      sqlx::Error::ColumnDecode { .. } => Error::new(422, error.to_string()),
61      sqlx::Error::Decode(_) => Error::new(422, error.to_string()),
62      sqlx::Error::PoolTimedOut => Error::new(503, error.to_string()),
63      sqlx::Error::PoolClosed => Error::new(503, error.to_string()),
64      sqlx::Error::Tls(_) => Error::new(500, error.to_string()),
65      sqlx::Error::Io(_) => Error::new(500, error.to_string()),
66      sqlx::Error::Protocol(_) => Error::new(500, error.to_string()),
67      sqlx::Error::Configuration(_) => Error::new(500, error.to_string()),
68      sqlx::Error::AnyDriverError(_) => Error::new(500, error.to_string()),
69      sqlx::Error::Database(err) => {
70        if let Some(code) = err.code() {
71          match code.trim() {
72            // Unique violation
73            "23505" => return Error::new(409, err.to_string()),
74            _ => (),
75          }
76        }
77        Error::new(500, err.to_string())
78      }
79      sqlx::Error::Migrate(_) => Error::new(500, error.to_string()),
80      sqlx::Error::TypeNotFound { type_name } => {
81        Error::new(500, format!("Type not found: {}", type_name))
82      }
83      sqlx::Error::WorkerCrashed => Error::new(500, error.to_string()),
84      _ => Error::new(500, error.to_string()),
85    }
86  }
87}