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}; | ||||
|     /// | ||||
|     /// 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}; | ||||
|     /// | ||||
|     /// 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 | ||||
|     (Location, "Location") => [String] | ||||
|     (Location, "Location") => Cow[str] | ||||
|  | ||||
|     test_location { | ||||
|         // 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 | ||||
|     ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+}) => { | ||||
|         $(#[$a])* | ||||
| @@ -329,6 +364,14 @@ macro_rules! header { | ||||
|  | ||||
|         __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)*}) => { | ||||
|         header! { | ||||
|             $(#[$a])* | ||||
|   | ||||
| @@ -21,16 +21,16 @@ header! { | ||||
|     /// use hyper::header::{Headers, Referer}; | ||||
|     /// | ||||
|     /// 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}; | ||||
|     /// | ||||
|     /// 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 | ||||
|     (Referer, "Referer") => [String] | ||||
|     (Referer, "Referer") => Cow[str] | ||||
|  | ||||
|     test_referer { | ||||
|         // Testcase from the RFC | ||||
|   | ||||
| @@ -22,10 +22,10 @@ header! { | ||||
|     /// use hyper::header::{Headers, Server}; | ||||
|     /// | ||||
|     /// 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? | ||||
|     (Server, "Server") => [String] | ||||
|     (Server, "Server") => Cow[str] | ||||
|  | ||||
|     test_server { | ||||
|         // Testcase from RFC | ||||
|   | ||||
| @@ -29,14 +29,14 @@ header! { | ||||
|     /// use hyper::header::{Headers, UserAgent}; | ||||
|     /// | ||||
|     /// 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 { | ||||
|         // Testcase from RFC | ||||
|         test_header!(test1, vec![b"CERN-LineMode/2.15 libwww/2.17b3"]); | ||||
|         // 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}; | ||||
|  | ||||
|     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::<UserAgent>(), agent.get_type()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user