diff --git a/src/http/h1/parse.rs b/src/http/h1/parse.rs index c1ead352..197f5a1c 100644 --- a/src/http/h1/parse.rs +++ b/src/http/h1/parse.rs @@ -160,7 +160,8 @@ impl Http1Transaction for ClientTransaction { httparse::Status::Complete(len) => { trace!("Response.try_parse Complete({})", len); let code = res.code.unwrap(); - let reason = match StatusCode::from_u16(code).canonical_reason() { + let status = try!(StatusCode::try_from(code).map_err(|_| ::Error::Status)); + let reason = match status.canonical_reason() { Some(reason) if reason == res.reason.unwrap() => Cow::Borrowed(reason), _ => Cow::Owned(res.reason.unwrap().to_owned()) }; diff --git a/src/http/mod.rs b/src/http/mod.rs index 7ab0ff7e..5e4568d1 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -89,7 +89,7 @@ impl RawStatus { /// Converts this into a StatusCode. #[inline] pub fn status(&self) -> StatusCode { - StatusCode::from_u16(self.0) + StatusCode::try_from(self.0).unwrap() } } diff --git a/src/lib.rs b/src/lib.rs index 3ef683cd..ad5ec7ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,6 @@ mod method; pub mod header; mod http; pub mod server; -pub mod status; +mod status; mod uri; mod version; diff --git a/src/status.rs b/src/status.rs index e12e7216..a4f0ea58 100644 --- a/src/status.rs +++ b/src/status.rs @@ -213,11 +213,35 @@ pub enum StatusCode { Unregistered(u16), } +#[derive(Debug)] +pub struct InvalidStatusCode { + _inner: (), +} + impl StatusCode { - #[doc(hidden)] - // Not part of public API or API contract. Could disappear. - pub fn from_u16(n: u16) -> StatusCode { + /// Try to convert a `u16` into a `StatusCode`. + /// + /// # Errors + /// + /// This will return an error if the provided argument is not within the + /// range `100...599`. + /// + /// # Note + /// + /// This function is temporary. When the `TryFrom` trait becomes stable, + /// this will be deprecated and replaced by `TryFrom`. + pub fn try_from(n: u16) -> Result { + if n < 100 || n > 599 { + Err(InvalidStatusCode { + _inner: (), + }) + } else { + Ok(StatusCode::from_u16(n)) + } + } + + fn from_u16(n: u16) -> StatusCode { match n { 100 => StatusCode::Continue, 101 => StatusCode::SwitchingProtocols, @@ -490,7 +514,7 @@ impl Copy for StatusCode {} /// Formats the status code, *including* the canonical reason. /// /// ```rust -/// # use hyper::status::StatusCode::{ImATeapot, Unregistered}; +/// # use hyper::StatusCode::{ImATeapot, Unregistered}; /// assert_eq!(format!("{}", ImATeapot), "418 I'm a teapot"); /// assert_eq!(format!("{}", Unregistered(123)), /// "123 "); @@ -750,4 +774,16 @@ mod tests { Some("Network Authentication Required")); } + + #[test] + fn try_from() { + StatusCode::try_from(100).unwrap(); + StatusCode::try_from(599).unwrap(); + StatusCode::try_from(200).unwrap(); + + StatusCode::try_from(99).unwrap_err(); + StatusCode::try_from(600).unwrap_err(); + StatusCode::try_from(0).unwrap_err(); + StatusCode::try_from(1000).unwrap_err(); + } }