1 | use std::path::{Path, PathBuf}; |
2 | |
3 | /// Represents any kind of error that can occur while parsing the UCD. |
4 | #[derive (Debug)] |
5 | pub struct Error { |
6 | pub(crate) kind: ErrorKind, |
7 | pub(crate) line: Option<u64>, |
8 | pub(crate) path: Option<PathBuf>, |
9 | } |
10 | |
11 | /// The kind of error that occurred while parsing the UCD. |
12 | #[derive (Debug)] |
13 | pub enum ErrorKind { |
14 | /// An I/O error. |
15 | Io(std::io::Error), |
16 | /// A generic parse error. |
17 | Parse(String), |
18 | } |
19 | |
20 | impl Error { |
21 | /// Create a new parse error from the given message. |
22 | pub(crate) fn parse(msg: String) -> Error { |
23 | Error { kind: ErrorKind::Parse(msg), line: None, path: None } |
24 | } |
25 | |
26 | /// Return the specific kind of this error. |
27 | pub fn kind(&self) -> &ErrorKind { |
28 | &self.kind |
29 | } |
30 | |
31 | /// Return the line number at which this error occurred, if available. |
32 | pub fn line(&self) -> Option<u64> { |
33 | self.line |
34 | } |
35 | |
36 | /// Return the file path associated with this error, if one exists. |
37 | pub fn path(&self) -> Option<&Path> { |
38 | self.path.as_ref().map(|p| &**p) |
39 | } |
40 | |
41 | /// Unwrap this error into its underlying kind. |
42 | pub fn into_kind(self) -> ErrorKind { |
43 | self.kind |
44 | } |
45 | |
46 | /// Returns true if and only if this is an I/O error. |
47 | /// |
48 | /// If this returns true, the underlying `ErrorKind` is guaranteed to be |
49 | /// `ErrorKind::Io`. |
50 | pub fn is_io_error(&self) -> bool { |
51 | match self.kind { |
52 | ErrorKind::Io(_) => true, |
53 | _ => false, |
54 | } |
55 | } |
56 | } |
57 | |
58 | impl std::error::Error for Error {} |
59 | |
60 | impl std::fmt::Display for Error { |
61 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
62 | if let Some(ref path: &PathBuf) = self.path { |
63 | if let Some(line: u64) = self.line { |
64 | write!(f, " {}: {}: " , path.display(), line)?; |
65 | } else { |
66 | write!(f, " {}: " , path.display())?; |
67 | } |
68 | } else if let Some(line: u64) = self.line { |
69 | write!(f, "error on line {}: " , line)?; |
70 | } |
71 | match self.kind { |
72 | ErrorKind::Io(ref err: &Error) => write!(f, " {}" , err), |
73 | ErrorKind::Parse(ref msg: &String) => write!(f, " {}" , msg), |
74 | } |
75 | } |
76 | } |
77 | |