Skip to content

Commit 5d66939

Browse files
committed
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.
1 parent ca6cf2b commit 5d66939

File tree

6 files changed

+42
-46
lines changed

6 files changed

+42
-46
lines changed

src/header/shared/charset.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ impl Display for Charset {
103103
}
104104

105105
impl FromStr for Charset {
106-
type Err = ();
107-
fn from_str(s: &str) -> Result<Charset, ()> {
106+
type Err = ::Error;
107+
fn from_str(s: &str) -> ::Result<Charset> {
108108
Ok(match s.to_ascii_uppercase().as_ref() {
109109
"US-ASCII" => Us_Ascii,
110110
"ISO-8859-1" => Iso_8859_1,

src/header/shared/encoding.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
//! Provides an Encoding enum.
2-
31
use std::fmt;
42
use std::str;
53

@@ -37,8 +35,8 @@ impl fmt::Display for Encoding {
3735
}
3836

3937
impl str::FromStr for Encoding {
40-
type Err = ();
41-
fn from_str(s: &str) -> Result<Encoding, ()> {
38+
type Err = ::Error;
39+
fn from_str(s: &str) -> ::Result<Encoding> {
4240
match s {
4341
"chunked" => Ok(Chunked),
4442
"deflate" => Ok(Deflate),

src/header/shared/entity.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ impl Display for EntityTag {
107107
}
108108

109109
impl FromStr for EntityTag {
110-
type Err = ();
111-
fn from_str(s: &str) -> Result<EntityTag, ()> {
110+
type Err = ::Error;
111+
fn from_str(s: &str) -> ::Result<EntityTag> {
112112
let length: usize = s.len();
113113
let slice = &s[..];
114114
// Early exits if it doesn't terminate in a DQUOTE.
115115
if !slice.ends_with('"') {
116-
return Err(());
116+
return Err(::Error::Header);
117117
}
118118
// The etag is weak if its first char is not a DQUOTE.
119119
if slice.starts_with('"') && check_slice_validity(&slice[1..length-1]) {
@@ -123,7 +123,7 @@ impl FromStr for EntityTag {
123123
} else if slice.starts_with("W/\"") && check_slice_validity(&slice[3..length-1]) {
124124
return Ok(EntityTag { weak: true, tag: slice[3..length-1].to_owned() });
125125
}
126-
Err(())
126+
Err(::Error::Header)
127127
}
128128
}
129129

@@ -144,12 +144,12 @@ mod tests {
144144
#[test]
145145
fn test_etag_parse_failures() {
146146
// Expected failures
147-
assert_eq!("no-dquotes".parse::<EntityTag>(), Err(()));
148-
assert_eq!("w/\"the-first-w-is-case-sensitive\"".parse::<EntityTag>(), Err(()));
149-
assert_eq!("".parse::<EntityTag>(), Err(()));
150-
assert_eq!("\"unmatched-dquotes1".parse::<EntityTag>(), Err(()));
151-
assert_eq!("unmatched-dquotes2\"".parse::<EntityTag>(), Err(()));
152-
assert_eq!("matched-\"dquotes\"".parse::<EntityTag>(), Err(()));
147+
assert!("no-dquotes".parse::<EntityTag>().is_err());
148+
assert!("w/\"the-first-w-is-case-sensitive\"".parse::<EntityTag>().is_err());
149+
assert!("".parse::<EntityTag>().is_err());
150+
assert!("\"unmatched-dquotes1".parse::<EntityTag>().is_err());
151+
assert!("unmatched-dquotes2\"".parse::<EntityTag>().is_err());
152+
assert!("matched-\"dquotes\"".parse::<EntityTag>().is_err());
153153
}
154154

155155
#[test]

src/header/shared/httpdate.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ use time;
3131
pub struct HttpDate(pub time::Tm);
3232

3333
impl FromStr for HttpDate {
34-
type Err = ();
35-
fn from_str(s: &str) -> Result<Self, ()> {
34+
type Err = ::Error;
35+
fn from_str(s: &str) -> ::Result<HttpDate> {
3636
match time::strptime(s, "%a, %d %b %Y %T %Z").or_else(|_| {
3737
time::strptime(s, "%A, %d-%b-%y %T %Z")
3838
}).or_else(|_| {
3939
time::strptime(s, "%c")
4040
}) {
4141
Ok(t) => Ok(HttpDate(t)),
42-
Err(_) => Err(()),
42+
Err(_) => Err(::Error::Header),
4343
}
4444
}
4545
}
@@ -71,21 +71,21 @@ mod tests {
7171

7272
#[test]
7373
fn test_imf_fixdate() {
74-
assert_eq!("Sun, 07 Nov 1994 08:48:37 GMT".parse(), Ok(NOV_07));
74+
assert_eq!("Sun, 07 Nov 1994 08:48:37 GMT".parse::<HttpDate>().unwrap(), NOV_07);
7575
}
7676

7777
#[test]
7878
fn test_rfc_850() {
79-
assert_eq!("Sunday, 07-Nov-94 08:48:37 GMT".parse(), Ok(NOV_07));
79+
assert_eq!("Sunday, 07-Nov-94 08:48:37 GMT".parse::<HttpDate>().unwrap(), NOV_07);
8080
}
8181

8282
#[test]
8383
fn test_asctime() {
84-
assert_eq!("Sun Nov 7 08:48:37 1994".parse(), Ok(NOV_07));
84+
assert_eq!("Sun Nov 7 08:48:37 1994".parse::<HttpDate>().unwrap(), NOV_07);
8585
}
8686

8787
#[test]
8888
fn test_no_date() {
89-
assert_eq!("this-is-no-date".parse(), Err::<HttpDate, ()>(()));
89+
assert!("this-is-no-date".parse::<HttpDate>().is_err());
9090
}
9191
}

src/header/shared/language.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ pub struct Language {
1515
}
1616

1717
impl FromStr for Language {
18-
type Err = ();
19-
fn from_str(s: &str) -> Result<Language, ()> {
18+
type Err = ::Error;
19+
fn from_str(s: &str) -> ::Result<Language> {
2020
let mut i = s.split("-");
2121
let p = i.next();
2222
let s = i.next();
@@ -29,7 +29,7 @@ impl FromStr for Language {
2929
primary: p.to_owned(),
3030
sub: None
3131
}),
32-
_ => Err(())
32+
_ => Err(::Error::Header)
3333
}
3434
}
3535
}

src/header/shared/quality_item.rs

+18-20
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
//! Provides a struct for quality values.
2-
//!
3-
//! [RFC7231 Section 5.3.1](https://tools.ietf.org/html/rfc7231#section-5.3.1)
4-
//! gives more information on quality values in HTTP header fields.
5-
61
use std::cmp;
72
use std::default::Default;
83
use std::fmt;
@@ -19,6 +14,9 @@ use std::str;
1914
/// floating point data type (`f32`) consumes four bytes, hyper uses an `u16` value to store the
2015
/// quality internally. For performance reasons you may set quality directly to a value between
2116
/// 0 and 1000 e.g. `Quality(532)` matches the quality `q=0.532`.
17+
///
18+
/// [RFC7231 Section 5.3.1](https://tools.ietf.org/html/rfc7231#section-5.3.1)
19+
/// gives more information on quality values in HTTP header fields.
2220
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
2321
pub struct Quality(pub u16);
2422

@@ -73,8 +71,8 @@ impl<T: fmt::Display> fmt::Display for QualityItem<T> {
7371
}
7472

7573
impl<T: str::FromStr> str::FromStr for QualityItem<T> {
76-
type Err = ();
77-
fn from_str(s: &str) -> Result<Self, ()> {
74+
type Err = ::Error;
75+
fn from_str(s: &str) -> ::Result<QualityItem<T>> {
7876
// Set defaults used if parsing fails.
7977
let mut raw_item = s;
8078
let mut quality = 1f32;
@@ -85,25 +83,25 @@ impl<T: str::FromStr> str::FromStr for QualityItem<T> {
8583
if start == "q=" || start == "Q=" {
8684
let q_part = &parts[0][2..parts[0].len()];
8785
if q_part.len() > 5 {
88-
return Err(());
86+
return Err(::Error::Header);
8987
}
9088
match q_part.parse::<f32>() {
9189
Ok(q_value) => {
9290
if 0f32 <= q_value && q_value <= 1f32 {
9391
quality = q_value;
9492
raw_item = parts[1];
9593
} else {
96-
return Err(());
94+
return Err(::Error::Header);
9795
}
9896
},
99-
Err(_) => return Err(()),
97+
Err(_) => return Err(::Error::Header),
10098
}
10199
}
102100
}
103101
match raw_item.parse::<T>() {
104102
// we already checked above that the quality is within range
105103
Ok(item) => Ok(QualityItem::new(item, from_f32(quality))),
106-
Err(_) => return Err(()),
104+
Err(_) => return Err(::Error::Header),
107105
}
108106
}
109107
}
@@ -155,40 +153,40 @@ mod tests {
155153

156154
#[test]
157155
fn test_quality_item_from_str1() {
158-
let x: Result<QualityItem<Encoding>, ()> = "chunked".parse();
156+
let x: ::Result<QualityItem<Encoding>> = "chunked".parse();
159157
assert_eq!(x.unwrap(), QualityItem{ item: Chunked, quality: Quality(1000), });
160158
}
161159
#[test]
162160
fn test_quality_item_from_str2() {
163-
let x: Result<QualityItem<Encoding>, ()> = "chunked; q=1".parse();
161+
let x: ::Result<QualityItem<Encoding>> = "chunked; q=1".parse();
164162
assert_eq!(x.unwrap(), QualityItem{ item: Chunked, quality: Quality(1000), });
165163
}
166164
#[test]
167165
fn test_quality_item_from_str3() {
168-
let x: Result<QualityItem<Encoding>, ()> = "gzip; q=0.5".parse();
166+
let x: ::Result<QualityItem<Encoding>> = "gzip; q=0.5".parse();
169167
assert_eq!(x.unwrap(), QualityItem{ item: Gzip, quality: Quality(500), });
170168
}
171169
#[test]
172170
fn test_quality_item_from_str4() {
173-
let x: Result<QualityItem<Encoding>, ()> = "gzip; q=0.273".parse();
171+
let x: ::Result<QualityItem<Encoding>> = "gzip; q=0.273".parse();
174172
assert_eq!(x.unwrap(), QualityItem{ item: Gzip, quality: Quality(273), });
175173
}
176174
#[test]
177175
fn test_quality_item_from_str5() {
178-
let x: Result<QualityItem<Encoding>, ()> = "gzip; q=0.2739999".parse();
179-
assert_eq!(x, Err(()));
176+
let x: ::Result<QualityItem<Encoding>> = "gzip; q=0.2739999".parse();
177+
assert!(x.is_err());
180178
}
181179
#[test]
182180
fn test_quality_item_from_str6() {
183-
let x: Result<QualityItem<Encoding>, ()> = "gzip; q=2".parse();
184-
assert_eq!(x, Err(()));
181+
let x: ::Result<QualityItem<Encoding>> = "gzip; q=2".parse();
182+
assert!(x.is_err());
185183
}
186184
#[test]
187185
fn test_quality_item_ordering() {
188186
let x: QualityItem<Encoding> = "gzip; q=0.5".parse().ok().unwrap();
189187
let y: QualityItem<Encoding> = "gzip; q=0.273".parse().ok().unwrap();
190188
let comparision_result: bool = x.gt(&y);
191-
assert_eq!(comparision_result, true)
189+
assert!(comparision_result)
192190
}
193191

194192
#[test]

0 commit comments

Comments
 (0)