1use std::{
2 collections::VecDeque,
3 fmt::Display,
4 num::ParseIntError,
5 str::Utf8Error,
6 sync::{MutexGuard, PoisonError},
7};
8
9use base64::DecodeError;
10use serde::{ser::SerializeStruct, Serialize, Serializer};
11
12use crate::{
13 mzml::{attributes::AttributeType, Tag},
14 obo::ValueType,
15};
16
17#[derive(Debug)]
19pub enum ParseError {
20 IntError((Tag, ParseIntError)),
22 Utf8Error((Tag, Utf8Error)),
24 XMLError((Tag, quick_xml::Error)),
26 UnexpectedAttribute((Tag, String)),
28 MissingAttribute((Tag, String)),
30 MissingAttributeValue((Tag, String, AttributeType)),
32 UnexpectedTag(String),
34 MissingRef {
36 breadcrumbs: Breadcrumbs,
38 tag: Tag,
40 ref_to_tag: Tag,
42 ref_id: String,
44 },
45 MissingValue((Breadcrumbs, String, ValueType)),
47 UnexpectedValue((Breadcrumbs, String, String)),
49 InvalidValue((Breadcrumbs, String, String)),
51
52 UnknownAccession((Breadcrumbs, String)),
54 }
61
62impl ParseError {
63 pub fn description(&self) -> String {
65 match self {
66 ParseError::IntError((tag, int_error)) => {
67 format!("Couldn't convert integer at tag {}: {}", tag, int_error)
68 }
69 ParseError::Utf8Error(_) => todo!(),
70 ParseError::XMLError(_) => todo!(),
71 ParseError::UnexpectedAttribute((tag, string)) => {
72 format!("{} tag has an unexpected attribute {}", tag, string)
73 }
74 ParseError::MissingAttribute((tag, string)) => {
75 format!("{} tag is missing required attribute. {}", tag, string)
76 }
77 ParseError::MissingAttributeValue((tag, attribute, attribute_type)) => {
78 format!(
79 "{} tag is missing value of type {:?} for attribute {}",
80 tag, attribute_type, attribute
81 )
82 }
83 ParseError::UnexpectedTag(string) => {
84 format!("Unexpected tag: {}", string)
85 }
86 ParseError::MissingRef {
87 breadcrumbs: _breadcrumbs,
88 tag,
89 ref_to_tag,
90 ref_id,
91 } => {
92 format!(
93 "Tag {} includes a reference to a {} tag with id {}, but this doesn't exist",
94 tag, ref_to_tag, ref_id
95 )
96 }
97 ParseError::MissingValue((_breadcrumbs, data, value_type)) => {
98 format!(
99 " Missing value of type {:?} for cvParam {}",
100 value_type, data
101 )
102 }
103 ParseError::InvalidValue((_breadcrumbs, data, value)) => {
104 format!("Found an invalid value ({}) for cvParam {}", value, data)
105 }
106 ParseError::UnexpectedValue((_breadcrumbs, data, value)) => {
107 format!(
108 "Found a value ({}) when one wasn't expected for cvParam {}",
109 value, data
110 )
111 }
112 ParseError::UnknownAccession((_breadcrumbs, accession)) => {
113 format!(
114 "Found an accession (cvParam) ({}) that was not present in the ontology",
115 accession
116 )
117 }
118 }
119 }
120}
121
122impl Display for ParseError {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 match self {
125 ParseError::IntError(_) => {
126 write!(f, "{}", self.description())
127 }
128 ParseError::Utf8Error(_) => {
129 write!(f, "{}", self.description())
130 },
131 ParseError::XMLError(_) => {
132 write!(f, "{}", self.description())
133 },
134 ParseError::UnexpectedAttribute(_) => {
135 write!(f, "{}", self.description())
136 }
137 ParseError::MissingAttribute(_) => {
138 write!(f, "{}", self.description())
139 }
140 ParseError::MissingAttributeValue(_) => {
141 write!(f, "{}", self.description())
142 }
143 ParseError::UnexpectedTag(_) => {
144 write!(f, "{}", self.description())
145 }
146 ParseError::MissingRef {
147 breadcrumbs,
148 tag: _,
149 ref_to_tag: _,
150 ref_id: _,
151 } => {
152 write!(
153 f,
154 "[{}] {}",
155 breadcrumbs, self.description()
156 )
157 }
158 ParseError::MissingValue((breadcrumbs, _data, _value_type)) => {
159 write!(
160 f,
161 "[{}] {}",
162 breadcrumbs, self.description()
163 )
164 }
165 ParseError::InvalidValue((breadcrumbs, _data, _value)) => {
166 write!(
167 f,
168 "[{}] {}",
169 breadcrumbs, self.description()
170 )
171 }
172 ParseError::UnexpectedValue((breadcrumbs, _data, _value)) => {
173 write!(
174 f,
175 "[{}] {}",
176 breadcrumbs, self.description()
177 )
178 }
179 ParseError::UnknownAccession((breadcrumbs, _accession)) => {
180 write!(
181 f,
182 "[{}] {}",
183 breadcrumbs, self.description()
184 )
185 }
186
187 }
191 }
192}
193
194impl Serialize for ParseError {
195 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
196 where
197 S: Serializer,
198 {
199 let mut state = serializer.serialize_struct("parse_error", 2)?;
200
201 match self {
202 ParseError::IntError((tag, _error)) => {
203 state.serialize_field("type", "IntError")?;
204 state.serialize_field("tag", tag)?;
205 state.serialize_field("description", &self.description())?;
206 }
207 ParseError::Utf8Error((tag, _error)) => {
208 state.serialize_field("type", "Utf8Error")?;
209 state.serialize_field("tag", tag)?;
210 state.serialize_field("description", &self.description())?;
211 }
212 ParseError::XMLError((tag, _error)) => {
213 state.serialize_field("type", "XMLError")?;
214 state.serialize_field("tag", tag)?;
215 state.serialize_field("description", &self.description())?;
216 }
217 ParseError::UnexpectedAttribute((tag, _error)) => {
218 state.serialize_field("type", "UnexpectedAttribute")?;
219 state.serialize_field("tag", tag)?;
220 state.serialize_field("description", &self.description())?;
221 }
222 ParseError::MissingAttribute((tag, _error)) => {
223 state.serialize_field("type", "MissingAttribute")?;
224 state.serialize_field("tag", tag)?;
225 state.serialize_field("description", &self.description())?;
226 }
227 ParseError::MissingAttributeValue((tag, _attribute, _attribute_value)) => {
228 state.serialize_field("type", "MissingAttributeValue")?;
229 state.serialize_field("tag", tag)?;
230 state.serialize_field("description", &self.description())?;
231 }
232 ParseError::UnexpectedTag(_) => {
233 state.serialize_field("type", "UnexpectedTag")?;
234 state.serialize_field("description", &self.description())?;
235 }
236 ParseError::MissingRef {
237 breadcrumbs,
238 tag,
239 ref_to_tag,
240 ref_id,
241 } => {
242 state.serialize_field("type", "MissingRef")?;
243 state.serialize_field("tag", tag)?;
244 state.serialize_field("description", &self.description())?;
245 state.serialize_field("location", &format!("{}", breadcrumbs))?;
246 state.serialize_field("ref_to_tag", ref_to_tag)?;
247 state.serialize_field("ref_id", ref_id)?;
248 }
249 ParseError::MissingValue((breadcrumbs, _details, value_type)) => {
250 state.serialize_field("type", "MissingValue")?;
251 state.serialize_field("description", &self.description())?;
252 state.serialize_field("location", &format!("{}", breadcrumbs))?;
253 state.serialize_field("expected_value_type", value_type)?;
254 }
255 ParseError::UnexpectedValue((breadcrumbs, _, _)) => {
256 state.serialize_field("type", "UnexpectedValue")?;
257 state.serialize_field("description", &self.description())?;
258 state.serialize_field("location", &format!("{}", breadcrumbs))?;
259 }
260 ParseError::InvalidValue((breadcrumbs, _, _)) => {
261 state.serialize_field("type", "InvalidValue")?;
262 state.serialize_field("description", &self.description())?;
263 state.serialize_field("location", &format!("{}", breadcrumbs))?;
264 }
265 ParseError::UnknownAccession((breadcrumbs, _)) => {
266 state.serialize_field("type", "UnknownAccession")?;
267 state.serialize_field("description", &self.description())?;
268 state.serialize_field("location", &format!("{}", breadcrumbs))?;
269 }
270 }
271
272 state.end()
273 }
274}
275
276#[derive(Debug, Clone)]
278pub struct Breadcrumbs(pub VecDeque<(Tag, Option<String>)>);
279
280impl std::fmt::Display for Breadcrumbs {
281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
282 for (index, (tag, id)) in self.0.iter().enumerate() {
283 if index > 0 {
284 write!(f, ">")?;
285 }
286
287 write!(f, "{}", tag)?;
288
289 if let Some(id) = id {
290 write!(f, "[{}]", id)?;
291 }
292 }
293
294 Ok(())
295 }
296}
297
298#[non_exhaustive]
300#[derive(Debug)]
301pub enum FatalParseError {
302 IOError(std::io::Error),
304 XMLError(quick_xml::Error),
306 UnexpectedTag(String),
308 InvalidTag((Tag, String)),
311 MissingOpeningTag(String),
313 MissingClosingTag(String),
315 UnexpectedError(String),
317 InvalidUtf8(Utf8Error),
319 UnexpectedEvent(String),
321}
322
323impl Serialize for FatalParseError {
324 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
325 where
326 S: Serializer,
327 {
328 let mut state = serializer.serialize_struct("fatal_error", 2)?;
329
330 match self {
331 FatalParseError::IOError(error) => {
332 state.serialize_field("type", "IOError")?;
333 state.serialize_field("details", &format!("{}", error))?;
334 }
335 FatalParseError::XMLError(error) => {
336 state.serialize_field("type", "XMLError")?;
337 state.serialize_field("details", &format!("{}", error))?;
338 }
339 FatalParseError::UnexpectedTag(error) => {
340 state.serialize_field("type", "UnexpectedTag")?;
341 state.serialize_field("details", error)?;
342 }
343 FatalParseError::MissingOpeningTag(error) => {
344 state.serialize_field("type", "MissingOpeningTag")?;
345 state.serialize_field("details", error)?;
346 }
347 FatalParseError::MissingClosingTag(error) => {
348 state.serialize_field("type", "MissingOpeningTag")?;
349 state.serialize_field("details", error)?;
350 }
351 FatalParseError::UnexpectedError(error) => {
352 state.serialize_field("type", "UnexpectedError")?;
353 state.serialize_field("details", error)?;
354 }
355 FatalParseError::UnexpectedEvent(error) => {
356 state.serialize_field("type", "UnexpectedEvent")?;
357 state.serialize_field("details", error)?;
358 }
359 FatalParseError::InvalidUtf8(error) => {
360 state.serialize_field("type", "InvalidUtf8")?;
361 state.serialize_field("details", &format!("{:?}", error))?;
362 }
363 FatalParseError::InvalidTag((tag, error)) => {
364 state.serialize_field("type", "InvalidTag")?;
365 state.serialize_field("tag", &format!("{}", tag))?;
366 state.serialize_field("details", error)?;
367 }
368 }
369
370 state.end()
371 }
372}
373
374impl From<std::io::Error> for FatalParseError {
375 fn from(error: std::io::Error) -> Self {
376 FatalParseError::IOError(error)
377 }
378}
379
380impl From<Utf8Error> for FatalParseError {
381 fn from(error: Utf8Error) -> Self {
382 FatalParseError::InvalidUtf8(error)
383 }
384}
385
386impl From<quick_xml::Error> for FatalParseError {
387 fn from(error: quick_xml::Error) -> Self {
388 FatalParseError::XMLError(error)
389 }
390}
391
392#[derive(Debug)]
394pub enum DataError {
395 MutexError,
397 IOError(std::io::Error),
399 Base64DecodeError(DecodeError),
401 UnknownDataType,
403}
404
405impl<'a, D> From<PoisonError<MutexGuard<'a, D>>> for DataError {
406 fn from(_poison_error: PoisonError<MutexGuard<'a, D>>) -> Self {
407 Self::MutexError
408 }
409}
410
411impl From<std::io::Error> for DataError {
412 fn from(io_error: std::io::Error) -> Self {
413 Self::IOError(io_error)
414 }
415}
416
417impl From<DecodeError> for DataError {
418 fn from(decode_error: DecodeError) -> Self {
419 Self::Base64DecodeError(decode_error)
420 }
421}