octofhir_fhir_model/
error.rs1pub type Result<T> = std::result::Result<T, ModelError>;
5
6#[derive(Debug, thiserror::Error)]
8pub enum ModelError {
9 #[error("Type not found: {type_name}")]
11 TypeNotFound {
12 type_name: String,
14 },
15
16 #[error("Property '{property}' not found on type '{type_name}'")]
18 PropertyNotFound {
19 type_name: String,
21 property: String,
23 },
24
25 #[error("Schema loading error: {message}")]
27 SchemaLoadError {
28 message: String,
30 },
31
32 #[error("Validation error: {message}")]
34 ValidationError {
35 message: String,
37 },
38
39 #[error("Constraint evaluation error: {constraint_key}: {message}")]
41 ConstraintError {
42 constraint_key: String,
44 message: String,
46 },
47
48 #[error("Reference resolution error: {reference}: {message}")]
50 ReferenceError {
51 reference: String,
53 message: String,
55 },
56
57 #[error("Type incompatibility: expected {expected}, got {actual}")]
59 TypeIncompatibility {
60 expected: String,
62 actual: String,
64 },
65
66 #[error("Invalid configuration: {message}")]
68 InvalidConfiguration {
69 message: String,
71 },
72
73 #[error("I/O error: {0}")]
75 IoError(#[from] std::io::Error),
76
77 #[cfg(feature = "serde")]
79 #[error("JSON error: {0}")]
80 JsonError(#[from] serde_json::Error),
81
82 #[error("FHIRPath evaluation error: {message}")]
84 EvaluationError {
85 message: String,
87 },
88
89 #[error("Model error: {message}")]
91 Generic {
92 message: String,
94 },
95}
96
97impl ModelError {
98 pub fn type_not_found(type_name: impl Into<String>) -> Self {
100 Self::TypeNotFound {
101 type_name: type_name.into(),
102 }
103 }
104
105 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 pub fn schema_load_error(message: impl Into<String>) -> Self {
115 Self::SchemaLoadError {
116 message: message.into(),
117 }
118 }
119
120 pub fn validation_error(message: impl Into<String>) -> Self {
122 Self::ValidationError {
123 message: message.into(),
124 }
125 }
126
127 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 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 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 pub fn invalid_configuration(message: impl Into<String>) -> Self {
153 Self::InvalidConfiguration {
154 message: message.into(),
155 }
156 }
157
158 pub fn evaluation_error(message: impl Into<String>) -> Self {
160 Self::EvaluationError {
161 message: message.into(),
162 }
163 }
164
165 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}