use axum::http::StatusCode;
use axum::Json;
#[cfg(feature = "serialization")]
use serde::Serialize;
pub type ApiJsonResponse<T> = Result<Json<T>, (StatusCode, Json<String>)>;
pub trait ApiResponse<T> {
fn into_json_response(self) -> ApiJsonResponse<T>;
}
impl<T> ApiResponse<T> for Json<T> {
fn into_json_response(self) -> ApiJsonResponse<T> {
Ok(self)
}
}
#[cfg(feature = "serialization")]
impl<T> ApiResponse<T> for T where T: Serialize {
fn into_json_response(self) -> ApiJsonResponse<T> {
Ok(Json(self))
}
}
pub trait FailureResponse {
fn status_code(&self) -> StatusCode;
fn response(&self) -> String;
}
impl FailureResponse for StatusCode {
fn status_code(&self) -> StatusCode {
self.clone()
}
fn response(&self) -> String {
self.canonical_reason().unwrap_or_default().to_string()
}
}
impl<T, E> ApiResponse<T> for Result<T, E>
where T: ApiResponse<T>, E: FailureResponse
{
fn into_json_response(self) -> ApiJsonResponse<T> {
match self {
Ok(value) => value.into_json_response(),
Err(error) => Err((error.status_code(), Json(error.response())))
}
}
}
pub fn error_response<T>(status_code: StatusCode, error_message: &str) -> ApiJsonResponse<T>
where
T: ApiResponse<T>,
{
Err((status_code, Json(error_message.to_string())))
}