diff options
author | Sam Scott <sam.scott89@gmail.com> | 2017-02-15 17:43:33 +0000 |
---|---|---|
committer | Sam Scott <sam.scott89@gmail.com> | 2017-02-15 17:43:50 +0000 |
commit | 4a6b46f9222cad61ceb8e9246b4cc33eb4f61f57 (patch) | |
tree | 735a7cc371bcf6025eaecfb1acf8dec317d0e928 /src | |
parent | c0457909e41735b17b66e11a1d2cf1660f6b3c6d (diff) |
Some _very_ hacky code to get nested url_encoded params working.
Diffstat (limited to 'src')
-rw-r--r-- | src/de.rs | 181 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/ser/key.rs | 24 | ||||
-rw-r--r-- | src/ser/part.rs | 14 | ||||
-rw-r--r-- | src/ser/value.rs | 26 |
5 files changed, 230 insertions, 17 deletions
@@ -2,6 +2,11 @@ use serde::de; +use std::collections::{ + HashMap, +}; +use std::borrow::Cow; + #[doc(inline)] pub use serde::de::value::Error; use serde::de::value::MapDeserializer; @@ -25,7 +30,7 @@ use url::form_urlencoded::parse; /// Ok(meal)); /// ``` pub fn from_bytes<T: de::Deserialize>(input: &[u8]) -> Result<T, Error> { - T::deserialize(Deserializer::new(parse(input))) + T::deserialize(&mut Deserializer::new(parse(input))) } /// Deserializes a `application/x-wwww-url-encoded` value from a `&str`. @@ -80,25 +85,25 @@ impl<'a> Deserializer<'a> { } } -impl<'a> de::Deserializer for Deserializer<'a> { +impl<'a, 'b> de::Deserializer for &'b mut Deserializer<'a> { type Error = Error; fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: de::Visitor, { - self.deserialize_map(visitor) + self.deserialize_str(visitor) } fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: de::Visitor, { - visitor.visit_map(self.inner) + visitor.visit_map(&mut self.inner) } fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: de::Visitor, { - visitor.visit_seq(self.inner) + visitor.visit_seq(&mut self.inner) } fn deserialize_seq_fixed_size<V>(self, @@ -107,7 +112,18 @@ impl<'a> de::Deserializer for Deserializer<'a> { -> Result<V::Value, Self::Error> where V: de::Visitor, { - visitor.visit_seq(self.inner) + visitor.visit_seq(&mut self.inner) + } + + // _serde::Deserializer::deserialize_struct(deserializer,"A", FIELDS, __Visitor) + fn deserialize_struct<V>(self, + name: &'static str, + fields: &'static [&'static str], + visitor: V) + -> Result<V::Value, Self::Error> + where V: de::Visitor + { + visitor.visit_map(FlatMapVisitor::new(self)) } forward_to_deserialize! { @@ -132,10 +148,161 @@ impl<'a> de::Deserializer for Deserializer<'a> { unit_struct newtype_struct tuple_struct - struct + // struct struct_field tuple enum ignored_any } } + + +use std::marker::PhantomData; +use serde::de::MapVisitor; +use std::iter; +use std::collections::hash_map::{Iter,IntoIter}; + +#[derive(Debug)] +enum Level { + Flat(String), + Nested(String), +} +struct FlatMapVisitor<'a, 'b> + where 'a: 'b +{ + de: &'b mut Deserializer<'a>, + iter: iter::Peekable<iter::Fuse<IntoIter<String, Level>>>, + // iter: iter::Peekable<iter::Fuse<Iter<'c, String, String>>>, + +} + +use serde::de::value::CowStrDeserializer; + +impl<'a, 'b, 'c> FlatMapVisitor<'a, 'b> + where 'a :'b +{ + fn new(de: &'b mut Deserializer<'a>) -> Self { + + let mut map = HashMap::<String, Level>::new(); + + while let Ok(Some((k,v))) = de.inner.visit::<Cow<String>, Cow<String>>() { + let (ldepth, rdepth) = k.chars().fold((0, 0), |(acc0, acc1), x| { + match x { + '[' => (acc0+1, acc1), + ']' => (acc0, acc1+1), + _ => (acc0, acc1) + } + }); + debug_assert!(ldepth == rdepth); + + // a[b][c][d] = 1 => a, b], c][d] + if ldepth > 1 { + let ksplit: Vec<&str> = k.splitn(3, '[').collect(); + let a = ksplit[0]; + let b = ksplit[1]; + let c = ksplit[2]; + let x = match map.get(a.into()) { + Some(&Level::Flat(_)) => { + panic!("Tried adding a nested element to a flat level"); + }, + Some(&Level::Nested(ref x)) => { + // map.get(a) = x&b[c][d]=v + format!("{}&{}[{}={}", &x, &b[..b.len()-1], &c, &v).into() + }, + None => { + // map.insert(a, b[c][d]=v) + format!("{}[{}={}", &b[..b.len()-1],c, v).into() + } + }; + map.insert(a.into(), Level::Nested(x)); + } else if ldepth == 1 { + let ksplit: Vec<&str> = k.splitn(2, '[').collect(); + let a = ksplit[0]; + let b = ksplit[1]; + // k is of the form a[b] + let x = match map.get(a.into()) { + Some(&Level::Flat(_)) => { + panic!("Tried adding a nested element to a flat level"); + }, + Some(&Level::Nested(ref x)) => { + // map.get(a) = x&b=v + format!("{}&{}={}", &x, &b[..b.len()-1], &v).into() + }, + None => { + // map.insert(a, b=v) + format!("{}={}", &b[..b.len()-1], &v).into() + } + }; + map.insert(a.into(), Level::Nested(x)); + } else { + // k is of the form a + let x = match map.get(k.as_ref()) { + Some(_) => { + panic!("Attempted to set the value of {} twice", k); + // map.get(a) = x&b=v + // format!("{}&{}={}", &x, &b[..b.len()-1], &v).into() + }, + None => { + v + // map.insert(a, b=v) + // format!("{}={}", &b[..b.len()-1], &v).into() + } + }; + map.insert(k.into_owned(), Level::Flat(x.into_owned())); + } + } + println!("Map constructed: {:?}", map); + FlatMapVisitor { + de: de, + iter: map.into_iter().fuse().peekable(), + } + } + + +} + +use serde::de::value::ValueDeserializer; + + +impl<'a, 'b, 'c> de::MapVisitor for FlatMapVisitor<'a, 'b> { + type Error = Error; + + // __Visitor::visit_map + // visit_map -> visit_key::<__Field> -> + // MapVisitor::visit_key::<__Field>() + // -> visit_key_seed(PhantomData<__Field>) + // -> __Field::deserialize() + // seed.deserialize(key.into_deserializer()) + // becoes flat(seed).deserialize() + + // Swap for visit_key_seed(FlatDeserializer<__Field>) + fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error> + where K: de::DeserializeSeed, + { + + if let Some(&(ref key, _)) = self.iter.peek() { + return seed.deserialize(key.clone().into_deserializer()).map(Some) + }; + Ok(None) + + } + + fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error> + where V: de::DeserializeSeed, + { + if let Some((_, value)) = self.iter.next() { + // seed.deserialize(value.into_deserializer()) + match value { + Level::Flat(ref x) => { + seed.deserialize(x.clone().into_deserializer()) + }, + Level::Nested(ref x) => { + + seed.deserialize(&mut Deserializer::new(parse(x.as_bytes()))) + } + } + } else { + panic!("Somehow the list was empty after a non-empty key was returned"); + } + } +} @@ -8,6 +8,8 @@ extern crate dtoa; extern crate serde; extern crate url; + + pub mod de; pub mod ser; diff --git a/src/ser/key.rs b/src/ser/key.rs index 6cbbff4..a84f311 100644 --- a/src/ser/key.rs +++ b/src/ser/key.rs @@ -1,4 +1,5 @@ -use ser::Error; +use ser::{Error}; +use serde::ser::{SerializeStruct}; use ser::part::Sink; use serde::Serialize; use std::borrow::Cow; @@ -44,7 +45,6 @@ impl<End, Ok> KeySink<End> impl<End, Ok> Sink for KeySink<End> where End: for<'key> FnOnce(Key<'key>) -> Result<Ok, Error> { - type Ok = Ok; fn serialize_static_str(self, value: &'static str) @@ -74,3 +74,23 @@ impl<End, Ok> Sink for KeySink<End> Error::Custom("unsupported key".into()) } } + +impl<End, Ok> SerializeStruct for KeySink<End> +where End: for<'key> FnOnce(Key<'key>) -> Result<Ok, Error> +{ + type Ok = Ok; + type Error = Error; + + fn serialize_field<T: ?Sized + Serialize>(&mut self, + _key: &'static str, + _value: &T) + -> Result<(), Error> { + Err(Error::top_level()) + } + + fn end(self) -> Result<Self::Ok, Error> { + Err(self.unsupported()) + } +} + + diff --git a/src/ser/part.rs b/src/ser/part.rs index 42653c0..d2ade0a 100644 --- a/src/ser/part.rs +++ b/src/ser/part.rs @@ -14,8 +14,8 @@ impl<S: Sink> PartSerializer<S> { } } -pub trait Sink: Sized { - type Ok; +pub trait Sink: Sized + ser::SerializeStruct { + // type Ok; fn serialize_static_str(self, value: &'static str) @@ -33,7 +33,7 @@ pub trait Sink: Sized { fn unsupported(self) -> Error; } -impl<S: Sink> ser::Serializer for PartSerializer<S> { +impl<S: Sink<Error=Error>> ser::Serializer for PartSerializer<S> { type Ok = S::Ok; type Error = Error; type SerializeSeq = ser::Impossible<S::Ok, Error>; @@ -41,7 +41,7 @@ impl<S: Sink> ser::Serializer for PartSerializer<S> { type SerializeTupleStruct = ser::Impossible<S::Ok, Error>; type SerializeTupleVariant = ser::Impossible<S::Ok, Error>; type SerializeMap = ser::Impossible<S::Ok, Error>; - type SerializeStruct = ser::Impossible<S::Ok, Error>; + type SerializeStruct = S; type SerializeStructVariant = ser::Impossible<S::Ok, Error>; fn serialize_bool(self, v: bool) -> Result<S::Ok, Error> { @@ -193,7 +193,9 @@ impl<S: Sink> ser::Serializer for PartSerializer<S> { _name: &'static str, _len: usize) -> Result<Self::SerializeStruct, Error> { - Err(self.sink.unsupported()) + // Err(self.sink.unsupported()) + Ok(self.sink) + } fn serialize_struct_variant @@ -207,7 +209,7 @@ impl<S: Sink> ser::Serializer for PartSerializer<S> { } } -impl<S: Sink> PartSerializer<S> { +impl<S: Sink<Error=Error>> PartSerializer<S> { fn serialize_integer<I>(self, value: I) -> Result<S::Ok, Error> where I: itoa::Integer, { diff --git a/src/ser/value.rs b/src/ser/value.rs index e4e1f2c..56b410e 100644 --- a/src/ser/value.rs +++ b/src/ser/value.rs @@ -1,6 +1,6 @@ use ser::Error; use ser::part::{PartSerializer, Sink}; -use serde::ser::Serialize; +use serde::ser::{Serialize, SerializeStruct}; use std::str; use url::form_urlencoded::Serializer as UrlEncodedSerializer; use url::form_urlencoded::Target as UrlEncodedTarget; @@ -28,7 +28,7 @@ impl<'key, 'target, Target> ValueSink<'key, 'target, Target> impl<'key, 'target, Target> Sink for ValueSink<'key, 'target, Target> where Target: 'target + UrlEncodedTarget, { - type Ok = (); + // type Ok = (); fn serialize_str(self, value: &str) -> Result<(), Error> { self.urlencoder.append_pair(self.key, value); @@ -57,3 +57,25 @@ impl<'key, 'target, Target> Sink for ValueSink<'key, 'target, Target> Error::Custom("unsupported value".into()) } } + + +impl<'key, 'target, Target> SerializeStruct for ValueSink<'key, 'target, Target> + where Target: 'target + UrlEncodedTarget, +{ + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized + Serialize>(&mut self, + key: &'static str, + value: &T) + -> Result<(), Error> { + let newk = format!("{}[{}]", self.key, key); + let value_sink = ValueSink::new(self.urlencoder, &newk); + value.serialize(super::part::PartSerializer::new(value_sink)) + } + + fn end(self) -> Result<Self::Ok, Error> { + Ok(()) + } +} + |