1use std::io;
2
3use derive_more::Display;
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Debug, Display, PartialEq, Eq, Serialize, Deserialize)]
8#[display(fmt = "{kind}: {description}")]
9#[serde(rename_all = "snake_case", deny_unknown_fields)]
10pub struct Error {
11 pub kind: ErrorKind,
13
14 pub description: String,
16}
17
18impl std::error::Error for Error {}
19
20impl Error {
21 pub fn to_io_error(&self) -> io::Error {
23 io::Error::new(self.kind.into(), self.description.to_string())
24 }
25}
26
27impl<'a> From<&'a str> for Error {
28 fn from(x: &'a str) -> Self {
29 Self::from(x.to_string())
30 }
31}
32
33impl From<String> for Error {
34 fn from(x: String) -> Self {
35 Self {
36 kind: ErrorKind::Other,
37 description: x,
38 }
39 }
40}
41
42impl From<io::Error> for Error {
43 fn from(x: io::Error) -> Self {
44 Self {
45 kind: ErrorKind::from(x.kind()),
46 description: x.to_string(),
47 }
48 }
49}
50
51impl From<Error> for io::Error {
52 fn from(x: Error) -> Self {
53 Self::new(x.kind.into(), x.description)
54 }
55}
56
57#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Serialize, Deserialize)]
59#[serde(rename_all = "snake_case", deny_unknown_fields)]
60pub enum ErrorKind {
61 NotFound,
63
64 PermissionDenied,
66
67 ConnectionRefused,
69
70 ConnectionReset,
72
73 ConnectionAborted,
75
76 NotConnected,
78
79 AddrInUse,
81
82 AddrNotAvailable,
84
85 BrokenPipe,
87
88 AlreadyExists,
90
91 WouldBlock,
94
95 InvalidInput,
97
98 InvalidData,
100
101 TimedOut,
103
104 WriteZero,
107
108 Interrupted,
110
111 Other,
113
114 UnexpectedEof,
117
118 Unsupported,
120
121 OutOfMemory,
123
124 Loop,
126
127 TaskCancelled,
129
130 TaskPanicked,
132
133 Unknown,
135}
136
137impl From<io::ErrorKind> for ErrorKind {
138 fn from(kind: io::ErrorKind) -> Self {
139 match kind {
140 io::ErrorKind::NotFound => Self::NotFound,
141 io::ErrorKind::PermissionDenied => Self::PermissionDenied,
142 io::ErrorKind::ConnectionRefused => Self::ConnectionRefused,
143 io::ErrorKind::ConnectionReset => Self::ConnectionReset,
144 io::ErrorKind::ConnectionAborted => Self::ConnectionAborted,
145 io::ErrorKind::NotConnected => Self::NotConnected,
146 io::ErrorKind::AddrInUse => Self::AddrInUse,
147 io::ErrorKind::AddrNotAvailable => Self::AddrNotAvailable,
148 io::ErrorKind::BrokenPipe => Self::BrokenPipe,
149 io::ErrorKind::AlreadyExists => Self::AlreadyExists,
150 io::ErrorKind::WouldBlock => Self::WouldBlock,
151 io::ErrorKind::InvalidInput => Self::InvalidInput,
152 io::ErrorKind::InvalidData => Self::InvalidData,
153 io::ErrorKind::TimedOut => Self::TimedOut,
154 io::ErrorKind::WriteZero => Self::WriteZero,
155 io::ErrorKind::Interrupted => Self::Interrupted,
156 io::ErrorKind::Other => Self::Other,
157 io::ErrorKind::OutOfMemory => Self::OutOfMemory,
158 io::ErrorKind::UnexpectedEof => Self::UnexpectedEof,
159 io::ErrorKind::Unsupported => Self::Unsupported,
160
161 _ => Self::Unknown,
163 }
164 }
165}
166
167impl From<ErrorKind> for io::ErrorKind {
168 fn from(kind: ErrorKind) -> Self {
169 match kind {
170 ErrorKind::NotFound => Self::NotFound,
171 ErrorKind::PermissionDenied => Self::PermissionDenied,
172 ErrorKind::ConnectionRefused => Self::ConnectionRefused,
173 ErrorKind::ConnectionReset => Self::ConnectionReset,
174 ErrorKind::ConnectionAborted => Self::ConnectionAborted,
175 ErrorKind::NotConnected => Self::NotConnected,
176 ErrorKind::AddrInUse => Self::AddrInUse,
177 ErrorKind::AddrNotAvailable => Self::AddrNotAvailable,
178 ErrorKind::BrokenPipe => Self::BrokenPipe,
179 ErrorKind::AlreadyExists => Self::AlreadyExists,
180 ErrorKind::WouldBlock => Self::WouldBlock,
181 ErrorKind::InvalidInput => Self::InvalidInput,
182 ErrorKind::InvalidData => Self::InvalidData,
183 ErrorKind::TimedOut => Self::TimedOut,
184 ErrorKind::WriteZero => Self::WriteZero,
185 ErrorKind::Interrupted => Self::Interrupted,
186 ErrorKind::Other => Self::Other,
187 ErrorKind::OutOfMemory => Self::OutOfMemory,
188 ErrorKind::UnexpectedEof => Self::UnexpectedEof,
189 ErrorKind::Unsupported => Self::Unsupported,
190 _ => Self::Other,
191 }
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 mod error {
200 use super::*;
201
202 #[test]
203 fn should_be_able_to_serialize_to_json() {
204 let error = Error {
205 kind: ErrorKind::AddrInUse,
206 description: "some description".to_string(),
207 };
208
209 let value = serde_json::to_value(error).unwrap();
210 assert_eq!(
211 value,
212 serde_json::json!({
213 "kind": "addr_in_use",
214 "description": "some description",
215 })
216 );
217 }
218
219 #[test]
220 fn should_be_able_to_deserialize_from_json() {
221 let value = serde_json::json!({
222 "kind": "addr_in_use",
223 "description": "some description",
224 });
225
226 let error: Error = serde_json::from_value(value).unwrap();
227 assert_eq!(
228 error,
229 Error {
230 kind: ErrorKind::AddrInUse,
231 description: "some description".to_string(),
232 }
233 );
234 }
235
236 #[test]
237 fn should_be_able_to_serialize_to_msgpack() {
238 let error = Error {
239 kind: ErrorKind::AddrInUse,
240 description: "some description".to_string(),
241 };
242
243 let _ = rmp_serde::encode::to_vec_named(&error).unwrap();
248 }
249
250 #[test]
251 fn should_be_able_to_deserialize_from_msgpack() {
252 let buf = rmp_serde::encode::to_vec_named(&Error {
257 kind: ErrorKind::AddrInUse,
258 description: "some description".to_string(),
259 })
260 .unwrap();
261
262 let error: Error = rmp_serde::decode::from_slice(&buf).unwrap();
263 assert_eq!(
264 error,
265 Error {
266 kind: ErrorKind::AddrInUse,
267 description: "some description".to_string(),
268 }
269 );
270 }
271 }
272
273 mod error_kind {
274 use super::*;
275
276 #[test]
277 fn should_be_able_to_serialize_to_json() {
278 let kind = ErrorKind::AddrInUse;
279
280 let value = serde_json::to_value(kind).unwrap();
281 assert_eq!(value, serde_json::json!("addr_in_use"));
282 }
283
284 #[test]
285 fn should_be_able_to_deserialize_from_json() {
286 let value = serde_json::json!("addr_in_use");
287
288 let kind: ErrorKind = serde_json::from_value(value).unwrap();
289 assert_eq!(kind, ErrorKind::AddrInUse);
290 }
291
292 #[test]
293 fn should_be_able_to_serialize_to_msgpack() {
294 let kind = ErrorKind::AddrInUse;
295
296 let _ = rmp_serde::encode::to_vec_named(&kind).unwrap();
301 }
302
303 #[test]
304 fn should_be_able_to_deserialize_from_msgpack() {
305 let buf = rmp_serde::encode::to_vec_named(&ErrorKind::AddrInUse).unwrap();
310
311 let kind: ErrorKind = rmp_serde::decode::from_slice(&buf).unwrap();
312 assert_eq!(kind, ErrorKind::AddrInUse);
313 }
314 }
315}