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
use std::error::Error as StdError;
use std::fmt;
use std::io::{self, ErrorKind};

/// KCP protocol errors
#[derive(Debug)]
pub enum Error {
    ConvInconsistent(u32, u32),
    InvalidMtu(usize),
    InvalidSegmentSize(usize),
    InvalidSegmentDataSize(usize, usize),
    IoError(io::Error),
    NeedUpdate,
    RecvQueueEmpty,
    ExpectingFragment,
    UnsupportCmd(u8),
    UserBufTooBig,
    UserBufTooSmall,
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ConvInconsistent(..) => "segment's conv number is inconsistent",
            Error::InvalidMtu(_) => "invalid mtu size",
            Error::InvalidSegmentSize(_) => "invalid segment size",
            Error::InvalidSegmentDataSize(..) => "segment's data size is invalid",
            Error::IoError(ref e) => e.description(),
            Error::NeedUpdate => "need call kcp's update method",
            Error::RecvQueueEmpty => "receive queue is empty",
            Error::ExpectingFragment => "expecting other fragments",
            Error::UnsupportCmd(_) => "cmd isn't supported",
            Error::UserBufTooBig => "user's buffer is too big",
            Error::UserBufTooSmall => "user's buffer is too small",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::IoError(ref e) => Some(e),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ConvInconsistent(ref s, ref o) => write!(f, "conv inconsistent, expected {}, found {}", *s, *o),
            Error::InvalidMtu(ref e) => write!(f, "invalid mtu {}", *e),
            Error::InvalidSegmentSize(ref e) => write!(f, "invalid segment size of {}", *e),
            Error::InvalidSegmentDataSize(ref s, ref o) => {
                write!(f, "invalid segment data size, expected {}, found {}", *s, *o)
            }
            Error::IoError(ref e) => e.fmt(f),
            Error::UnsupportCmd(ref e) => write!(f, "cmd {} is not supported", *e),
            ref e => write!(f, "{}", e.description()),
        }
    }
}

fn make_io_error<T>(kind: ErrorKind, msg: T) -> io::Error
where
    T: Into<Box<StdError + Send + Sync>>,
{
    io::Error::new(kind, msg)
}

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        let kind = match err {
            Error::ConvInconsistent(..) => ErrorKind::Other,
            Error::InvalidMtu(..) => ErrorKind::Other,
            Error::InvalidSegmentSize(..) => ErrorKind::Other,
            Error::InvalidSegmentDataSize(..) => ErrorKind::Other, 
            Error::IoError(err) => return err,
            Error::NeedUpdate => ErrorKind::Other,
            Error::RecvQueueEmpty => ErrorKind::WouldBlock,
            Error::ExpectingFragment => ErrorKind::WouldBlock,
            Error::UnsupportCmd(..) => ErrorKind::Other,
            Error::UserBufTooBig => ErrorKind::Other,
            Error::UserBufTooSmall => ErrorKind::Other,
        };

        make_io_error(kind, err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}