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
127
128
129
/// A crate that makes many of the I/O errors in stdlib de/serializable.

use deltoid_derive::Delta;
use serde_derive::{Deserialize, Serialize};

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

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Delta, Hash)]
#[derive(Serialize, Deserialize)]
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, Delta, Hash)]
#[derive(Serialize, Deserialize)]
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),
        }
    }
}