1use crate::header::StatusCode;
2
3use std::error::Error as StdError;
4use std::{fmt, io};
5
6pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug)]
12pub struct Error {
13 kind: ErrorKind,
14 source: Option<Box<dyn StdError + Send + Sync>>,
15}
16
17impl Error {
18 pub fn new<K, E>(kind: K, error: E) -> Self
20 where
21 K: Into<ErrorKind>,
22 E: Into<Box<dyn StdError + Send + Sync>>,
23 {
24 Self {
25 kind: kind.into(),
26 source: Some(error.into()),
27 }
28 }
29
30 pub fn empty<K>(kind: K) -> Self
32 where
33 K: Into<ErrorKind>,
34 {
35 Self {
36 kind: kind.into(),
37 source: None,
38 }
39 }
40
41 pub fn status_code(&self) -> StatusCode {
43 match self.kind {
44 ErrorKind::Client(c) => c.into(),
45 ErrorKind::Server(s) => s.into(),
46 }
47 }
48
49 pub fn from_client_io(error: io::Error) -> Self {
51 Self::new(ClientErrorKind::from_io(&error), error)
53 }
54
55 pub fn from_server_error<E>(error: E) -> Self
57 where
58 E: Into<Box<dyn StdError + Send + Sync>>,
59 {
60 Self::new(ServerErrorKind::InternalServerError, error)
61 }
62}
63
64impl<T> From<T> for Error
65where
66 T: Into<ErrorKind>,
67{
68 fn from(e: T) -> Self {
69 Self::empty(e)
70 }
71}
72
73#[cfg(feature = "json")]
74mod deserialize_error {
75 use super::*;
76
77 use types::request::DeserializeError;
78
79 impl From<DeserializeError> for Error {
80 fn from(e: DeserializeError) -> Self {
81 Self::new(ClientErrorKind::BadRequest, e)
82 }
83 }
84}
85
86impl fmt::Display for Error {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 fmt::Debug::fmt(self, f)
89 }
90}
91
92impl StdError for Error {
93 fn source(&self) -> Option<&(dyn StdError + 'static)> {
94 self.source.as_ref().map(|e| e.source()).flatten()
95 }
96}
97
98#[derive(Debug)]
100pub enum ErrorKind {
101 Client(ClientErrorKind),
102 Server(ServerErrorKind),
103}
104
105impl From<ClientErrorKind> for ErrorKind {
106 fn from(k: ClientErrorKind) -> Self {
107 Self::Client(k)
108 }
109}
110
111impl From<ServerErrorKind> for ErrorKind {
112 fn from(k: ServerErrorKind) -> Self {
113 Self::Server(k)
114 }
115}
116
117macro_rules! error_kind {
118 ($name:ident, $($kind:ident => $status:ident),*) => (
119 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
120 pub enum $name {
121 $($kind),*
122 }
123
124 impl From<$name> for StatusCode {
125 fn from(k: $name) -> Self {
126 match k {
127 $($name::$kind => Self::$status),*
128 }
129 }
130 }
131 )
132}
133
134error_kind!( ClientErrorKind,
136 BadRequest => BAD_REQUEST,
137 Unauthorized => UNAUTHORIZED,
138 PaymentRequired => PAYMENT_REQUIRED,
139 Forbidden => FORBIDDEN,
140 NotFound => NOT_FOUND,
141 MethodNotAllowed => METHOD_NOT_ALLOWED,
142 NotAcceptable => NOT_ACCEPTABLE,
143 ProxyAuthenticationRequired => PROXY_AUTHENTICATION_REQUIRED,
144 RequestTimeout => REQUEST_TIMEOUT,
145 Conflict => CONFLICT,
146 Gone => GONE,
147 LengthRequired => LENGTH_REQUIRED,
148 PreconditionFailed => PRECONDITION_FAILED,
149 RequestEntityTooLarge => PAYLOAD_TOO_LARGE,
150 RequestURITooLarge => URI_TOO_LONG,
151 UnsupportedMediaType => UNSUPPORTED_MEDIA_TYPE,
152 RequestedRangeNotSatisfiable => RANGE_NOT_SATISFIABLE,
153 ExpectationFailed => EXPECTATION_FAILED
154);
155
156impl ClientErrorKind {
157 pub fn from_io(error: &io::Error) -> Self {
159 use io::ErrorKind::*;
160 match error.kind() {
161 NotFound => Self::NotFound,
162 PermissionDenied => Self::Unauthorized,
163 AlreadyExists => Self::Conflict,
165 UnexpectedEof => Self::RequestEntityTooLarge,
166 InvalidInput | InvalidData | Other => Self::BadRequest,
167 TimedOut => Self::RequestTimeout,
168 _ => Self::ExpectationFailed,
169 }
170 }
171}
172
173error_kind!( ServerErrorKind,
175 InternalServerError => INTERNAL_SERVER_ERROR,
176 NotImplemented => NOT_IMPLEMENTED,
177 BadGateway => BAD_GATEWAY,
178 ServiceUnavailable => SERVICE_UNAVAILABLE,
179 GatewayTimeout => GATEWAY_TIMEOUT
180);