refactor(header): make some headers more allocator friendly
Change the internal implementation of some simple headers to make them more allocator friendly. Also add a constructor method to allow changing the implementation in the future again. The headers are: - Location - Referrer - Server - UserAgent This change was suggested in [#1104]. BREAKING CHANGES: - Old code that creates the header structs directly will stop working. - It's not possible to implement DerefMut for a Cow<'static,str>. Code that needs to modify header after creation will stop working.
This commit is contained in:
		| @@ -21,16 +21,16 @@ header! { | |||||||
|     /// use hyper::header::{Headers, Location}; |     /// use hyper::header::{Headers, Location}; | ||||||
|     /// |     /// | ||||||
|     /// let mut headers = Headers::new(); |     /// let mut headers = Headers::new(); | ||||||
|     /// headers.set(Location("/People.html#tim".to_owned())); |     /// headers.set(Location::new("/People.html#tim")); | ||||||
|     /// ``` |     /// ``` | ||||||
|     /// ``` |     /// ``` | ||||||
|     /// use hyper::header::{Headers, Location}; |     /// use hyper::header::{Headers, Location}; | ||||||
|     /// |     /// | ||||||
|     /// let mut headers = Headers::new(); |     /// let mut headers = Headers::new(); | ||||||
|     /// headers.set(Location("http://www.example.com/index.html".to_owned())); |     /// headers.set(Location::new("http://www.example.com/index.html")); | ||||||
|     /// ``` |     /// ``` | ||||||
|     // TODO: Use URL |     // TODO: Use URL | ||||||
|     (Location, "Location") => [String] |     (Location, "Location") => Cow[str] | ||||||
|  |  | ||||||
|     test_location { |     test_location { | ||||||
|         // Testcase from RFC |         // Testcase from RFC | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ macro_rules! header { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |     // Single value cow header | ||||||
|  |     ($(#[$a:meta])*($id:ident, $n:expr) => Cow[$value:ty]) => { | ||||||
|  |         $(#[$a])* | ||||||
|  |         #[derive(Clone, Debug, PartialEq)] | ||||||
|  |         pub struct $id(::std::borrow::Cow<'static,$value>); | ||||||
|  |         impl $id { | ||||||
|  |             /// Creates a new $id | ||||||
|  |             pub fn new<I: Into<::std::borrow::Cow<'static,$value>>>(value: I) -> Self { | ||||||
|  |                 $id(value.into()) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         impl ::std::ops::Deref for $id { | ||||||
|  |             type Target = $value; | ||||||
|  |             fn deref(&self) -> &Self::Target { | ||||||
|  |                 &(self.0) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         impl $crate::header::Header for $id { | ||||||
|  |             fn header_name() -> &'static str { | ||||||
|  |                 static NAME: &'static str = $n; | ||||||
|  |                 NAME | ||||||
|  |             } | ||||||
|  |             fn parse_header(raw: &$crate::header::Raw) -> $crate::Result<Self> { | ||||||
|  |                 $crate::header::parsing::from_one_raw_str::<<$value as ::std::borrow::ToOwned>::Owned>(raw).map($id::new) | ||||||
|  |             } | ||||||
|  |             fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||||
|  |                 ::std::fmt::Display::fmt(&**self, f) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         impl ::std::fmt::Display for $id { | ||||||
|  |             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||||
|  |                 ::std::fmt::Display::fmt(&**self, f) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|     // List header, one or more items with "*" option |     // List header, one or more items with "*" option | ||||||
|     ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+}) => { |     ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+}) => { | ||||||
|         $(#[$a])* |         $(#[$a])* | ||||||
| @@ -329,6 +364,14 @@ macro_rules! header { | |||||||
|  |  | ||||||
|         __hyper__tm! { $id, $tm { $($tf)* }} |         __hyper__tm! { $id, $tm { $($tf)* }} | ||||||
|     }; |     }; | ||||||
|  |     ($(#[$a:meta])*($id:ident, $n:expr) => Cow[$item:ty] $tm:ident{$($tf:item)*}) => { | ||||||
|  |         header! { | ||||||
|  |             $(#[$a])* | ||||||
|  |             ($id, $n) => Cow[$item] | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         __hyper__tm! { $id, $tm { $($tf)* }} | ||||||
|  |     }; | ||||||
|     ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+} $tm:ident{$($tf:item)*}) => { |     ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+} $tm:ident{$($tf:item)*}) => { | ||||||
|         header! { |         header! { | ||||||
|             $(#[$a])* |             $(#[$a])* | ||||||
|   | |||||||
| @@ -21,16 +21,16 @@ header! { | |||||||
|     /// use hyper::header::{Headers, Referer}; |     /// use hyper::header::{Headers, Referer}; | ||||||
|     /// |     /// | ||||||
|     /// let mut headers = Headers::new(); |     /// let mut headers = Headers::new(); | ||||||
|     /// headers.set(Referer("/People.html#tim".to_owned())); |     /// headers.set(Referer::new("/People.html#tim")); | ||||||
|     /// ``` |     /// ``` | ||||||
|     /// ``` |     /// ``` | ||||||
|     /// use hyper::header::{Headers, Referer}; |     /// use hyper::header::{Headers, Referer}; | ||||||
|     /// |     /// | ||||||
|     /// let mut headers = Headers::new(); |     /// let mut headers = Headers::new(); | ||||||
|     /// headers.set(Referer("http://www.example.com/index.html".to_owned())); |     /// headers.set(Referer::new("http://www.example.com/index.html")); | ||||||
|     /// ``` |     /// ``` | ||||||
|     // TODO Use URL |     // TODO Use URL | ||||||
|     (Referer, "Referer") => [String] |     (Referer, "Referer") => Cow[str] | ||||||
|  |  | ||||||
|     test_referer { |     test_referer { | ||||||
|         // Testcase from the RFC |         // Testcase from the RFC | ||||||
|   | |||||||
| @@ -22,10 +22,10 @@ header! { | |||||||
|     /// use hyper::header::{Headers, Server}; |     /// use hyper::header::{Headers, Server}; | ||||||
|     /// |     /// | ||||||
|     /// let mut headers = Headers::new(); |     /// let mut headers = Headers::new(); | ||||||
|     /// headers.set(Server("hyper/0.5.2".to_owned())); |     /// headers.set(Server::new("hyper/0.5.2")); | ||||||
|     /// ``` |     /// ``` | ||||||
|     // TODO: Maybe parse as defined in the spec? |     // TODO: Maybe parse as defined in the spec? | ||||||
|     (Server, "Server") => [String] |     (Server, "Server") => Cow[str] | ||||||
|  |  | ||||||
|     test_server { |     test_server { | ||||||
|         // Testcase from RFC |         // Testcase from RFC | ||||||
|   | |||||||
| @@ -29,14 +29,14 @@ header! { | |||||||
|     /// use hyper::header::{Headers, UserAgent}; |     /// use hyper::header::{Headers, UserAgent}; | ||||||
|     /// |     /// | ||||||
|     /// let mut headers = Headers::new(); |     /// let mut headers = Headers::new(); | ||||||
|     /// headers.set(UserAgent("hyper/0.5.2".to_owned())); |     /// headers.set(UserAgent::new("hyper/0.5.2")); | ||||||
|     /// ``` |     /// ``` | ||||||
|     (UserAgent, "User-Agent") => [String] |     (UserAgent, "User-Agent") => Cow[str] | ||||||
|  |  | ||||||
|     test_user_agent { |     test_user_agent { | ||||||
|         // Testcase from RFC |         // Testcase from RFC | ||||||
|         test_header!(test1, vec![b"CERN-LineMode/2.15 libwww/2.17b3"]); |         test_header!(test1, vec![b"CERN-LineMode/2.15 libwww/2.17b3"]); | ||||||
|         // Own testcase |         // Own testcase | ||||||
|         test_header!(test2, vec![b"Bunnies"], Some(UserAgent("Bunnies".to_owned()))); |         test_header!(test2, vec![b"Bunnies"], Some(UserAgent::new("Bunnies"))); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -148,7 +148,7 @@ fn test_get_type() { | |||||||
|     use ::header::{ContentLength, UserAgent}; |     use ::header::{ContentLength, UserAgent}; | ||||||
|  |  | ||||||
|     let len = ContentLength(5); |     let len = ContentLength(5); | ||||||
|     let agent = UserAgent("hyper".to_owned()); |     let agent = UserAgent::new("hyper"); | ||||||
|  |  | ||||||
|     assert_eq!(TypeId::of::<ContentLength>(), len.get_type()); |     assert_eq!(TypeId::of::<ContentLength>(), len.get_type()); | ||||||
|     assert_eq!(TypeId::of::<UserAgent>(), agent.get_type()); |     assert_eq!(TypeId::of::<UserAgent>(), agent.get_type()); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user