1use std::fmt;
2use std::error;
3use async_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
4
5pub type Result<T> = std::result::Result<T, Error>;
6pub(crate) type BoxError = Box<dyn error::Error + Send + Sync>;
7
8#[derive(Debug)]
9pub(super) enum Kind {
10 Binance,
11 SerdeUrlEncoded,
12 Reqwest,
13 Tungstenite,
14 SerdeJson,
15 Hmac,
16 Url,
17}
18
19#[derive(Debug)]
20pub struct WsCloseError {
21 code: CloseCode,
22 reason: String,
23}
24
25impl WsCloseError {
26 pub(super) fn new<T: Into<String>>(code: CloseCode, reason: T) -> Self {
27 WsCloseError { code, reason: reason.into() }
28 }
29}
30
31impl fmt::Display for WsCloseError {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 write!(f, "{}", self.reason)
34 }
35}
36
37impl error::Error for WsCloseError {
38 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
39 None
40 }
41}
42
43pub struct ClientError {
44 code: u16,
45 reason: String,
46 message: String
47}
48
49impl ClientError {
50 pub(super) fn new<T: Into<String>>(code: u16, reason: T, message: T) -> Self {
51 ClientError { code, reason: reason.into(), message: message.into() }
52 }
53}
54
55impl fmt::Display for ClientError {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 write!(f, "{}", self.message)
58 }
59}
60
61impl fmt::Debug for ClientError {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 let mut builder = f.debug_struct("ClientError");
64
65 builder.field("code", &self.code);
66 builder.field("reason", &self.reason);
67 builder.finish()
68 }
69}
70
71impl error::Error for ClientError {
72 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
73 None
74 }
75}
76
77pub struct Error {
78 kind: Kind,
79 source: Option<BoxError>
80}
81
82impl Error {
83 pub(super) fn new<E>(kind: Kind, source: Option<E>) -> Self
84 where
85 E: Into<BoxError>,
86 {
87 Error {
88 kind,
89 source: source.map(Into::into)
90 }
91 }
92}
93
94impl fmt::Debug for Error {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 let mut builder = f.debug_struct("tokio-binance::Error");
97
98 builder.field("kind", &self.kind);
99
100 if let Some(ref source) = self.source {
101 builder.field("source", source);
102 }
103
104 builder.finish()
105 }
106}
107
108impl error::Error for Error {
109 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
110 self.source.as_ref().map(|e| &**e as _)
111 }
112}
113
114impl fmt::Display for Error {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 if let Some(ref source) = self.source {
117 write!(f, "{:?}: {}", self.kind, source)
118 } else {
119 write!(f, "No source for this error")
120 }
121 }
122}
123
124impl From<ClientError> for Error {
125 fn from(error: ClientError) -> Self {
126 Error::new(Kind::Binance, Some(error))
127 }
128}
129
130impl From<WsCloseError> for Error {
131 fn from(error: WsCloseError) -> Self {
132 Error::new(Kind::Binance, Some(error))
133 }
134}
135
136impl From<reqwest::Error> for Error {
137 fn from(error: reqwest::Error) -> Self {
138 Error::new(Kind::Reqwest, Some(error))
139 }
140}
141
142impl From<serde_urlencoded::ser::Error> for Error {
143 fn from(error: serde_urlencoded::ser::Error) -> Self {
144 Error::new(Kind::SerdeUrlEncoded, Some(error))
145 }
146}
147
148impl From<async_tungstenite::tungstenite::Error> for Error {
149 fn from(error: async_tungstenite::tungstenite::Error) -> Self {
150 Error::new(Kind::Tungstenite, Some(error))
151 }
152}
153
154impl From<url::ParseError> for Error {
155 fn from(error: url::ParseError) -> Self {
156 Error::new(Kind::Url, Some(error))
157 }
158}
159
160impl From<serde_json::error::Error> for Error {
161 fn from(error: serde_json::error::Error) -> Self {
162 Error::new(Kind::SerdeJson, Some(error))
163 }
164}
165
166impl From<hmac::crypto_mac::InvalidKeyLength> for Error {
167 fn from(error: hmac::crypto_mac::InvalidKeyLength) -> Self {
168 Error::new(Kind::Hmac, Some(error))
169 }
170}