diff --git a/Cargo.toml b/Cargo.toml index 2fe9490..45d2c14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,13 +16,16 @@ travis-ci = { repository = "nox/hyper_serde" } doctest = false [dependencies] -cookie = {version = "0.10", default-features = false} -hyper = "0.10" -mime = "0.2" +cookie = {version = "0.11", default-features = false} +http = "0.1" +hyper = { version = "0.12" } +mime = "0.3" serde = "1.0" serde_bytes = "0.10" time = "0.1" +headers-ext = { git = "https://github.com/hyperium/headers.git", branch = "ng" } [dev-dependencies] serde_test = "1.0" time = "0.1" + diff --git a/src/lib.rs b/src/lib.rs index 92b3af0..7edc02e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,10 +4,10 @@ //! The supported types are: //! //! * `cookie::Cookie` -//! * `hyper::header::ContentType` +//! * `headers_ext::ContentType` //! * `hyper::header::Headers` -//! * `hyper::http::RawStatus` -//! * `hyper::method::Method` +//! * `hyper::RawStatus` +//! * `hyper::Method` //! * `mime::Mime` //! * `time::Tm` //! @@ -54,25 +54,30 @@ #![deny(unsafe_code)] extern crate cookie; +extern crate http; extern crate hyper; extern crate mime; extern crate serde; extern crate serde_bytes; extern crate time; +extern crate headers_ext; use cookie::Cookie; -use hyper::header::{ContentType, Headers}; -use hyper::http::RawStatus; -use hyper::method::Method; +use headers_ext::ContentType; +use hyper::StatusCode; +use hyper::header::{HeaderName, HeaderValue}; +use http::HeaderMap; +use hyper::Method; use mime::Mime; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_bytes::{ByteBuf, Bytes}; -use serde::de::{self, MapAccess, SeqAccess, Visitor}; +use serde::de::{self, MapAccess, SeqAccess, Visitor, Error}; use serde::ser::{SerializeMap, SerializeSeq}; use std::cmp; use std::fmt; use std::ops::{Deref, DerefMut}; use std::str; +use std::str::FromStr; use time::{Tm, strptime}; /// Deserialises a `T` value with a given deserializer. @@ -262,7 +267,7 @@ impl<'de> Deserialize<'de> for De { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - deserialize(deserializer).map(ContentType).map(De::new) + deserialize(deserializer).map(|v: mime::Mime| ContentType::from(v)).map(De::new) } } @@ -270,7 +275,7 @@ impl<'a> Serialize for Ser<'a, ContentType> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - serialize(&self.v.0, serializer) + serialize(&mime::Mime::from(self.v.clone()), serializer) } } @@ -309,14 +314,15 @@ impl<'a, 'cookie> Serialize for Ser<'a, Cookie<'cookie>> { } } -impl<'de> Deserialize<'de> for De { + +impl<'de> Deserialize<'de> for De { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct HeadersVisitor; impl<'de> Visitor<'de> for HeadersVisitor { - type Value = De; + type Value = De; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a map from header names to header values") @@ -325,7 +331,7 @@ impl<'de> Deserialize<'de> for De { fn visit_unit(self) -> Result where E: de::Error, { - Ok(De::new(Headers::new())) + Ok(De::new(HeaderMap::new())) } fn visit_map(self, @@ -333,9 +339,11 @@ impl<'de> Deserialize<'de> for De { -> Result where V: MapAccess<'de>, { - let mut headers = Headers::new(); - while let Some((k, v)) = visitor.next_entry::()? { - headers.set_raw(k, v.0); + let mut headers = HeaderMap::new(); + while let Some((k, values)) = visitor.next_entry::()? { + for v in values.0.iter() { + headers.append(HeaderName::from_str(&k).map_err(V::Error::custom)?, HeaderValue::from_bytes(&v).map_err(V::Error::custom)?); + } } Ok(De::new(headers)) } @@ -383,7 +391,7 @@ impl<'de> Deserialize<'de> for De { } } -impl<'a> Serialize for Ser<'a, Headers> { +impl<'a> Serialize for Ser<'a, HeaderMap> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { @@ -408,11 +416,10 @@ impl<'a> Serialize for Ser<'a, Headers> { } } - let mut serializer = serializer.serialize_map(Some(self.v.len()))?; - for header in self.v.iter() { - let name = header.name(); - let value = self.v.get_raw(name).unwrap(); - serializer.serialize_entry(name, &Value(value, self.pretty))?; + let mut serializer = serializer.serialize_map(Some(self.v.keys_len()))?; + for name in self.v.keys() { + let values = self.v.get_all(name); + serializer.serialize_entry(name.as_str(), &Value(&values.iter().map(|v| v.as_bytes().iter().cloned().collect()).collect::>>(), self.pretty))?; } serializer.end() } @@ -466,7 +473,7 @@ impl<'de> Deserialize<'de> for De { fn visit_str(self, v: &str) -> Result where E: de::Error, { - v.parse::().map(De::new).map_err(|()| { + v.parse::().map(De::new).map_err(|_| { E::custom("could not parse mime type") }) } @@ -484,20 +491,63 @@ impl<'a> Serialize for Ser<'a, Mime> { } } -impl<'de> Deserialize<'de> for De { +impl<'de> Deserialize<'de> for De { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - let (code, reason) = Deserialize::deserialize(deserializer)?; - Ok(De::new(RawStatus(code, reason))) + let code = Deserialize::deserialize(deserializer)?; + Ok(De::new(StatusCode::from_u16(code).map_err(D::Error::custom)?)) + } +} + +impl<'a> Serialize for Ser<'a, StatusCode> { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + self.v.as_u16().serialize(serializer) } } -impl<'a> Serialize for Ser<'a, RawStatus> { +impl<'a> Serialize for Ser<'a, (StatusCode, String)> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - (self.v.0, &self.v.1).serialize(serializer) + let mut serializer = serializer.serialize_seq(Some(2))?; + serializer.serialize_element(&Ser::new(&self.v.0))?; + serializer.serialize_element(&self.v.1)?; + serializer.end() + } +} + +impl<'de> Deserialize<'de> for De<(StatusCode, String)> { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de>, + { + Ok(De::new(deserializer.deserialize_seq(StatusVisitor)?)) + } +} + +struct StatusVisitor; + +impl<'de> Visitor<'de> for StatusVisitor { + type Value = (StatusCode, String); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "an array containing a status code and a reason string") + } + + fn visit_seq(self, mut visitor: V) -> Result + where V: SeqAccess<'de>, + { + + let code = visitor.next_element::()?.ok_or_else(|| + V::Error::custom("Can't find the status code") + )?; + let code = StatusCode::from_u16(code).map_err(V::Error::custom)?; + let reason = visitor.next_element::()?.ok_or_else(|| + V::Error::custom("Can't find the reason string") + )?; + Ok((code, reason)) } } diff --git a/tests/supported.rs b/tests/supported.rs index 6e2fa84..bdeea68 100644 --- a/tests/supported.rs +++ b/tests/supported.rs @@ -7,8 +7,8 @@ extern crate time; use cookie::Cookie; use hyper::header::{ContentType, Headers}; -use hyper::http::RawStatus; -use hyper::method::Method; +use hyper::RawStatus; +use hyper::Method; use hyper_serde::{De, Ser, Serde}; use mime::Mime; use serde::{Deserialize, Serialize}; diff --git a/tests/tokens.rs b/tests/tokens.rs index b05c369..f19c185 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -1,16 +1,14 @@ extern crate cookie; extern crate hyper; extern crate hyper_serde; -#[macro_use] -extern crate mime; extern crate serde; extern crate serde_test; extern crate time; use cookie::Cookie; use hyper::header::{ContentType, Headers}; -use hyper::http::RawStatus; -use hyper::method::Method; +use hyper::RawStatus; +use hyper::Method; use hyper_serde::{De, Ser, deserialize}; use serde::Deserialize; use serde_test::{Deserializer, Token, assert_ser_tokens}; @@ -19,7 +17,7 @@ use time::Duration; #[test] fn test_content_type() { - let content_type = ContentType(mime!(Application / Json)); + let content_type = ContentType("Application/Json".parse().unwrap()); let tokens = &[Token::Str("application/json")]; assert_ser_tokens(&Ser::new(&content_type), tokens); @@ -58,10 +56,10 @@ fn test_headers_not_empty() { use hyper::header::Host; let mut headers = Headers::new(); - headers.set(Host { - hostname: "baguette".to_owned(), - port: None, - }); + headers.set(Host::new( + "baguette", + None + )); // In Hyper 0.9, Headers is internally a HashMap and thus testing this // with multiple headers is non-deterministic.