Skip to content

Commit

Permalink
feat(headers): add AcceptLanguage header
Browse files Browse the repository at this point in the history
Adds header support for Accept-Language, using a struct for the primary
and sub components of the language.
  • Loading branch information
hugoduncan committed Feb 14, 2015
1 parent 361e451 commit 20a585e
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
86 changes: 86 additions & 0 deletions src/header/common/accept_language.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use header::{self, QualityItem};
use std::str::FromStr;
use std::fmt;

/// A language tag.
/// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.10
#[derive(Clone, PartialEq, Debug)]
pub struct Language{
primary: String,
sub: Option<String>
}

impl FromStr for Language {
type Err = ();
fn from_str(s: &str) -> Result<Language, ()> {
let mut i = s.split_str("-");
let p = i.next();
let s = i.next();
match (p, s) {
(Some(p),Some(s)) => Ok(Language{primary: p.to_string(),
sub: Some(s.to_string())}),
(Some(p),_) => Ok(Language{primary: p.to_string(), sub: None}),
_ => Err(())
}
}
}

impl fmt::Display for Language {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "{}", self.primary));
match self.sub {
Some(ref s) => write!(f, "-{}", s),
None => Ok(())
}
}
}

/// The `Accept-Language` header
///
/// The `Accept-Language` header can be used by clients to indicate what
/// response languages they accept.
#[derive(Clone, PartialEq, Debug)]
pub struct AcceptLanguage(pub Vec<QualityItem<Language>>);

impl_list_header!(AcceptLanguage,
"Accept-Language",
Vec<QualityItem<Language>>);

bench_header!(bench, AcceptLanguage,
{ vec![b"en-us;q=1.0, en;q=0.5, fr".to_vec()] });

#[test]
fn test_parse_header() {
let a: AcceptLanguage = header::Header::parse_header(
[b"en-us;q=1.0, en;q=0.5, fr".to_vec()].as_slice()).unwrap();
let b = AcceptLanguage(vec![
QualityItem { item: Language{primary: "en".to_string(),
sub: Some("us".to_string())},
quality: 1f32 },
QualityItem { item: Language{primary: "en".to_string(), sub: None},
quality: 0.5f32 },
QualityItem { item: Language{primary: "fr".to_string(), sub: None},
quality: 1f32 },
]);
assert_eq!(format!("{}", a), format!("{}", b));
assert_eq!(a, b);
}

#[test]
fn test_display() {
assert_eq!("en".to_string(),
format!("{}", Language{primary: "en".to_string(),
sub: None}));
assert_eq!("en-us".to_string(),
format!("{}", Language{primary: "en".to_string(),
sub: Some("us".to_string())}));
}

#[test]
fn test_from_str() {
assert_eq!(Language { primary: "en".to_string(), sub: None },
"en".parse().unwrap());
assert_eq!(Language { primary: "en".to_string(),
sub: Some("us".to_string()) },
"en-us".parse().unwrap());
}
2 changes: 2 additions & 0 deletions src/header/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
pub use self::access_control::*;
pub use self::accept::Accept;
pub use self::accept_encoding::AcceptEncoding;
pub use self::accept_language::AcceptLanguage;
pub use self::allow::Allow;
pub use self::authorization::{Authorization, Scheme, Basic};
pub use self::cache_control::{CacheControl, CacheDirective};
Expand Down Expand Up @@ -147,6 +148,7 @@ macro_rules! impl_header(
mod access_control;
mod accept;
mod accept_encoding;
mod accept_language;
mod allow;
mod authorization;
mod cache_control;
Expand Down

0 comments on commit 20a585e

Please sign in to comment.