feat(langtags): use true language tags in headers
Make hyper dependant on rust-language-tags providing complete parsing and formatting of language tags. Remove builtin solution for simple tags. BREAKING CHANGE: AcceptLanguage and ContentLanguage use LanguageTag now, Language removed from Hyper.
This commit is contained in:
		| @@ -13,6 +13,7 @@ keywords = ["http", "hyper", "hyperium"] | |||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
| httparse = "0.1" | httparse = "0.1" | ||||||
|  | language-tags = "0.0.7" | ||||||
| log = "0.3" | log = "0.3" | ||||||
| mime = "0.0.12" | mime = "0.0.12" | ||||||
| num_cpus = "0.2" | num_cpus = "0.2" | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| use header::{Language, QualityItem}; | use language_tags::LanguageTag; | ||||||
|  | use header::QualityItem; | ||||||
|  |  | ||||||
| header! { | header! { | ||||||
|     #[doc="`Accept-Language` header, defined in"] |     #[doc="`Accept-Language` header, defined in"] | ||||||
| @@ -20,61 +21,47 @@ header! { | |||||||
|     #[doc=""] |     #[doc=""] | ||||||
|     #[doc="# Examples"] |     #[doc="# Examples"] | ||||||
|     #[doc="```"] |     #[doc="```"] | ||||||
|     #[doc="use hyper::header::{Headers, AcceptLanguage, Language, qitem};"] |     #[doc="use hyper::LanguageTag;"] | ||||||
|  |     #[doc="use hyper::header::{Headers, AcceptLanguage, qitem};"] | ||||||
|     #[doc=""] |     #[doc=""] | ||||||
|     #[doc="let mut headers = Headers::new();"] |     #[doc="let mut headers = Headers::new();"] | ||||||
|  |     #[doc="let mut langtag: LanguageTag = Default::default();"] | ||||||
|  |     #[doc="langtag.language = Some(\"en\".to_owned());"] | ||||||
|  |     #[doc="langtag.region = Some(\"US\".to_owned());"] | ||||||
|     #[doc="headers.set("] |     #[doc="headers.set("] | ||||||
|     #[doc="    AcceptLanguage(vec!["] |     #[doc="    AcceptLanguage(vec!["] | ||||||
|     #[doc="        qitem("] |     #[doc="        qitem(langtag),"] | ||||||
|     #[doc="            Language {"] |  | ||||||
|     #[doc="                 primary: \"en\".to_owned(),"] |  | ||||||
|     #[doc="                 sub: Some(\"us\".to_owned()),"] |  | ||||||
|     #[doc="            }"] |  | ||||||
|     #[doc="        ),"] |  | ||||||
|     #[doc="    ])"] |     #[doc="    ])"] | ||||||
|     #[doc=");"] |     #[doc=");"] | ||||||
|     #[doc="```"] |     #[doc="```"] | ||||||
|     #[doc="```"] |     #[doc="```"] | ||||||
|     #[doc="use hyper::header::{Headers, AcceptLanguage, Language, QualityItem, Quality, qitem};"] |     #[doc="# extern crate hyper;"] | ||||||
|     #[doc=""] |     #[doc="# #[macro_use] extern crate language_tags;"] | ||||||
|  |     #[doc="# use hyper::header::{Headers, AcceptLanguage, QualityItem, Quality, qitem};"] | ||||||
|  |     #[doc="# "] | ||||||
|  |     #[doc="# fn main() {"] | ||||||
|     #[doc="let mut headers = Headers::new();"] |     #[doc="let mut headers = Headers::new();"] | ||||||
|     #[doc="headers.set("] |     #[doc="headers.set("] | ||||||
|     #[doc="    AcceptLanguage(vec!["] |     #[doc="    AcceptLanguage(vec!["] | ||||||
|     #[doc="        qitem("] |     #[doc="        qitem(langtag!(da)),"] | ||||||
|     #[doc="            Language {"] |     #[doc="        QualityItem::new(langtag!(en;;;GB), Quality(800)),"] | ||||||
|     #[doc="                primary: \"da\".to_owned(),"] |     #[doc="        QualityItem::new(langtag!(en), Quality(700)),"] | ||||||
|     #[doc="                sub: None,"] |  | ||||||
|     #[doc="             }"] |  | ||||||
|     #[doc="        ),"] |  | ||||||
|     #[doc="        QualityItem::new("] |  | ||||||
|     #[doc="            Language {"] |  | ||||||
|     #[doc="                primary: \"en\".to_owned(),"] |  | ||||||
|     #[doc="                sub: Some(\"gb\".to_owned()),"] |  | ||||||
|     #[doc="            },"] |  | ||||||
|     #[doc="            Quality(800),"] |  | ||||||
|     #[doc="        ),"] |  | ||||||
|     #[doc="        QualityItem::new("] |  | ||||||
|     #[doc="            Language {"] |  | ||||||
|     #[doc="                primary: \"en\".to_owned(),"] |  | ||||||
|     #[doc="                sub: None,"] |  | ||||||
|     #[doc="            },"] |  | ||||||
|     #[doc="            Quality(700),"] |  | ||||||
|     #[doc="        ),"] |  | ||||||
|     #[doc="    ])"] |     #[doc="    ])"] | ||||||
|     #[doc=");"] |     #[doc=");"] | ||||||
|  |     #[doc="# }"] | ||||||
|     #[doc="```"] |     #[doc="```"] | ||||||
|     (AcceptLanguage, "Accept-Language") => (QualityItem<Language>)+ |     (AcceptLanguage, "Accept-Language") => (QualityItem<LanguageTag>)+ | ||||||
|  |  | ||||||
|     test_accept_language { |     test_accept_language { | ||||||
|         // From the RFC |         // From the RFC | ||||||
|         test_header!(test1, vec![b"da, en-gb;q=0.8, en;q=0.7"]); |         test_header!(test1, vec![b"da, en-gb;q=0.8, en;q=0.7"]); | ||||||
|         // Own test |         // Own test | ||||||
|         test_header!( |         test_header!( | ||||||
|             test2, vec![b"en-us, en; q=0.5, fr"], |             test2, vec![b"en-US, en; q=0.5, fr"], | ||||||
|             Some(AcceptLanguage(vec![ |             Some(AcceptLanguage(vec![ | ||||||
|                 qitem(Language {primary: "en".to_owned(), sub: Some("us".to_owned())}), |                 qitem(langtag!(en;;;US)), | ||||||
|                 QualityItem::new(Language{primary: "en".to_owned(), sub: None}, Quality(500)), |                 QualityItem::new(langtag!(en), Quality(500)), | ||||||
|                 qitem(Language {primary: "fr".to_owned(), sub: None}), |                 qitem(langtag!(fr)), | ||||||
|         ]))); |         ]))); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| use header::{Language, QualityItem}; | use language_tags::LanguageTag; | ||||||
|  | use header::QualityItem; | ||||||
|  |  | ||||||
| header! { | header! { | ||||||
|     #[doc="`Content-Language` header, defined in"] |     #[doc="`Content-Language` header, defined in"] | ||||||
| @@ -20,42 +21,36 @@ header! { | |||||||
|     #[doc=""] |     #[doc=""] | ||||||
|     #[doc="# Examples"] |     #[doc="# Examples"] | ||||||
|     #[doc="```"] |     #[doc="```"] | ||||||
|     #[doc="use hyper::header::{Headers, ContentLanguage, Language, qitem};"] |     #[doc="# extern crate hyper;"] | ||||||
|  |     #[doc="# #[macro_use] extern crate language_tags;"] | ||||||
|  |     #[doc="# use hyper::header::{Headers, ContentLanguage, qitem};"] | ||||||
|  |     #[doc="# "] | ||||||
|  |     #[doc="# fn main() {"] | ||||||
|  |     #[doc="let mut headers = Headers::new();"] | ||||||
|  |     #[doc="headers.set("] | ||||||
|  |     #[doc="    ContentLanguage(vec!["] | ||||||
|  |     #[doc="        qitem(langtag!(en)),"] | ||||||
|  |     #[doc="    ])"] | ||||||
|  |     #[doc=");"] | ||||||
|  |     #[doc="# }"] | ||||||
|  |     #[doc="```"] | ||||||
|  |     #[doc="```"] | ||||||
|  |     #[doc="# extern crate hyper;"] | ||||||
|  |     #[doc="# #[macro_use] extern crate language_tags;"] | ||||||
|  |     #[doc="# use hyper::header::{Headers, ContentLanguage, qitem};"] | ||||||
|  |     #[doc="# "] | ||||||
|  |     #[doc="# fn main() {"] | ||||||
|     #[doc=""] |     #[doc=""] | ||||||
|     #[doc="let mut headers = Headers::new();"] |     #[doc="let mut headers = Headers::new();"] | ||||||
|     #[doc="headers.set("] |     #[doc="headers.set("] | ||||||
|     #[doc="    ContentLanguage(vec!["] |     #[doc="    ContentLanguage(vec!["] | ||||||
|     #[doc="        qitem("] |     #[doc="        qitem(langtag!(da)),"] | ||||||
|     #[doc="            Language { "] |     #[doc="        qitem(langtag!(en;;;GB)),"] | ||||||
|     #[doc="                 primary: \"en\".to_owned(),"] |  | ||||||
|     #[doc="                 sub: None,"] |  | ||||||
|     #[doc="            }"] |  | ||||||
|     #[doc="        ),"] |  | ||||||
|     #[doc="    ])"] |     #[doc="    ])"] | ||||||
|     #[doc=");"] |     #[doc=");"] | ||||||
|  |     #[doc="# }"] | ||||||
|     #[doc="```"] |     #[doc="```"] | ||||||
|     #[doc="```"] |     (ContentLanguage, "Content-Language") => (QualityItem<LanguageTag>)+ | ||||||
|     #[doc="use hyper::header::{Headers, ContentLanguage, Language, qitem};"] |  | ||||||
|     #[doc=""] |  | ||||||
|     #[doc="let mut headers = Headers::new();"] |  | ||||||
|     #[doc="headers.set("] |  | ||||||
|     #[doc="    ContentLanguage(vec!["] |  | ||||||
|     #[doc="        qitem("] |  | ||||||
|     #[doc="            Language {"] |  | ||||||
|     #[doc="                primary: \"da\".to_owned(),"] |  | ||||||
|     #[doc="                sub: None,"] |  | ||||||
|     #[doc="             }"] |  | ||||||
|     #[doc="        ),"] |  | ||||||
|     #[doc="        qitem("] |  | ||||||
|     #[doc="            Language {"] |  | ||||||
|     #[doc="                primary: \"en\".to_owned(),"] |  | ||||||
|     #[doc="                sub: Some(\"gb\".to_owned()),"] |  | ||||||
|     #[doc="            }"] |  | ||||||
|     #[doc="        ),"] |  | ||||||
|     #[doc="    ])"] |  | ||||||
|     #[doc=");"] |  | ||||||
|     #[doc="```"] |  | ||||||
|     (ContentLanguage, "Content-Language") => (QualityItem<Language>)+ |  | ||||||
|  |  | ||||||
|     test_content_language { |     test_content_language { | ||||||
|         test_header!(test1, vec![b"da"]); |         test_header!(test1, vec![b"da"]); | ||||||
|   | |||||||
| @@ -103,10 +103,12 @@ macro_rules! __hyper__deref { | |||||||
| macro_rules! __hyper__tm { | macro_rules! __hyper__tm { | ||||||
|     ($id:ident, $tm:ident{$($tf:item)*}) => { |     ($id:ident, $tm:ident{$($tf:item)*}) => { | ||||||
|         #[allow(unused_imports)] |         #[allow(unused_imports)] | ||||||
|  |         #[cfg(test)] | ||||||
|         mod $tm{ |         mod $tm{ | ||||||
|             use std::str; |             use std::str; | ||||||
|             use $crate::header::*; |             use $crate::header::*; | ||||||
|             use $crate::mime::*; |             use $crate::mime::*; | ||||||
|  |             use $crate::language_tags::*; | ||||||
|             use $crate::method::Method; |             use $crate::method::Method; | ||||||
|             use super::$id as HeaderField; |             use super::$id as HeaderField; | ||||||
|             $($tf)* |             $($tf)* | ||||||
|   | |||||||
| @@ -1,45 +0,0 @@ | |||||||
| use std::str::FromStr; |  | ||||||
| use std::fmt; |  | ||||||
|  |  | ||||||
| /// A language tag. |  | ||||||
| /// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.10 |  | ||||||
| /// |  | ||||||
| /// Note: This is no complete language tag implementation, it should be replaced with |  | ||||||
| /// github.com/pyfisch/rust-language-tag once it is ready. |  | ||||||
| #[derive(Clone, PartialEq, Debug)] |  | ||||||
| pub struct Language { |  | ||||||
|     /// The language tag |  | ||||||
|     pub primary: String, |  | ||||||
|     /// A language subtag or country code |  | ||||||
|     pub sub: Option<String> |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl FromStr for Language { |  | ||||||
|     type Err = ::Error; |  | ||||||
|     fn from_str(s: &str) -> ::Result<Language> { |  | ||||||
|         let mut i = s.split("-"); |  | ||||||
|         let p = i.next(); |  | ||||||
|         let s = i.next(); |  | ||||||
|         match (p, s) { |  | ||||||
|             (Some(p), Some(s)) => Ok(Language { |  | ||||||
|                 primary: p.to_owned(), |  | ||||||
|                 sub: Some(s.to_owned()) |  | ||||||
|                 }), |  | ||||||
|             (Some(p), _) => Ok(Language { |  | ||||||
|                 primary: p.to_owned(), |  | ||||||
|                 sub: None |  | ||||||
|                 }), |  | ||||||
|             _ => Err(::Error::Header) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl fmt::Display for Language { |  | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |  | ||||||
|         try!(f.write_str(&self.primary[..])); |  | ||||||
|         match self.sub { |  | ||||||
|             Some(ref s) => write!(f, "-{}", s), |  | ||||||
|             None => Ok(()) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -2,12 +2,10 @@ pub use self::charset::Charset; | |||||||
| pub use self::encoding::Encoding; | pub use self::encoding::Encoding; | ||||||
| pub use self::entity::EntityTag; | pub use self::entity::EntityTag; | ||||||
| pub use self::httpdate::HttpDate; | pub use self::httpdate::HttpDate; | ||||||
| pub use self::language::Language; |  | ||||||
| pub use self::quality_item::{Quality, QualityItem, qitem, q}; | pub use self::quality_item::{Quality, QualityItem, qitem, q}; | ||||||
|  |  | ||||||
| mod charset; | mod charset; | ||||||
| mod encoding; | mod encoding; | ||||||
| mod entity; | mod entity; | ||||||
| mod httpdate; | mod httpdate; | ||||||
| mod language; |  | ||||||
| mod quality_item; | mod quality_item; | ||||||
|   | |||||||
| @@ -141,6 +141,9 @@ extern crate traitobject; | |||||||
| extern crate typeable; | extern crate typeable; | ||||||
| extern crate solicit; | extern crate solicit; | ||||||
|  |  | ||||||
|  | #[macro_use] | ||||||
|  | extern crate language_tags; | ||||||
|  |  | ||||||
| #[macro_use] | #[macro_use] | ||||||
| extern crate mime as mime_crate; | extern crate mime as mime_crate; | ||||||
|  |  | ||||||
| @@ -157,6 +160,7 @@ pub use error::{Result, Error}; | |||||||
| pub use method::Method::{Get, Head, Post, Delete}; | pub use method::Method::{Get, Head, Post, Delete}; | ||||||
| pub use status::StatusCode::{Ok, BadRequest, NotFound}; | pub use status::StatusCode::{Ok, BadRequest, NotFound}; | ||||||
| pub use server::Server; | pub use server::Server; | ||||||
|  | pub use language_tags::LanguageTag; | ||||||
|  |  | ||||||
| macro_rules! todo( | macro_rules! todo( | ||||||
|     ($($arg:tt)*) => (if cfg!(not(ndebug)) { |     ($($arg:tt)*) => (if cfg!(not(ndebug)) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user