feat(mime): upgrade to mime v0.3
The new mime crate has several benefits: - Faster formatting - Easier to use. Most common mime types are now just constants, like `mime::TEXT_PLAIN`. - Proper suffix support. - Extensible without breaking backwards compatiblity. This means we can always add new constants, but before we couldn't add new variants to the enums. - It's now impossible for a `Mime` to contain invalid tokens. Before, with the `Ext(String)` variants, it was possible to create an illegal mime. Closes #738 BREAKING CHANGE: Most uses of `mime` will likely break. There is no more `mime!` macro, nor a `Mime` constructor, nor `TopLevel` and `SubLevel` enums. Instead, in most cases, a constant exists that can now be used. For less common mime types, they can be created by parsing a string.
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| use mime::Mime; | ||||
| use mime::{self, Mime}; | ||||
|  | ||||
| use header::{QualityItem, qitem}; | ||||
|  | ||||
| @@ -24,94 +24,89 @@ header! { | ||||
|     /// ``` | ||||
|     /// | ||||
|     /// # Example values | ||||
|     /// * `audio/*; q=0.2, audio/basic` (`*` value won't parse correctly) | ||||
|     /// * `audio/*; q=0.2, audio/basic` | ||||
|     /// * `text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c` | ||||
|     /// | ||||
|     /// # Examples | ||||
|     /// ``` | ||||
|     /// use hyper::header::{Headers, Accept, qitem}; | ||||
|     /// use hyper::mime::{Mime, TopLevel, SubLevel}; | ||||
|     /// use hyper::mime; | ||||
|     /// | ||||
|     /// let mut headers = Headers::new(); | ||||
|     /// | ||||
|     /// headers.set( | ||||
|     ///     Accept(vec![ | ||||
|     ///         qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), | ||||
|     ///         qitem(mime::TEXT_HTML), | ||||
|     ///     ]) | ||||
|     /// ); | ||||
|     /// ``` | ||||
|     /// ``` | ||||
|     /// use hyper::header::{Headers, Accept, qitem}; | ||||
|     /// use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value}; | ||||
|     /// use hyper::mime; | ||||
|     /// | ||||
|     /// let mut headers = Headers::new(); | ||||
|     /// headers.set( | ||||
|     ///     Accept(vec![ | ||||
|     ///         qitem(Mime(TopLevel::Application, SubLevel::Json, | ||||
|     ///                    vec![(Attr::Charset, Value::Utf8)])), | ||||
|     ///         qitem(mime::APPLICATION_JSON), | ||||
|     ///     ]) | ||||
|     /// ); | ||||
|     /// ``` | ||||
|     /// ``` | ||||
|     /// use hyper::header::{Headers, Accept, QualityItem, q, qitem}; | ||||
|     /// use hyper::mime::{Mime, TopLevel, SubLevel}; | ||||
|     /// use hyper::mime; | ||||
|     /// | ||||
|     /// let mut headers = Headers::new(); | ||||
|     /// | ||||
|     /// headers.set( | ||||
|     ///     Accept(vec![ | ||||
|     ///         qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), | ||||
|     ///         qitem(Mime(TopLevel::Application, | ||||
|     ///                    SubLevel::Ext("xhtml+xml".to_owned()), vec![])), | ||||
|     ///         QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), | ||||
|     ///                          q(900)), | ||||
|     ///                          qitem(Mime(TopLevel::Image, | ||||
|     ///                                     SubLevel::Ext("webp".to_owned()), vec![])), | ||||
|     ///                          QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), | ||||
|     ///                                           q(800)) | ||||
|     ///         qitem(mime::TEXT_HTML), | ||||
|     ///         qitem("application/xhtml+xml".parse().unwrap()), | ||||
|     ///         QualityItem::new( | ||||
|     ///             mime::TEXT_XML, | ||||
|     ///             q(900) | ||||
|     ///         ), | ||||
|     ///         qitem("image/webp".parse().unwrap()), | ||||
|     ///         QualityItem::new( | ||||
|     ///             mime::STAR_STAR, | ||||
|     ///             q(800) | ||||
|     ///         ), | ||||
|     ///     ]) | ||||
|     /// ); | ||||
|     /// ``` | ||||
|     /// | ||||
|     /// # Notes | ||||
|     /// * Using always Mime types to represent `media-range` differs from the ABNF. | ||||
|     /// * **FIXME**: `accept-ext` is not supported. | ||||
|     (Accept, "Accept") => (QualityItem<Mime>)+ | ||||
|  | ||||
|     test_accept { | ||||
|         // Tests from the RFC | ||||
|         // FIXME: Test fails, first value containing a "*" fails to parse | ||||
|         // test_header!( | ||||
|         //    test1, | ||||
|         //    vec![b"audio/*; q=0.2, audio/basic"], | ||||
|         //    Some(HeaderField(vec![ | ||||
|         //        QualityItem::new(Mime(TopLevel::Audio, SubLevel::Star, vec![]), q(200)), | ||||
|         //        qitem(Mime(TopLevel::Audio, SubLevel::Ext("basic".to_owned()), vec![])), | ||||
|         //        ]))); | ||||
|          test_header!( | ||||
|             test1, | ||||
|             vec![b"audio/*; q=0.2, audio/basic"], | ||||
|             Some(HeaderField(vec![ | ||||
|                 QualityItem::new("audio/*".parse().unwrap(), q(200)), | ||||
|                 qitem("audio/basic".parse().unwrap()), | ||||
|                 ]))); | ||||
|         test_header!( | ||||
|             test2, | ||||
|             vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"], | ||||
|             Some(HeaderField(vec![ | ||||
|                 QualityItem::new(Mime(TopLevel::Text, SubLevel::Plain, vec![]), q(500)), | ||||
|                 qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), | ||||
|                 QualityItem::new(TEXT_PLAIN, q(500)), | ||||
|                 qitem(TEXT_HTML), | ||||
|                 QualityItem::new( | ||||
|                     Mime(TopLevel::Text, SubLevel::Ext("x-dvi".to_owned()), vec![]), | ||||
|                     "text/x-dvi".parse().unwrap(), | ||||
|                     q(800)), | ||||
|                 qitem(Mime(TopLevel::Text, SubLevel::Ext("x-c".to_owned()), vec![])), | ||||
|                 qitem("text/x-c".parse().unwrap()), | ||||
|                 ]))); | ||||
|         // Custom tests | ||||
|         test_header!( | ||||
|             test3, | ||||
|             vec![b"text/plain; charset=utf-8"], | ||||
|             Some(Accept(vec![ | ||||
|                 qitem(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])), | ||||
|                 qitem(TEXT_PLAIN_UTF_8), | ||||
|                 ]))); | ||||
|         test_header!( | ||||
|             test4, | ||||
|             vec![b"text/plain; charset=utf-8; q=0.5"], | ||||
|             Some(Accept(vec![ | ||||
|                 QualityItem::new(Mime(TopLevel::Text, | ||||
|                     SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]), | ||||
|                 QualityItem::new(TEXT_PLAIN_UTF_8, | ||||
|                     q(500)), | ||||
|             ]))); | ||||
|  | ||||
| @@ -127,22 +122,22 @@ header! { | ||||
| impl Accept { | ||||
|     /// A constructor to easily create `Accept: */*`. | ||||
|     pub fn star() -> Accept { | ||||
|         Accept(vec![qitem(mime!(Star/Star))]) | ||||
|         Accept(vec![qitem(mime::STAR_STAR)]) | ||||
|     } | ||||
|  | ||||
|     /// A constructor to easily create `Accept: application/json`. | ||||
|     pub fn json() -> Accept { | ||||
|         Accept(vec![qitem(mime!(Application/Json))]) | ||||
|         Accept(vec![qitem(mime::APPLICATION_JSON)]) | ||||
|     } | ||||
|  | ||||
|     /// A constructor to easily create `Accept: text/*`. | ||||
|     pub fn text() -> Accept { | ||||
|         Accept(vec![qitem(mime!(Text/Star))]) | ||||
|         Accept(vec![qitem(mime::TEXT_STAR)]) | ||||
|     } | ||||
|  | ||||
|     /// A constructor to easily create `Accept: image/*`. | ||||
|     pub fn image() -> Accept { | ||||
|         Accept(vec![qitem(mime!(Image/Star))]) | ||||
|         Accept(vec![qitem(mime::IMAGE_STAR)]) | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| use mime::Mime; | ||||
| use mime::{self, Mime}; | ||||
|  | ||||
| header! { | ||||
|     /// `Content-Type` header, defined in | ||||
| @@ -22,7 +22,8 @@ header! { | ||||
|     /// ``` | ||||
|     /// | ||||
|     /// # Example values | ||||
|     /// * `text/html; charset=ISO-8859-4` | ||||
|     /// * `text/html; charset=utf-8` | ||||
|     /// * `application/json | ||||
|     /// | ||||
|     /// # Examples | ||||
|     /// ``` | ||||
| @@ -36,13 +37,12 @@ header! { | ||||
|     /// ``` | ||||
|     /// ``` | ||||
|     /// use hyper::header::{Headers, ContentType}; | ||||
|     /// use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value}; | ||||
|     /// use hyper::mime; | ||||
|     /// | ||||
|     /// let mut headers = Headers::new(); | ||||
|     /// | ||||
|     /// headers.set( | ||||
|     ///     ContentType(Mime(TopLevel::Text, SubLevel::Html, | ||||
|     ///                      vec![(Attr::Charset, Value::Utf8)])) | ||||
|     ///     ContentType(mime::TEXT_HTML) | ||||
|     /// ); | ||||
|     /// ``` | ||||
|     (ContentType, "Content-Type") => [Mime] | ||||
| @@ -50,13 +50,8 @@ header! { | ||||
|     test_content_type { | ||||
|         test_header!( | ||||
|             test1, | ||||
|             // FIXME: Should be b"text/html; charset=ISO-8859-4" but mime crate lowercases | ||||
|             // the whole value so parsing and formatting the value gives a different result | ||||
|             vec![b"text/html; charset=iso-8859-4"], | ||||
|             Some(HeaderField(Mime( | ||||
|                 TopLevel::Text, | ||||
|                 SubLevel::Html, | ||||
|                 vec![(Attr::Charset, Value::Ext("iso-8859-4".to_owned()))])))); | ||||
|             vec![b"text/html"], | ||||
|             Some(HeaderField(TEXT_HTML))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -64,45 +59,45 @@ impl ContentType { | ||||
|     /// A constructor  to easily create a `Content-Type: application/json` header. | ||||
|     #[inline] | ||||
|     pub fn json() -> ContentType { | ||||
|         ContentType(mime!(Application/Json)) | ||||
|         ContentType(mime::APPLICATION_JSON) | ||||
|     } | ||||
|  | ||||
|     /// A constructor  to easily create a `Content-Type: text/plain; charset=utf-8` header. | ||||
|     #[inline] | ||||
|     pub fn plaintext() -> ContentType { | ||||
|         ContentType(mime!(Text/Plain; Charset=Utf8)) | ||||
|         ContentType(mime::TEXT_PLAIN_UTF_8) | ||||
|     } | ||||
|  | ||||
|     /// A constructor  to easily create a `Content-Type: text/html; charset=utf-8` header. | ||||
|     #[inline] | ||||
|     pub fn html() -> ContentType { | ||||
|         ContentType(mime!(Text/Html; Charset=Utf8)) | ||||
|         ContentType(mime::TEXT_HTML) | ||||
|     } | ||||
|  | ||||
|     /// A constructor  to easily create a `Content-Type: application/www-form-url-encoded` header. | ||||
|     #[inline] | ||||
|     pub fn form_url_encoded() -> ContentType { | ||||
|         ContentType(mime!(Application/WwwFormUrlEncoded)) | ||||
|         ContentType(mime::APPLICATION_WWW_FORM_URLENCODED) | ||||
|     } | ||||
|     /// A constructor  to easily create a `Content-Type: image/jpeg` header. | ||||
|     #[inline] | ||||
|     pub fn jpeg() -> ContentType { | ||||
|         ContentType(mime!(Image/Jpeg)) | ||||
|         ContentType(mime::IMAGE_JPEG) | ||||
|     } | ||||
|  | ||||
|     /// A constructor  to easily create a `Content-Type: image/png` header. | ||||
|     #[inline] | ||||
|     pub fn png() -> ContentType { | ||||
|         ContentType(mime!(Image/Png)) | ||||
|         ContentType(mime::IMAGE_PNG) | ||||
|     } | ||||
|  | ||||
|     /// A constructor  to easily create a `Content-Type: application/octet-stream` header. | ||||
|     #[inline] | ||||
|     pub fn octet_stream() -> ContentType { | ||||
|         ContentType(mime!(Application/OctetStream)) | ||||
|         ContentType(mime::APPLICATION_OCTET_STREAM) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Eq for ContentType {} | ||||
|  | ||||
| bench_header!(bench, ContentType, { vec![b"application/json; charset=utf-8".to_vec()] }); | ||||
| bench_header!(bench, ContentType, { vec![b"application/json".to_vec()] }); | ||||
|   | ||||
| @@ -905,9 +905,7 @@ mod tests { | ||||
|     use http::{ServerTransaction, Http1Transaction}; | ||||
|     use bytes::BytesMut; | ||||
|  | ||||
|     use mime::Mime; | ||||
|     use mime::TopLevel::Text; | ||||
|     use mime::SubLevel::Plain; | ||||
|     use mime; | ||||
|  | ||||
|     #[test] | ||||
|     fn test_link() { | ||||
| @@ -956,7 +954,7 @@ mod tests { | ||||
|             .push_media_desc(MediaDesc::Screen) | ||||
|             .set_title("previous chapter") | ||||
|             .set_title_star("title* unparsed") | ||||
|             .set_media_type(Mime(Text, Plain, vec![])); | ||||
|             .set_media_type(mime::TEXT_PLAIN); | ||||
|  | ||||
|         let link_header = b"<http://example.com/TheBook/chapter2>; \ | ||||
|             rel=\"previous\"; anchor=\"../anchor/example/\"; \ | ||||
| @@ -1015,7 +1013,7 @@ mod tests { | ||||
|             .push_media_desc(MediaDesc::Screen) | ||||
|             .set_title("previous chapter") | ||||
|             .set_title_star("title* unparsed") | ||||
|             .set_media_type(Mime(Text, Plain, vec![])); | ||||
|             .set_media_type(mime::TEXT_PLAIN); | ||||
|  | ||||
|         let link = Link::new(vec![link_value]); | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| //! ## Mime | ||||
| //! | ||||
| //! Several header fields use MIME values for their contents. Keeping with the | ||||
| //! strongly-typed theme, the [mime](http://seanmonstar.github.io/mime.rs) crate | ||||
| //! strongly-typed theme, the [mime](https://docs.rs/mime) crate | ||||
| //! is used, such as `ContentType(pub Mime)`. | ||||
|  | ||||
| pub use self::accept::Accept; | ||||
|   | ||||
| @@ -696,11 +696,7 @@ impl PartialEq<HeaderName> for str { | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use std::fmt; | ||||
|     use mime::Mime; | ||||
|     use mime::TopLevel::Text; | ||||
|     use mime::SubLevel::Plain; | ||||
|     use super::{Headers, Header, Raw, ContentLength, ContentType, | ||||
|                 Accept, Host, qitem, SetCookie}; | ||||
|     use super::{Headers, Header, Raw, ContentLength, ContentType, Host, SetCookie}; | ||||
|  | ||||
|     #[cfg(feature = "nightly")] | ||||
|     use test::Bencher; | ||||
| @@ -723,25 +719,6 @@ mod tests { | ||||
|         assert_eq!(headers.get(), Some(&ContentLength(10))); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_content_type() { | ||||
|         let content_type = Header::parse_header(&b"text/plain".as_ref().into()); | ||||
|         assert_eq!(content_type.ok(), Some(ContentType(Mime(Text, Plain, vec![])))); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_accept() { | ||||
|         let text_plain = qitem(Mime(Text, Plain, vec![])); | ||||
|         let application_vendor = "application/vnd.github.v3.full+json; q=0.5".parse().unwrap(); | ||||
|  | ||||
|         let accept = Header::parse_header(&b"text/plain".as_ref().into()); | ||||
|         assert_eq!(accept.ok(), Some(Accept(vec![text_plain.clone()]))); | ||||
|  | ||||
|         let bytevec = b"application/vnd.github.v3.full+json; q=0.5, text/plain".as_ref().into(); | ||||
|         let accept = Header::parse_header(&bytevec); | ||||
|         assert_eq!(accept.ok(), Some(Accept(vec![application_vendor, text_plain]))); | ||||
|     } | ||||
|  | ||||
|     #[derive(Clone, PartialEq, Debug)] | ||||
|     struct CrazyLength(Option<bool>, usize); | ||||
|  | ||||
| @@ -882,7 +859,7 @@ mod tests { | ||||
|         let mut headers = Headers::new(); | ||||
|         headers.set(ContentLength(10)); | ||||
|         assert_eq!(headers.len(), 1); | ||||
|         headers.set(ContentType(Mime(Text, Plain, vec![]))); | ||||
|         headers.set(ContentType::json()); | ||||
|         assert_eq!(headers.len(), 2); | ||||
|         // Redundant, should not increase count. | ||||
|         headers.set(ContentLength(20)); | ||||
| @@ -893,7 +870,7 @@ mod tests { | ||||
|     fn test_clear() { | ||||
|         let mut headers = Headers::new(); | ||||
|         headers.set(ContentLength(10)); | ||||
|         headers.set(ContentType(Mime(Text, Plain, vec![]))); | ||||
|         headers.set(ContentType::json()); | ||||
|         assert_eq!(headers.len(), 2); | ||||
|         headers.clear(); | ||||
|         assert_eq!(headers.len(), 0); | ||||
|   | ||||
| @@ -20,7 +20,7 @@ extern crate futures_cpupool; | ||||
| extern crate httparse; | ||||
| extern crate language_tags; | ||||
| #[macro_use] extern crate log; | ||||
| #[macro_use] pub extern crate mime; | ||||
| pub extern crate mime; | ||||
| extern crate base64; | ||||
| extern crate time; | ||||
| extern crate tokio_core as tokio; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user