use std::string::FromUtf8Error;
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
Json,
};
use serde_json::json;
use thiserror::Error;
pub type AppResult<T> = Result<T, AppError>;
#[derive(Debug, Error)]
pub enum AppError {
#[error("failed to bind TCP listener: {0}")]
Bind(#[source] std::io::Error),
#[error("HTTP server stopped unexpectedly: {0}")]
Serve(#[source] std::io::Error),
#[error("duckdb error: {0}")]
DuckDb(#[from] duckdb::Error),
#[error("CSV error: {0}")]
Csv(#[from] csv::Error),
#[error("spreadsheet error: {0}")]
Spreadsheet(#[from] calamine::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("UTF-8 error: {0}")]
Utf8(#[from] FromUtf8Error),
#[error("task join error: {0}")]
Join(#[from] tokio::task::JoinError),
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("validation error: {0}")]
Validation(String),
}
impl IntoResponse for AppError {
fn into_response(self) -> Response {
let status = match self {
AppError::Validation(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR,
};
let body = Json(json!({"error": self.to_string()}));
(status, body).into_response()
}
}