1use std::error;
2use std::fmt;
3use std::result;
4
5use crate::header;
6use crate::header::MaxSizeReached;
7use crate::method;
8use crate::status;
9use crate::uri;
10
11pub struct Error {
18 inner: ErrorKind,
19}
20
21pub type Result<T> = result::Result<T, Error>;
23
24enum ErrorKind {
25 StatusCode(status::InvalidStatusCode),
26 Method(method::InvalidMethod),
27 Uri(uri::InvalidUri),
28 UriParts(uri::InvalidUriParts),
29 HeaderName(header::InvalidHeaderName),
30 HeaderValue(header::InvalidHeaderValue),
31 MaxSizeReached(MaxSizeReached),
32}
33
34impl fmt::Debug for Error {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 f.debug_tuple("http::Error")
37 .field(&self.get_ref())
39 .finish()
40 }
41}
42
43impl fmt::Display for Error {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 fmt::Display::fmt(self.get_ref(), f)
46 }
47}
48
49impl Error {
50 pub(crate) fn is_empty_uri(&self) -> bool {
51 match self.inner {
52 ErrorKind::Uri(ref err) => err.is_empty(),
53 _ => false,
54 }
55 }
56
57 pub fn is<T: error::Error + 'static>(&self) -> bool {
59 self.get_ref().is::<T>()
60 }
61
62 pub fn get_ref(&self) -> &(dyn error::Error + 'static) {
64 use self::ErrorKind::*;
65
66 match self.inner {
67 StatusCode(ref e) => e,
68 Method(ref e) => e,
69 Uri(ref e) => e,
70 UriParts(ref e) => e,
71 HeaderName(ref e) => e,
72 HeaderValue(ref e) => e,
73 MaxSizeReached(ref e) => e,
74 }
75 }
76}
77
78impl error::Error for Error {
79 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
82 self.get_ref().source()
83 }
84}
85
86impl From<MaxSizeReached> for Error {
87 fn from(err: MaxSizeReached) -> Error {
88 Error {
89 inner: ErrorKind::MaxSizeReached(err),
90 }
91 }
92}
93
94impl From<status::InvalidStatusCode> for Error {
95 fn from(err: status::InvalidStatusCode) -> Error {
96 Error {
97 inner: ErrorKind::StatusCode(err),
98 }
99 }
100}
101
102impl From<method::InvalidMethod> for Error {
103 fn from(err: method::InvalidMethod) -> Error {
104 Error {
105 inner: ErrorKind::Method(err),
106 }
107 }
108}
109
110impl From<uri::InvalidUri> for Error {
111 fn from(err: uri::InvalidUri) -> Error {
112 Error {
113 inner: ErrorKind::Uri(err),
114 }
115 }
116}
117
118impl From<uri::InvalidUriParts> for Error {
119 fn from(err: uri::InvalidUriParts) -> Error {
120 Error {
121 inner: ErrorKind::UriParts(err),
122 }
123 }
124}
125
126impl From<header::InvalidHeaderName> for Error {
127 fn from(err: header::InvalidHeaderName) -> Error {
128 Error {
129 inner: ErrorKind::HeaderName(err),
130 }
131 }
132}
133
134impl From<header::InvalidHeaderValue> for Error {
135 fn from(err: header::InvalidHeaderValue) -> Error {
136 Error {
137 inner: ErrorKind::HeaderValue(err),
138 }
139 }
140}
141
142impl From<std::convert::Infallible> for Error {
143 fn from(err: std::convert::Infallible) -> Error {
144 match err {}
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn inner_error_is_invalid_status_code() {
154 if let Err(e) = status::StatusCode::from_u16(6666) {
155 let err: Error = e.into();
156 let ie = err.get_ref();
157 assert!(!ie.is::<header::InvalidHeaderValue>());
158 assert!(ie.is::<status::InvalidStatusCode>());
159 ie.downcast_ref::<status::InvalidStatusCode>().unwrap();
160
161 assert!(!err.is::<header::InvalidHeaderValue>());
162 assert!(err.is::<status::InvalidStatusCode>());
163 } else {
164 panic!("Bad status allowed!");
165 }
166 }
167}