Skip to content

Commit

Permalink
feat(headers): adds Accept
Browse files Browse the repository at this point in the history
Moved utils to shared/. Added quality_value.
  • Loading branch information
pyfisch authored and seanmonstar committed Jan 3, 2015
1 parent 08cc8aa commit 76126fc
Show file tree
Hide file tree
Showing 29 changed files with 393 additions and 155 deletions.
73 changes: 34 additions & 39 deletions src/header/common/accept.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use header::{Header, HeaderFormat};
use std::fmt::{mod, Show};
use std::str::from_utf8;
use mime::Mime;
use std::fmt;

use header;
use header::shared;

use mime;

/// The `Accept` header.
///
Expand All @@ -14,60 +16,53 @@ use mime::Mime;
/// ```
/// # use hyper::header::Headers;
/// # use hyper::header::common::Accept;
/// # use hyper::header::shared::qitem;
/// use hyper::mime::Mime;
/// use hyper::mime::TopLevel::Text;
/// use hyper::mime::SubLevel::{Html, Xml};
/// # let mut headers = Headers::new();
/// headers.set(Accept(vec![ Mime(Text, Html, vec![]), Mime(Text, Xml, vec![]) ]));
/// headers.set(Accept(vec![
/// qitem(Mime(Text, Html, vec![])),
/// qitem(Mime(Text, Xml, vec![])) ]));
/// ```
#[deriving(Clone, PartialEq, Show)]
pub struct Accept(pub Vec<Mime>);
pub struct Accept(pub Vec<shared::QualityItem<mime::Mime>>);

deref!(Accept -> Vec<Mime>);
deref!(Accept -> Vec<shared::QualityItem<mime::Mime>>);

impl Header for Accept {
impl header::Header for Accept {
fn header_name(_: Option<Accept>) -> &'static str {
"Accept"
}

fn parse_header(raw: &[Vec<u8>]) -> Option<Accept> {
let mut mimes: Vec<Mime> = vec![];
for mimes_raw in raw.iter() {
match from_utf8(mimes_raw.as_slice()) {
Ok(mimes_str) => {
for mime_str in mimes_str.split(',') {
match mime_str.trim().parse() {
Some(mime) => mimes.push(mime),
None => return None
}
}
},
Err(_) => return None
};
}

if !mimes.is_empty() {
Some(Accept(mimes))
} else {
// Currently is just a None, but later it can be Accept for */*
None
}
// TODO: Return */* if no value is given.
shared::from_comma_delimited(raw).map(Accept)
}
}

impl HeaderFormat for Accept {
impl header::HeaderFormat for Accept {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let Accept(ref value) = *self;
let last = value.len() - 1;
for (i, mime) in value.iter().enumerate() {
try!(mime.fmt(fmt));
if i < last {
try!(", ".fmt(fmt));
}
}
Ok(())
shared::fmt_comma_delimited(fmt, self[])
}
}

bench_header!(bench, Accept, { vec![b"text/plain; q=0.5, text/html".to_vec()] });

#[test]
fn test_parse_header_no_quality() {
let a: Accept = header::Header::parse_header([b"text/plain; charset=utf-8".to_vec()].as_slice()).unwrap();
let b = Accept(vec![
shared::QualityItem{item: mime::Mime(mime::TopLevel::Text, mime::SubLevel::Plain, vec![(mime::Attr::Charset, mime::Value::Utf8)]), quality: 1f32},
]);
assert_eq!(a, b);
}

#[test]
fn test_parse_header_with_quality() {
let a: Accept = header::Header::parse_header([b"text/plain; charset=utf-8; q=0.5".to_vec()].as_slice()).unwrap();
let b = Accept(vec![
shared::QualityItem{item: mime::Mime(mime::TopLevel::Text, mime::SubLevel::Plain, vec![(mime::Attr::Charset, mime::Value::Utf8)]), quality: 0.5f32},
]);
assert_eq!(a, b);
}
39 changes: 39 additions & 0 deletions src/header/common/accept_encoding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::fmt;

use header;
use header::shared;

/// The `Accept-Encoding` header
///
/// The `Accept-Encoding` header can be used by clients to indicate what
/// response encodings they accept.
#[deriving(Clone, PartialEq, Show)]
pub struct AcceptEncoding(pub Vec<shared::QualityItem<shared::Encoding>>);

deref!(AcceptEncoding -> Vec<shared::QualityItem<shared::Encoding>>);

impl header::Header for AcceptEncoding {
fn header_name(_: Option<AcceptEncoding>) -> &'static str {
"AcceptEncoding"
}

fn parse_header(raw: &[Vec<u8>]) -> Option<AcceptEncoding> {
shared::from_comma_delimited(raw).map(AcceptEncoding)
}
}

impl header::HeaderFormat for AcceptEncoding {
fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
shared::fmt_comma_delimited(fmt, self[])
}
}

#[test]
fn test_parse_header() {
let a: AcceptEncoding = header::Header::parse_header([b"gzip;q=1.0, identity; q=0.5".to_vec()].as_slice()).unwrap();
let b = AcceptEncoding(vec![
shared::QualityItem{item: shared::Gzip, quality: 1f32},
shared::QualityItem{item: shared::Identity, quality: 0.5f32},
]);
assert_eq!(a, b);
}
3 changes: 1 addition & 2 deletions src/header/common/allow.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use header::{Header, HeaderFormat};
use method::Method;
use std::fmt::{mod};
use super::util::{from_comma_delimited, fmt_comma_delimited};
use header::shared::util::{from_comma_delimited, fmt_comma_delimited};

/// The `Allow` header.
/// See also https://tools.ietf.org/html/rfc7231#section-7.4.1
Expand Down Expand Up @@ -46,4 +46,3 @@ mod tests {
}

bench_header!(bench, Allow, { vec![b"OPTIONS,GET,PUT,POST,DELETE,HEAD,TRACE,CONNECT,PATCH,fOObAr".to_vec()] });

2 changes: 1 addition & 1 deletion src/header/common/cache_control.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;
use std::str::FromStr;
use header::{Header, HeaderFormat};
use super::util::{from_one_comma_delimited, fmt_comma_delimited};
use header::shared::util::{from_one_comma_delimited, fmt_comma_delimited};

/// The Cache-Control header.
#[deriving(PartialEq, Clone, Show)]
Expand Down
2 changes: 1 addition & 1 deletion src/header/common/connection.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use header::{Header, HeaderFormat};
use std::fmt::{mod, Show};
use std::str::FromStr;
use super::util::{from_comma_delimited, fmt_comma_delimited};
use header::shared::util::{from_comma_delimited, fmt_comma_delimited};

pub use self::ConnectionOption::{KeepAlive, Close, ConnectionHeader};

Expand Down
2 changes: 1 addition & 1 deletion src/header/common/content_length.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt::{mod, Show};

use header::{Header, HeaderFormat};
use super::util::from_one_raw_str;
use header::shared::util::from_one_raw_str;

/// The `Content-Length` header.
///
Expand Down
2 changes: 1 addition & 1 deletion src/header/common/content_type.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use header::{Header, HeaderFormat};
use std::fmt::{mod, Show};
use super::util::from_one_raw_str;
use header::shared::util::from_one_raw_str;
use mime::Mime;

/// The `Content-Type` header.
Expand Down
4 changes: 2 additions & 2 deletions src/header/common/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::fmt::{mod, Show};
use std::str::FromStr;
use time::Tm;
use header::{Header, HeaderFormat};
use super::util::{from_one_raw_str, tm_from_str};
use header::shared::util::from_one_raw_str;
use header::shared::time::tm_from_str;

// Egh, replace as soon as something better than time::Tm exists.
/// The `Date` header field.
Expand Down Expand Up @@ -41,4 +42,3 @@ impl FromStr for Date {
bench_header!(imf_fixdate, Date, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] });
bench_header!(rfc_850, Date, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] });
bench_header!(asctime, Date, { vec![b"Sun Nov 6 08:49:37 1994".to_vec()] });

2 changes: 1 addition & 1 deletion src/header/common/etag.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use header::{Header, HeaderFormat};
use std::fmt::{mod};
use super::util::from_one_raw_str;
use header::shared::util::from_one_raw_str;

/// The `Etag` header.
///
Expand Down
4 changes: 2 additions & 2 deletions src/header/common/expires.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::fmt::{mod, Show};
use std::str::FromStr;
use time::Tm;
use header::{Header, HeaderFormat};
use super::util::{from_one_raw_str, tm_from_str};
use header::shared::util::from_one_raw_str;
use header::shared::time::tm_from_str;

/// The `Expires` header field.
#[deriving(Copy, PartialEq, Clone)]
Expand Down Expand Up @@ -40,4 +41,3 @@ impl FromStr for Expires {
bench_header!(imf_fixdate, Expires, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] });
bench_header!(rfc_850, Expires, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] });
bench_header!(asctime, Expires, { vec![b"Sun Nov 6 08:49:37 1994".to_vec()] });

2 changes: 1 addition & 1 deletion src/header/common/host.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use header::{Header, HeaderFormat};
use Port;
use std::fmt::{mod, Show};
use super::util::from_one_raw_str;
use header::shared::util::from_one_raw_str;

/// The `Host` header.
///
Expand Down
4 changes: 2 additions & 2 deletions src/header/common/if_modified_since.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::fmt::{mod, Show};
use std::str::FromStr;
use time::Tm;
use header::{Header, HeaderFormat};
use super::util::{from_one_raw_str, tm_from_str};
use header::shared::util::from_one_raw_str;
use header::shared::time::tm_from_str;

/// The `If-Modified-Since` header field.
#[deriving(Copy, PartialEq, Clone)]
Expand Down Expand Up @@ -40,4 +41,3 @@ impl FromStr for IfModifiedSince {
bench_header!(imf_fixdate, IfModifiedSince, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] });
bench_header!(rfc_850, IfModifiedSince, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] });
bench_header!(asctime, IfModifiedSince, { vec![b"Sun Nov 6 08:49:37 1994".to_vec()] });

4 changes: 2 additions & 2 deletions src/header/common/last_modified.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::fmt::{mod, Show};
use std::str::FromStr;
use time::Tm;
use header::{Header, HeaderFormat};
use super::util::{from_one_raw_str, tm_from_str};
use header::shared::util::from_one_raw_str;
use header::shared::time::tm_from_str;

/// The `LastModified` header field.
#[deriving(Copy, PartialEq, Clone)]
Expand Down Expand Up @@ -40,4 +41,3 @@ impl FromStr for LastModified {
bench_header!(imf_fixdate, LastModified, { vec![b"Sun, 07 Nov 1994 08:48:37 GMT".to_vec()] });
bench_header!(rfc_850, LastModified, { vec![b"Sunday, 06-Nov-94 08:49:37 GMT".to_vec()] });
bench_header!(asctime, LastModified, { vec![b"Sun Nov 6 08:49:37 1994".to_vec()] });

2 changes: 1 addition & 1 deletion src/header/common/location.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use header::{Header, HeaderFormat};
use std::fmt::{mod, Show};
use super::util::from_one_raw_str;
use header::shared::util::from_one_raw_str;

/// The `Location` header.
///
Expand Down
6 changes: 4 additions & 2 deletions src/header/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! is used, such as `ContentType(pub Mime)`.
pub use self::accept::Accept;
pub use self::accept_encoding::AcceptEncoding;
pub use self::allow::Allow;
pub use self::authorization::Authorization;
pub use self::cache_control::CacheControl;
Expand Down Expand Up @@ -76,6 +77,9 @@ macro_rules! deref(
/// Exposes the Accept header.
pub mod accept;

/// Exposes the AcceptEncoding header.
pub mod accept_encoding;

/// Exposes the Allow header.
pub mod allow;

Expand Down Expand Up @@ -135,5 +139,3 @@ pub mod user_agent;

/// Exposes the Vary header.
pub mod vary;

pub mod util;
3 changes: 1 addition & 2 deletions src/header/common/server.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use header::{Header, HeaderFormat};
use std::fmt::{mod, Show};
use super::util::from_one_raw_str;
use header::shared::util::from_one_raw_str;

/// The `Server` header field.
///
Expand Down Expand Up @@ -28,4 +28,3 @@ impl HeaderFormat for Server {
}

bench_header!(bench, Server, { vec![b"Some String".to_vec()] });

5 changes: 2 additions & 3 deletions src/header/common/set_cookie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,15 @@ fn test_fmt() {

#[test]
fn cookie_jar() {
let jar = CookieJar::new("secret".as_bytes());
let jar = CookieJar::new(b"secret");
let cookie = Cookie::new("foo".to_string(), "bar".to_string());
jar.encrypted().add(cookie);

let cookies = SetCookie::from_cookie_jar(&jar);

let mut new_jar = CookieJar::new("secret".as_bytes());
let mut new_jar = CookieJar::new(b"secret");
cookies.apply_to_cookie_jar(&mut new_jar);

assert_eq!(jar.encrypted().find("foo"), new_jar.encrypted().find("foo"));
assert_eq!(jar.iter().collect::<Vec<Cookie>>(), new_jar.iter().collect::<Vec<Cookie>>());
}

2 changes: 1 addition & 1 deletion src/header/common/transfer_encoding.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use header::{Header, HeaderFormat};
use std::fmt;
use std::str::FromStr;
use super::util::{from_comma_delimited, fmt_comma_delimited};
use header::shared::util::{from_comma_delimited, fmt_comma_delimited};

use self::Encoding::{Chunked, Gzip, Deflate, Compress, EncodingExt};

Expand Down
2 changes: 1 addition & 1 deletion src/header/common/upgrade.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use header::{Header, HeaderFormat};
use std::fmt::{mod, Show};
use std::str::FromStr;
use super::util::{from_comma_delimited, fmt_comma_delimited};
use header::shared::util::{from_comma_delimited, fmt_comma_delimited};

use self::Protocol::{WebSocket, ProtocolExt};

Expand Down
2 changes: 1 addition & 1 deletion src/header/common/user_agent.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use header::{Header, HeaderFormat};
use std::fmt::{mod, Show};
use super::util::from_one_raw_str;
use header::shared::util::from_one_raw_str;

/// The `User-Agent` header field.
///
Expand Down
Loading

0 comments on commit 76126fc

Please sign in to comment.