1use std::fmt;
4use std::io;
5
6use crate::store::block::BlockError;
7use crate::units::UnitsError;
8
9#[derive(Debug)]
11pub enum MolRsError {
12 Block(BlockError),
14
15 Units(UnitsError),
17
18 Io(io::Error),
20
21 Parse {
23 line: Option<usize>,
25 message: String,
27 },
28
29 Validation {
31 message: String,
33 },
34
35 Zarr {
37 message: String,
39 },
40
41 NotFound {
43 entity: &'static str,
45 message: String,
47 },
48
49 Other(String),
51}
52
53impl fmt::Display for MolRsError {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 match self {
56 MolRsError::Block(e) => write!(f, "Block error: {}", e),
57 MolRsError::Units(e) => write!(f, "Units error: {}", e),
58 MolRsError::Io(e) => write!(f, "IO error: {}", e),
59 MolRsError::Parse {
60 line: Some(line),
61 message,
62 } => {
63 write!(f, "Parse error at line {}: {}", line, message)
64 }
65 MolRsError::Parse {
66 line: None,
67 message,
68 } => {
69 write!(f, "Parse error: {}", message)
70 }
71 MolRsError::Validation { message } => {
72 write!(f, "Validation error: {}", message)
73 }
74 MolRsError::NotFound { entity, message } => {
75 write!(f, "{} not found: {}", entity, message)
76 }
77 MolRsError::Zarr { message } => {
78 write!(f, "Zarr error: {}", message)
79 }
80 MolRsError::Other(msg) => write!(f, "{}", msg),
81 }
82 }
83}
84
85impl std::error::Error for MolRsError {
86 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
87 match self {
88 MolRsError::Block(e) => Some(e),
89 MolRsError::Units(e) => Some(e),
90 MolRsError::Io(e) => Some(e),
91 _ => None,
92 }
93 }
94}
95
96impl From<BlockError> for MolRsError {
98 fn from(err: BlockError) -> Self {
99 MolRsError::Block(err)
100 }
101}
102
103impl From<UnitsError> for MolRsError {
104 fn from(err: UnitsError) -> Self {
105 MolRsError::Units(err)
106 }
107}
108
109impl From<io::Error> for MolRsError {
110 fn from(err: io::Error) -> Self {
111 MolRsError::Io(err)
112 }
113}
114
115impl From<String> for MolRsError {
116 fn from(msg: String) -> Self {
117 MolRsError::Other(msg)
118 }
119}
120
121impl From<&str> for MolRsError {
122 fn from(msg: &str) -> Self {
123 MolRsError::Other(msg.to_string())
124 }
125}
126
127#[cfg(feature = "zarr")]
128impl From<zarrs::group::GroupCreateError> for MolRsError {
129 fn from(e: zarrs::group::GroupCreateError) -> Self {
130 MolRsError::zarr(e.to_string())
131 }
132}
133
134#[cfg(feature = "zarr")]
135impl From<zarrs::storage::StorageError> for MolRsError {
136 fn from(e: zarrs::storage::StorageError) -> Self {
137 MolRsError::zarr(e.to_string())
138 }
139}
140
141#[cfg(feature = "zarr")]
142impl From<zarrs::array::ArrayCreateError> for MolRsError {
143 fn from(e: zarrs::array::ArrayCreateError) -> Self {
144 MolRsError::zarr(e.to_string())
145 }
146}
147
148#[cfg(feature = "zarr")]
149impl From<zarrs::array::ArrayError> for MolRsError {
150 fn from(e: zarrs::array::ArrayError) -> Self {
151 MolRsError::zarr(e.to_string())
152 }
153}
154
155#[cfg(feature = "zarr")]
156impl From<zarrs::node::NodeCreateError> for MolRsError {
157 fn from(e: zarrs::node::NodeCreateError) -> Self {
158 MolRsError::zarr(e.to_string())
159 }
160}
161
162impl MolRsError {
164 pub fn parse_error(line: usize, message: impl Into<String>) -> Self {
166 MolRsError::Parse {
167 line: Some(line),
168 message: message.into(),
169 }
170 }
171
172 pub fn parse(message: impl Into<String>) -> Self {
174 MolRsError::Parse {
175 line: None,
176 message: message.into(),
177 }
178 }
179
180 pub fn validation(message: impl Into<String>) -> Self {
182 MolRsError::Validation {
183 message: message.into(),
184 }
185 }
186
187 pub fn not_found(entity: &'static str, message: impl Into<String>) -> Self {
189 MolRsError::NotFound {
190 entity,
191 message: message.into(),
192 }
193 }
194
195 pub fn zarr(message: impl Into<String>) -> Self {
197 MolRsError::Zarr {
198 message: message.into(),
199 }
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206 use crate::store::block::BlockError;
207
208 #[test]
209 fn test_error_display() {
210 let err = MolRsError::parse_error(42, "unexpected token");
211 assert_eq!(
212 format!("{}", err),
213 "Parse error at line 42: unexpected token"
214 );
215
216 let err = MolRsError::parse("invalid format");
217 assert_eq!(format!("{}", err), "Parse error: invalid format");
218
219 let err = MolRsError::validation("inconsistent dimensions");
220 assert_eq!(
221 format!("{}", err),
222 "Validation error: inconsistent dimensions"
223 );
224 }
225
226 #[test]
227 fn test_from_block_error() {
228 let block_err = BlockError::RankZero {
229 key: "test".to_string(),
230 };
231 let err: MolRsError = block_err.into();
232 assert!(matches!(err, MolRsError::Block(_)));
233 }
234
235 #[test]
236 fn test_from_string() {
237 let err: MolRsError = "test error".into();
238 assert!(matches!(err, MolRsError::Other(_)));
239 assert_eq!(format!("{}", err), "test error");
240 }
241}