Skip to main content

gestalt/
error.rs

1#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
2#[error("{message}")]
3/// Error returned by typed provider handlers and runtime helpers.
4pub struct Error {
5    status: Option<u16>,
6    message: String,
7    expose_message: bool,
8}
9
10pub(crate) const HTTP_BAD_REQUEST: u16 = 400;
11pub(crate) const HTTP_NOT_FOUND: u16 = 404;
12pub(crate) const HTTP_INTERNAL_SERVER_ERROR: u16 = 500;
13pub(crate) const HTTP_NOT_IMPLEMENTED: u16 = 501;
14pub(crate) const INTERNAL_ERROR_MESSAGE: &str = "internal error";
15
16/// Convenient result alias for Gestalt SDK operations.
17pub type Result<T> = std::result::Result<T, Error>;
18
19impl Error {
20    /// Creates an error without an explicit HTTP status code override.
21    pub fn new(message: impl Into<String>) -> Self {
22        Self {
23            status: None,
24            message: message.into(),
25            expose_message: true,
26        }
27    }
28
29    /// Creates an error with an explicit HTTP status code.
30    pub fn with_status(status: u16, message: impl Into<String>) -> Self {
31        Self {
32            status: Some(status),
33            message: message.into(),
34            expose_message: true,
35        }
36    }
37
38    /// Creates a `400 Bad Request` error.
39    pub fn bad_request(message: impl Into<String>) -> Self {
40        Self::with_status(HTTP_BAD_REQUEST, message)
41    }
42
43    /// Creates a `500 Internal Server Error`.
44    pub fn internal(message: impl Into<String>) -> Self {
45        Self::with_status(HTTP_INTERNAL_SERVER_ERROR, message)
46    }
47
48    /// Creates a `404 Not Found` error.
49    pub fn not_found(message: impl Into<String>) -> Self {
50        Self::with_status(HTTP_NOT_FOUND, message)
51    }
52
53    /// Creates a `501 Not Implemented` error.
54    pub fn unimplemented(message: impl Into<String>) -> Self {
55        Self::with_status(HTTP_NOT_IMPLEMENTED, message)
56    }
57
58    /// Returns the HTTP status code that should be used for this error, when
59    /// one was supplied.
60    pub fn status(&self) -> Option<u16> {
61        self.status
62    }
63
64    /// Returns the human-readable error message.
65    pub fn message(&self) -> &str {
66        &self.message
67    }
68
69    pub(crate) fn expose_message(&self) -> bool {
70        self.expose_message
71    }
72
73    pub(crate) fn hidden_internal(message: impl Into<String>) -> Self {
74        Self {
75            status: Some(HTTP_INTERNAL_SERVER_ERROR),
76            message: message.into(),
77            expose_message: false,
78        }
79    }
80}
81
82impl From<serde_json::Error> for Error {
83    fn from(value: serde_json::Error) -> Self {
84        Self::hidden_internal(value.to_string())
85    }
86}
87
88impl From<std::io::Error> for Error {
89    fn from(value: std::io::Error) -> Self {
90        Self::hidden_internal(value.to_string())
91    }
92}
93
94impl From<tonic::transport::Error> for Error {
95    fn from(value: tonic::transport::Error) -> Self {
96        Self::hidden_internal(value.to_string())
97    }
98}