diff --git a/src/client/response.rs b/src/client/response.rs index ba2984edb7..1dcd21c4b1 100644 --- a/src/client/response.rs +++ b/src/client/response.rs @@ -171,7 +171,7 @@ mod tests { None => panic!("Transfer-Encoding: chunked expected!"), }; // The body is correct? - assert_eq!(read_to_string(res), Ok("qwert".to_string())); + assert_eq!(read_to_string(res).unwrap(), "qwert".to_string()); } /// Tests that when a chunk size is not a valid radix-16 number, an error @@ -228,6 +228,6 @@ mod tests { let res = Response::new(Box::new(stream)).unwrap(); - assert_eq!(read_to_string(res), Ok("1".to_string())); + assert_eq!(read_to_string(res).unwrap(), "1".to_string()); } } diff --git a/src/error.rs b/src/error.rs index 21104c0788..f5d591f922 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,5 @@ //! HttpError and HttpResult module. -use std::error::{Error, FromError}; +use std::error::Error; use std::fmt; use std::io::Error as IoError; @@ -15,7 +15,7 @@ use self::HttpError::{HttpMethodError, HttpUriError, HttpVersionError, pub type HttpResult = Result; /// A set of errors that can occur parsing HTTP streams. -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug)] pub enum HttpError { /// An invalid `Method`, such as `GE,T`. HttpMethodError, @@ -61,20 +61,20 @@ impl Error for HttpError { } } -impl FromError for HttpError { - fn from_error(err: IoError) -> HttpError { +impl From for HttpError { + fn from(err: IoError) -> HttpError { HttpIoError(err) } } -impl FromError for HttpError { - fn from_error(err: url::ParseError) -> HttpError { +impl From for HttpError { + fn from(err: url::ParseError) -> HttpError { HttpUriError(err) } } -impl FromError for HttpError { - fn from_error(err: httparse::Error) -> HttpError { +impl From for HttpError { + fn from(err: httparse::Error) -> HttpError { match err { httparse::Error::HeaderName => HttpHeaderError, httparse::Error::HeaderValue => HttpHeaderError, diff --git a/src/header/common/expect.rs b/src/header/common/expect.rs index 3725310c48..0bb9eac601 100644 --- a/src/header/common/expect.rs +++ b/src/header/common/expect.rs @@ -1,4 +1,7 @@ use std::fmt; +use std::str; + +use unicase::UniCase; use header::{Header, HeaderFormat}; @@ -16,14 +19,29 @@ pub enum Expect { Continue } +const EXPECT_CONTINUE: UniCase<&'static str> = UniCase("100-continue"); + impl Header for Expect { fn header_name() -> &'static str { "Expect" } fn parse_header(raw: &[Vec]) -> Option { - if &[b"100-continue"] == raw { - Some(Expect::Continue) + if raw.len() == 1 { + let text = unsafe { + // safe because: + // 1. we just checked raw.len == 1 + // 2. we don't actually care if it's utf8, we just want to + // compare the bytes with the "case" normalized. If it's not + // utf8, then the byte comparison will fail, and we'll return + // None. No big deal. + str::from_utf8_unchecked(raw.get_unchecked(0)) + }; + if UniCase(text) == EXPECT_CONTINUE { + Some(Expect::Continue) + } else { + None + } } else { None } diff --git a/src/header/shared/entity.rs b/src/header/shared/entity.rs index 049b1deaaa..4168dc2f80 100644 --- a/src/header/shared/entity.rs +++ b/src/header/shared/entity.rs @@ -141,11 +141,11 @@ mod tests { #[test] fn test_etag_parse_success() { // Expected success - assert_eq!("\"foobar\"".parse().unwrap(), EntityTag::new(false, "foobar".to_string())); - assert_eq!("\"\"".parse().unwrap(), EntityTag::new(false, "".to_string())); - assert_eq!("W/\"weaktag\"".parse().unwrap(), EntityTag::new(true, "weaktag".to_string())); - assert_eq!("W/\"\x65\x62\"".parse().unwrap(), EntityTag::new(true, "\x65\x62".to_string())); - assert_eq!("W/\"\"".parse().unwrap(), EntityTag::new(true, "".to_string())); + assert_eq!("\"foobar\"".parse::().unwrap(), EntityTag::new(false, "foobar".to_string())); + assert_eq!("\"\"".parse::().unwrap(), EntityTag::new(false, "".to_string())); + assert_eq!("W/\"weaktag\"".parse::().unwrap(), EntityTag::new(true, "weaktag".to_string())); + assert_eq!("W/\"\x65\x62\"".parse::().unwrap(), EntityTag::new(true, "\x65\x62".to_string())); + assert_eq!("W/\"\"".parse::().unwrap(), EntityTag::new(true, "".to_string())); } #[test] diff --git a/src/header/shared/quality_item.rs b/src/header/shared/quality_item.rs index fd191d1269..59adf3e998 100644 --- a/src/header/shared/quality_item.rs +++ b/src/header/shared/quality_item.rs @@ -114,7 +114,7 @@ impl str::FromStr for QualityItem { let mut raw_item = s; let mut quality = 1f32; - let parts: Vec<&str> = s.rsplitn(1, ';').map(|x| x.trim()).collect(); + let parts: Vec<&str> = s.rsplitn(2, ';').map(|x| x.trim()).collect(); if parts.len() == 2 { let start = &parts[0][0..2]; if start == "q=" || start == "Q=" { diff --git a/src/http.rs b/src/http.rs index 50648c036c..b541e946fb 100644 --- a/src/http.rs +++ b/src/http.rs @@ -120,8 +120,7 @@ fn eat(rdr: &mut R, bytes: &[u8]) -> io::Result<()> { match try!(rdr.read(&mut buf)) { 1 if buf[0] == b => (), _ => return Err(io::Error::new(io::ErrorKind::InvalidInput, - "Invalid characters found", - None)) + "Invalid characters found")), } } Ok(()) @@ -135,8 +134,7 @@ fn read_chunk_size(rdr: &mut R) -> io::Result { match try!($rdr.read(&mut buf)) { 1 => buf[0], _ => return Err(io::Error::new(io::ErrorKind::InvalidInput, - "Invalid chunk size line", - None)), + "Invalid chunk size line")), } }) @@ -163,8 +161,7 @@ fn read_chunk_size(rdr: &mut R) -> io::Result { match byte!(rdr) { LF => break, _ => return Err(io::Error::new(io::ErrorKind::InvalidInput, - "Invalid chunk size line", - None)) + "Invalid chunk size line")) } }, @@ -190,8 +187,7 @@ fn read_chunk_size(rdr: &mut R) -> io::Result { // other octet, the chunk size line is invalid! _ => { return Err(io::Error::new(io::ErrorKind::InvalidInput, - "Invalid chunk size line", - None)) + "Invalid chunk size line")); } } } @@ -441,7 +437,7 @@ mod tests { use std::str::from_utf8; let mut w = super::HttpWriter::SizedWriter(Vec::new(), 8); w.write_all(b"foo bar").unwrap(); - assert_eq!(w.write(b"baz"), Ok(1)); + assert_eq!(w.write(b"baz").unwrap(), 1); let buf = w.end().unwrap(); let s = from_utf8(buf.as_ref()).unwrap(); @@ -450,22 +446,22 @@ mod tests { #[test] fn test_read_chunk_size() { - fn read(s: &str, result: io::Result) { - assert_eq!(read_chunk_size(&mut s.as_bytes()), result); + fn read(s: &str, result: u64) { + assert_eq!(read_chunk_size(&mut s.as_bytes()).unwrap(), result); } fn read_err(s: &str) { assert_eq!(read_chunk_size(&mut s.as_bytes()).unwrap_err().kind(), io::ErrorKind::InvalidInput); } - read("1\r\n", Ok(1)); - read("01\r\n", Ok(1)); - read("0\r\n", Ok(0)); - read("00\r\n", Ok(0)); - read("A\r\n", Ok(10)); - read("a\r\n", Ok(10)); - read("Ff\r\n", Ok(255)); - read("Ff \r\n", Ok(255)); + read("1\r\n", 1); + read("01\r\n", 1); + read("0\r\n", 0); + read("00\r\n", 0); + read("A\r\n", 10); + read("a\r\n", 10); + read("Ff\r\n", 255); + read("Ff \r\n", 255); // Missing LF or CRLF read_err("F\rF"); read_err("F"); @@ -475,14 +471,14 @@ mod tests { read_err("-\r\n"); read_err("-1\r\n"); // Acceptable (if not fully valid) extensions do not influence the size - read("1;extension\r\n", Ok(1)); - read("a;ext name=value\r\n", Ok(10)); - read("1;extension;extension2\r\n", Ok(1)); - read("1;;; ;\r\n", Ok(1)); - read("2; extension...\r\n", Ok(2)); - read("3 ; extension=123\r\n", Ok(3)); - read("3 ;\r\n", Ok(3)); - read("3 ; \r\n", Ok(3)); + read("1;extension\r\n", 1); + read("a;ext name=value\r\n", 10); + read("1;extension;extension2\r\n", 1); + read("1;;; ;\r\n", 1); + read("2; extension...\r\n", 2); + read("3 ; extension=123\r\n", 3); + read("3 ;\r\n", 3); + read("3 ; \r\n", 3); // Invalid extensions cause an error read_err("1 invalid extension\r\n"); read_err("1 A\r\n"); diff --git a/src/lib.rs b/src/lib.rs index 656f7f542f..39cee2128d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ #![doc(html_root_url = "https://hyperium.github.io/hyper/hyper/index.html")] -#![feature(core, io, unsafe_destructor, into_cow, convert)] +#![feature(core, into_cow)] #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] #![cfg_attr(test, feature(test))] diff --git a/src/method.rs b/src/method.rs index 672cf26f87..ec58cf636c 100644 --- a/src/method.rs +++ b/src/method.rs @@ -129,9 +129,9 @@ mod tests { #[test] fn test_from_str() { - assert_eq!(Ok(Get), FromStr::from_str("GET")); - assert_eq!(Ok(Extension("MOVE".to_string())), - FromStr::from_str("MOVE")); + assert_eq!(Get, FromStr::from_str("GET").unwrap()); + assert_eq!(Extension("MOVE".to_string()), + FromStr::from_str("MOVE").unwrap()); } #[test] diff --git a/src/net.rs b/src/net.rs index 66dd705ce5..3242ae6e62 100644 --- a/src/net.rs +++ b/src/net.rs @@ -202,10 +202,9 @@ impl NetworkListener for HttpListener { let stream = CloneTcpStream(try!(tcp.accept()).0); match SslStream::new_server(&**ssl_context, stream) { Ok(ssl_stream) => HttpStream::Https(ssl_stream), - Err(StreamError(ref e)) => { + Err(StreamError(e)) => { return Err(io::Error::new(io::ErrorKind::ConnectionAborted, - "SSL Handshake Interrupted", - Some(e.to_string()))); + e)); }, Err(e) => return Err(lift_ssl_error(e)) } @@ -326,8 +325,7 @@ impl<'v> NetworkConnector for HttpConnector<'v> { }, _ => { Err(io::Error::new(io::ErrorKind::InvalidInput, - "Invalid scheme for Http", - None)) + "Invalid scheme for Http")) } } } @@ -338,13 +336,8 @@ fn lift_ssl_error(ssl: SslError) -> io::Error { match ssl { StreamError(err) => err, SslSessionClosed => io::Error::new(io::ErrorKind::ConnectionAborted, - "SSL Connection Closed", - None), - // Unfortunately throw this away. No way to support this - // detail without a better Error abstraction. - OpenSslErrors(errs) => io::Error::new(io::ErrorKind::Other, - "Error in OpenSSL", - Some(format!("{:?}", errs))) + "SSL Connection Closed"), + e@OpenSslErrors(..) => io::Error::new(io::ErrorKind::Other, e) } } diff --git a/src/server/listener.rs b/src/server/listener.rs index a2e0714cfc..b258dcd768 100644 --- a/src/server/listener.rs +++ b/src/server/listener.rs @@ -73,7 +73,6 @@ impl Sentinel { //fn cancel(mut self) { self.active = false; } } -#[unsafe_destructor] impl Drop for Sentinel { fn drop(&mut self) { // If we were cancelled, get out of here. diff --git a/src/server/request.rs b/src/server/request.rs index d572cddeb3..c99069f9fa 100644 --- a/src/server/request.rs +++ b/src/server/request.rs @@ -115,7 +115,7 @@ mod tests { let mut stream = BufReader::new(mock); let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap(); - assert_eq!(read_to_string(req), Ok("".to_string())); + assert_eq!(read_to_string(req).unwrap(), "".to_string()); } #[test] @@ -132,7 +132,7 @@ mod tests { let mut stream = BufReader::new(mock); let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap(); - assert_eq!(read_to_string(req), Ok("".to_string())); + assert_eq!(read_to_string(req).unwrap(), "".to_string()); } #[test] @@ -149,7 +149,7 @@ mod tests { let mut stream = BufReader::new(mock); let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap(); - assert_eq!(read_to_string(req), Ok("".to_string())); + assert_eq!(read_to_string(req).unwrap(), "".to_string()); } #[test] @@ -190,7 +190,7 @@ mod tests { None => panic!("Transfer-Encoding: chunked expected!"), }; // The content is correctly read? - assert_eq!(read_to_string(req), Ok("qwert".to_string())); + assert_eq!(read_to_string(req).unwrap(), "qwert".to_string()); } /// Tests that when a chunk size is not a valid radix-16 number, an error @@ -262,7 +262,7 @@ mod tests { let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap(); - assert_eq!(read_to_string(req), Ok("1".to_string())); + assert_eq!(read_to_string(req).unwrap(), "1".to_string()); } } diff --git a/src/uri.rs b/src/uri.rs index fac8506539..03dbd748a2 100644 --- a/src/uri.rs +++ b/src/uri.rs @@ -74,15 +74,14 @@ impl FromStr for RequestUri { #[test] fn test_uri_fromstr() { - use error::HttpResult; - fn read(s: &str, result: HttpResult) { - assert_eq!(s.parse(), result); + fn read(s: &str, result: RequestUri) { + assert_eq!(s.parse::().unwrap(), result); } - read("*", Ok(RequestUri::Star)); - read("http://hyper.rs/", Ok(RequestUri::AbsoluteUri(Url::parse("http://hyper.rs/").unwrap()))); - read("hyper.rs", Ok(RequestUri::Authority("hyper.rs".to_string()))); - read("/", Ok(RequestUri::AbsolutePath("/".to_string()))); + read("*", RequestUri::Star); + read("http://hyper.rs/", RequestUri::AbsoluteUri(Url::parse("http://hyper.rs/").unwrap())); + read("hyper.rs", RequestUri::Authority("hyper.rs".to_string())); + read("/", RequestUri::AbsolutePath("/".to_string())); }