use axum::{
http::StatusCode,
response::{IntoResponse, Response},
Json,
};
use serde_json::json;
use trusty_common::memory_core::palace::PalaceId;
use crate::AppState;
pub(crate) fn open_handle(
state: &AppState,
id: &str,
) -> Result<std::sync::Arc<trusty_common::memory_core::PalaceHandle>, ApiError> {
state
.registry
.open_palace(&state.data_root, &PalaceId::new(id))
.map_err(|e| ApiError::not_found(format!("palace not found: {id} ({e:#})")))
}
pub(crate) struct ApiError {
pub(crate) status: StatusCode,
pub(crate) message: String,
}
impl ApiError {
pub(crate) fn bad_request(msg: impl Into<String>) -> Self {
Self {
status: StatusCode::BAD_REQUEST,
message: msg.into(),
}
}
pub(crate) fn not_found(msg: impl Into<String>) -> Self {
Self {
status: StatusCode::NOT_FOUND,
message: msg.into(),
}
}
#[allow(dead_code)]
pub(crate) fn conflict(msg: impl Into<String>) -> Self {
Self {
status: StatusCode::CONFLICT,
message: msg.into(),
}
}
pub(crate) fn internal(msg: impl Into<String>) -> Self {
Self {
status: StatusCode::INTERNAL_SERVER_ERROR,
message: msg.into(),
}
}
pub(crate) fn unprocessable(msg: impl Into<String>) -> Self {
Self {
status: StatusCode::UNPROCESSABLE_ENTITY,
message: msg.into(),
}
}
}
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
(self.status, Json(json!({ "error": self.message }))).into_response()
}
}
impl From<crate::service::ServiceError> for ApiError {
fn from(e: crate::service::ServiceError) -> Self {
match e {
crate::service::ServiceError::BadRequest(m) => ApiError::bad_request(m),
crate::service::ServiceError::NotFound(m) => ApiError::not_found(m),
crate::service::ServiceError::Conflict(m) => ApiError::conflict(m),
crate::service::ServiceError::Internal(m) => ApiError::internal(m),
}
}
}