-
Notifications
You must be signed in to change notification settings - Fork 92
/
Copy patherror.rs
150 lines (138 loc) · 4.14 KB
/
error.rs
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use chrono::ParseError as ChronoError;
use hyper::Error as HyperError;
#[cfg(feature = "voice")]
use opus::Error as OpusError;
use serde_json::Error as JsonError;
use serde_json::Value;
use std::error::Error as StdError;
use std::fmt::Display;
use std::io::Error as IoError;
use websocket::result::WebSocketError;
/// Discord API `Result` alias type.
pub type Result<T> = ::std::result::Result<T, Error>;
/// Discord API error type.
#[derive(Debug)]
pub enum Error {
/// A `hyper` crate error
Hyper(HyperError),
/// A `chrono` crate error
Chrono(ChronoError),
/// A `serde_json` crate error
Json(JsonError),
/// A `websocket` crate error
WebSocket(WebSocketError),
/// A `std::io` module error
Io(IoError),
/// An error in the Opus library, with the function name and error code
#[cfg(feature = "voice")]
Opus(OpusError),
/// A websocket connection was closed, possibly with a message
Closed(Option<u16>, String),
/// A json decoding error, with a description and the offending value
Decode(&'static str, Value),
/// A generic non-success response from the REST API
Status(::hyper::status::StatusCode, Option<Value>),
/// A rate limit error, with how many milliseconds to wait before retrying
RateLimited(u64),
/// A Discord protocol error, with a description
Protocol(&'static str),
/// A command execution failure, with a command name and output
Command(&'static str, ::std::process::Output),
/// A miscellaneous error, with a description
Other(&'static str),
}
impl Error {
#[doc(hidden)]
pub fn from_response(response: ::hyper::client::Response) -> Error {
let status = response.status;
let value = ::serde_json::from_reader(response).ok();
if status == ::hyper::status::StatusCode::TooManyRequests {
if let Some(Value::Object(ref map)) = value {
if let Some(delay) = map.get("retry_after").and_then(|v| v.as_u64()) {
return Error::RateLimited(delay);
}
}
}
Error::Status(status, value)
}
}
impl From<IoError> for Error {
fn from(err: IoError) -> Error {
Error::Io(err)
}
}
impl From<HyperError> for Error {
fn from(err: HyperError) -> Error {
Error::Hyper(err)
}
}
impl From<ChronoError> for Error {
fn from(err: ChronoError) -> Error {
Error::Chrono(err)
}
}
impl From<JsonError> for Error {
fn from(err: JsonError) -> Error {
Error::Json(err)
}
}
impl From<WebSocketError> for Error {
fn from(err: WebSocketError) -> Error {
Error::WebSocket(err)
}
}
#[cfg(feature = "voice")]
impl From<OpusError> for Error {
fn from(err: OpusError) -> Error {
Error::Opus(err)
}
}
impl Display for Error {
#[allow(deprecated)]
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Error::Hyper(ref inner) => inner.fmt(f),
Error::Chrono(ref inner) => inner.fmt(f),
Error::Json(ref inner) => inner.fmt(f),
Error::WebSocket(ref inner) => inner.fmt(f),
Error::Io(ref inner) => inner.fmt(f),
#[cfg(feature = "voice")]
Error::Opus(ref inner) => inner.fmt(f),
Error::Command(cmd, _) => write!(f, "Command failed: {}", cmd),
_ => f.write_str(self.description()),
}
}
}
impl StdError for Error {
#[allow(deprecated)]
fn description(&self) -> &str {
match *self {
Error::Hyper(ref inner) => inner.description(),
Error::Chrono(ref inner) => inner.description(),
Error::Json(ref inner) => inner.description(),
Error::WebSocket(ref inner) => inner.description(),
Error::Io(ref inner) => inner.description(),
#[cfg(feature = "voice")]
Error::Opus(ref inner) => inner.description(),
Error::Closed(_, _) => "Connection closed",
Error::Decode(msg, _) | Error::Protocol(msg) | Error::Other(msg) => msg,
Error::Status(status, _) => status
.canonical_reason()
.unwrap_or("Unknown bad HTTP status"),
Error::RateLimited(_) => "Rate limited",
Error::Command(_, _) => "Command failed",
}
}
fn cause(&self) -> Option<&dyn StdError> {
match *self {
Error::Hyper(ref inner) => Some(inner),
Error::Chrono(ref inner) => Some(inner),
Error::Json(ref inner) => Some(inner),
Error::WebSocket(ref inner) => Some(inner),
Error::Io(ref inner) => Some(inner),
#[cfg(feature = "voice")]
Error::Opus(ref inner) => Some(inner),
_ => None,
}
}
}