diff --git a/Cargo.toml b/Cargo.toml index c356ece7..d293bff7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_urlencoded" -version = "0.4.3" +version = "0.5.0" authors = ["Anthony Ramine "] license = "MIT/Apache-2.0" repository = "https://github.com/nox/serde_urlencoded" @@ -18,5 +18,5 @@ test = false [dependencies] dtoa = "0.4.0" itoa = "0.3.0" -serde = "0.9.3" +serde = "1.0.0" url = "1.0.0" diff --git a/src/de.rs b/src/de.rs index 10015487..9eec6a94 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,16 +1,15 @@ //! Deserialization support for the `application/x-www-form-urlencoded` format. -use serde::de; -use serde::de::value::{MapDeserializer, ValueDeserializer as SerdeValueDeserializer}; +use serde::de::{self, IntoDeserializer}; + +use serde::de::value::MapDeserializer; +use std::borrow::Cow; +use std::io::Read; +use url::form_urlencoded::Parse as UrlEncodedParse; +use url::form_urlencoded::parse; #[doc(inline)] pub use serde::de::value::Error; -use std::borrow::Cow; -use std::io::Read; -use std::iter::Map; -use std::marker::PhantomData; -use url::form_urlencoded::Parse as UrlEncodedParse; -use url::form_urlencoded::parse; /// Deserializes a `application/x-wwww-url-encoded` value from a `&[u8]`. /// @@ -27,7 +26,9 @@ use url::form_urlencoded::parse; /// b"bread=baguette&cheese=comt%C3%A9&meat=ham&fat=butter"), /// Ok(meal)); /// ``` -pub fn from_bytes(input: &[u8]) -> Result { +pub fn from_bytes<'de, T>(input: &'de [u8]) -> Result + where T: de::Deserialize<'de>, +{ T::deserialize(Deserializer::new(parse(input))) } @@ -46,14 +47,16 @@ pub fn from_bytes(input: &[u8]) -> Result { /// "bread=baguette&cheese=comt%C3%A9&meat=ham&fat=butter"), /// Ok(meal)); /// ``` -pub fn from_str(input: &str) -> Result { +pub fn from_str<'de, T>(input: &'de str) -> Result + where T: de::Deserialize<'de>, +{ from_bytes(input.as_bytes()) } /// Convenience function that reads all bytes from `reader` and deserializes /// them with `from_bytes`. pub fn from_reader(mut reader: R) -> Result - where T: de::Deserialize, + where T: de::DeserializeOwned, R: Read, { let mut buf = vec![]; @@ -73,53 +76,41 @@ pub fn from_reader(mut reader: R) -> Result /// /// * Everything else but `deserialize_seq` and `deserialize_seq_fixed_size` /// defers to `deserialize`. -pub struct Deserializer<'a> { - inner: MapDeserializer, - fn((Cow<'a, str>, Cow<'a, str>)) - -> (Cow<'a, str>, Value<'a>)>, - Error>, +pub struct Deserializer<'de> { + inner: MapDeserializer<'de, PartIterator<'de>, Error>, } -impl<'a> Deserializer<'a> { +impl<'de> Deserializer<'de> { /// Returns a new `Deserializer`. - pub fn new(parser: UrlEncodedParse<'a>) -> Self { + pub fn new(parser: UrlEncodedParse<'de>) -> Self { Deserializer { - inner: MapDeserializer::new(parser.map(Value::wrap_pair)), + inner: MapDeserializer::new(PartIterator(parser)), } } } -impl<'a> de::Deserializer for Deserializer<'a> { +impl<'de> de::Deserializer<'de> for Deserializer<'de> { type Error = Error; - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor, + fn deserialize_any(self, visitor: V) -> Result + where V: de::Visitor<'de>, { self.deserialize_map(visitor) } fn deserialize_map(self, visitor: V) -> Result - where V: de::Visitor, + where V: de::Visitor<'de>, { visitor.visit_map(self.inner) } fn deserialize_seq(self, visitor: V) -> Result - where V: de::Visitor, + where V: de::Visitor<'de>, { visitor.visit_seq(self.inner) } - fn deserialize_seq_fixed_size(self, - _len: usize, - visitor: V) - -> Result - where V: de::Visitor, - { - visitor.visit_seq(self.inner) - } - - forward_to_deserialize! { + forward_to_deserialize_any! { bool u8 u16 @@ -142,68 +133,65 @@ impl<'a> de::Deserializer for Deserializer<'a> { newtype_struct tuple_struct struct - struct_field + identifier tuple enum ignored_any } } -struct Value<'a>(Cow<'a, str>); +struct PartIterator<'de>(UrlEncodedParse<'de>); -impl<'a> Value<'a> { - fn wrap_pair((k, v): (Cow<'a, str>, Cow<'a, str>)) -> (Cow<'a, str>, Self) { - (k, Value(v)) +impl<'de> Iterator for PartIterator<'de> { + type Item = (Part<'de>, Part<'de>); + + fn next(&mut self) -> Option { + self.0.next().map(|(k, v)| (Part(k), Part(v))) } } -impl<'a, E> SerdeValueDeserializer for Value<'a> - where E: de::Error, +struct Part<'de>(Cow<'de, str>); + +impl<'de> IntoDeserializer<'de> for Part<'de> { - type Deserializer = ValueDeserializer<'a, E>; + type Deserializer = Self; fn into_deserializer(self) -> Self::Deserializer { - ValueDeserializer { - value: self.0, - marker: PhantomData, - } + self } } -struct ValueDeserializer<'a, E> { - value: Cow<'a, str>, - marker: PhantomData, +macro_rules! forward_parsed_value { + ($($ty:ident => $method:ident,)*) => { + $( + fn $method(self, visitor: V) -> Result + where V: de::Visitor<'de> + { + match self.0.parse::<$ty>() { + Ok(val) => val.into_deserializer().$method(visitor), + Err(e) => Err(de::Error::custom(e)) + } + } + )* + } } -impl<'a, E> de::Deserializer for ValueDeserializer<'a, E> - where E: de::Error, -{ - type Error = E; +impl<'de> de::Deserializer<'de> for Part<'de> { + type Error = Error; - fn deserialize(self, visitor: V) -> Result - where V: de::Visitor, + fn deserialize_any(self, visitor: V) -> Result + where V: de::Visitor<'de>, { - self.value.into_deserializer().deserialize(visitor) + self.0.into_deserializer().deserialize_any(visitor) } fn deserialize_option(self, visitor: V) -> Result - where V: de::Visitor, + where V: de::Visitor<'de>, { - visitor.visit_some(self.value.into_deserializer()) + visitor.visit_some(self) } - forward_to_deserialize! { - bool - u8 - u16 - u32 - u64 - i8 - i16 - i32 - i64 - f32 - f64 + forward_to_deserialize_any! { char str string @@ -214,12 +202,25 @@ impl<'a, E> de::Deserializer for ValueDeserializer<'a, E> newtype_struct tuple_struct struct - struct_field + identifier tuple enum ignored_any seq - seq_fixed_size map } + + forward_parsed_value! { + bool => deserialize_bool, + u8 => deserialize_u8, + u16 => deserialize_u16, + u32 => deserialize_u32, + u64 => deserialize_u64, + i8 => deserialize_i8, + i16 => deserialize_i16, + i32 => deserialize_i32, + i64 => deserialize_i64, + f32 => deserialize_f32, + f64 => deserialize_f64, + } } diff --git a/src/ser/mod.rs b/src/ser/mod.rs index f36be4ff..7d6bab82 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -27,7 +27,7 @@ use url::form_urlencoded::Target as UrlEncodedTarget; /// serde_urlencoded::to_string(meal), /// Ok("bread=baguette&cheese=comt%C3%A9&meat=ham&fat=butter".to_owned())); /// ``` -pub fn to_string(input: &T) -> Result { +pub fn to_string(input: T) -> Result { let mut urlencoder = UrlEncodedSerializer::new("".to_owned()); input.serialize(Serializer::new(&mut urlencoder))?; Ok(urlencoder.finish()) @@ -99,9 +99,9 @@ pub struct SeqSerializer<'output, Target: 'output + UrlEncodedTarget> { /// Tuple serializer. /// -/// Never instantiated, tuples are not supported at top-level. -pub struct TupleSerializer<'output, T: 'output + UrlEncodedTarget> { - inner: ser::Impossible<&'output mut UrlEncodedSerializer, Error>, +/// Mostly used for arrays. +pub struct TupleSerializer<'output, Target: 'output + UrlEncodedTarget> { + urlencoder: &'output mut UrlEncodedSerializer, } /// Tuple struct serializer. @@ -234,7 +234,7 @@ impl<'output, Target> ser::Serializer for Serializer<'output, Target> /// Returns an error. fn serialize_unit_variant(self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str) -> Result { Err(Error::top_level()) @@ -253,7 +253,7 @@ impl<'output, Target> ser::Serializer for Serializer<'output, Target> fn serialize_newtype_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _value: &T) -> Result { @@ -280,18 +280,11 @@ impl<'output, Target> ser::Serializer for Serializer<'output, Target> Ok(SeqSerializer { urlencoder: self.urlencoder }) } - /// Serializes a sequence, given length is ignored. - fn serialize_seq_fixed_size(self, - _len: usize) - -> Result { - Ok(SeqSerializer { urlencoder: self.urlencoder }) - } - /// Returns an error. fn serialize_tuple(self, _len: usize) -> Result { - Err(Error::top_level()) + Ok(TupleSerializer { urlencoder: self.urlencoder }) } /// Returns an error. @@ -306,7 +299,7 @@ impl<'output, Target> ser::Serializer for Serializer<'output, Target> fn serialize_tuple_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _len: usize) -> Result { @@ -335,7 +328,7 @@ impl<'output, Target> ser::Serializer for Serializer<'output, Target> fn serialize_struct_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _len: usize) -> Result { @@ -369,16 +362,17 @@ impl<'output, Target> ser::SerializeTuple for TupleSerializer<'output, Target> fn serialize_element(&mut self, value: &T) -> Result<(), Error> { - self.inner.serialize_element(value) + value.serialize(pair::PairSerializer::new(self.urlencoder)) } fn end(self) -> Result { - self.inner.end() + Ok(self.urlencoder) } } impl<'output, Target> ser::SerializeTupleStruct - for TupleStructSerializer<'output, Target> + for + TupleStructSerializer<'output, Target> where Target: 'output + UrlEncodedTarget, { type Ok = &'output mut UrlEncodedSerializer; @@ -396,7 +390,8 @@ impl<'output, Target> ser::SerializeTupleStruct } impl<'output, Target> ser::SerializeTupleVariant - for TupleVariantSerializer<'output, Target> + for + TupleVariantSerializer<'output, Target> where Target: 'output + UrlEncodedTarget, { type Ok = &'output mut UrlEncodedSerializer; @@ -480,7 +475,8 @@ impl<'output, Target> ser::SerializeStruct for StructSerializer<'output, Target> } impl<'output, Target> ser::SerializeStructVariant - for StructVariantSerializer<'output, Target> + for + StructVariantSerializer<'output, Target> where Target: 'output + UrlEncodedTarget, { type Ok = &'output mut UrlEncodedSerializer; diff --git a/src/ser/pair.rs b/src/ser/pair.rs index 68156476..8fedcc0a 100644 --- a/src/ser/pair.rs +++ b/src/ser/pair.rs @@ -103,7 +103,7 @@ impl<'target, Target> ser::Serializer for PairSerializer<'target, Target> fn serialize_unit_variant(self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str) -> Result<(), Error> { Err(Error::unsupported_pair()) @@ -120,7 +120,7 @@ impl<'target, Target> ser::Serializer for PairSerializer<'target, Target> fn serialize_newtype_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _value: &T) -> Result<(), Error> { @@ -143,12 +143,6 @@ impl<'target, Target> ser::Serializer for PairSerializer<'target, Target> Err(Error::unsupported_pair()) } - fn serialize_seq_fixed_size(self, - _len: usize) - -> Result { - Err(Error::unsupported_pair()) - } - fn serialize_tuple(self, len: usize) -> Result { if len == 2 { Ok(self) @@ -167,7 +161,7 @@ impl<'target, Target> ser::Serializer for PairSerializer<'target, Target> fn serialize_tuple_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _len: usize) -> Result { @@ -190,7 +184,7 @@ impl<'target, Target> ser::Serializer for PairSerializer<'target, Target> fn serialize_struct_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _len: usize) -> Result { diff --git a/src/ser/part.rs b/src/ser/part.rs index 42653c01..36ce1414 100644 --- a/src/ser/part.rs +++ b/src/ser/part.rs @@ -113,7 +113,7 @@ impl ser::Serializer for PartSerializer { fn serialize_unit_variant(self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, variant: &'static str) -> Result { self.sink.serialize_static_str(variant.into()) @@ -130,7 +130,7 @@ impl ser::Serializer for PartSerializer { fn serialize_newtype_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _value: &T) -> Result { @@ -153,13 +153,6 @@ impl ser::Serializer for PartSerializer { Err(self.sink.unsupported()) } - - fn serialize_seq_fixed_size(self, - _len: usize) - -> Result { - Err(self.sink.unsupported()) - } - fn serialize_tuple(self, _len: usize) -> Result { @@ -176,7 +169,7 @@ impl ser::Serializer for PartSerializer { fn serialize_tuple_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _len: usize) -> Result { @@ -199,7 +192,7 @@ impl ser::Serializer for PartSerializer { fn serialize_struct_variant (self, _name: &'static str, - _variant_index: usize, + _variant_index: u32, _variant: &'static str, _len: usize) -> Result {