Skip to main content

helios_fhirpath/
error.rs

1//! Error types for FHIRPath CLI and server operations
2//!
3//! This module provides error types for the FHIRPath executables,
4//! supporting both CLI and server error scenarios with appropriate
5//! error messages and HTTP status codes.
6
7use std::fmt;
8
9/// Result type alias for FHIRPath operations
10pub type FhirPathResult<T> = Result<T, FhirPathError>;
11
12/// Error types for FHIRPath operations
13#[derive(Debug)]
14pub enum FhirPathError {
15    /// Parse error with message
16    ParseError(String),
17
18    /// Evaluation error with message
19    EvaluationError(String),
20
21    /// IO error (file operations, etc.)
22    IoError(std::io::Error),
23
24    /// JSON serialization/deserialization error
25    JsonError(serde_json::Error),
26
27    /// Invalid input parameters
28    InvalidInput(String),
29
30    /// Resource not found
31    NotFound(String),
32
33    /// Feature not implemented
34    NotImplemented(String),
35
36    /// Server configuration error
37    ConfigError(String),
38
39    /// HTTP-specific error with status code
40    HttpError(u16, String),
41
42    /// Network error (for terminology server operations)
43    NetworkError(String),
44
45    /// Terminology server error
46    TerminologyError(String),
47}
48
49impl fmt::Display for FhirPathError {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        match self {
52            FhirPathError::ParseError(msg) => write!(f, "Parse error: {}", msg),
53            FhirPathError::EvaluationError(msg) => write!(f, "Evaluation error: {}", msg),
54            FhirPathError::IoError(err) => write!(f, "IO error: {}", err),
55            FhirPathError::JsonError(err) => write!(f, "JSON error: {}", err),
56            FhirPathError::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
57            FhirPathError::NotFound(msg) => write!(f, "Not found: {}", msg),
58            FhirPathError::NotImplemented(msg) => write!(f, "Not implemented: {}", msg),
59            FhirPathError::ConfigError(msg) => write!(f, "Configuration error: {}", msg),
60            FhirPathError::HttpError(code, msg) => write!(f, "HTTP {} error: {}", code, msg),
61            FhirPathError::NetworkError(msg) => write!(f, "Network error: {}", msg),
62            FhirPathError::TerminologyError(msg) => write!(f, "Terminology error: {}", msg),
63        }
64    }
65}
66
67impl std::error::Error for FhirPathError {}
68
69impl From<std::io::Error> for FhirPathError {
70    fn from(err: std::io::Error) -> Self {
71        FhirPathError::IoError(err)
72    }
73}
74
75impl From<serde_json::Error> for FhirPathError {
76    fn from(err: serde_json::Error) -> Self {
77        FhirPathError::JsonError(err)
78    }
79}
80
81impl From<String> for FhirPathError {
82    fn from(err: String) -> Self {
83        FhirPathError::InvalidInput(err)
84    }
85}
86
87impl axum::response::IntoResponse for FhirPathError {
88    fn into_response(self) -> axum::response::Response {
89        self.into()
90    }
91}
92
93impl From<FhirPathError> for axum::response::Response {
94    fn from(err: FhirPathError) -> Self {
95        use axum::Json;
96        use axum::http::StatusCode;
97        use axum::response::IntoResponse;
98
99        let (status, message) = match err {
100            FhirPathError::ParseError(msg) => (StatusCode::BAD_REQUEST, msg),
101            FhirPathError::EvaluationError(msg) => (StatusCode::UNPROCESSABLE_ENTITY, msg),
102            FhirPathError::InvalidInput(msg) => (StatusCode::BAD_REQUEST, msg),
103            FhirPathError::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
104            FhirPathError::NotImplemented(msg) => (StatusCode::NOT_IMPLEMENTED, msg),
105            FhirPathError::ConfigError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg),
106            FhirPathError::HttpError(code, msg) => (
107                StatusCode::from_u16(code).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
108                msg,
109            ),
110            FhirPathError::NetworkError(msg) => (StatusCode::BAD_GATEWAY, msg),
111            FhirPathError::TerminologyError(msg) => (StatusCode::BAD_GATEWAY, msg),
112            _ => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()),
113        };
114
115        // Create FHIR OperationOutcome
116        let operation_outcome = serde_json::json!({
117            "resourceType": "OperationOutcome",
118            "issue": [{
119                "severity": "error",
120                "code": match status {
121                    StatusCode::BAD_REQUEST => "invalid",
122                    StatusCode::NOT_FOUND => "not-found",
123                    StatusCode::UNPROCESSABLE_ENTITY => "processing",
124                    StatusCode::NOT_IMPLEMENTED => "not-supported",
125                    _ => "exception",
126                },
127                "diagnostics": message
128            }]
129        });
130
131        (status, Json(operation_outcome)).into_response()
132    }
133}