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
11/// A generic "error" for HTTP connections
12///
13/// This error type is less specific than the error returned from other
14/// functions in this crate, but all other errors can be converted to this
15/// error. Consumers of this crate can typically consume and work with this form
16/// of error for conversions with the `?` operator.
17pub struct Error {
18 inner: ErrorKind,
19}
20
21/// A `Result` typedef to use with the `http::Error` type
22pub 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&mut DebugTuple<'_, '_>.debug_tuple(name:"http::Error")
37 // Skip the noise of the ErrorKind enum
38 .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 /// Return true if the underlying error has the same type as T.
51 pub fn is<T: error::Error + 'static>(&self) -> bool {
52 self.get_ref().is::<T>()
53 }
54
55 /// Return a reference to the lower level, inner error.
56 pub fn get_ref(&self) -> &(dyn error::Error + 'static) {
57 use self::ErrorKind::*;
58
59 match self.inner {
60 StatusCode(ref e: &InvalidStatusCode) => e,
61 Method(ref e: &InvalidMethod) => e,
62 Uri(ref e: &InvalidUri) => e,
63 UriParts(ref e: &InvalidUriParts) => e,
64 HeaderName(ref e: &InvalidHeaderName) => e,
65 HeaderValue(ref e: &InvalidHeaderValue) => e,
66 MaxSizeReached(ref e: &MaxSizeReached) => e,
67 }
68 }
69}
70
71impl error::Error for Error {
72 // Return any available cause from the inner error. Note the inner error is
73 // not itself the cause.
74 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}
161