octofhir_fhir_model/
error.rs

1//! Error types for FHIR model operations
2
3/// Result type for FHIR model operations
4pub type Result<T> = std::result::Result<T, ModelError>;
5
6/// Error types for FHIR model operations
7#[derive(Debug, thiserror::Error)]
8pub enum ModelError {
9    /// Type not found in model
10    #[error("Type not found: {type_name}")]
11    TypeNotFound {
12        /// Name of the type that was not found
13        type_name: String,
14    },
15
16    /// Property not found on type
17    #[error("Property '{property}' not found on type '{type_name}'")]
18    PropertyNotFound {
19        /// Name of the type being accessed
20        type_name: String,
21        /// Name of the property that was not found
22        property: String,
23    },
24
25    /// Schema loading error
26    #[error("Schema loading error: {message}")]
27    SchemaLoadError {
28        /// Error message describing the schema loading failure
29        message: String,
30    },
31
32    /// Validation error
33    #[error("Validation error: {message}")]
34    ValidationError {
35        /// Error message describing the validation failure
36        message: String,
37    },
38
39    /// Constraint evaluation error
40    #[error("Constraint evaluation error: {constraint_key}: {message}")]
41    ConstraintError {
42        /// Key identifying the constraint that failed
43        constraint_key: String,
44        /// Error message describing the constraint failure
45        message: String,
46    },
47
48    /// Reference resolution error
49    #[error("Reference resolution error: {reference}: {message}")]
50    ReferenceError {
51        /// The reference that could not be resolved
52        reference: String,
53        /// Error message describing the resolution failure
54        message: String,
55    },
56
57    /// Type incompatibility error
58    #[error("Type incompatibility: expected {expected}, got {actual}")]
59    TypeIncompatibility {
60        /// The expected type
61        expected: String,
62        /// The actual type that was encountered
63        actual: String,
64    },
65
66    /// Configuration error
67    #[error("Invalid configuration: {message}")]
68    InvalidConfiguration {
69        /// Error message describing the configuration error
70        message: String,
71    },
72
73    /// Network or I/O error
74    #[error("I/O error: {0}")]
75    IoError(#[from] std::io::Error),
76
77    /// JSON parsing error
78    #[cfg(feature = "serde")]
79    #[error("JSON error: {0}")]
80    JsonError(#[from] serde_json::Error),
81
82    /// FHIRPath evaluation error
83    #[error("FHIRPath evaluation error: {message}")]
84    EvaluationError {
85        /// Error message describing the evaluation failure
86        message: String,
87    },
88
89    /// Generic error with message
90    #[error("Model error: {message}")]
91    Generic {
92        /// Error message describing the generic failure
93        message: String,
94    },
95}
96
97impl ModelError {
98    /// Create a type not found error
99    pub fn type_not_found(type_name: impl Into<String>) -> Self {
100        Self::TypeNotFound {
101            type_name: type_name.into(),
102        }
103    }
104
105    /// Create a property not found error
106    pub fn property_not_found(type_name: impl Into<String>, property: impl Into<String>) -> Self {
107        Self::PropertyNotFound {
108            type_name: type_name.into(),
109            property: property.into(),
110        }
111    }
112
113    /// Create a schema loading error
114    pub fn schema_load_error(message: impl Into<String>) -> Self {
115        Self::SchemaLoadError {
116            message: message.into(),
117        }
118    }
119
120    /// Create a validation error
121    pub fn validation_error(message: impl Into<String>) -> Self {
122        Self::ValidationError {
123            message: message.into(),
124        }
125    }
126
127    /// Create a constraint error
128    pub fn constraint_error(constraint_key: impl Into<String>, message: impl Into<String>) -> Self {
129        Self::ConstraintError {
130            constraint_key: constraint_key.into(),
131            message: message.into(),
132        }
133    }
134
135    /// Create a reference error
136    pub fn reference_error(reference: impl Into<String>, message: impl Into<String>) -> Self {
137        Self::ReferenceError {
138            reference: reference.into(),
139            message: message.into(),
140        }
141    }
142
143    /// Create a type incompatibility error
144    pub fn type_incompatibility(expected: impl Into<String>, actual: impl Into<String>) -> Self {
145        Self::TypeIncompatibility {
146            expected: expected.into(),
147            actual: actual.into(),
148        }
149    }
150
151    /// Create an invalid configuration error
152    pub fn invalid_configuration(message: impl Into<String>) -> Self {
153        Self::InvalidConfiguration {
154            message: message.into(),
155        }
156    }
157
158    /// Create an evaluation error
159    pub fn evaluation_error(message: impl Into<String>) -> Self {
160        Self::EvaluationError {
161            message: message.into(),
162        }
163    }
164
165    /// Create a generic error
166    pub fn generic(message: impl Into<String>) -> Self {
167        Self::Generic {
168            message: message.into(),
169        }
170    }
171}
172
173#[cfg(test)]
174mod tests {
175    use super::*;
176
177    #[test]
178    fn test_error_creation() {
179        let error = ModelError::type_not_found("Patient");
180        assert!(matches!(error, ModelError::TypeNotFound { .. }));
181        assert_eq!(error.to_string(), "Type not found: Patient");
182
183        let error = ModelError::property_not_found("Patient", "name");
184        assert!(matches!(error, ModelError::PropertyNotFound { .. }));
185        assert_eq!(
186            error.to_string(),
187            "Property 'name' not found on type 'Patient'"
188        );
189    }
190
191    #[test]
192    fn test_error_chain() {
193        let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
194        let model_error = ModelError::from(io_error);
195        assert!(matches!(model_error, ModelError::IoError(_)));
196    }
197}