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