1pub use int_enum::IntEnum;
7use std::error::Error;
8use std::fmt::{Debug, Display, Error as FmtError, Formatter};
9use std::sync::PoisonError;
10use std::time::SystemTimeError;
11use url::ParseError;
12
13#[repr(i16)]
15#[derive(Debug, PartialEq, PartialOrd, Copy, Clone, IntEnum)]
16pub enum ErrorCode {
17 UrlParseError = -4,
18 ConnectionError = -3,
19 Timeout = -2,
20 Unknown = -1,
21
22 Continue = 100,
23 OK = 200,
24 Created = 201,
25 Accepted = 202,
26 NoContent = 204,
27 BadRequest = 400,
28 Unauthorized = 401,
29 Forbidden = 403,
30 NotFound = 404,
31 MethodNotAllowed = 405,
32 NotAcceptable = 406,
33 RequestTimeout = 408,
34 Conflict = 409,
35 Gone = 410,
36 LengthRequired = 411,
37 PreconditionFailed = 412,
38 PayloadTooLarge = 413,
39 URITooLong = 414,
40 UnsupportedMediaType = 415,
41 RangeNotSatisfiable = 416,
42 ExpectationFailed = 417,
43 ImATeapot = 418,
44 MisdirectedRequest = 421,
45 UnprocessableEntity = 422,
46 Locked = 423,
47 FailedDependency = 424,
48 TooEarly = 425,
49 UpgradeRequired = 426,
50 PreconditionRequired = 428,
51 TooManyRequests = 429,
52 RequestHeaderFieldsTooLarge = 431,
53 UnavailableForLegalReasons = 451,
54 InternalServerError = 500,
55 NotImplemented = 501,
56 BadGateway = 502,
57 ServiceUnavailable = 503,
58 GatewayTimeout = 504,
59 HTTPVersionNotSupported = 505,
60 VariantAlsoNegotiates = 506,
61 InsufficientStorage = 507,
62 LoopDetected = 508,
63 NotExtended = 510,
64 NetworkAuthenticationRequired = 511,
65}
66
67#[derive(PartialEq, Debug, Clone)]
69pub struct ReductError {
70 pub status: ErrorCode,
72
73 pub message: String,
75}
76
77impl Display for ReductError {
78 fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
79 write!(f, "[{:?}] {}", self.status, self.message)
80 }
81}
82
83impl Display for ErrorCode {
84 fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
85 write!(f, "{}", self.int_value())
86 }
87}
88
89impl From<std::io::Error> for ReductError {
90 fn from(err: std::io::Error) -> Self {
91 ReductError {
93 status: ErrorCode::InternalServerError,
94 message: err.to_string(),
95 }
96 }
97}
98
99impl From<SystemTimeError> for ReductError {
100 fn from(err: SystemTimeError) -> Self {
101 ReductError {
103 status: ErrorCode::InternalServerError,
104 message: err.to_string(),
105 }
106 }
107}
108
109impl From<ParseError> for ReductError {
110 fn from(err: ParseError) -> Self {
111 ReductError {
113 status: ErrorCode::UrlParseError,
114 message: err.to_string(),
115 }
116 }
117}
118
119impl<T> From<PoisonError<T>> for ReductError {
120 fn from(_: PoisonError<T>) -> Self {
121 ReductError {
123 status: ErrorCode::InternalServerError,
124 message: "Poison error".to_string(),
125 }
126 }
127}
128
129impl From<Box<dyn std::any::Any + Send>> for ReductError {
130 fn from(err: Box<dyn std::any::Any + Send>) -> Self {
131 ReductError {
133 status: ErrorCode::InternalServerError,
134 message: format!("{:?}", err),
135 }
136 }
137}
138
139impl Error for ReductError {
140 fn description(&self) -> &str {
141 &self.message
142 }
143}
144
145impl ReductError {
146 pub fn new(status: ErrorCode, message: &str) -> Self {
147 ReductError {
148 status,
149 message: message.to_string(),
150 }
151 }
152
153 pub fn status(&self) -> ErrorCode {
154 self.status
155 }
156
157 pub fn message(&self) -> &str {
158 &self.message
159 }
160
161 pub fn ok() -> ReductError {
162 ReductError {
163 status: ErrorCode::OK,
164 message: "".to_string(),
165 }
166 }
167
168 pub fn no_content(msg: &str) -> ReductError {
170 ReductError {
171 status: ErrorCode::NoContent,
172 message: msg.to_string(),
173 }
174 }
175
176 pub fn not_found(msg: &str) -> ReductError {
178 ReductError {
179 status: ErrorCode::NotFound,
180 message: msg.to_string(),
181 }
182 }
183
184 pub fn conflict(msg: &str) -> ReductError {
186 ReductError {
187 status: ErrorCode::Conflict,
188 message: msg.to_string(),
189 }
190 }
191
192 pub fn bad_request(msg: &str) -> ReductError {
194 ReductError {
195 status: ErrorCode::BadRequest,
196 message: msg.to_string(),
197 }
198 }
199
200 pub fn unauthorized(msg: &str) -> ReductError {
202 ReductError {
203 status: ErrorCode::Unauthorized,
204 message: msg.to_string(),
205 }
206 }
207
208 pub fn forbidden(msg: &str) -> ReductError {
210 ReductError {
211 status: ErrorCode::Forbidden,
212 message: msg.to_string(),
213 }
214 }
215
216 pub fn unprocessable_entity(msg: &str) -> ReductError {
218 ReductError {
219 status: ErrorCode::UnprocessableEntity,
220 message: msg.to_string(),
221 }
222 }
223
224 pub fn too_early(msg: &str) -> ReductError {
226 ReductError {
227 status: ErrorCode::TooEarly,
228 message: msg.to_string(),
229 }
230 }
231
232 pub fn internal_server_error(msg: &str) -> ReductError {
234 ReductError {
235 status: ErrorCode::InternalServerError,
236 message: msg.to_string(),
237 }
238 }
239}
240
241#[macro_export]
243macro_rules! no_content {
244 ($msg:expr, $($arg:tt)*) => {
245 ReductError::no_content(&format!($msg, $($arg)*))
246 };
247 ($msg:expr) => {
248 ReductError::no_content($msg)
249 };
250}
251
252#[macro_export]
253macro_rules! bad_request {
254 ($msg:expr, $($arg:tt)*) => {
255 ReductError::bad_request(&format!($msg, $($arg)*))
256 };
257 ($msg:expr) => {
258 ReductError::bad_request($msg)
259 };
260}
261
262#[macro_export]
263macro_rules! unprocessable_entity {
264 ($msg:expr, $($arg:tt)*) => {
265 ReductError::unprocessable_entity(&format!($msg, $($arg)*))
266 };
267 ($msg:expr) => {
268 ReductError::unprocessable_entity($msg)
269 };
270}
271
272#[macro_export]
273macro_rules! not_found {
274 ($msg:expr, $($arg:tt)*) => {
275 ReductError::not_found(&format!($msg, $($arg)*))
276 };
277 ($msg:expr) => {
278 ReductError::not_found($msg)
279 };
280}
281#[macro_export]
282macro_rules! conflict {
283 ($msg:expr, $($arg:tt)*) => {
284 ReductError::conflict(&format!($msg, $($arg)*))
285 };
286 ($msg:expr) => {
287 ReductError::conflict($msg)
288 };
289}
290
291#[macro_export]
292macro_rules! too_early {
293 ($msg:expr, $($arg:tt)*) => {
294 ReductError::too_early(&format!($msg, $($arg)*))
295 };
296 ($msg:expr) => {
297 ReductError::too_early($msg)
298 };
299}
300
301#[macro_export]
302macro_rules! internal_server_error {
303 ($msg:expr, $($arg:tt)*) => {
304 ReductError::internal_server_error(&format!($msg, $($arg)*))
305 };
306 ($msg:expr) => {
307 ReductError::internal_server_error($msg)
308 };
309}
310
311#[macro_export]
312macro_rules! unauthorized {
313 ($msg:expr, $($arg:tt)*) => {
314 ReductError::unauthorized(&format!($msg, $($arg)*))
315 };
316 ($msg:expr) => {
317 ReductError::unauthorized($msg)
318 };
319}