Have a custom type for deserialising values (fixes #16)
This lets us handle Option values correctly.
This commit is contained in:
parent
f122a88561
commit
7ddde33a33
89
src/de.rs
89
src/de.rs
@ -1,11 +1,14 @@
|
|||||||
//! Deserialization support for the `application/x-www-form-urlencoded` format.
|
//! Deserialization support for the `application/x-www-form-urlencoded` format.
|
||||||
|
|
||||||
use serde::de;
|
use serde::de;
|
||||||
|
use serde::de::value::{MapDeserializer, ValueDeserializer as SerdeValueDeserializer};
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use serde::de::value::Error;
|
pub use serde::de::value::Error;
|
||||||
use serde::de::value::MapDeserializer;
|
use std::borrow::Cow;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::iter::Map;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use url::form_urlencoded::Parse as UrlEncodedParse;
|
use url::form_urlencoded::Parse as UrlEncodedParse;
|
||||||
use url::form_urlencoded::parse;
|
use url::form_urlencoded::parse;
|
||||||
|
|
||||||
@ -71,13 +74,18 @@ pub fn from_reader<T, R>(mut reader: R) -> Result<T, Error>
|
|||||||
/// * Everything else but `deserialize_seq` and `deserialize_seq_fixed_size`
|
/// * Everything else but `deserialize_seq` and `deserialize_seq_fixed_size`
|
||||||
/// defers to `deserialize`.
|
/// defers to `deserialize`.
|
||||||
pub struct Deserializer<'a> {
|
pub struct Deserializer<'a> {
|
||||||
inner: MapDeserializer<UrlEncodedParse<'a>, Error>,
|
inner: MapDeserializer<Map<UrlEncodedParse<'a>,
|
||||||
|
fn((Cow<'a, str>, Cow<'a, str>))
|
||||||
|
-> (Cow<'a, str>, Value<'a>)>,
|
||||||
|
Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Deserializer<'a> {
|
impl<'a> Deserializer<'a> {
|
||||||
/// Returns a new `Deserializer`.
|
/// Returns a new `Deserializer`.
|
||||||
pub fn new(parser: UrlEncodedParse<'a>) -> Self {
|
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
|
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<E> 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<E>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E> de::Deserializer for ValueDeserializer<'a, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
type Error = E;
|
||||||
|
|
||||||
|
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
self.value.into_deserializer().deserialize(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,3 +23,12 @@ fn deserialize_reader() {
|
|||||||
assert_eq!(serde_urlencoded::from_reader(b"first=23&last=42" as &[_]),
|
assert_eq!(serde_urlencoded::from_reader(b"first=23&last=42" as &[_]),
|
||||||
Ok(result));
|
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));
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user