From f122a88561b6bea9d6e56c53b0946fbc323e2432 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 6 May 2017 10:43:25 +0200 Subject: [PATCH 1/3] Reformat de --- src/de.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/de.rs b/src/de.rs index 623bb491..0ab9b078 100644 --- a/src/de.rs +++ b/src/de.rs @@ -50,7 +50,8 @@ pub fn from_str(input: &str) -> Result { /// 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, R: Read + where T: de::Deserialize, + R: Read, { let mut buf = vec![]; reader.read_to_end(&mut buf) From 7ddde33a33b1f295ec8e4a2edd74487353210bd5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 6 May 2017 10:59:42 +0200 Subject: [PATCH 2/3] Have a custom type for deserialising values (fixes #16) This lets us handle Option values correctly. --- src/de.rs | 89 +++++++++++++++++++++++++++++++++++++-- tests/test_deserialize.rs | 9 ++++ 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/de.rs b/src/de.rs index 0ab9b078..10015487 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,11 +1,14 @@ //! Deserialization support for the `application/x-www-form-urlencoded` format. use serde::de; +use serde::de::value::{MapDeserializer, ValueDeserializer as SerdeValueDeserializer}; #[doc(inline)] pub use serde::de::value::Error; -use serde::de::value::MapDeserializer; +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; @@ -71,13 +74,18 @@ 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, Error>, + inner: MapDeserializer, + fn((Cow<'a, str>, Cow<'a, str>)) + -> (Cow<'a, str>, Value<'a>)>, + Error>, } impl<'a> Deserializer<'a> { /// Returns a new `Deserializer`. pub fn new(parser: UrlEncodedParse<'a>) -> Self { - Deserializer { inner: MapDeserializer::new(parser) } + Deserializer { + inner: MapDeserializer::new(parser.map(Value::wrap_pair)), + } } } @@ -140,3 +148,78 @@ impl<'a> de::Deserializer for Deserializer<'a> { ignored_any } } + +struct Value<'a>(Cow<'a, str>); + +impl<'a> Value<'a> { + fn wrap_pair((k, v): (Cow<'a, str>, Cow<'a, str>)) -> (Cow<'a, str>, Self) { + (k, Value(v)) + } +} + +impl<'a, E> SerdeValueDeserializer for Value<'a> + where E: de::Error, +{ + type Deserializer = ValueDeserializer<'a, E>; + + fn into_deserializer(self) -> Self::Deserializer { + ValueDeserializer { + value: self.0, + marker: PhantomData, + } + } +} + +struct ValueDeserializer<'a, E> { + value: Cow<'a, str>, + marker: PhantomData, +} + +impl<'a, E> de::Deserializer for ValueDeserializer<'a, E> + where E: de::Error, +{ + type Error = E; + + fn deserialize(self, visitor: V) -> Result + where V: de::Visitor, + { + self.value.into_deserializer().deserialize(visitor) + } + + fn deserialize_option(self, visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_some(self.value.into_deserializer()) + } + + forward_to_deserialize! { + bool + u8 + u16 + u32 + u64 + i8 + i16 + i32 + i64 + f32 + f64 + char + str + string + unit + bytes + byte_buf + unit_struct + newtype_struct + tuple_struct + struct + struct_field + tuple + enum + ignored_any + seq + seq_fixed_size + map + } +} diff --git a/tests/test_deserialize.rs b/tests/test_deserialize.rs index eeb2ce62..bd92ba9e 100644 --- a/tests/test_deserialize.rs +++ b/tests/test_deserialize.rs @@ -23,3 +23,12 @@ fn deserialize_reader() { assert_eq!(serde_urlencoded::from_reader(b"first=23&last=42" as &[_]), Ok(result)); } + +#[test] +fn deserialize_option() { + let result = vec![ + ("first".to_owned(), Some(23)), + ("last".to_owned(), Some(42)), + ]; + assert_eq!(serde_urlencoded::from_str("first=23&last=42"), Ok(result)); +} From 81aad8e8bdf0b85551b43fa806e295cfe0364131 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 6 May 2017 11:06:12 +0200 Subject: [PATCH 3/3] Bump version to 0.4.3 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a788d23e..c356ece7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_urlencoded" -version = "0.4.2" +version = "0.4.3" authors = ["Anthony Ramine "] license = "MIT/Apache-2.0" repository = "https://github.com/nox/serde_urlencoded"