use std::fmt;
pub type FhirPathResult<T> = Result<T, FhirPathError>;
#[derive(Debug)]
pub enum FhirPathError {
ParseError(String),
EvaluationError(String),
IoError(std::io::Error),
JsonError(serde_json::Error),
InvalidInput(String),
NotFound(String),
NotImplemented(String),
ConfigError(String),
HttpError(u16, String),
NetworkError(String),
TerminologyError(String),
}
impl fmt::Display for FhirPathError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FhirPathError::ParseError(msg) => write!(f, "Parse error: {}", msg),
FhirPathError::EvaluationError(msg) => write!(f, "Evaluation error: {}", msg),
FhirPathError::IoError(err) => write!(f, "IO error: {}", err),
FhirPathError::JsonError(err) => write!(f, "JSON error: {}", err),
FhirPathError::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
FhirPathError::NotFound(msg) => write!(f, "Not found: {}", msg),
FhirPathError::NotImplemented(msg) => write!(f, "Not implemented: {}", msg),
FhirPathError::ConfigError(msg) => write!(f, "Configuration error: {}", msg),
FhirPathError::HttpError(code, msg) => write!(f, "HTTP {} error: {}", code, msg),
FhirPathError::NetworkError(msg) => write!(f, "Network error: {}", msg),
FhirPathError::TerminologyError(msg) => write!(f, "Terminology error: {}", msg),
}
}
}
impl std::error::Error for FhirPathError {}
impl From<std::io::Error> for FhirPathError {
fn from(err: std::io::Error) -> Self {
FhirPathError::IoError(err)
}
}
impl From<serde_json::Error> for FhirPathError {
fn from(err: serde_json::Error) -> Self {
FhirPathError::JsonError(err)
}
}
impl From<String> for FhirPathError {
fn from(err: String) -> Self {
FhirPathError::InvalidInput(err)
}
}
impl axum::response::IntoResponse for FhirPathError {
fn into_response(self) -> axum::response::Response {
self.into()
}
}
impl From<FhirPathError> for axum::response::Response {
fn from(err: FhirPathError) -> Self {
use axum::Json;
use axum::http::StatusCode;
use axum::response::IntoResponse;
let (status, message) = match err {
FhirPathError::ParseError(msg) => (StatusCode::BAD_REQUEST, msg),
FhirPathError::EvaluationError(msg) => (StatusCode::UNPROCESSABLE_ENTITY, msg),
FhirPathError::InvalidInput(msg) => (StatusCode::BAD_REQUEST, msg),
FhirPathError::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
FhirPathError::NotImplemented(msg) => (StatusCode::NOT_IMPLEMENTED, msg),
FhirPathError::ConfigError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg),
FhirPathError::HttpError(code, msg) => (
StatusCode::from_u16(code).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
msg,
),
FhirPathError::NetworkError(msg) => (StatusCode::BAD_GATEWAY, msg),
FhirPathError::TerminologyError(msg) => (StatusCode::BAD_GATEWAY, msg),
_ => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()),
};
let operation_outcome = serde_json::json!({
"resourceType": "OperationOutcome",
"issue": [{
"severity": "error",
"code": match status {
StatusCode::BAD_REQUEST => "invalid",
StatusCode::NOT_FOUND => "not-found",
StatusCode::UNPROCESSABLE_ENTITY => "processing",
StatusCode::NOT_IMPLEMENTED => "not-supported",
_ => "exception",
},
"diagnostics": message
}]
});
(status, Json(operation_outcome)).into_response()
}
}