1use std::error;
9use std::fmt;
10use std::io;
11use std::result;
12
13use status::StatusCode;
14
15pub type Result<T> = result::Result<T, Error>;
16
17#[derive(Debug)]
18pub enum ErrorKind {
19 Io(io::Error),
21 BadResponse(String),
23 CommandFailed(StatusCode, String),
25}
26
27#[derive(Debug)]
28pub struct Error {
29 kind: ErrorKind,
30 command: String,
31}
32
33impl Error {
34 pub fn new<C: Into<String>>(kind: ErrorKind, command: C) -> Error {
35 Error { kind: kind, command: command.into() }
36 }
37
38 pub fn io<C: Into<String>>(err: io::Error, command: C) -> Error {
39 Error::new(ErrorKind::Io(err), command)
40 }
41
42 pub fn io_custom<E, C>(kind: io::ErrorKind, error: E, command: C) -> Error
43 where E: Into<Box<error::Error + Send + Sync>>, C: Into<String>
44 {
45 Error::new(ErrorKind::Io(io::Error::new(kind, error)), command)
46 }
47
48 pub fn bad_response<D, C>(desc: D, command: C) -> Error
49 where D: Into<String>, C: Into<String>
50 {
51 Error::new(ErrorKind::BadResponse(desc.into()), command)
52 }
53
54 pub fn command_failed<M, C>(code: StatusCode, message: M, command: C) -> Error
55 where M: Into<String>, C: Into<String>
56 {
57 Error::new(ErrorKind::CommandFailed(code, message.into()), command)
58 }
59
60 pub fn kind(&self) -> &ErrorKind { &self.kind }
61 pub fn command(&self) -> &str { &self.command }
62
63 pub fn is_fatal(&self) -> bool {
65 match self.kind {
66 ErrorKind::Io(_) | ErrorKind::BadResponse(_) => true,
67 _ => false,
68 }
69 }
70}
71
72impl fmt::Display for Error {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 let have_command = self.command.len() > 0;
75 if have_command {
76 write!(f, "command failed: '{}' (", self.command)?;
77 }
78 match self.kind {
79 ErrorKind::Io(ref err) => write!(f, "I/O error: {}", err)?,
80 ErrorKind::BadResponse(ref desc) => write!(f, "bad response: {}", desc)?,
81 ErrorKind::CommandFailed(code, ref msg) => write!(f, "{}- {}", code, msg)?,
82 }
83 if have_command {
84 write!(f, ")")?;
85 }
86 Ok(())
87 }
88}
89
90impl error::Error for Error {
91 fn description(&self) -> &str {
92 match self.kind {
93 ErrorKind::Io(ref err) => err.description(),
94 ErrorKind::BadResponse(ref desc) => desc.as_ref(),
95 ErrorKind::CommandFailed(_, ref msg) => msg.as_ref(),
96 }
97 }
98
99 fn cause(&self) -> Option<&::std::error::Error> {
100 match self.kind {
101 ErrorKind::Io(ref err) => Some(err),
102 _ => None,
103 }
104 }
105}