1use std::{convert::From, error, fmt, result, str};
2
3pub type Result<T> = result::Result<T, Error>;
4
5pub struct Error {
6 repr: Repr,
7}
8
9impl fmt::Debug for Error {
10 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11 fmt::Debug::fmt(&self.repr, f)
12 }
13}
14
15enum Repr {
16 Other(String),
17 Simple(ErrorKind),
18 Custom(Box<Custom>),
19}
20
21#[derive(Debug)]
22struct Custom {
23 kind: ErrorKind,
24 error: Box<dyn error::Error + Send + Sync>,
25}
26
27#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
28pub enum ErrorKind {
29 Protocol,
30 IO,
31 Client,
32 Network,
33 Server,
34 Serialization,
35 Other,
36}
37
38impl ErrorKind {
39 pub(crate) fn as_str(self) -> &'static str {
40 match self {
41 ErrorKind::Protocol => "invalid protocol",
42 ErrorKind::IO => "io issue",
43 ErrorKind::Client => "client error",
44 ErrorKind::Network => "network issue",
45 ErrorKind::Server => "server error",
46 ErrorKind::Serialization => "serialization failure",
47 ErrorKind::Other => "other",
48 }
49 }
50}
51
52impl From<&'static str> for Error {
53 #[inline]
54 fn from(s: &'static str) -> Error {
55 Error {
56 repr: Repr::Other(s.to_owned()),
57 }
58 }
59}
60
61impl From<String> for Error {
62 #[inline]
63 fn from(s: String) -> Error {
64 Error {
65 repr: Repr::Other(s),
66 }
67 }
68}
69
70impl From<serde_json::error::Error> for Error {
71 #[inline]
72 fn from(err: serde_json::error::Error) -> Error {
73 Error::new(ErrorKind::IO, err)
74 }
75}
76
77impl From<std::io::Error> for Error {
78 #[inline]
79 fn from(err: std::io::Error) -> Error {
80 Error::new(ErrorKind::IO, err)
81 }
82}
83
84impl From<Box<dyn std::error::Error + Send + Sync>> for Error {
85 #[inline]
86 fn from(err: Box<dyn std::error::Error + Send + Sync>) -> Error {
87 Error::_new(ErrorKind::Other, err)
88 }
89}
90impl From<ErrorKind> for Error {
91 #[inline]
92 fn from(kind: ErrorKind) -> Error {
93 Error {
94 repr: Repr::Simple(kind),
95 }
96 }
97}
98
99impl Error {
100 pub fn new<E>(kind: ErrorKind, error: E) -> Error
101 where
102 E: Into<Box<dyn error::Error + Send + Sync>>,
103 {
104 Self::_new(kind, error.into())
105 }
106
107 fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
108 Error {
109 repr: Repr::Custom(Box::new(Custom { kind, error })),
110 }
111 }
112
113 pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
114 match self.repr {
115 Repr::Other(..) => None,
116 Repr::Simple(..) => None,
117 Repr::Custom(ref c) => Some(&*c.error),
118 }
119 }
120
121 pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
122 match self.repr {
123 Repr::Other(..) => None,
124 Repr::Simple(..) => None,
125 Repr::Custom(ref mut c) => Some(&mut *c.error),
126 }
127 }
128
129 pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
130 match self.repr {
131 Repr::Other(..) => None,
132 Repr::Simple(..) => None,
133 Repr::Custom(c) => Some(c.error),
134 }
135 }
136
137 pub fn kind(&self) -> ErrorKind {
138 match self.repr {
139 Repr::Other(_) => ErrorKind::Other,
140 Repr::Custom(ref c) => c.kind,
141 Repr::Simple(kind) => kind,
142 }
143 }
144}
145
146impl fmt::Debug for Repr {
147 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
148 match &*self {
149 Repr::Other(s) => write!(fmt, "{}", s),
150 Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
151 Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
152 }
153 }
154}
155
156impl fmt::Display for Error {
157 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
158 match &self.repr {
159 Repr::Other(s) => write!(fmt, "{}", s),
160 Repr::Custom(ref c) => c.error.fmt(fmt),
161 Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
162 }
163 }
164}
165
166impl error::Error for Error {
167 fn description(&self) -> &str {
168 match &self.repr {
169 Repr::Other(s) => &s[..],
170 Repr::Simple(..) => self.kind().as_str(),
171 Repr::Custom(ref c) => c.error.description(),
172 }
173 }
174
175 fn cause(&self) -> Option<&dyn error::Error> {
176 match self.repr {
177 Repr::Other(..) => None,
178 Repr::Simple(..) => None,
179 Repr::Custom(ref c) => c.error.source(),
180 }
181 }
182 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
183 match self.repr {
184 Repr::Other(..) => None,
185 Repr::Simple(..) => None,
186 Repr::Custom(ref c) => c.error.source(),
187 }
188 }
189}