1use std::fmt::{self, Debug, Display};
4use std::{error, io, result};
5
6use serde::{de, ser};
7
8use lexpr::parse;
9pub use lexpr::parse::error::Location;
10
11pub struct Error(Box<ErrorImpl>);
14
15pub type Result<T> = result::Result<T, Error>;
17
18enum ErrorImpl {
19 Message(String, Option<Location>),
20 Io(io::Error),
21 Parse(parse::Error),
22}
23
24impl Error {
25 pub fn location(&self) -> Option<Location> {
27 match &*self.0 {
28 ErrorImpl::Message(_, loc) => *loc,
29 ErrorImpl::Parse(e) => e.location(),
30 ErrorImpl::Io(_) => None,
31 }
32 }
33 pub fn classify(&self) -> Category {
40 match &*self.0 {
41 ErrorImpl::Message(_, _) => Category::Data,
42 ErrorImpl::Io(_) => Category::Io,
43 ErrorImpl::Parse(e) => match e.classify() {
44 parse::error::Category::Syntax => Category::Syntax,
45 parse::error::Category::Io => Category::Io,
46 parse::error::Category::Eof => Category::Eof,
47 },
48 }
49 }
50}
51
52#[derive(Copy, Clone, PartialEq, Eq, Debug)]
54pub enum Category {
55 Io,
57
58 Syntax,
61
62 Data,
67
68 Eof,
73}
74
75impl From<Error> for io::Error {
76 fn from(l: Error) -> Self {
104 if let ErrorImpl::Io(err) = *l.0 {
105 err
106 } else {
107 match l.classify() {
108 Category::Io => unreachable!(),
109 Category::Syntax | Category::Data => io::Error::new(io::ErrorKind::InvalidData, l),
110 Category::Eof => io::Error::new(io::ErrorKind::UnexpectedEof, l),
111 }
112 }
113 }
114}
115
116impl error::Error for Error {
117 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
118 match &*self.0 {
119 ErrorImpl::Io(e) => Some(e),
120 ErrorImpl::Parse(e) => Some(e),
121 _ => None,
122 }
123 }
124}
125
126impl Display for Error {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 match &*self.0 {
129 ErrorImpl::Message(msg, _) => Display::fmt(msg, f),
130 ErrorImpl::Io(e) => Display::fmt(e, f),
131 ErrorImpl::Parse(e) => Display::fmt(e, f),
132 }
133 }
134}
135
136impl Debug for Error {
137 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
138 match &*self.0 {
139 ErrorImpl::Message(msg, loc) => formatter
140 .debug_tuple("Message")
141 .field(msg)
142 .field(loc)
143 .finish(),
144 ErrorImpl::Io(e) => formatter.debug_tuple("Io").field(e).finish(),
145 ErrorImpl::Parse(e) => formatter.debug_tuple("Parse").field(e).finish(),
146 }
147 }
148}
149
150impl de::Error for Error {
151 fn custom<T: Display>(msg: T) -> Error {
152 Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
153 }
154
155 fn invalid_type(unexp: de::Unexpected<'_>, exp: &dyn de::Expected) -> Self {
156 if let de::Unexpected::Unit = unexp {
157 Error::custom(format_args!("invalid type: null, expected {}", exp))
158 } else {
159 Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
160 }
161 }
162}
163
164impl ser::Error for Error {
165 fn custom<T: Display>(msg: T) -> Error {
166 Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
167 }
168}
169
170impl From<io::Error> for Error {
171 fn from(e: io::Error) -> Self {
172 Error(Box::new(ErrorImpl::Io(e)))
173 }
174}
175
176impl From<parse::Error> for Error {
177 fn from(e: parse::Error) -> Self {
178 Error(Box::new(ErrorImpl::Parse(e)))
179 }
180}