1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/// A crate that makes many of the I/O errors in stdlib de/serializable.

use std::fmt;
use std::io;

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(serde::Deserialize, serde::Serialize)]
pub struct IoError {
    kind: IoErrKind,
    description: String,
}

impl IoError {
    pub fn kind(&self) -> IoErrKind { self.kind }

    pub fn description(&self) -> &str { &self.description }

    pub fn into_description(self) -> String { self.description }
}

impl From<io::Error> for IoError {
    fn from(err: io::Error) -> IoError {
        IoError {
            kind: IoErrKind::from(err.kind()),
            description: String::from(err.to_string()),
        }
    }
}

impl From<IoError> for io::Error {
    fn from(err: IoError) -> io::Error {
        io::Error::new(err.kind.into(), err.description)
    }
}

impl fmt::Display for IoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}: {}", self.kind, self.description)
    }
}


/// A copy of `io::ErrorKind` that can be properly de/serialized.
/// It's possible to convert between io::ErrorKind and `IoErrKind`
/// by using the From trait.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(serde::Deserialize, serde::Serialize)]
pub enum IoErrKind {
    NotFound,
    PermissionDenied,
    ConnectionRefused,
    ConnectionReset,
    ConnectionAborted,
    NotConnected,
    AddrInUse,
    AddrNotAvailable,
    BrokenPipe,
    AlreadyExists,
    WouldBlock,
    InvalidInput,
    InvalidData,
    TimedOut,
    WriteZero,
    Interrupted,
    Other,
    UnexpectedEof,
    #[doc(hidden)] __Nonexhaustive,
}

impl fmt::Display for IoErrKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl From<io::ErrorKind> for IoErrKind {
    fn from(kind: io::ErrorKind) -> IoErrKind {
        match kind {
            io::ErrorKind::NotFound => IoErrKind::NotFound,
            io::ErrorKind::PermissionDenied => IoErrKind::PermissionDenied,
            io::ErrorKind::ConnectionRefused => IoErrKind::ConnectionRefused,
            io::ErrorKind::ConnectionReset => IoErrKind::ConnectionReset,
            io::ErrorKind::ConnectionAborted => IoErrKind::ConnectionAborted,
            io::ErrorKind::NotConnected => IoErrKind::NotConnected,
            io::ErrorKind::AddrInUse => IoErrKind::AddrInUse,
            io::ErrorKind::AddrNotAvailable => IoErrKind::AddrNotAvailable,
            io::ErrorKind::BrokenPipe => IoErrKind::BrokenPipe,
            io::ErrorKind::AlreadyExists => IoErrKind::AlreadyExists,
            io::ErrorKind::WouldBlock => IoErrKind::WouldBlock,
            io::ErrorKind::InvalidInput => IoErrKind::InvalidInput,
            io::ErrorKind::InvalidData => IoErrKind::InvalidData,
            io::ErrorKind::TimedOut => IoErrKind::TimedOut,
            io::ErrorKind::WriteZero => IoErrKind::WriteZero,
            io::ErrorKind::Interrupted => IoErrKind::Interrupted,
            io::ErrorKind::Other => IoErrKind::Other,
            io::ErrorKind::UnexpectedEof => IoErrKind::UnexpectedEof,
            kind => panic!("Unknown enum variant io::ErrorKind::{:?}", kind),
        }
    }
}

impl From<IoErrKind> for io::ErrorKind {
    fn from(kind: IoErrKind) -> io::ErrorKind {
        match kind {
            IoErrKind::NotFound => io::ErrorKind::NotFound,
            IoErrKind::PermissionDenied => io::ErrorKind::PermissionDenied,
            IoErrKind::ConnectionRefused => io::ErrorKind::ConnectionRefused,
            IoErrKind::ConnectionReset => io::ErrorKind::ConnectionReset,
            IoErrKind::ConnectionAborted => io::ErrorKind::ConnectionAborted,
            IoErrKind::NotConnected => io::ErrorKind::NotConnected,
            IoErrKind::AddrInUse => io::ErrorKind::AddrInUse,
            IoErrKind::AddrNotAvailable => io::ErrorKind::AddrNotAvailable,
            IoErrKind::BrokenPipe => io::ErrorKind::BrokenPipe,
            IoErrKind::AlreadyExists => io::ErrorKind::AlreadyExists,
            IoErrKind::WouldBlock => io::ErrorKind::WouldBlock,
            IoErrKind::InvalidInput => io::ErrorKind::InvalidInput,
            IoErrKind::InvalidData => io::ErrorKind::InvalidData,
            IoErrKind::TimedOut => io::ErrorKind::TimedOut,
            IoErrKind::WriteZero => io::ErrorKind::WriteZero,
            IoErrKind::Interrupted => io::ErrorKind::Interrupted,
            IoErrKind::Other => io::ErrorKind::Other,
            IoErrKind::UnexpectedEof => io::ErrorKind::UnexpectedEof,
            kind => panic!("Unknown enum variant IoErrKind::{:?}", kind),
        }
    }
}