nom_xml/
error.rs

1use std::fmt::{self, Debug, Display};
2
3#[macro_export]
4macro_rules! warnln {
5    ($($arg:tt)*) => ({
6        eprintln!("\x1B[33mWARNING:\x1B[0m {}", format!($($arg)*));
7    });
8}
9
10#[derive(Debug)]
11pub enum Error {
12    NomError(nom::error::Error<String>),
13    NomErrorFast(nom::error::ErrorKind),
14    IoError(std::io::Error),
15    UserAbort(String),
16}
17
18impl Display for Error {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        match self {
21            Error::NomError(e) => write!(f, "NomError: {}", e),
22            Error::NomErrorFast(kind) => write!(f, "NomErrorFast: {:?}", kind),
23            Error::IoError(e) => write!(f, "IoError: {}", e),
24            Error::UserAbort(e) => write!(f, "UserAbort: {}", e),
25        }
26    }
27}
28
29impl std::error::Error for Error {
30    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
31        match self {
32            Error::NomError(_) => None,
33            Error::NomErrorFast(_) => None,
34            Error::IoError(e) => Some(e),
35            Error::UserAbort(_) => None,
36        }
37    }
38}
39
40impl From<std::io::Error> for Error {
41    fn from(error: std::io::Error) -> Self {
42        Error::IoError(error)
43    }
44}
45
46impl From<nom::error::Error<&str>> for Error {
47    fn from(error: nom::error::Error<&str>) -> Self {
48        Error::NomError(nom::error::Error::new(error.input.into(), error.code))
49    }
50}
51
52impl From<nom::error::Error<String>> for Error {
53    fn from(error: nom::error::Error<String>) -> Self {
54        Error::NomError(error)
55    }
56}
57
58impl From<Error> for nom::Err<Error> {
59    fn from(error: Error) -> Self {
60        nom::Err::Failure(error)
61    }
62}
63
64impl From<Box<dyn std::error::Error>> for Error {
65    fn from(error: Box<dyn std::error::Error>) -> Self {
66        Error::NomError(nom::error::Error::new(
67            error.to_string(),
68            nom::error::ErrorKind::Fail,
69        ))
70    }
71}
72
73impl<I> nom::error::ParseError<I> for Error
74where
75    I: Debug + ToString,
76{
77    fn from_error_kind(input: I, kind: nom::error::ErrorKind) -> Self {
78        if cfg!(debug_assertions) {
79            Error::NomError(nom::error::Error::new(input.to_string(), kind))
80        } else {
81            Error::NomErrorFast(kind)
82        }
83    }
84
85    fn append(input: I, kind: nom::error::ErrorKind, _other: Self) -> Self {
86        if cfg!(debug_assertions) {
87            Error::NomError(nom::error::Error::new(input.to_string(), kind))
88        } else {
89            Error::NomErrorFast(kind)
90        }
91    }
92
93    fn from_char(input: I, _: char) -> Self {
94        if cfg!(debug_assertions) {
95            Error::NomError(nom::error::Error::new(
96                input.to_string(),
97                nom::error::ErrorKind::Char,
98            ))
99        } else {
100            Error::NomErrorFast(nom::error::ErrorKind::Char)
101        }
102    }
103
104    fn or(self, _other: Self) -> Self {
105        self
106    }
107}
108
109impl<I, E> nom::error::FromExternalError<I, E> for Error
110where
111    I: Debug + ToString,
112    E: Debug + Display,
113{
114    fn from_external_error(input: I, kind: nom::error::ErrorKind, _e: E) -> Self {
115        if cfg!(debug_assertions) {
116            Error::NomError(nom::error::Error::new(input.to_string(), kind))
117        } else {
118            Error::NomErrorFast(kind)
119        }
120    }
121}
122
123pub trait ConvertNomError<E> {
124    fn convert_nom_error(self) -> nom::Err<Error>;
125}
126
127impl<E> ConvertNomError<nom::error::Error<E>> for nom::Err<nom::error::Error<E>>
128where
129    E: Debug + ToString,
130{
131    fn convert_nom_error(self) -> nom::Err<Error> {
132        match self {
133            nom::Err::Error(e) => {
134                let nom::error::Error { input, code } = e;
135                nom::Err::Error(if cfg!(debug_assertions) {
136                    Error::NomError(nom::error::Error::new(input.to_string(), code))
137                } else {
138                    Error::NomErrorFast(code)
139                })
140            }
141            nom::Err::Failure(e) => {
142                let nom::error::Error { input, code } = e;
143                nom::Err::Failure(if cfg!(debug_assertions) {
144                    Error::NomError(nom::error::Error::new(input.to_string(), code))
145                } else {
146                    Error::NomErrorFast(code)
147                })
148            }
149            nom::Err::Incomplete(needed) => nom::Err::Incomplete(needed),
150        }
151    }
152}