use axum::Json;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use crate::models::{DeltaErrorModel, DeltaErrorResponse, DeltaErrorType};
#[derive(Debug, thiserror::Error)]
pub enum DeltaBackendError {
#[error("{0}")]
NotFound(String),
#[error("{0}")]
NotFoundGeneric(String),
#[error("{0}")]
AlreadyExists(String),
#[error("{0}")]
PermissionDenied(String),
#[error("{0}")]
Unauthenticated(String),
#[error("invalid argument: {0}")]
InvalidArgument(String),
#[error("commit version conflict: {0}")]
CommitVersionConflict(String),
#[error("update requirement conflict: {0}")]
UpdateRequirementConflict(String),
#[error("resource exhausted: {0}")]
ResourceExhausted(String),
#[error("not implemented: {0}")]
NotImplemented(&'static str),
#[error("internal error: {0}")]
Internal(String),
}
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct DeltaApiError(#[from] pub DeltaBackendError);
impl DeltaApiError {
pub fn invalid_argument(message: impl Into<String>) -> Self {
DeltaApiError(DeltaBackendError::InvalidArgument(message.into()))
}
pub fn permission_denied(message: impl Into<String>) -> Self {
DeltaApiError(DeltaBackendError::PermissionDenied(message.into()))
}
pub fn not_found(message: impl Into<String>) -> Self {
DeltaApiError(DeltaBackendError::NotFound(message.into()))
}
pub fn not_implemented(what: &'static str) -> Self {
DeltaApiError(DeltaBackendError::NotImplemented(what))
}
fn parts(&self) -> (StatusCode, DeltaErrorType) {
use DeltaErrorType::*;
match &self.0 {
DeltaBackendError::NotFound(_) => (StatusCode::NOT_FOUND, NoSuchTableException),
DeltaBackendError::NotFoundGeneric(_) => (StatusCode::NOT_FOUND, NotFoundException),
DeltaBackendError::AlreadyExists(_) => (StatusCode::CONFLICT, AlreadyExistsException),
DeltaBackendError::PermissionDenied(_) => {
(StatusCode::FORBIDDEN, PermissionDeniedException)
}
DeltaBackendError::Unauthenticated(_) => {
(StatusCode::UNAUTHORIZED, NotAuthorizedException)
}
DeltaBackendError::InvalidArgument(_) => {
(StatusCode::BAD_REQUEST, InvalidParameterValueException)
}
DeltaBackendError::CommitVersionConflict(_) => {
(StatusCode::CONFLICT, CommitVersionConflictException)
}
DeltaBackendError::UpdateRequirementConflict(_) => {
(StatusCode::CONFLICT, UpdateRequirementConflictException)
}
DeltaBackendError::ResourceExhausted(_) => {
(StatusCode::TOO_MANY_REQUESTS, ResourceExhaustedException)
}
DeltaBackendError::NotImplemented(_) => {
(StatusCode::NOT_IMPLEMENTED, NotImplementedException)
}
DeltaBackendError::Internal(_) => (
StatusCode::INTERNAL_SERVER_ERROR,
InternalServerErrorException,
),
}
}
}
impl IntoResponse for DeltaApiError {
fn into_response(self) -> Response {
let (status, error_type) = self.parts();
let body = DeltaErrorResponse {
error: DeltaErrorModel {
message: self.0.to_string(),
error_type,
code: status.as_u16(),
stack: None,
},
};
(status, Json(body)).into_response()
}
}
pub type DeltaApiResult<T> = Result<T, DeltaApiError>;