diff --git a/benches/client_mock_tcp.rs b/benches/client_mock_tcp.rs index eb5760ee90..5caae756e5 100644 --- a/benches/client_mock_tcp.rs +++ b/benches/client_mock_tcp.rs @@ -1,4 +1,4 @@ -#![feature(core, collections, io, test)] +#![feature(collections, io, test)] extern crate hyper; extern crate test; diff --git a/src/header/common/authorization.rs b/src/header/common/authorization.rs index adb8e2650e..9999089e4f 100644 --- a/src/header/common/authorization.rs +++ b/src/header/common/authorization.rs @@ -32,9 +32,9 @@ impl Header for Authorization { match (from_utf8(unsafe { &raw[].get_unchecked(0)[] }), Scheme::scheme(None::)) { (Ok(header), Some(scheme)) if header.starts_with(scheme) && header.len() > scheme.len() + 1 => { - header[scheme.len() + 1..].parse::().map(|s| Authorization(s)) + header[scheme.len() + 1..].parse::().map(|s| Authorization(s)).ok() }, - (Ok(header), None) => header.parse::().map(|s| Authorization(s)), + (Ok(header), None) => header.parse::().map(|s| Authorization(s)).ok(), _ => None } } else { @@ -108,32 +108,33 @@ impl Scheme for Basic { } impl FromStr for Basic { - fn from_str(s: &str) -> Option { + type Err = (); + fn from_str(s: &str) -> Result { match s.from_base64() { Ok(decoded) => match String::from_utf8(decoded) { Ok(text) => { let mut parts = &mut text[].split(':'); let user = match parts.next() { Some(part) => part.to_string(), - None => return None + None => return Err(()) }; let password = match parts.next() { Some(part) => Some(part.to_string()), None => None }; - Some(Basic { + Ok(Basic { username: user, password: password }) }, Err(e) => { debug!("Basic::from_utf8 error={:?}", e); - None + Err(()) } }, Err(e) => { debug!("Basic::from_base64 error={:?}", e); - None + Err(()) } } } diff --git a/src/header/common/cache_control.rs b/src/header/common/cache_control.rs index f49ea5ccc9..50e4a4af4c 100644 --- a/src/header/common/cache_control.rs +++ b/src/header/common/cache_control.rs @@ -96,28 +96,29 @@ impl fmt::Display for CacheDirective { } impl FromStr for CacheDirective { - fn from_str(s: &str) -> Option { + type Err = Option<::Err>; + fn from_str(s: &str) -> Result::Err>> { use self::CacheDirective::*; match s { - "no-cache" => Some(NoCache), - "no-store" => Some(NoStore), - "no-transform" => Some(NoTransform), - "only-if-cached" => Some(OnlyIfCached), - "must-revalidate" => Some(MustRevalidate), - "public" => Some(Public), - "private" => Some(Private), - "proxy-revalidate" => Some(ProxyRevalidate), - "" => None, + "no-cache" => Ok(NoCache), + "no-store" => Ok(NoStore), + "no-transform" => Ok(NoTransform), + "only-if-cached" => Ok(OnlyIfCached), + "must-revalidate" => Ok(MustRevalidate), + "public" => Ok(Public), + "private" => Ok(Private), + "proxy-revalidate" => Ok(ProxyRevalidate), + "" => Err(None), _ => match s.find('=') { Some(idx) if idx+1 < s.len() => match (&s[..idx], &s[idx+1..].trim_matches('"')) { - ("max-age" , secs) => secs.parse().map(MaxAge), - ("max-stale", secs) => secs.parse().map(MaxStale), - ("min-fresh", secs) => secs.parse().map(MinFresh), - ("s-maxage", secs) => secs.parse().map(SMaxAge), - (left, right) => Some(Extension(left.to_string(), Some(right.to_string()))) + ("max-age" , secs) => secs.parse().map(MaxAge).map_err(|x| Some(x)), + ("max-stale", secs) => secs.parse().map(MaxStale).map_err(|x| Some(x)), + ("min-fresh", secs) => secs.parse().map(MinFresh).map_err(|x| Some(x)), + ("s-maxage", secs) => secs.parse().map(SMaxAge).map_err(|x| Some(x)), + (left, right) => Ok(Extension(left.to_string(), Some(right.to_string()))) }, - Some(_) => None, - None => Some(Extension(s.to_string(), None)) + Some(_) => Err(None), + None => Ok(Extension(s.to_string(), None)) } } } diff --git a/src/header/common/connection.rs b/src/header/common/connection.rs index a4735f9335..3c1dd88dd2 100644 --- a/src/header/common/connection.rs +++ b/src/header/common/connection.rs @@ -31,11 +31,12 @@ pub enum ConnectionOption { } impl FromStr for ConnectionOption { - fn from_str(s: &str) -> Option { + type Err = (); + fn from_str(s: &str) -> Result { match s { - "keep-alive" => Some(KeepAlive), - "close" => Some(Close), - s => Some(ConnectionHeader(UniCase(s.to_string()))) + "keep-alive" => Ok(KeepAlive), + "close" => Ok(Close), + s => Ok(ConnectionHeader(UniCase(s.to_string()))) } } } diff --git a/src/header/common/cookie.rs b/src/header/common/cookie.rs index 6f7c36ab36..fa68ab2d18 100644 --- a/src/header/common/cookie.rs +++ b/src/header/common/cookie.rs @@ -30,8 +30,8 @@ impl Header for Cookie { Ok(cookies_str) => { for cookie_str in cookies_str.split(';') { match cookie_str.trim().parse() { - Some(cookie) => cookies.push(cookie), - None => return None + Ok(cookie) => cookies.push(cookie), + Err(_) => return None } } }, diff --git a/src/header/common/date.rs b/src/header/common/date.rs index 28e7ad5bdf..b9e6d97bad 100644 --- a/src/header/common/date.rs +++ b/src/header/common/date.rs @@ -35,8 +35,9 @@ impl HeaderFormat for Date { } impl FromStr for Date { - fn from_str(s: &str) -> Option { - tm_from_str(s).map(Date) + type Err = (); + fn from_str(s: &str) -> Result { + tm_from_str(s).map(Date).ok_or(()) } } diff --git a/src/header/common/expires.rs b/src/header/common/expires.rs index 7878326da4..8969bfdb94 100644 --- a/src/header/common/expires.rs +++ b/src/header/common/expires.rs @@ -34,8 +34,9 @@ impl HeaderFormat for Expires { } impl FromStr for Expires { - fn from_str(s: &str) -> Option { - tm_from_str(s).map(Expires) + type Err = (); + fn from_str(s: &str) -> Result { + tm_from_str(s).map(Expires).ok_or(()) } } diff --git a/src/header/common/host.rs b/src/header/common/host.rs index 2e0a167cb7..6e0bb06d3d 100644 --- a/src/header/common/host.rs +++ b/src/header/common/host.rs @@ -46,7 +46,7 @@ impl Header for Host { }; let port = match idx { - Some(idx) => s[idx + 1..].parse(), + Some(idx) => s[idx + 1..].parse().ok(), None => None }; diff --git a/src/header/common/if_modified_since.rs b/src/header/common/if_modified_since.rs index e9d78be38e..11edfc9e94 100644 --- a/src/header/common/if_modified_since.rs +++ b/src/header/common/if_modified_since.rs @@ -34,8 +34,9 @@ impl HeaderFormat for IfModifiedSince { } impl FromStr for IfModifiedSince { - fn from_str(s: &str) -> Option { - tm_from_str(s).map(IfModifiedSince) + type Err = (); + fn from_str(s: &str) -> Result { + tm_from_str(s).map(IfModifiedSince).ok_or(()) } } diff --git a/src/header/common/last_modified.rs b/src/header/common/last_modified.rs index e44b447d54..ae0aafae75 100644 --- a/src/header/common/last_modified.rs +++ b/src/header/common/last_modified.rs @@ -34,8 +34,9 @@ impl HeaderFormat for LastModified { } impl FromStr for LastModified { - fn from_str(s: &str) -> Option { - tm_from_str(s).map(LastModified) + type Err = (); + fn from_str(s: &str) -> Result { + tm_from_str(s).map(LastModified).ok_or(()) } } diff --git a/src/header/common/set_cookie.rs b/src/header/common/set_cookie.rs index 436fc98ca8..a0e37bc15f 100644 --- a/src/header/common/set_cookie.rs +++ b/src/header/common/set_cookie.rs @@ -26,8 +26,8 @@ impl Header for SetCookie { match from_utf8(&set_cookies_raw[]) { Ok(s) if !s.is_empty() => { match s.parse() { - Some(cookie) => set_cookies.push(cookie), - None => () + Ok(cookie) => set_cookies.push(cookie), + Err(_) => () } }, _ => () diff --git a/src/header/common/upgrade.rs b/src/header/common/upgrade.rs index 6e304a701a..9347d3a2da 100644 --- a/src/header/common/upgrade.rs +++ b/src/header/common/upgrade.rs @@ -22,12 +22,13 @@ pub enum Protocol { } impl FromStr for Protocol { - fn from_str(s: &str) -> Option { + type Err = (); + fn from_str(s: &str) -> Result { if UniCase(s) == UniCase("websocket") { - Some(WebSocket) + Ok(WebSocket) } else { - Some(ProtocolExt(s.to_string())) + Ok(ProtocolExt(s.to_string())) } } } diff --git a/src/header/mod.rs b/src/header/mod.rs index 73986e888a..4a9a3a7e98 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -349,7 +349,7 @@ impl<'a> fmt::Debug for HeaderView<'a> { } impl<'a> Extend> for Headers { - fn extend>>(&mut self, mut iter: I) { + fn extend>>(&mut self, iter: I) { for header in iter { self.data.insert((*header.0).clone(), (*header.1).clone()); } @@ -571,7 +571,7 @@ mod tests { } // we JUST checked that raw.len() == 1, so raw[0] WILL exist. match from_utf8(unsafe { &raw[].get_unchecked(0)[] }) { - Ok(s) => FromStr::from_str(s), + Ok(s) => FromStr::from_str(s).ok(), Err(_) => None }.map(|u| CrazyLength(Some(false), u)) } diff --git a/src/header/parsing.rs b/src/header/parsing.rs index 940fd1a583..16964f261c 100644 --- a/src/header/parsing.rs +++ b/src/header/parsing.rs @@ -12,7 +12,7 @@ pub fn from_one_raw_str(raw: &[Vec]) -> Option { } // we JUST checked that raw.len() == 1, so raw[0] WILL exist. match str::from_utf8(&raw[0][]) { - Ok(s) => str::FromStr::from_str(s), + Ok(s) => str::FromStr::from_str(s).ok(), Err(_) => None } } @@ -34,7 +34,7 @@ pub fn from_one_comma_delimited(raw: &[u8]) -> Option> { Some(s.as_slice() .split(',') .map(|x| x.trim()) - .filter_map(str::FromStr::from_str) + .filter_map(|x| x.parse().ok()) .collect()) } Err(_) => None diff --git a/src/header/shared/encoding.rs b/src/header/shared/encoding.rs index 8a20447ad6..f78e97f10b 100644 --- a/src/header/shared/encoding.rs +++ b/src/header/shared/encoding.rs @@ -37,14 +37,15 @@ impl fmt::Display for Encoding { } impl str::FromStr for Encoding { - fn from_str(s: &str) -> Option { + type Err = (); + fn from_str(s: &str) -> Result { match s { - "chunked" => Some(Chunked), - "deflate" => Some(Deflate), - "gzip" => Some(Gzip), - "compress" => Some(Compress), - "identity" => Some(Identity), - _ => Some(EncodingExt(s.to_string())) + "chunked" => Ok(Chunked), + "deflate" => Ok(Deflate), + "gzip" => Ok(Gzip), + "compress" => Ok(Compress), + "identity" => Ok(Identity), + _ => Ok(EncodingExt(s.to_string())) } } } diff --git a/src/header/shared/quality_item.rs b/src/header/shared/quality_item.rs index 73eaf05644..0e953f05d7 100644 --- a/src/header/shared/quality_item.rs +++ b/src/header/shared/quality_item.rs @@ -38,7 +38,8 @@ impl fmt::Display for QualityItem { } impl str::FromStr for QualityItem { - fn from_str(s: &str) -> Option { + type Err = (); + fn from_str(s: &str) -> Result { // Set defaults used if parsing fails. let mut raw_item = s; let mut quality = 1f32; @@ -49,28 +50,28 @@ impl str::FromStr for QualityItem { if start == "q=" || start == "Q=" { let q_part = &parts[0][2..parts[0].len()]; if q_part.len() > 5 { - return None; + return Err(()); } - let x: Option = q_part.parse(); + let x: Result = q_part.parse(); match x { - Some(q_value) => { + Ok(q_value) => { if 0f32 <= q_value && q_value <= 1f32 { quality = q_value; raw_item = parts[1]; } else { - return None; + return Err(()); } }, - None => return None, + Err(_) => return Err(()), } } } - let x: Option = raw_item.parse(); + let x: Result = raw_item.parse(); match x { - Some(item) => { - Some(QualityItem{ item: item, quality: quality, }) + Ok(item) => { + Ok(QualityItem{ item: item, quality: quality, }) }, - None => return None, + Err(_) => return Err(()), } } } @@ -103,26 +104,26 @@ fn test_quality_item_show3() { #[test] fn test_quality_item_from_str1() { - let x: Option> = "chunked".parse(); + let x: Result, ()> = "chunked".parse(); assert_eq!(x.unwrap(), QualityItem{ item: Chunked, quality: 1f32, }); } #[test] fn test_quality_item_from_str2() { - let x: Option> = "chunked; q=1".parse(); + let x: Result, ()> = "chunked; q=1".parse(); assert_eq!(x.unwrap(), QualityItem{ item: Chunked, quality: 1f32, }); } #[test] fn test_quality_item_from_str3() { - let x: Option> = "gzip; q=0.5".parse(); + let x: Result, ()> = "gzip; q=0.5".parse(); assert_eq!(x.unwrap(), QualityItem{ item: Gzip, quality: 0.5f32, }); } #[test] fn test_quality_item_from_str4() { - let x: Option> = "gzip; q=0.273".parse(); + let x: Result, ()> = "gzip; q=0.273".parse(); assert_eq!(x.unwrap(), QualityItem{ item: Gzip, quality: 0.273f32, }); } #[test] fn test_quality_item_from_str5() { - let x: Option> = "gzip; q=0.2739999".parse(); - assert_eq!(x, None); + let x: Result, ()> = "gzip; q=0.2739999".parse(); + assert_eq!(x, Err(())); } diff --git a/src/http.rs b/src/http.rs index 75c2bda42f..2d081bcb43 100644 --- a/src/http.rs +++ b/src/http.rs @@ -4,7 +4,7 @@ use std::borrow::IntoCow; use std::cmp::min; use std::old_io::{self, Reader, IoResult, BufWriter}; use std::num::from_u16; -use std::str::{self, FromStr}; +use std::str; use std::string::CowString; use url::Url; @@ -625,7 +625,7 @@ pub fn read_status(stream: &mut R) -> HttpResult { try!(stream.read_byte()), ]; - let code = match str::from_utf8(code.as_slice()).ok().and_then(FromStr::from_str) { + let code = match str::from_utf8(code.as_slice()).ok().and_then(|x| x.parse().ok()) { Some(num) => num, None => return Err(HttpStatusError) }; diff --git a/src/method.rs b/src/method.rs index 323482f1f0..6fc62ff82b 100644 --- a/src/method.rs +++ b/src/method.rs @@ -68,11 +68,12 @@ impl Method { } impl FromStr for Method { - fn from_str(s: &str) -> Option { + type Err = (); + fn from_str(s: &str) -> Result { if s == "" { - None + Err(()) } else { - Some(match s { + Ok(match s { "OPTIONS" => Options, "GET" => Get, "POST" => Post, @@ -127,8 +128,8 @@ mod tests { #[test] fn test_from_str() { - assert_eq!(Some(Get), FromStr::from_str("GET")); - assert_eq!(Some(Extension("MOVE".to_string())), + assert_eq!(Ok(Get), FromStr::from_str("GET")); + assert_eq!(Ok(Extension("MOVE".to_string())), FromStr::from_str("MOVE")); }