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}