feat(headers): return hyper::Error instead of () from header components
This allows more precise errors in the future and makes it easier to use the try!() macro in some cases. BREAKING CHANGE: Error enum extended. Return type of header/shared/ types changed.
This commit is contained in:
		| @@ -103,8 +103,8 @@ impl Display for Charset { | ||||
| } | ||||
|  | ||||
| impl FromStr for Charset { | ||||
|     type Err = (); | ||||
|     fn from_str(s: &str) -> Result<Charset, ()> { | ||||
|     type Err = ::Error; | ||||
|     fn from_str(s: &str) -> ::Result<Charset> { | ||||
|         Ok(match s.to_ascii_uppercase().as_ref() { | ||||
|             "US-ASCII" => Us_Ascii, | ||||
|             "ISO-8859-1" => Iso_8859_1, | ||||
|   | ||||
| @@ -1,5 +1,3 @@ | ||||
| //! Provides an Encoding enum. | ||||
|  | ||||
| use std::fmt; | ||||
| use std::str; | ||||
|  | ||||
| @@ -37,8 +35,8 @@ impl fmt::Display for Encoding { | ||||
| } | ||||
|  | ||||
| impl str::FromStr for Encoding { | ||||
|     type Err = (); | ||||
|     fn from_str(s: &str) -> Result<Encoding, ()> { | ||||
|     type Err = ::Error; | ||||
|     fn from_str(s: &str) -> ::Result<Encoding> { | ||||
|         match s { | ||||
|             "chunked" => Ok(Chunked), | ||||
|             "deflate" => Ok(Deflate), | ||||
|   | ||||
| @@ -107,13 +107,13 @@ impl Display for EntityTag { | ||||
| } | ||||
|  | ||||
| impl FromStr for EntityTag { | ||||
|     type Err = (); | ||||
|     fn from_str(s: &str) -> Result<EntityTag, ()> { | ||||
|     type Err = ::Error; | ||||
|     fn from_str(s: &str) -> ::Result<EntityTag> { | ||||
|         let length: usize = s.len(); | ||||
|         let slice = &s[..]; | ||||
|         // Early exits if it doesn't terminate in a DQUOTE. | ||||
|         if !slice.ends_with('"') { | ||||
|             return Err(()); | ||||
|             return Err(::Error::Header); | ||||
|         } | ||||
|         // The etag is weak if its first char is not a DQUOTE. | ||||
|         if slice.starts_with('"') && check_slice_validity(&slice[1..length-1]) { | ||||
| @@ -123,7 +123,7 @@ impl FromStr for EntityTag { | ||||
|         } else if slice.starts_with("W/\"") && check_slice_validity(&slice[3..length-1]) { | ||||
|             return Ok(EntityTag { weak: true, tag: slice[3..length-1].to_owned() }); | ||||
|         } | ||||
|         Err(()) | ||||
|         Err(::Error::Header) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -144,12 +144,12 @@ mod tests { | ||||
|     #[test] | ||||
|     fn test_etag_parse_failures() { | ||||
|         // Expected failures | ||||
|         assert_eq!("no-dquotes".parse::<EntityTag>(), Err(())); | ||||
|         assert_eq!("w/\"the-first-w-is-case-sensitive\"".parse::<EntityTag>(), Err(())); | ||||
|         assert_eq!("".parse::<EntityTag>(), Err(())); | ||||
|         assert_eq!("\"unmatched-dquotes1".parse::<EntityTag>(), Err(())); | ||||
|         assert_eq!("unmatched-dquotes2\"".parse::<EntityTag>(), Err(())); | ||||
|         assert_eq!("matched-\"dquotes\"".parse::<EntityTag>(), Err(())); | ||||
|         assert!("no-dquotes".parse::<EntityTag>().is_err()); | ||||
|         assert!("w/\"the-first-w-is-case-sensitive\"".parse::<EntityTag>().is_err()); | ||||
|         assert!("".parse::<EntityTag>().is_err()); | ||||
|         assert!("\"unmatched-dquotes1".parse::<EntityTag>().is_err()); | ||||
|         assert!("unmatched-dquotes2\"".parse::<EntityTag>().is_err()); | ||||
|         assert!("matched-\"dquotes\"".parse::<EntityTag>().is_err()); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|   | ||||
| @@ -31,15 +31,15 @@ use time; | ||||
| pub struct HttpDate(pub time::Tm); | ||||
|  | ||||
| impl FromStr for HttpDate { | ||||
|     type Err = (); | ||||
|     fn from_str(s: &str) -> Result<Self, ()> { | ||||
|     type Err = ::Error; | ||||
|     fn from_str(s: &str) -> ::Result<HttpDate> { | ||||
|         match time::strptime(s, "%a, %d %b %Y %T %Z").or_else(|_| { | ||||
|             time::strptime(s, "%A, %d-%b-%y %T %Z") | ||||
|             }).or_else(|_| { | ||||
|                 time::strptime(s, "%c") | ||||
|                 }) { | ||||
|                     Ok(t) => Ok(HttpDate(t)), | ||||
|                     Err(_) => Err(()), | ||||
|                     Err(_) => Err(::Error::Header), | ||||
|                     } | ||||
|     } | ||||
| } | ||||
| @@ -71,21 +71,21 @@ mod tests { | ||||
|  | ||||
|     #[test] | ||||
|     fn test_imf_fixdate() { | ||||
|         assert_eq!("Sun, 07 Nov 1994 08:48:37 GMT".parse(), Ok(NOV_07)); | ||||
|         assert_eq!("Sun, 07 Nov 1994 08:48:37 GMT".parse::<HttpDate>().unwrap(), NOV_07); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_rfc_850() { | ||||
|         assert_eq!("Sunday, 07-Nov-94 08:48:37 GMT".parse(), Ok(NOV_07)); | ||||
|         assert_eq!("Sunday, 07-Nov-94 08:48:37 GMT".parse::<HttpDate>().unwrap(), NOV_07); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_asctime() { | ||||
|         assert_eq!("Sun Nov  7 08:48:37 1994".parse(), Ok(NOV_07)); | ||||
|         assert_eq!("Sun Nov  7 08:48:37 1994".parse::<HttpDate>().unwrap(), NOV_07); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_no_date() { | ||||
|         assert_eq!("this-is-no-date".parse(), Err::<HttpDate, ()>(())); | ||||
|         assert!("this-is-no-date".parse::<HttpDate>().is_err()); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -15,8 +15,8 @@ pub struct Language { | ||||
| } | ||||
|  | ||||
| impl FromStr for Language { | ||||
|     type Err = (); | ||||
|     fn from_str(s: &str) -> Result<Language, ()> { | ||||
|     type Err = ::Error; | ||||
|     fn from_str(s: &str) -> ::Result<Language> { | ||||
|         let mut i = s.split("-"); | ||||
|         let p = i.next(); | ||||
|         let s = i.next(); | ||||
| @@ -29,7 +29,7 @@ impl FromStr for Language { | ||||
|                 primary: p.to_owned(), | ||||
|                 sub: None | ||||
|                 }), | ||||
|             _ => Err(()) | ||||
|             _ => Err(::Error::Header) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,3 @@ | ||||
| //! Provides a struct for quality values. | ||||
| //! | ||||
| //! [RFC7231 Section 5.3.1](https://tools.ietf.org/html/rfc7231#section-5.3.1) | ||||
| //! gives more information on quality values in HTTP header fields. | ||||
|  | ||||
| use std::cmp; | ||||
| use std::default::Default; | ||||
| use std::fmt; | ||||
| @@ -19,6 +14,9 @@ use std::str; | ||||
| /// floating point data type (`f32`) consumes four bytes, hyper uses an `u16` value to store the | ||||
| /// quality internally. For performance reasons you may set quality directly to a value between | ||||
| /// 0 and 1000 e.g. `Quality(532)` matches the quality `q=0.532`. | ||||
| /// | ||||
| /// [RFC7231 Section 5.3.1](https://tools.ietf.org/html/rfc7231#section-5.3.1) | ||||
| /// gives more information on quality values in HTTP header fields. | ||||
| #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | ||||
| pub struct Quality(pub u16); | ||||
|  | ||||
| @@ -73,8 +71,8 @@ impl<T: fmt::Display> fmt::Display for QualityItem<T> { | ||||
| } | ||||
|  | ||||
| impl<T: str::FromStr> str::FromStr for QualityItem<T> { | ||||
|     type Err = (); | ||||
|     fn from_str(s: &str) -> Result<Self, ()> { | ||||
|     type Err = ::Error; | ||||
|     fn from_str(s: &str) -> ::Result<QualityItem<T>> { | ||||
|         // Set defaults used if parsing fails. | ||||
|         let mut raw_item = s; | ||||
|         let mut quality = 1f32; | ||||
| @@ -85,7 +83,7 @@ impl<T: str::FromStr> str::FromStr for QualityItem<T> { | ||||
|             if start == "q=" || start == "Q=" { | ||||
|                 let q_part = &parts[0][2..parts[0].len()]; | ||||
|                 if q_part.len() > 5 { | ||||
|                     return Err(()); | ||||
|                     return Err(::Error::Header); | ||||
|                 } | ||||
|                 match q_part.parse::<f32>() { | ||||
|                     Ok(q_value) => { | ||||
| @@ -93,17 +91,17 @@ impl<T: str::FromStr> str::FromStr for QualityItem<T> { | ||||
|                             quality = q_value; | ||||
|                             raw_item = parts[1]; | ||||
|                             } else { | ||||
|                                 return Err(()); | ||||
|                                 return Err(::Error::Header); | ||||
|                             } | ||||
|                         }, | ||||
|                     Err(_) => return Err(()), | ||||
|                     Err(_) => return Err(::Error::Header), | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         match raw_item.parse::<T>() { | ||||
|             // we already checked above that the quality is within range | ||||
|             Ok(item) => Ok(QualityItem::new(item, from_f32(quality))), | ||||
|             Err(_) => return Err(()), | ||||
|             Err(_) => return Err(::Error::Header), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -155,40 +153,40 @@ mod tests { | ||||
|  | ||||
|     #[test] | ||||
|     fn test_quality_item_from_str1() { | ||||
|         let x: Result<QualityItem<Encoding>, ()> = "chunked".parse(); | ||||
|         let x: ::Result<QualityItem<Encoding>> = "chunked".parse(); | ||||
|         assert_eq!(x.unwrap(), QualityItem{ item: Chunked, quality: Quality(1000), }); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_quality_item_from_str2() { | ||||
|         let x: Result<QualityItem<Encoding>, ()> = "chunked; q=1".parse(); | ||||
|         let x: ::Result<QualityItem<Encoding>> = "chunked; q=1".parse(); | ||||
|         assert_eq!(x.unwrap(), QualityItem{ item: Chunked, quality: Quality(1000), }); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_quality_item_from_str3() { | ||||
|         let x: Result<QualityItem<Encoding>, ()> = "gzip; q=0.5".parse(); | ||||
|         let x: ::Result<QualityItem<Encoding>> = "gzip; q=0.5".parse(); | ||||
|         assert_eq!(x.unwrap(), QualityItem{ item: Gzip, quality: Quality(500), }); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_quality_item_from_str4() { | ||||
|         let x: Result<QualityItem<Encoding>, ()> = "gzip; q=0.273".parse(); | ||||
|         let x: ::Result<QualityItem<Encoding>> = "gzip; q=0.273".parse(); | ||||
|         assert_eq!(x.unwrap(), QualityItem{ item: Gzip, quality: Quality(273), }); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_quality_item_from_str5() { | ||||
|         let x: Result<QualityItem<Encoding>, ()> = "gzip; q=0.2739999".parse(); | ||||
|         assert_eq!(x, Err(())); | ||||
|         let x: ::Result<QualityItem<Encoding>> = "gzip; q=0.2739999".parse(); | ||||
|         assert!(x.is_err()); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_quality_item_from_str6() { | ||||
|         let x: Result<QualityItem<Encoding>, ()> = "gzip; q=2".parse(); | ||||
|         assert_eq!(x, Err(())); | ||||
|         let x: ::Result<QualityItem<Encoding>> = "gzip; q=2".parse(); | ||||
|         assert!(x.is_err()); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_quality_item_ordering() { | ||||
|         let x: QualityItem<Encoding> = "gzip; q=0.5".parse().ok().unwrap(); | ||||
|         let y: QualityItem<Encoding> = "gzip; q=0.273".parse().ok().unwrap(); | ||||
|         let comparision_result: bool = x.gt(&y); | ||||
|         assert_eq!(comparision_result, true) | ||||
|         assert!(comparision_result) | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user