1use axum::http::StatusCode;
4use axum::response::{IntoResponse, Response};
5use serde::Serialize;
6
7#[derive(Debug)]
9pub enum ServerError {
10 Store(rvf_types::RvfError),
12 BadRequest(String),
14 NotReady,
16}
17
18#[derive(Serialize)]
20struct ErrorBody {
21 error: String,
22 code: u16,
23}
24
25impl IntoResponse for ServerError {
26 fn into_response(self) -> Response {
27 let (status, message, code) = match &self {
28 ServerError::Store(e) => {
29 let code = error_code(e);
30 let status = status_for_error(e);
31 (status, format!("{e:?}"), code)
32 }
33 ServerError::BadRequest(msg) => {
34 (StatusCode::BAD_REQUEST, msg.clone(), 400)
35 }
36 ServerError::NotReady => {
37 (StatusCode::SERVICE_UNAVAILABLE, "Store not ready".into(), 503)
38 }
39 };
40
41 let body = ErrorBody {
42 error: message,
43 code,
44 };
45
46 (status, axum::Json(body)).into_response()
47 }
48}
49
50fn error_code(e: &rvf_types::RvfError) -> u16 {
51 match e {
52 rvf_types::RvfError::Code(c) => *c as u16,
53 _ => 500,
54 }
55}
56
57fn status_for_error(e: &rvf_types::RvfError) -> StatusCode {
58 match e {
59 rvf_types::RvfError::Code(c) => match c {
60 rvf_types::ErrorCode::DimensionMismatch => StatusCode::BAD_REQUEST,
61 rvf_types::ErrorCode::ReadOnly => StatusCode::FORBIDDEN,
62 rvf_types::ErrorCode::LockHeld => StatusCode::CONFLICT,
63 rvf_types::ErrorCode::ManifestNotFound => StatusCode::NOT_FOUND,
64 _ => StatusCode::INTERNAL_SERVER_ERROR,
65 },
66 _ => StatusCode::INTERNAL_SERVER_ERROR,
67 }
68}
69
70impl From<rvf_types::RvfError> for ServerError {
71 fn from(e: rvf_types::RvfError) -> Self {
72 ServerError::Store(e)
73 }
74}