Merge pull request #534 from pyfisch/errors
feat(headers): return hyper::Error instead of () from header components
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