1use std::fmt;
4
5use axum::http::StatusCode;
6use axum::response::{IntoResponse, Response};
7use serde_json::json;
8
9#[derive(Debug)]
10pub enum SeamError {
11 Validation(String),
12 NotFound(String),
13 Internal(String),
14}
15
16impl SeamError {
17 pub fn validation(msg: impl Into<String>) -> Self {
18 Self::Validation(msg.into())
19 }
20
21 pub fn not_found(msg: impl Into<String>) -> Self {
22 Self::NotFound(msg.into())
23 }
24
25 pub fn internal(msg: impl Into<String>) -> Self {
26 Self::Internal(msg.into())
27 }
28
29 fn code(&self) -> &str {
30 match self {
31 Self::Validation(_) => "VALIDATION_ERROR",
32 Self::NotFound(_) => "NOT_FOUND",
33 Self::Internal(_) => "INTERNAL_ERROR",
34 }
35 }
36
37 fn message(&self) -> &str {
38 match self {
39 Self::Validation(m) | Self::NotFound(m) | Self::Internal(m) => m,
40 }
41 }
42
43 fn status(&self) -> StatusCode {
44 match self {
45 Self::Validation(_) => StatusCode::BAD_REQUEST,
46 Self::NotFound(_) => StatusCode::NOT_FOUND,
47 Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
48 }
49 }
50}
51
52impl fmt::Display for SeamError {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 write!(f, "{}: {}", self.code(), self.message())
55 }
56}
57
58impl std::error::Error for SeamError {}
59
60impl IntoResponse for SeamError {
61 fn into_response(self) -> Response {
62 let body = json!({
63 "error": {
64 "code": self.code(),
65 "message": self.message(),
66 }
67 });
68 (self.status(), axum::Json(body)).into_response()
69 }
70}