feat(http): add optional serialization of common types via serde
				
					
				
			This is behind a Cargo feature to avoid forcing downstream users to depend on `serde`. It is needed for Servo IPC to work.
This commit is contained in:
		| @@ -36,10 +36,16 @@ optional = true | ||||
| version = "0.4" | ||||
| default-features = false | ||||
|  | ||||
| [dependencies.serde] | ||||
| version = "*" | ||||
| optional = true | ||||
|  | ||||
| [dev-dependencies] | ||||
| env_logger = "*" | ||||
|  | ||||
| [features] | ||||
| default = ["ssl"] | ||||
| ssl = ["openssl", "cookie/secure"] | ||||
| serde-serialization = ["serde"] | ||||
| nightly = [] | ||||
|  | ||||
|   | ||||
| @@ -158,6 +158,31 @@ macro_rules! test_header { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! __hyper_generate_header_serialization { | ||||
|     ($id:ident) => { | ||||
|         #[cfg(feature = "serde-serialization")] | ||||
|         impl ::serde::Serialize for $id { | ||||
|             fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> | ||||
|                             where S: ::serde::Serializer { | ||||
|                 format!("{}", self).serialize(serializer) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #[cfg(feature = "serde-serialization")] | ||||
|         impl ::serde::Deserialize for $id { | ||||
|             fn deserialize<D>(deserializer: &mut D) -> Result<$id, D::Error> | ||||
|                               where D: ::serde::Deserializer { | ||||
|                 let string_representation: String = | ||||
|                     try!(::serde::Deserialize::deserialize(deserializer)); | ||||
|                 Ok($crate::header::Header::parse_header(&[ | ||||
|                     string_representation.into_bytes() | ||||
|                 ]).unwrap()) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! header { | ||||
|     // $a:meta: Attributes associated with the header item (usually docs) | ||||
| @@ -190,6 +215,8 @@ macro_rules! header { | ||||
|                 self.fmt_header(f) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         __hyper_generate_header_serialization!($id); | ||||
|     }; | ||||
|     // List header, one or more items | ||||
|     ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)+) => { | ||||
| @@ -216,6 +243,7 @@ macro_rules! header { | ||||
|                 self.fmt_header(f) | ||||
|             } | ||||
|         } | ||||
|         __hyper_generate_header_serialization!($id); | ||||
|     }; | ||||
|     // Single value header | ||||
|     ($(#[$a:meta])*($id:ident, $n:expr) => [$value:ty]) => { | ||||
| @@ -241,6 +269,7 @@ macro_rules! header { | ||||
|                 ::std::fmt::Display::fmt(&**self, f) | ||||
|             } | ||||
|         } | ||||
|         __hyper_generate_header_serialization!($id); | ||||
|     }; | ||||
|     // List header, one or more items with "*" option | ||||
|     ($(#[$a:meta])*($id:ident, $n:expr) => {Any / ($item:ty)+}) => { | ||||
| @@ -281,6 +310,7 @@ macro_rules! header { | ||||
|                 self.fmt_header(f) | ||||
|             } | ||||
|         } | ||||
|         __hyper_generate_header_serialization!($id); | ||||
|     }; | ||||
|  | ||||
|     // optional test module | ||||
|   | ||||
| @@ -92,6 +92,13 @@ use unicase::UniCase; | ||||
|  | ||||
| use self::internals::Item; | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| use serde::{Deserialize, Deserializer, Serialize, Serializer}; | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| use serde::de; | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| use serde::ser; | ||||
|  | ||||
| pub use self::shared::*; | ||||
| pub use self::common::*; | ||||
|  | ||||
| @@ -322,6 +329,65 @@ impl fmt::Debug for Headers { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| impl Serialize for Headers { | ||||
|     fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { | ||||
|         struct HeadersVisitor<'a> { | ||||
|             iter: HeadersItems<'a>, | ||||
|             len: usize, | ||||
|         } | ||||
|  | ||||
|         impl<'a> ser::MapVisitor for HeadersVisitor<'a> { | ||||
|             fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error> | ||||
|                         where S: Serializer { | ||||
|                 match self.iter.next() { | ||||
|                     Some(header_item) => { | ||||
|                         try!(serializer.visit_map_elt(header_item.name(), | ||||
|                                                       header_item.value_string())); | ||||
|                         Ok(Some(())) | ||||
|                     } | ||||
|                     None => Ok(None), | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             fn len(&self) -> Option<usize> { | ||||
|                 Some(self.len) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         serializer.visit_map(HeadersVisitor { | ||||
|             iter: self.iter(), | ||||
|             len: self.len(), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| impl Deserialize for Headers { | ||||
|     fn deserialize<D>(deserializer: &mut D) -> Result<Headers, D::Error> where D: Deserializer { | ||||
|         struct HeadersVisitor; | ||||
|  | ||||
|         impl de::Visitor for HeadersVisitor { | ||||
|             type Value = Headers; | ||||
|  | ||||
|             fn visit_map<V>(&mut self, mut visitor: V) -> Result<Headers, V::Error> | ||||
|                             where V: de::MapVisitor { | ||||
|                 let mut result = Headers::new(); | ||||
|                 while let Some((key, value)) = try!(visitor.visit()) { | ||||
|                     let (key, value): (String, String) = (key, value); | ||||
|                     result.set_raw(key, vec![value.into_bytes()]); | ||||
|                 } | ||||
|                 try!(visitor.end()); | ||||
|                 Ok(result) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let result = Headers::new(); | ||||
|         try!(deserializer.visit_map(HeadersVisitor)); | ||||
|         Ok(result) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// An `Iterator` over the fields in a `Headers` map. | ||||
| pub struct HeadersItems<'a> { | ||||
|     inner: Iter<'a, HeaderName, Item> | ||||
|   | ||||
| @@ -7,6 +7,9 @@ use header::Headers; | ||||
| use version::HttpVersion; | ||||
| use version::HttpVersion::{Http10, Http11}; | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| use serde::{Deserialize, Deserializer, Serialize, Serializer}; | ||||
|  | ||||
| pub use self::message::{HttpMessage, RequestHead, ResponseHead, Protocol}; | ||||
|  | ||||
| pub mod h1; | ||||
| @@ -17,6 +20,21 @@ pub mod message; | ||||
| #[derive(Clone, PartialEq, Debug)] | ||||
| pub struct RawStatus(pub u16, pub Cow<'static, str>); | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| impl Serialize for RawStatus { | ||||
|     fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { | ||||
|         (self.0, self.1.clone().into_owned()).serialize(serializer) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| impl Deserialize for RawStatus { | ||||
|     fn deserialize<D>(deserializer: &mut D) -> Result<RawStatus, D::Error> where D: Deserializer { | ||||
|         let representation: (u16, String) = try!(Deserialize::deserialize(deserializer)); | ||||
|         Ok(RawStatus(representation.0, Cow::Owned(representation.1))) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Checks if a connection should be kept alive. | ||||
| #[inline] | ||||
| pub fn should_keep_alive(version: HttpVersion, headers: &Headers) -> bool { | ||||
|   | ||||
| @@ -133,6 +133,8 @@ extern crate time; | ||||
| extern crate url; | ||||
| #[cfg(feature = "openssl")] | ||||
| extern crate openssl; | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| extern crate serde; | ||||
| extern crate cookie; | ||||
| extern crate unicase; | ||||
| extern crate httparse; | ||||
|   | ||||
| @@ -7,6 +7,9 @@ use error::Error; | ||||
| use self::Method::{Options, Get, Post, Put, Delete, Head, Trace, Connect, Patch, | ||||
|                    Extension}; | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| use serde::{Deserialize, Deserializer, Serialize, Serializer}; | ||||
|  | ||||
| /// The Request Method (VERB) | ||||
| /// | ||||
| /// Currently includes 8 variants representing the 8 methods defined in | ||||
| @@ -125,6 +128,21 @@ impl fmt::Display for Method { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| impl Serialize for Method { | ||||
|     fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { | ||||
|         format!("{}", self).serialize(serializer) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "serde-serialization")] | ||||
| impl Deserialize for Method { | ||||
|     fn deserialize<D>(deserializer: &mut D) -> Result<Method, D::Error> where D: Deserializer { | ||||
|         let string_representation: String = try!(Deserialize::deserialize(deserializer)); | ||||
|         Ok(FromStr::from_str(&string_representation[..]).unwrap()) | ||||
|     } | ||||
| }  | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use std::collections::HashMap; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user