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 { | impl FromStr for Charset { | ||||||
|     type Err = (); |     type Err = ::Error; | ||||||
|     fn from_str(s: &str) -> Result<Charset, ()> { |     fn from_str(s: &str) -> ::Result<Charset> { | ||||||
|         Ok(match s.to_ascii_uppercase().as_ref() { |         Ok(match s.to_ascii_uppercase().as_ref() { | ||||||
|             "US-ASCII" => Us_Ascii, |             "US-ASCII" => Us_Ascii, | ||||||
|             "ISO-8859-1" => Iso_8859_1, |             "ISO-8859-1" => Iso_8859_1, | ||||||
|   | |||||||
| @@ -1,5 +1,3 @@ | |||||||
| //! Provides an Encoding enum. |  | ||||||
|  |  | ||||||
| use std::fmt; | use std::fmt; | ||||||
| use std::str; | use std::str; | ||||||
|  |  | ||||||
| @@ -37,8 +35,8 @@ impl fmt::Display for Encoding { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl str::FromStr for Encoding { | impl str::FromStr for Encoding { | ||||||
|     type Err = (); |     type Err = ::Error; | ||||||
|     fn from_str(s: &str) -> Result<Encoding, ()> { |     fn from_str(s: &str) -> ::Result<Encoding> { | ||||||
|         match s { |         match s { | ||||||
|             "chunked" => Ok(Chunked), |             "chunked" => Ok(Chunked), | ||||||
|             "deflate" => Ok(Deflate), |             "deflate" => Ok(Deflate), | ||||||
|   | |||||||
| @@ -107,13 +107,13 @@ impl Display for EntityTag { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl FromStr for EntityTag { | impl FromStr for EntityTag { | ||||||
|     type Err = (); |     type Err = ::Error; | ||||||
|     fn from_str(s: &str) -> Result<EntityTag, ()> { |     fn from_str(s: &str) -> ::Result<EntityTag> { | ||||||
|         let length: usize = s.len(); |         let length: usize = s.len(); | ||||||
|         let slice = &s[..]; |         let slice = &s[..]; | ||||||
|         // Early exits if it doesn't terminate in a DQUOTE. |         // Early exits if it doesn't terminate in a DQUOTE. | ||||||
|         if !slice.ends_with('"') { |         if !slice.ends_with('"') { | ||||||
|             return Err(()); |             return Err(::Error::Header); | ||||||
|         } |         } | ||||||
|         // The etag is weak if its first char is not a DQUOTE. |         // The etag is weak if its first char is not a DQUOTE. | ||||||
|         if slice.starts_with('"') && check_slice_validity(&slice[1..length-1]) { |         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]) { |         } 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() }); |             return Ok(EntityTag { weak: true, tag: slice[3..length-1].to_owned() }); | ||||||
|         } |         } | ||||||
|         Err(()) |         Err(::Error::Header) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -144,12 +144,12 @@ mod tests { | |||||||
|     #[test] |     #[test] | ||||||
|     fn test_etag_parse_failures() { |     fn test_etag_parse_failures() { | ||||||
|         // Expected failures |         // Expected failures | ||||||
|         assert_eq!("no-dquotes".parse::<EntityTag>(), Err(())); |         assert!("no-dquotes".parse::<EntityTag>().is_err()); | ||||||
|         assert_eq!("w/\"the-first-w-is-case-sensitive\"".parse::<EntityTag>(), Err(())); |         assert!("w/\"the-first-w-is-case-sensitive\"".parse::<EntityTag>().is_err()); | ||||||
|         assert_eq!("".parse::<EntityTag>(), Err(())); |         assert!("".parse::<EntityTag>().is_err()); | ||||||
|         assert_eq!("\"unmatched-dquotes1".parse::<EntityTag>(), Err(())); |         assert!("\"unmatched-dquotes1".parse::<EntityTag>().is_err()); | ||||||
|         assert_eq!("unmatched-dquotes2\"".parse::<EntityTag>(), Err(())); |         assert!("unmatched-dquotes2\"".parse::<EntityTag>().is_err()); | ||||||
|         assert_eq!("matched-\"dquotes\"".parse::<EntityTag>(), Err(())); |         assert!("matched-\"dquotes\"".parse::<EntityTag>().is_err()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|   | |||||||
| @@ -31,15 +31,15 @@ use time; | |||||||
| pub struct HttpDate(pub time::Tm); | pub struct HttpDate(pub time::Tm); | ||||||
|  |  | ||||||
| impl FromStr for HttpDate { | impl FromStr for HttpDate { | ||||||
|     type Err = (); |     type Err = ::Error; | ||||||
|     fn from_str(s: &str) -> Result<Self, ()> { |     fn from_str(s: &str) -> ::Result<HttpDate> { | ||||||
|         match time::strptime(s, "%a, %d %b %Y %T %Z").or_else(|_| { |         match time::strptime(s, "%a, %d %b %Y %T %Z").or_else(|_| { | ||||||
|             time::strptime(s, "%A, %d-%b-%y %T %Z") |             time::strptime(s, "%A, %d-%b-%y %T %Z") | ||||||
|             }).or_else(|_| { |             }).or_else(|_| { | ||||||
|                 time::strptime(s, "%c") |                 time::strptime(s, "%c") | ||||||
|                 }) { |                 }) { | ||||||
|                     Ok(t) => Ok(HttpDate(t)), |                     Ok(t) => Ok(HttpDate(t)), | ||||||
|                     Err(_) => Err(()), |                     Err(_) => Err(::Error::Header), | ||||||
|                     } |                     } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -71,21 +71,21 @@ mod tests { | |||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_imf_fixdate() { |     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] |     #[test] | ||||||
|     fn test_rfc_850() { |     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] |     #[test] | ||||||
|     fn test_asctime() { |     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] |     #[test] | ||||||
|     fn test_no_date() { |     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 { | impl FromStr for Language { | ||||||
|     type Err = (); |     type Err = ::Error; | ||||||
|     fn from_str(s: &str) -> Result<Language, ()> { |     fn from_str(s: &str) -> ::Result<Language> { | ||||||
|         let mut i = s.split("-"); |         let mut i = s.split("-"); | ||||||
|         let p = i.next(); |         let p = i.next(); | ||||||
|         let s = i.next(); |         let s = i.next(); | ||||||
| @@ -29,7 +29,7 @@ impl FromStr for Language { | |||||||
|                 primary: p.to_owned(), |                 primary: p.to_owned(), | ||||||
|                 sub: None |                 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::cmp; | ||||||
| use std::default::Default; | use std::default::Default; | ||||||
| use std::fmt; | 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 | /// 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 | /// 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`. | /// 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)] | #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] | ||||||
| pub struct Quality(pub u16); | 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> { | impl<T: str::FromStr> str::FromStr for QualityItem<T> { | ||||||
|     type Err = (); |     type Err = ::Error; | ||||||
|     fn from_str(s: &str) -> Result<Self, ()> { |     fn from_str(s: &str) -> ::Result<QualityItem<T>> { | ||||||
|         // Set defaults used if parsing fails. |         // Set defaults used if parsing fails. | ||||||
|         let mut raw_item = s; |         let mut raw_item = s; | ||||||
|         let mut quality = 1f32; |         let mut quality = 1f32; | ||||||
| @@ -85,7 +83,7 @@ impl<T: str::FromStr> str::FromStr for QualityItem<T> { | |||||||
|             if start == "q=" || start == "Q=" { |             if start == "q=" || start == "Q=" { | ||||||
|                 let q_part = &parts[0][2..parts[0].len()]; |                 let q_part = &parts[0][2..parts[0].len()]; | ||||||
|                 if q_part.len() > 5 { |                 if q_part.len() > 5 { | ||||||
|                     return Err(()); |                     return Err(::Error::Header); | ||||||
|                 } |                 } | ||||||
|                 match q_part.parse::<f32>() { |                 match q_part.parse::<f32>() { | ||||||
|                     Ok(q_value) => { |                     Ok(q_value) => { | ||||||
| @@ -93,17 +91,17 @@ impl<T: str::FromStr> str::FromStr for QualityItem<T> { | |||||||
|                             quality = q_value; |                             quality = q_value; | ||||||
|                             raw_item = parts[1]; |                             raw_item = parts[1]; | ||||||
|                             } else { |                             } else { | ||||||
|                                 return Err(()); |                                 return Err(::Error::Header); | ||||||
|                             } |                             } | ||||||
|                         }, |                         }, | ||||||
|                     Err(_) => return Err(()), |                     Err(_) => return Err(::Error::Header), | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         match raw_item.parse::<T>() { |         match raw_item.parse::<T>() { | ||||||
|             // we already checked above that the quality is within range |             // we already checked above that the quality is within range | ||||||
|             Ok(item) => Ok(QualityItem::new(item, from_f32(quality))), |             Ok(item) => Ok(QualityItem::new(item, from_f32(quality))), | ||||||
|             Err(_) => return Err(()), |             Err(_) => return Err(::Error::Header), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -155,40 +153,40 @@ mod tests { | |||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_quality_item_from_str1() { |     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), }); |         assert_eq!(x.unwrap(), QualityItem{ item: Chunked, quality: Quality(1000), }); | ||||||
|     } |     } | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_quality_item_from_str2() { |     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), }); |         assert_eq!(x.unwrap(), QualityItem{ item: Chunked, quality: Quality(1000), }); | ||||||
|     } |     } | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_quality_item_from_str3() { |     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), }); |         assert_eq!(x.unwrap(), QualityItem{ item: Gzip, quality: Quality(500), }); | ||||||
|     } |     } | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_quality_item_from_str4() { |     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), }); |         assert_eq!(x.unwrap(), QualityItem{ item: Gzip, quality: Quality(273), }); | ||||||
|     } |     } | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_quality_item_from_str5() { |     fn test_quality_item_from_str5() { | ||||||
|         let x: Result<QualityItem<Encoding>, ()> = "gzip; q=0.2739999".parse(); |         let x: ::Result<QualityItem<Encoding>> = "gzip; q=0.2739999".parse(); | ||||||
|         assert_eq!(x, Err(())); |         assert!(x.is_err()); | ||||||
|     } |     } | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_quality_item_from_str6() { |     fn test_quality_item_from_str6() { | ||||||
|         let x: Result<QualityItem<Encoding>, ()> = "gzip; q=2".parse(); |         let x: ::Result<QualityItem<Encoding>> = "gzip; q=2".parse(); | ||||||
|         assert_eq!(x, Err(())); |         assert!(x.is_err()); | ||||||
|     } |     } | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_quality_item_ordering() { |     fn test_quality_item_ordering() { | ||||||
|         let x: QualityItem<Encoding> = "gzip; q=0.5".parse().ok().unwrap(); |         let x: QualityItem<Encoding> = "gzip; q=0.5".parse().ok().unwrap(); | ||||||
|         let y: QualityItem<Encoding> = "gzip; q=0.273".parse().ok().unwrap(); |         let y: QualityItem<Encoding> = "gzip; q=0.273".parse().ok().unwrap(); | ||||||
|         let comparision_result: bool = x.gt(&y); |         let comparision_result: bool = x.gt(&y); | ||||||
|         assert_eq!(comparision_result, true) |         assert!(comparision_result) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user