summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/de.rs79
-rw-r--r--tests/test_deserialize.rs28
2 files changed, 103 insertions, 4 deletions
diff --git a/src/de.rs b/src/de.rs
index f0b8614..def50ec 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -490,7 +490,7 @@ impl<'de> de::Deserializer<'de> for Deserializer {
-> Result<V::Value, Self::Error>
where V: de::Visitor<'de>,
{
- visitor.visit_map(self)
+ self.deserialize_map(visitor)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -541,10 +541,9 @@ impl<'de> de::MapAccess<'de> for Deserializer {
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: de::DeserializeSeed<'de>,
{
-
if let Some((key, value)) = self.iter.next() {
self.value = Some(value);
- return seed.deserialize(key.into_deserializer()).map(Some);
+ return seed.deserialize(ParsableStringDeserializer(key)).map(Some);
};
Ok(None)
@@ -579,7 +578,7 @@ macro_rules! deserialize_primitive {
stringify!($ty))))
},
Level::Flat(x) => {
- visitor.$visit_method(str::FromStr::from_str(&x).unwrap())
+ ParsableStringDeserializer(x).$method(visitor)
},
Level::Invalid(e) => {
Err(de::Error::custom(e))
@@ -703,3 +702,75 @@ impl<'de> IntoDeserializer<'de> for Level {
LevelDeserializer(self)
}
}
+
+macro_rules! forward_parsable_to_deserialize_any {
+ ($($ty:ident => $meth:ident,)*) => {
+ $(
+ fn $meth<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: de::Visitor<'de> {
+ match self.0.parse::<$ty>() {
+ Ok(val) => val.into_deserializer().$meth(visitor),
+ Err(e) => Err(de::Error::custom(e))
+ }
+ }
+ )*
+ }
+}
+
+
+pub struct ParsableStringDeserializer(String);
+
+impl<'de> de::Deserializer<'de> for ParsableStringDeserializer {
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where V: de::Visitor<'de>,
+ {
+ self.0.into_deserializer().deserialize_any(visitor)
+ }
+
+ forward_to_deserialize_any! {
+ // bool
+ // u8
+ // u16
+ // u32
+ // u64
+ // i8
+ // i16
+ // i32
+ // i64
+ // f32
+ // f64
+ map
+ struct
+ seq
+ option
+ char
+ str
+ string
+ unit
+ bytes
+ byte_buf
+ unit_struct
+ newtype_struct
+ tuple_struct
+ identifier
+ tuple
+ enum
+ ignored_any
+ }
+
+ forward_parsable_to_deserialize_any! {
+ 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/tests/test_deserialize.rs b/tests/test_deserialize.rs
index cd22458..4d44e5e 100644
--- a/tests/test_deserialize.rs
+++ b/tests/test_deserialize.rs
@@ -175,6 +175,34 @@ fn qs_test_simple() {
}
#[test]
+fn qs_u32_map() {
+ #[derive(Debug,Serialize,Deserialize,PartialEq)]
+ struct Query {
+ map: HashMap<u32, String>
+ }
+
+ let query = {
+ let mut map = HashMap::new();
+ map.insert(10, "Hello".into());
+ Query { map: map }
+ };
+
+ let params: Query = qs::from_str("map[10]=Hello").unwrap();
+ assert_eq!(params, query)
+}
+
+#[test]
+fn no_panic_on_parse_error() {
+ #[derive(Debug,Serialize,Deserialize,PartialEq)]
+ struct Query {
+ vec: Vec<u32>
+ }
+
+ let params: Result<Query, _> = qs::from_str("vec[]=a&vec[]=2");
+ assert!(params.is_err())
+}
+
+#[test]
fn qs_nesting() {
// t.deepEqual(qs.parse('a[b]=c'), { a: { b: 'c' } }, 'parses a single
// nested string');