1use std::path::{Path, PathBuf};
2
3/// Represents any kind of error that can occur while parsing the UCD.
4#[derive(Debug)]
5pub 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)]
13pub enum ErrorKind {
14 /// An I/O error.
15 Io(std::io::Error),
16 /// A generic parse error.
17 Parse(String),
18}
19
20impl 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
58impl std::error::Error for Error {}
59
60impl 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