Skip to main content

ullun/
error.rs

1//! Error types and Result alias
2
3use std::fmt;
4
5pub type Result<T> = std::result::Result<T, Error>;
6
7/// Framework error type that maps to HTTP status codes
8#[derive(Debug)]
9pub enum Error {
10    /// 400 Bad Request
11    BadRequest(String),
12    /// 401 Unauthorized
13    Unauthorized(String),
14    /// 403 Forbidden
15    Forbidden(String),
16    /// 404 Not Found
17    NotFound(String),
18    /// 500 Internal Server Error
19    Internal(String),
20    /// Custom status code + message
21    Custom(u16, String),
22}
23
24impl Error {
25    pub fn status_code(&self) -> u16 {
26        match self {
27            Error::BadRequest(_) => 400,
28            Error::Unauthorized(_) => 401,
29            Error::Forbidden(_) => 403,
30            Error::NotFound(_) => 404,
31            Error::Internal(_) => 500,
32            Error::Custom(code, _) => *code,
33        }
34    }
35
36    /// The status as an [`http::StatusCode`] (invalid custom codes become 500)
37    pub fn status(&self) -> http::StatusCode {
38        http::StatusCode::from_u16(self.status_code())
39            .unwrap_or(http::StatusCode::INTERNAL_SERVER_ERROR)
40    }
41
42    pub fn message(&self) -> &str {
43        match self {
44            Error::BadRequest(msg)
45            | Error::Unauthorized(msg)
46            | Error::Forbidden(msg)
47            | Error::NotFound(msg)
48            | Error::Internal(msg)
49            | Error::Custom(_, msg) => msg,
50        }
51    }
52}
53
54impl fmt::Display for Error {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        write!(f, "{}", self.message())
57    }
58}
59
60impl std::error::Error for Error {}
61
62// Convenience constructors
63impl Error {
64    pub fn bad_request(msg: impl Into<String>) -> Self {
65        Error::BadRequest(msg.into())
66    }
67
68    pub fn unauthorized(msg: impl Into<String>) -> Self {
69        Error::Unauthorized(msg.into())
70    }
71
72    pub fn forbidden(msg: impl Into<String>) -> Self {
73        Error::Forbidden(msg.into())
74    }
75
76    pub fn not_found(msg: impl Into<String>) -> Self {
77        Error::NotFound(msg.into())
78    }
79
80    pub fn internal(msg: impl Into<String>) -> Self {
81        Error::Internal(msg.into())
82    }
83
84    pub fn custom(status: u16, msg: impl Into<String>) -> Self {
85        Error::Custom(status, msg.into())
86    }
87}