use core::fmt;
#[derive(Debug, Clone)]
pub struct Error {
status: u16,
details: String,
}
impl Error {
pub fn new(status: u16, details: String) -> Self {
Self { status, details }
}
pub fn status(&self) -> u16 {
self.status
}
pub fn details(&self) -> &str {
&self.details
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.details)
}
}
impl std::error::Error for Error {
fn description(&self) -> &str {
&self.details
}
}
impl From<sqlx::Error> for Error {
fn from(error: sqlx::Error) -> Self {
match error {
sqlx::Error::RowNotFound => Error::new(404, "Not found".to_string()),
sqlx::Error::ColumnIndexOutOfBounds { .. } => Error::new(422, error.to_string()),
sqlx::Error::ColumnNotFound { .. } => Error::new(422, error.to_string()),
sqlx::Error::ColumnDecode { .. } => Error::new(422, error.to_string()),
sqlx::Error::Decode(_) => Error::new(422, error.to_string()),
sqlx::Error::PoolTimedOut => Error::new(503, error.to_string()),
sqlx::Error::PoolClosed => Error::new(503, error.to_string()),
sqlx::Error::Tls(_) => Error::new(500, error.to_string()),
sqlx::Error::Io(_) => Error::new(500, error.to_string()),
sqlx::Error::Protocol(_) => Error::new(500, error.to_string()),
sqlx::Error::Configuration(_) => Error::new(500, error.to_string()),
sqlx::Error::AnyDriverError(_) => Error::new(500, error.to_string()),
sqlx::Error::Database(err) => {
if let Some(code) = err.code() {
match code.trim() {
"23505" => return Error::new(409, err.to_string()),
_ => (),
}
}
Error::new(500, err.to_string())
}
sqlx::Error::Migrate(_) => Error::new(500, error.to_string()),
sqlx::Error::TypeNotFound { type_name } => {
Error::new(500, format!("Type not found: {}", type_name))
}
sqlx::Error::WorkerCrashed => Error::new(500, error.to_string()),
_ => Error::new(500, error.to_string()),
}
}
}