hyper_old_types/
error.rs

1//! Error and Result module.
2use std::error::Error as StdError;
3use std::fmt;
4use std::io::Error as IoError;
5use std::str::Utf8Error;
6use std::string::FromUtf8Error;
7
8use httparse;
9
10pub use uri::UriError;
11
12use self::Error::{
13    Method,
14    Uri,
15    Version,
16    Header,
17    Status,
18    Timeout,
19    Upgrade,
20    Closed,
21    Cancel,
22    Io,
23    TooLarge,
24    Incomplete,
25    Utf8
26};
27
28/// Result type often returned from methods that can have hyper `Error`s.
29pub type Result<T> = ::std::result::Result<T, Error>;
30
31/// A set of errors that can occur parsing HTTP streams.
32#[derive(Debug)]
33pub enum Error {
34    /// An invalid `Method`, such as `GE,T`.
35    Method,
36    /// An invalid `Uri`, such as `exam ple.domain`.
37    Uri(UriError),
38    /// An invalid `HttpVersion`, such as `HTP/1.1`
39    Version,
40    /// An invalid `Header`.
41    Header,
42    /// A message head is too large to be reasonable.
43    TooLarge,
44    /// A message reached EOF, but is not complete.
45    Incomplete,
46    /// An invalid `Status`, such as `1337 ELITE`.
47    Status,
48    /// A timeout occurred waiting for an IO event.
49    Timeout,
50    /// A protocol upgrade was encountered, but not yet supported in hyper.
51    Upgrade,
52    /// A pending item was dropped before ever being processed.
53    Cancel(Canceled),
54    /// Indicates a connection is closed.
55    Closed,
56    /// An `io::Error` that occurred while trying to read or write to a network stream.
57    Io(IoError),
58    /// Parsing a field as string failed
59    Utf8(Utf8Error),
60
61    #[doc(hidden)]
62    __Nonexhaustive(Void)
63}
64
65impl Error {
66    #[doc(hidden)]
67    pub fn __internal_new_canceled<E: Into<Box<StdError + Send + Sync>>>(cause: Option<E>) -> Error {
68        Error::Cancel(Canceled {
69            cause: cause.map(Into::into),
70        })
71    }
72}
73
74/// A pending item was dropped before ever being processed.
75///
76/// For example, a `Request` could be queued in the `Client`, *just*
77/// as the related connection gets closed by the remote. In that case,
78/// when the connection drops, the pending response future will be
79/// fulfilled with this error, signaling the `Request` was never started.
80#[derive(Debug)]
81pub struct Canceled {
82    cause: Option<Box<StdError + Send + Sync>>,
83}
84
85impl Canceled {
86    fn description(&self) -> &str {
87        "an operation was canceled internally before starting"
88    }
89}
90
91impl fmt::Display for Canceled {
92    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93        f.pad(self.description())
94    }
95}
96
97#[doc(hidden)]
98pub struct Void(());
99
100impl fmt::Debug for Void {
101    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
102        unreachable!()
103    }
104}
105
106impl fmt::Display for Error {
107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108        match *self {
109            Uri(ref e) => fmt::Display::fmt(e, f),
110            Io(ref e) => fmt::Display::fmt(e, f),
111            Utf8(ref e) => fmt::Display::fmt(e, f),
112            ref e => f.write_str(e.description()),
113        }
114    }
115}
116
117impl StdError for Error {
118    fn description(&self) -> &str {
119        match *self {
120            Method => "invalid Method specified",
121            Version => "invalid HTTP version specified",
122            Header => "invalid Header provided",
123            TooLarge => "message head is too large",
124            Status => "invalid Status provided",
125            Incomplete => "message is incomplete",
126            Timeout => "timeout",
127            Upgrade => "unsupported protocol upgrade",
128            Closed => "connection is closed",
129            Cancel(ref e) => e.description(),
130            Uri(ref e) => e.description(),
131            Io(ref e) => e.description(),
132            Utf8(ref e) => e.description(),
133            Error::__Nonexhaustive(..) =>  unreachable!(),
134        }
135    }
136
137    fn cause(&self) -> Option<&StdError> {
138        match *self {
139            Io(ref error) => Some(error),
140            Uri(ref error) => Some(error),
141            Utf8(ref error) => Some(error),
142            Cancel(ref e) => e.cause.as_ref().map(|e| &**e as &StdError),
143            Error::__Nonexhaustive(..) =>  unreachable!(),
144            _ => None,
145        }
146    }
147}
148
149impl From<UriError> for Error {
150    fn from(err: UriError) -> Error {
151        Uri(err)
152    }
153}
154
155impl From<IoError> for Error {
156    fn from(err: IoError) -> Error {
157        Io(err)
158    }
159}
160
161impl From<Utf8Error> for Error {
162    fn from(err: Utf8Error) -> Error {
163        Utf8(err)
164    }
165}
166
167impl From<FromUtf8Error> for Error {
168    fn from(err: FromUtf8Error) -> Error {
169        Utf8(err.utf8_error())
170    }
171}
172
173impl From<httparse::Error> for Error {
174    fn from(err: httparse::Error) -> Error {
175        match err {
176            httparse::Error::HeaderName |
177            httparse::Error::HeaderValue |
178            httparse::Error::NewLine |
179            httparse::Error::Token => Header,
180            httparse::Error::Status => Status,
181            httparse::Error::TooManyHeaders => TooLarge,
182            httparse::Error::Version => Version,
183        }
184    }
185}
186
187#[doc(hidden)]
188trait AssertSendSync: Send + Sync + 'static {}
189#[doc(hidden)]
190impl AssertSendSync for Error {}
191
192#[cfg(test)]
193mod tests {
194    use std::error::Error as StdError;
195    use std::io;
196    use httparse;
197    use super::Error;
198    use super::Error::*;
199
200    #[test]
201    fn test_cause() {
202        let orig = io::Error::new(io::ErrorKind::Other, "other");
203        let desc = orig.description().to_owned();
204        let e = Io(orig);
205        assert_eq!(e.cause().unwrap().description(), desc);
206    }
207
208    macro_rules! from {
209        ($from:expr => $error:pat) => {
210            match Error::from($from) {
211                e @ $error => {
212                    assert!(e.description().len() >= 5);
213                } ,
214                e => panic!("{:?}", e)
215            }
216        }
217    }
218
219    macro_rules! from_and_cause {
220        ($from:expr => $error:pat) => {
221            match Error::from($from) {
222                e @ $error => {
223                    let desc = e.cause().unwrap().description();
224                    assert_eq!(desc, $from.description().to_owned());
225                    assert_eq!(desc, e.description());
226                },
227                _ => panic!("{:?}", $from)
228            }
229        }
230    }
231
232    #[test]
233    fn test_from() {
234
235        from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => Io(..));
236
237        from!(httparse::Error::HeaderName => Header);
238        from!(httparse::Error::HeaderName => Header);
239        from!(httparse::Error::HeaderValue => Header);
240        from!(httparse::Error::NewLine => Header);
241        from!(httparse::Error::Status => Status);
242        from!(httparse::Error::Token => Header);
243        from!(httparse::Error::TooManyHeaders => TooLarge);
244        from!(httparse::Error::Version => Version);
245    }
246}