summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Scott <sam.scott89@gmail.com>2017-02-15 17:43:33 +0000
committerSam Scott <sam.scott89@gmail.com>2017-02-15 17:43:50 +0000
commit4a6b46f9222cad61ceb8e9246b4cc33eb4f61f57 (patch)
tree735a7cc371bcf6025eaecfb1acf8dec317d0e928 /src
parentc0457909e41735b17b66e11a1d2cf1660f6b3c6d (diff)
Some _very_ hacky code to get nested url_encoded params working.
Diffstat (limited to 'src')
-rw-r--r--src/de.rs181
-rw-r--r--src/lib.rs2
-rw-r--r--src/ser/key.rs24
-rw-r--r--src/ser/part.rs14
-rw-r--r--src/ser/value.rs26
5 files changed, 230 insertions, 17 deletions
diff --git a/src/de.rs b/src/de.rs
index 623bb49..3da294a 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -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");
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index bf7ad59..16cb4e2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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(())
+ }
+}
+