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 fn is<T: error::Error + 'static>(&self) -> bool {
52 self.get_ref().is::<T>()
53 }
54
55 pub fn get_ref(&self) -> &(dyn error::Error + 'static) {
57 use self::ErrorKind::*;
58
59 match self.inner {
60 StatusCode(ref e) => e,
61 Method(ref e) => e,
62 Uri(ref e) => e,
63 UriParts(ref e) => e,
64 HeaderName(ref e) => e,
65 HeaderValue(ref e) => e,
66 MaxSizeReached(ref e) => e,
67 }
68 }
69}
70
71impl error::Error for Error {
72 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
75 self.get_ref().source()
76 }
77}
78
79impl From<MaxSizeReached> for Error {
80 fn from(err: MaxSizeReached) -> Error {
81 Error {
82 inner: ErrorKind::MaxSizeReached(err),
83 }
84 }
85}
86
87impl From<status::InvalidStatusCode> for Error {
88 fn from(err: status::InvalidStatusCode) -> Error {
89 Error {
90 inner: ErrorKind::StatusCode(err),
91 }
92 }
93}
94
95impl From<method::InvalidMethod> for Error {
96 fn from(err: method::InvalidMethod) -> Error {
97 Error {
98 inner: ErrorKind::Method(err),
99 }
100 }
101}
102
103impl From<uri::InvalidUri> for Error {
104 fn from(err: uri::InvalidUri) -> Error {
105 Error {
106 inner: ErrorKind::Uri(err),
107 }
108 }
109}
110
111impl From<uri::InvalidUriParts> for Error {
112 fn from(err: uri::InvalidUriParts) -> Error {
113 Error {
114 inner: ErrorKind::UriParts(err),
115 }
116 }
117}
118
119impl From<header::InvalidHeaderName> for Error {
120 fn from(err: header::InvalidHeaderName) -> Error {
121 Error {
122 inner: ErrorKind::HeaderName(err),
123 }
124 }
125}
126
127impl From<header::InvalidHeaderValue> for Error {
128 fn from(err: header::InvalidHeaderValue) -> Error {
129 Error {
130 inner: ErrorKind::HeaderValue(err),
131 }
132 }
133}
134
135impl From<std::convert::Infallible> for Error {
136 fn from(err: std::convert::Infallible) -> Error {
137 match err {}
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn inner_error_is_invalid_status_code() {
147 if let Err(e) = status::StatusCode::from_u16(6666) {
148 let err: Error = e.into();
149 let ie = err.get_ref();
150 assert!(!ie.is::<header::InvalidHeaderValue>());
151 assert!(ie.is::<status::InvalidStatusCode>());
152 ie.downcast_ref::<status::InvalidStatusCode>().unwrap();
153
154 assert!(!err.is::<header::InvalidHeaderValue>());
155 assert!(err.is::<status::InvalidStatusCode>());
156 } else {
157 panic!("Bad status allowed!");
158 }
159 }
160}