1#[derive(Debug)]
2pub enum Error {
3 Api {
4 code: i64,
5 msg: String,
6 },
7 Http {
10 status: u16,
11 body: String,
12 },
13 InvalidHeaderValue(reqwest::header::InvalidHeaderValue),
14 Io(std::io::Error),
15 MissingCredentials,
18 Msg(String),
19 RateLimited {
22 retry_after_ms: u64,
23 },
24 RateLimitUnsatisfiable {
28 cost: u32,
29 burst: u32,
30 },
31 Reqwest(reqwest::Error),
32 SerdeJson(serde_json::Error),
33 TooManyPages {
35 max: usize,
36 },
37 SerdeUrlEncoded(serde_urlencoded::ser::Error),
38 SerdePathToError(serde_path_to_error::Error<serde_json::Error>),
39}
40
41impl std::fmt::Display for Error {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 match self {
44 Error::Api { code, msg } => write!(f, "Bybit API error: code: {code}, message: {msg}"),
45 Error::Http { status, body } => write!(f, "HTTP error: status: {status}, body: {body}"),
46 Error::InvalidHeaderValue(error) => write!(f, "invalid header value: {error}"),
47 Error::Io(error) => write!(f, "I/O error: {error}"),
48 Error::MissingCredentials => {
49 write!(
50 f,
51 "api_key and api_secret are required for private endpoints"
52 )
53 }
54 Error::Msg(msg) => write!(f, "{msg}"),
55 Error::RateLimited { retry_after_ms } => {
56 write!(f, "rate limited: retry after {retry_after_ms} ms")
57 }
58 Error::RateLimitUnsatisfiable { cost, burst } => write!(
59 f,
60 "rate limit can never be satisfied: request cost {cost}, bucket burst {burst}"
61 ),
62 Error::Reqwest(error) => write!(f, "reqwest error: {error}"),
63 Error::TooManyPages { max } => {
64 write!(f, "pagination did not finish after {max} pages")
65 }
66 Error::SerdeJson(error) => write!(f, "serde_json error: {error}"),
67 Error::SerdeUrlEncoded(error) => write!(f, "serde_urlencoded error: {error}"),
68 Error::SerdePathToError(error) => write!(
69 f,
70 "serde_path_to_error error: path: {}, msg: {}",
71 error.path(),
72 error.inner()
73 ),
74 }
75 }
76}
77
78impl std::error::Error for Error {
79 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
80 match self {
81 Error::InvalidHeaderValue(error) => Some(error),
82 Error::Io(error) => Some(error),
83 Error::Reqwest(error) => Some(error),
84 Error::SerdeJson(error) => Some(error),
85 Error::SerdeUrlEncoded(error) => Some(error),
86 Error::SerdePathToError(error) => Some(error),
87 Error::Api { .. }
88 | Error::Http { .. }
89 | Error::MissingCredentials
90 | Error::Msg(_)
91 | Error::RateLimited { .. }
92 | Error::RateLimitUnsatisfiable { .. }
93 | Error::TooManyPages { .. } => None,
94 }
95 }
96}
97
98impl From<std::io::Error> for Error {
99 fn from(err: std::io::Error) -> Self {
100 Error::Io(err)
101 }
102}
103
104impl From<String> for Error {
105 fn from(msg: String) -> Self {
106 Error::Msg(msg)
107 }
108}
109
110impl From<&str> for Error {
111 fn from(msg: &str) -> Self {
112 Error::Msg(msg.to_string())
113 }
114}
115
116impl From<super::http::APIErrorResponse> for Error {
117 fn from(resp: super::http::APIErrorResponse) -> Self {
118 Self::Api {
119 code: resp.ret_code,
120 msg: resp.ret_msg,
121 }
122 }
123}
124
125impl From<reqwest::header::InvalidHeaderValue> for Error {
126 fn from(err: reqwest::header::InvalidHeaderValue) -> Self {
127 Error::InvalidHeaderValue(err)
128 }
129}
130
131impl From<reqwest::Error> for Error {
132 fn from(err: reqwest::Error) -> Self {
133 Error::Reqwest(err)
134 }
135}
136
137impl From<serde_json::Error> for Error {
138 fn from(err: serde_json::Error) -> Self {
139 Error::SerdeJson(err)
140 }
141}
142
143impl From<serde_urlencoded::ser::Error> for Error {
144 fn from(err: serde_urlencoded::ser::Error) -> Self {
145 Error::SerdeUrlEncoded(err)
146 }
147}
148
149impl From<serde_path_to_error::Error<serde_json::Error>> for Error {
150 fn from(err: serde_path_to_error::Error<serde_json::Error>) -> Self {
151 Error::SerdePathToError(err)
152 }
153}