Files
rustical/crates/store/src/error.rs
2025-11-05 23:17:59 +01:00

64 lines
1.6 KiB
Rust

use axum::response::IntoResponse;
use http::StatusCode;
use tracing::error;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Not found")]
NotFound,
#[error("Resource already exists and overwrite=false")]
AlreadyExists,
#[error("Invalid principal type: {0}")]
InvalidPrincipalType(String),
#[error("Read-only")]
ReadOnly,
#[error("Error generating password hash")]
PasswordHash,
#[error(transparent)]
IO(#[from] std::io::Error),
#[error(transparent)]
Other(#[from] anyhow::Error),
#[error(transparent)]
IcalError(#[from] rustical_ical::Error),
}
impl Error {
#[must_use]
pub const fn status_code(&self) -> StatusCode {
match self {
Self::NotFound => StatusCode::NOT_FOUND,
Self::AlreadyExists => StatusCode::CONFLICT,
Self::ReadOnly => StatusCode::FORBIDDEN,
Self::IcalError(err) => err.status_code(),
Self::InvalidPrincipalType(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
#[must_use]
pub const fn is_not_found(&self) -> bool {
matches!(self, Self::NotFound)
}
}
impl IntoResponse for Error {
fn into_response(self) -> axum::response::Response {
if matches!(
self.status_code(),
StatusCode::INTERNAL_SERVER_ERROR
| StatusCode::PRECONDITION_FAILED
| StatusCode::CONFLICT
) {
error!("{self}");
}
(self.status_code(), self.to_string()).into_response()
}
}