From 6e71ba43eb6bd62f2b567224e387333016bd3a5c Mon Sep 17 00:00:00 2001 From: Sam Scott Date: Sat, 20 May 2017 22:07:44 +0100 Subject: Rewrite of most components. Simplify `ser` logic, and expand `de` functionality. --- Cargo.toml | 2 + examples/introduction.rs | 2 +- src/de.rs | 291 ++++++++++++++++++++---- src/lib.rs | 6 +- src/ser.rs | 564 ++++++++++++++++++++++++++++++++++++++++++++++ src/ser/key.rs | 108 --------- src/ser/mod.rs | 519 ------------------------------------------ src/ser/part.rs | 232 ------------------- src/ser/value.rs | 102 --------- tests/test_deserialize.rs | 35 +++ tests/test_serialize.rs | 47 ++++ 11 files changed, 898 insertions(+), 1010 deletions(-) create mode 100644 src/ser.rs delete mode 100644 src/ser/key.rs delete mode 100644 src/ser/mod.rs delete mode 100644 src/ser/part.rs delete mode 100644 src/ser/value.rs diff --git a/Cargo.toml b/Cargo.toml index 28071a3..be764fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ version = "0.1.0" repository = "samscott89/serde_qs" [dependencies] +data-encoding = "1.2" +error-chain = "0.10.0" dtoa = "0.4.0" fnv = "1.0.3" itoa = "0.3.0" diff --git a/examples/introduction.rs b/examples/introduction.rs index a8e984f..fb70665 100644 --- a/examples/introduction.rs +++ b/examples/introduction.rs @@ -131,7 +131,7 @@ fn main() { // Enums are supported, but only adjacently tagged enums // (see https://serde.rs/enum-representations.html for more information). #[derive(Deserialize, Debug, PartialEq, Serialize)] - #[serde(tag = "type", content = "value")] + // #[serde(tag = "type", content = "value")] enum AdjTaggedEnum { B(bool), S(String), diff --git a/src/de.rs b/src/de.rs index def50ec..0306d21 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,14 +1,16 @@ //! Deserialization support for querystrings. +use data_encoding::base64; + use serde::de; #[doc(inline)] pub use serde::de::value::Error; use serde::de::value::MapDeserializer; +use url::percent_encoding; use std::collections::btree_map::{BTreeMap, Entry, IntoIter}; use std::io::Read; -use url::percent_encoding; - +use std::vec; /// To override the default serialization parameters, first construct a new /// Config. /// @@ -390,8 +392,6 @@ impl> Parser { // key is simply "[]", so treat as a seq. b']' => { self.acc.clear(); - // println!("Empty key => vector"); - // println!("{:?}", node); self.parse_seq_value(node)?; self.depth += 1; Ok(true) @@ -400,8 +400,6 @@ impl> Parser { // Key is "[a..." so parse up to the closing "]" 0x20...0x7e => { let key = self.parse_key(b']', true)?; - // key.into() - // println!("key: {:?}", key); self.parse_map_value(key.into(), node)?; self.depth += 1; Ok(true) @@ -498,6 +496,49 @@ impl<'de> de::Deserializer<'de> for Deserializer { { visitor.visit_seq(MapDeserializer::new(self.iter)) } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V + ) -> Result + where V: de::Visitor<'de> + { + self.deserialize_map(visitor) + } + + fn deserialize_tuple( + self, + _len: usize, + visitor: V + ) -> Result + where V: de::Visitor<'de> + { + visitor.visit_seq(MapDeserializer::new(self.iter)) + + } + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V + ) -> Result + where V: de::Visitor<'de> + { + visitor.visit_seq(MapDeserializer::new(self.iter)) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V + ) -> Result + where V: de::Visitor<'de> + { + visitor.visit_enum(self) + } + forward_to_deserialize_any! { bool u8 @@ -520,13 +561,13 @@ impl<'de> de::Deserializer<'de> for Deserializer { unit_struct // seq // seq_fixed_size - newtype_struct - tuple_struct + // newtype_struct + // tuple_struct // struct identifier // struct_field - tuple - enum + // tuple + // enum ignored_any } } @@ -546,7 +587,6 @@ impl<'de> de::MapAccess<'de> for Deserializer { return seed.deserialize(ParsableStringDeserializer(key)).map(Some); }; Ok(None) - } fn next_value_seed(&mut self, seed: V) -> Result @@ -561,7 +601,99 @@ impl<'de> de::MapAccess<'de> for Deserializer { } } -struct LevelDeserializer(Level); +impl<'de> de::EnumAccess<'de> for Deserializer { + type Error = Error; + type Variant = LevelDeserializer; + + fn variant_seed(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where V: de::DeserializeSeed<'de> + { + if let Some((key, value)) = self.iter.next() { + Ok((seed.deserialize(ParsableStringDeserializer(key))?, LevelDeserializer(value))) + } else { + Err(de::Error::custom("No more values")) + } + } +} + +impl<'de> de::EnumAccess<'de> for LevelDeserializer { + type Error = Error; + type Variant = Self; + + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where V: de::DeserializeSeed<'de> + { + match self.0 { + // Level::Nested(map) => { + // Deserializer::with_map(map).variant_seed(seed) + // }, + // Level::Sequence(_) => { + // Err(de::Error::custom(format!("Expected Enum (map or a flat value), got a Sequence"))) + // }, + Level::Flat(x) => { + Ok((seed.deserialize(ParsableStringDeserializer(x))?, LevelDeserializer(Level::Invalid("")))) + }, + _ => { + Err(de::Error::custom("should not be here...")) + } + } + } +} + +impl<'de> de::VariantAccess<'de> for LevelDeserializer { + type Error = Error; + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: de::DeserializeSeed<'de> + { + seed.deserialize(self) + + } + fn tuple_variant( + self, + _len: usize, + visitor: V + ) -> Result + where + V: de::Visitor<'de> + { + de::Deserializer::deserialize_seq(self, visitor) + + } + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V + ) -> Result + where + V: de::Visitor<'de> + { + de::Deserializer::deserialize_map(self, visitor) + } +} + +struct LevelSeq>(I); + +impl<'de, I: Iterator> de::SeqAccess<'de> for LevelSeq { + type Error = Error; + fn next_element_seed(&mut self, seed: T) -> Result, Error> + where T: de::DeserializeSeed<'de> + { + if let Some(v) = self.0.next() { + seed.deserialize(v.into_deserializer()).map(Some) + } else { + Ok(None) + } + } +} + + + +pub struct LevelDeserializer(Level); macro_rules! deserialize_primitive { ($ty:ident, $method:ident, $visit_method:ident) => ( @@ -588,6 +720,22 @@ macro_rules! deserialize_primitive { ) } +impl LevelDeserializer { + fn to_deserializer(self) -> Result { + match self.0 { + Level::Nested(map) => { + Ok(Deserializer::with_map(map)) + }, + Level::Invalid(e) => { + Err(de::Error::custom(e)) + } + l => { + Err(de::Error::custom(format!("could not convert {:?} to Deserializer", l))) + }, + } + } +} + impl<'de> de::Deserializer<'de> for LevelDeserializer { type Error = Error; @@ -610,45 +758,25 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { } } - fn deserialize_map(self, visitor: V) -> Result - where V: de::Visitor<'de>, - { - if let Level::Nested(x) = self.0 { - Deserializer::with_map(x).deserialize_map(visitor) - } else { - Err(de::Error::custom(format!("value: {:?} does not appear to \ - be a map", - self.0))) - } - } - - fn deserialize_struct(self, - _name: &'static str, - _fields: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor<'de>, - { - - self.deserialize_map(visitor) - } - fn deserialize_seq(self, visitor: V) -> Result where V: de::Visitor<'de>, { match self.0 { Level::Nested(map) => { - SeqDeserializer::new(map.into_iter().map(|(_k, v)| v)) - .deserialize_any(visitor) + visitor.visit_seq(LevelSeq(map.into_iter().map(|(_k, v)| v))) + + // SeqDeserializer::new() + // .deserialize_any(visitor) }, Level::Sequence(x) => { - SeqDeserializer::new(x.into_iter()).deserialize_any(visitor) + // SeqDeserializer::new(x.into_iter()).deserialize_any(visitor) + visitor.visit_seq(LevelSeq(x.into_iter())) }, - Level::Flat(x) => { - SeqDeserializer::new(vec![x].into_iter()).deserialize_any(visitor) + Level::Invalid(e) => { + Err(de::Error::custom(e)) }, - _ => { - Err(de::Error::custom("value does not appear to be a sequence")) + x => { + visitor.visit_seq(LevelSeq(vec![x].into_iter())) }, } } @@ -666,6 +794,76 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { } } + fn deserialize_enum( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V + ) -> Result + where V: de::Visitor<'de> + { + match self.0 { + Level::Nested(map) => { + Deserializer::with_map(map).deserialize_enum(name, variants, visitor) + }, + Level::Flat(_) => { + visitor.visit_enum(self) + }, + _ => { + Err(de::Error::custom("value does not appear to be a sequence")) + }, + } + } + + fn deserialize_map(self, visitor: V) -> Result + where V: de::Visitor<'de>, + { + self.to_deserializer()?.deserialize_map(visitor) + + } + + fn deserialize_struct(self, + name: &'static str, + fields: &'static [&'static str], + visitor: V) + -> Result + where V: de::Visitor<'de>, + { + self.to_deserializer()?.deserialize_struct(name, fields, visitor) + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V + ) -> Result + where V: de::Visitor<'de> + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple( + self, + _len: usize, + visitor: V + ) -> Result + where V: de::Visitor<'de> + { + // self.to_deserializer()?.deserialize_tuple(len, visitor) + self.deserialize_seq(visitor) + + } + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V + ) -> Result + where V: de::Visitor<'de> + { + self.deserialize_seq(visitor) + } + deserialize_primitive!(bool, deserialize_bool, visit_bool); deserialize_primitive!(i8, deserialize_i8, visit_i8); deserialize_primitive!(i16, deserialize_i16, visit_i16); @@ -687,11 +885,11 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { bytes byte_buf unit_struct - newtype_struct - tuple_struct + // newtype_struct + // tuple_struct identifier - tuple - enum + // tuple + // enum ignored_any } } @@ -728,6 +926,7 @@ impl<'de> de::Deserializer<'de> for ParsableStringDeserializer { self.0.into_deserializer().deserialize_any(visitor) } + forward_to_deserialize_any! { // bool // u8 diff --git a/src/lib.rs b/src/lib.rs index d11e49f..7269046 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,7 +59,9 @@ //! assert_eq!(rec_params, params); //! //! # } - +extern crate data_encoding; +#[macro_use] +extern crate error_chain; extern crate itoa; extern crate dtoa; #[macro_use] @@ -72,4 +74,4 @@ pub mod ser; #[doc(inline)] pub use de::{Deserializer, from_bytes, from_reader, from_str}; #[doc(inline)] -pub use ser::{Serializer, to_string}; +pub use ser::{QsSerializer, to_string}; diff --git a/src/ser.rs b/src/ser.rs new file mode 100644 index 0000000..fa49fda --- /dev/null +++ b/src/ser.rs @@ -0,0 +1,564 @@ + +//! Serialization support for querystrings. + +use serde::ser; +use url::form_urlencoded::Serializer as UrlEncodedSerializer; +use url::form_urlencoded::Target as UrlEncodedTarget; + +use std::fmt::Display; +use std::borrow::Cow; +use std::str; + +/// Serializes a value into a querystring. +/// +/// ``` +/// # #[macro_use] +/// # extern crate serde_derive; +/// # extern crate serde_qs; +/// #[derive(Deserialize, Serialize)] +/// struct Query { +/// name: String, +/// age: u8, +/// occupation: String, +/// } +/// +/// # fn main(){ +/// let q = Query { +/// name: "Alice".to_owned(), +/// age: 24, +/// occupation: "Student".to_owned(), +/// }; +/// +/// +/// assert_eq!( +/// serde_qs::to_string(&q).unwrap(), +/// "name=Alice&age=24&occupation=Student"); +/// # } +/// ``` +pub fn to_string(input: &T) -> Result { + let mut urlencoder = UrlEncodedSerializer::new("".to_owned()); + input.serialize(&mut QsSerializer { key: None, urlencoder: &mut urlencoder })?; + Ok(urlencoder.finish()) +} + +/// A serializer for the querystring format. +/// +/// * Supported top-level inputs are structs and maps. +/// +/// * Supported values are currently most primitive types, structs, maps and +/// sequences. Sequences are serialized with an incrementing key index. +/// +/// * Newtype structs defer to their inner values. +pub struct QsSerializer<'a, Target: 'a + UrlEncodedTarget> { + key: Option>, + urlencoder: &'a mut UrlEncodedSerializer, +} + +impl<'a, Target: 'a + UrlEncodedTarget> QsSerializer<'a, Target> { + fn extend_key(&mut self, newkey: &str) { + let key = if let Some(ref key) = self.key { + format!("{}[{}]", key, newkey).into() + } else { + newkey.to_owned().into() + }; + self.key = Some(key) + } + + fn write_value(&mut self, value: &str) -> Result<()> { + if let Some(ref key) = self.key { + self.urlencoder.append_pair(&key, value); + Ok(()) + } else { + Err(Error::no_key()) + } + } +} + +error_chain!{ + errors { + Custom(msg: String) + Unsupported + } +} + +impl Error { + fn top_level() -> Self { + let msg = "top-level serializer supports only maps and structs"; + msg.into() + } + + fn no_key() -> Self { + let msg = "tried to serialize a value before serializing key"; + msg.into() + } +} + +macro_rules! serialize_as_string { + (Qs $($ty:ty => $meth:ident,)*) => { + $( + fn $meth(self, v: $ty) -> Result { + self.write_value(&v.to_string()) + } + )* + }; + ($($ty:ty => $meth:ident,)*) => { + $( + fn $meth(self, v: $ty) -> Result { + Ok(v.to_string()) + } + )* + }; +} + +impl<'a, Target: 'a + UrlEncodedTarget> ser::Serializer for &'a mut QsSerializer<'a, Target> { + type Ok = (); + type Error = Error; + type SerializeSeq = QsSeq<'a, Target>; + type SerializeTuple = QsSeq<'a, Target>; + type SerializeTupleStruct = QsSeq<'a, Target>; + type SerializeTupleVariant = QsSeq<'a, Target>; + type SerializeMap = QsMap<'a, Target>; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + serialize_as_string!{ + Qs + bool => serialize_bool, + u8 => serialize_u8, + u16 => serialize_u16, + u32 => serialize_u32, + u64 => serialize_u64, + i8 => serialize_i8, + i16 => serialize_i16, + i32 => serialize_i32, + i64 => serialize_i64, + f32 => serialize_f32, + f64 => serialize_f64, + char => serialize_char, + &str => serialize_str, + // &[u8] => serialize_bytes, + } + + fn serialize_bytes(self, _value: &[u8]) -> Result { + Err(Error::top_level()) + } + + + fn serialize_unit(self) -> Result { + self.write_value("") + } + + /// Returns an error. + fn serialize_unit_struct(self, + name: &'static str) + -> Result { + self.write_value(name) + } + + /// Returns an error. + fn serialize_unit_variant(self, + _name: &'static str, + _variant_index: u32, + variant: &'static str) + -> Result { + self.write_value(variant) + } + + /// Returns an error. + fn serialize_newtype_struct + (self, + _name: &'static str, + value: &T) + -> Result { + value.serialize(self) + } + + /// Returns an error. + fn serialize_newtype_variant + (self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T) + -> Result { + self.extend_key(variant); + value.serialize(self) + } + + fn serialize_none(self) -> Result { + Ok(()) + } + + fn serialize_some + (self, + value: &T) + -> Result { + // Err(ErrorKind::Unsupported.into()) + value.serialize(self) + } + + /// Returns an error. + fn serialize_seq(self, + _len: Option) + -> Result { + Ok(QsSeq(self, 0)) + } + + + fn serialize_tuple(self, + _len: usize) + -> Result { + Ok(QsSeq(self, 0)) + } + + /// Returns an error. + fn serialize_tuple_struct(self, + _name: &'static str, + _len: usize) + -> Result { + Ok(QsSeq(self, 0)) + } + + fn serialize_tuple_variant + (self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize) + -> Result + { + // self.write(variant)?; + self.extend_key(variant); + Ok(QsSeq(self, 0)) + } + + fn serialize_map(self, + _len: Option) + -> Result { + Ok(QsMap(self, None)) + } + + fn serialize_struct(self, + _name: &'static str, + _len: usize) + -> Result { + Ok(self) + } + + fn serialize_struct_variant + (self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize) + -> Result + { + self.extend_key(variant); + Ok(self) + } +} + + +impl ser::Error for Error { + fn custom(msg: T) -> Self + where T: Display { + ErrorKind::Custom(msg.to_string()).into() + } +} + +pub struct QsSeq<'a, Target: 'a + UrlEncodedTarget>(&'a mut QsSerializer<'a, Target>, usize); +pub struct QsMap<'a, Target: 'a + UrlEncodedTarget>(&'a mut QsSerializer<'a, Target>, Option>); + + +impl<'a, Target: 'a + UrlEncodedTarget> ser::SerializeTuple for QsSeq<'a, Target> { + type Ok = (); + type Error = Error; + fn serialize_element(&mut self, value: &T) -> Result<()> + where T: ser::Serialize + { + let mut serializer = QsSerializer { key: self.0.key.clone(), urlencoder: self.0.urlencoder }; + serializer.extend_key(&self.1.to_string()); + self.1 += 1; + value.serialize(&mut serializer) + } + + fn end(self) -> Result { + Ok(()) + + } +} + +impl<'a, Target: 'a + UrlEncodedTarget> ser::SerializeSeq for QsSeq<'a, Target> { + type Ok = (); + type Error = Error; + fn serialize_element(&mut self, value: &T) -> Result<()> + where T: ser::Serialize + { + let mut serializer = QsSerializer { key: self.0.key.clone(), urlencoder: self.0.urlencoder }; + serializer.extend_key(&self.1.to_string()); + self.1 += 1; + value.serialize(&mut serializer) + } + fn end(self) -> Result { + Ok(()) + + } +} + +impl<'a, Target: 'a + UrlEncodedTarget> ser::SerializeStruct for &'a mut QsSerializer<'a, Target> { + type Ok = (); + type Error = Error; + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where T: ser::Serialize + { + let mut serializer = QsSerializer { key: self.key.clone(), urlencoder: self.urlencoder }; + serializer.extend_key(key); + value.serialize(&mut serializer) + } + fn end(self) -> Result { + Ok(()) + } +} + +impl<'a, Target: 'a + UrlEncodedTarget> ser::SerializeStructVariant for &'a mut QsSerializer<'a, Target> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where T: ser::Serialize + { + let mut serializer = QsSerializer { key: self.key.clone(), urlencoder: self.urlencoder }; + serializer.extend_key(key); + value.serialize(&mut serializer) + } + + fn end(self) -> Result { + Ok(()) + } + +} + +impl<'a, Target: 'a + UrlEncodedTarget> ser::SerializeTupleVariant for QsSeq<'a, Target> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where T: ser::Serialize + { + let mut serializer = QsSerializer { key: self.0.key.clone(), urlencoder: self.0.urlencoder }; + serializer.extend_key(&self.1.to_string()); + self.1 += 1; + value.serialize(&mut serializer) + } + + fn end(self) -> Result { + Ok(()) + } + +} + +impl<'a, Target: 'a + UrlEncodedTarget> ser::SerializeTupleStruct for QsSeq<'a, Target> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where T: ser::Serialize + { + let mut serializer = QsSerializer { key: self.0.key.clone(), urlencoder: self.0.urlencoder }; + serializer.extend_key(&self.1.to_string()); + self.1 += 1; + value.serialize(&mut serializer) + } + + fn end(self) -> Result { + Ok(()) + } + +} + +impl<'a, Target: 'a + UrlEncodedTarget> ser::SerializeMap for QsMap<'a, Target> { + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, key: &T) -> Result<()> + where T: ser::Serialize + { + self.1 = Some(Cow::from(key.serialize(StringSerializer)?)); + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<()> + where T: ser::Serialize + { + let mut serializer = QsSerializer { key: self.0.key.clone(), urlencoder: self.0.urlencoder }; + if let Some(ref key) = self.1 { + serializer.extend_key(key); + } else { + return Err(Error::no_key()); + } + self.1 = None; + value.serialize(&mut serializer) + } + + fn end(self) -> Result { + Ok(()) + } + + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<()> + where K: ser::Serialize, V: ser::Serialize, + { + let mut serializer = QsSerializer { key: self.0.key.clone(), urlencoder: self.0.urlencoder }; + serializer.extend_key(&key.serialize(StringSerializer)?); + value.serialize(&mut serializer) + } + +} + +struct StringSerializer; + +impl ser::Serializer for StringSerializer { + type Ok = String; + type Error = Error; + type SerializeSeq = ser::Impossible; + type SerializeTuple = ser::Impossible; + type SerializeTupleStruct = ser::Impossible; + type SerializeTupleVariant = ser::Impossible; + type SerializeMap = ser::Impossible; + type SerializeStruct = ser::Impossible; + type SerializeStructVariant = ser::Impossible; + + serialize_as_string!{ + bool => serialize_bool, + u8 => serialize_u8, + u16 => serialize_u16, + u32 => serialize_u32, + u64 => serialize_u64, + i8 => serialize_i8, + i16 => serialize_i16, + i32 => serialize_i32, + i64 => serialize_i64, + f32 => serialize_f32, + f64 => serialize_f64, + char => serialize_char, + &str => serialize_str, + } + + + fn serialize_bytes(self, value: &[u8]) -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_unit(self) -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_unit_struct(self, + _name: &'static str) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_unit_variant(self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_newtype_struct + (self, + _name: &'static str, + _value: &T) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_newtype_variant + (self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_none(self) -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_some + (self, + _value: &T) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_seq(self, + _len: Option) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + + fn serialize_tuple(self, + _len: usize) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + /// Returns an error. + fn serialize_tuple_struct(self, + _name: &'static str, + _len: usize) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + fn serialize_tuple_variant + (self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize) + -> Result + { + Err(ErrorKind::Unsupported.into()) + } + + fn serialize_map(self, + _len: Option) + -> Result { + Err(ErrorKind::Unsupported.into()) + + } + + fn serialize_struct(self, + _name: &'static str, + _len: usize) + -> Result { + Err(ErrorKind::Unsupported.into()) + } + + fn serialize_struct_variant + (self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize) + -> Result + { + Err(ErrorKind::Unsupported.into()) + } + +} + diff --git a/src/ser/key.rs b/src/ser/key.rs deleted file mode 100644 index 10f1fff..0000000 --- a/src/ser/key.rs +++ /dev/null @@ -1,108 +0,0 @@ -use ser::Error; -use ser::part::Sink; -use serde::Serialize; -use serde::ser::{SerializeSeq, SerializeStruct}; -use std::borrow::Cow; -use std::ops::Deref; - -pub enum Key<'key> { - Static(&'static str), - Dynamic(Cow<'key, str>), -} - -impl<'key> Deref for Key<'key> { - type Target = str; - - fn deref(&self) -> &str { - match *self { - Key::Static(key) => key, - Key::Dynamic(ref key) => key, - } - } -} - -impl<'key> From> for Cow<'static, str> { - fn from(key: Key<'key>) -> Self { - match key { - Key::Static(key) => key.into(), - Key::Dynamic(key) => key.into_owned().into(), - } - } -} - -pub struct KeySink { - end: End, -} - -impl KeySink - where End: for<'key> FnOnce(Key<'key>) -> Result, -{ - pub fn new(end: End) -> Self { - KeySink { end: end } - } -} - -impl Sink for KeySink - where End: for<'key> FnOnce(Key<'key>) -> Result, -{ - fn serialize_static_str(self, value: &'static str) -> Result { - (self.end)(Key::Static(value)) - } - - fn serialize_str(self, value: &str) -> Result { - (self.end)(Key::Dynamic(value.into())) - } - - fn serialize_string(self, value: String) -> Result { - (self.end)(Key::Dynamic(value.into())) - } - - fn serialize_none(self) -> Result { - Err(self.unsupported()) - } - - fn serialize_some(self, - _value: &T) - -> Result { - Err(self.unsupported()) - } - - fn unsupported(&self) -> Error { - Error::Custom("unsupported key".into()) - } -} - -impl SerializeStruct for KeySink - where End: for<'key> FnOnce(Key<'key>) -> Result, -{ - type Ok = Ok; - type Error = Error; - - fn serialize_field(&mut self, - _key: &'static str, - _value: &T) - -> Result<(), Error> { - Err(self.unsupported()) - } - - fn end(self) -> Result { - Err(self.unsupported()) - } -} - -impl SerializeSeq for KeySink - where End: for<'key> FnOnce(Key<'key>) -> Result, -{ - type Ok = Ok; - type Error = Error; - - fn serialize_element(&mut self, - _value: &T) - -> Result<(), Error> { - Err(self.unsupported()) - } - - fn end(self) -> Result { - Err(self.unsupported()) - } -} diff --git a/src/ser/mod.rs b/src/ser/mod.rs deleted file mode 100644 index df35995..0000000 --- a/src/ser/mod.rs +++ /dev/null @@ -1,519 +0,0 @@ -//! Serialization support for querystrings. - -mod key; -mod part; -mod value; - -use serde::ser; -use std::borrow::Cow; -use std::error; -use std::fmt; -use std::str; -use url::form_urlencoded::Serializer as UrlEncodedSerializer; -use url::form_urlencoded::Target as UrlEncodedTarget; - -/// Serializes a value into a querystring. -/// -/// ``` -/// # #[macro_use] -/// # extern crate serde_derive; -/// # extern crate serde_qs; -/// #[derive(Deserialize, Serialize)] -/// struct Query { -/// name: String, -/// age: u8, -/// occupation: String, -/// } -/// -/// # fn main(){ -/// let q = Query { -/// name: "Alice".to_owned(), -/// age: 24, -/// occupation: "Student".to_owned(), -/// }; -/// -/// -/// assert_eq!( -/// serde_qs::to_string(&q), -/// Ok("name=Alice&age=24&occupation=Student".to_owned())); -/// # } -/// ``` -pub fn to_string(input: &T) -> Result { - let mut urlencoder = UrlEncodedSerializer::new("".to_owned()); - input.serialize(Serializer::new(&mut urlencoder))?; - Ok(urlencoder.finish()) -} - -/// A serializer for the querystring format. -/// -/// * Supported top-level inputs are structs and maps. -/// -/// * Supported values are currently most primitive types, structs, maps and -/// sequences. Sequences are serialized with an incrementing key index. -/// -/// * Newtype structs defer to their inner values. -pub struct Serializer<'output, Target: 'output + UrlEncodedTarget> { - urlencoder: &'output mut UrlEncodedSerializer, -} - -impl<'output, Target: 'output + UrlEncodedTarget> Serializer<'output, Target> { - /// Returns a new `Serializer`. - pub fn new(urlencoder: &'output mut UrlEncodedSerializer) -> Self { - Serializer { urlencoder: urlencoder } - } -} - -/// Errors returned during serializing to querystring. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Error { - Custom(Cow<'static, str>), - Utf8(str::Utf8Error), -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::Custom(ref msg) => msg.fmt(f), - Error::Utf8(ref err) => write!(f, "invalid UTF-8: {}", err), - } - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - match *self { - Error::Custom(ref msg) => msg, - Error::Utf8(ref err) => error::Error::description(err), - } - } - - /// The lower-level cause of this error, in the case of a `Utf8` error. - fn cause(&self) -> Option<&error::Error> { - match *self { - Error::Custom(_) => None, - Error::Utf8(ref err) => Some(err), - } - } -} - -impl ser::Error for Error { - fn custom(msg: T) -> Self { - Error::Custom(format!("{}", msg).into()) - } -} - -/// Sequence serializer. -pub struct SeqSerializer<'output, T: 'output + UrlEncodedTarget> { - inner: ser::Impossible<&'output mut UrlEncodedSerializer, Error>, -} - -/// Tuple serializer. -/// -/// Never instantiated, tuples are not supported at top-level. -pub struct TupleSerializer<'output, T: 'output + UrlEncodedTarget> { - inner: ser::Impossible<&'output mut UrlEncodedSerializer, Error>, -} - -/// Tuple struct serializer. -/// -/// Never instantiated, tuple structs are not supported. -pub struct TupleStructSerializer<'output, T: 'output + UrlEncodedTarget> { - inner: ser::Impossible<&'output mut UrlEncodedSerializer, Error>, -} - -/// Tuple variant serializer. -/// -/// Never instantiated, tuple variants are not supported. -pub struct TupleVariantSerializer<'output, T: 'output + UrlEncodedTarget> { - inner: ser::Impossible<&'output mut UrlEncodedSerializer, Error>, -} - -/// Map serializer. -pub struct MapSerializer<'output, Target: 'output + UrlEncodedTarget> { - urlencoder: &'output mut UrlEncodedSerializer, - key: Option>, -} - -/// Struct serializer. -pub struct StructSerializer<'output, Target: 'output + UrlEncodedTarget> { - urlencoder: &'output mut UrlEncodedSerializer, -} - -/// Struct variant serializer. -/// -/// Never instantiated, struct variants are not supported. -pub struct StructVariantSerializer<'output, T: 'output + UrlEncodedTarget> { - inner: ser::Impossible<&'output mut UrlEncodedSerializer, Error>, -} - -impl<'output, Target> ser::Serializer for Serializer<'output, Target> - where Target: 'output + UrlEncodedTarget, -{ - type Ok = &'output mut UrlEncodedSerializer; - type Error = Error; - type SerializeSeq = SeqSerializer<'output, Target>; - type SerializeTuple = TupleSerializer<'output, Target>; - type SerializeTupleStruct = TupleStructSerializer<'output, Target>; - type SerializeTupleVariant = TupleVariantSerializer<'output, Target>; - type SerializeMap = MapSerializer<'output, Target>; - type SerializeStruct = StructSerializer<'output, Target>; - type SerializeStructVariant = StructVariantSerializer<'output, Target>; - - /// Returns an error. - fn serialize_bool(self, _v: bool) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_i8(self, _v: i8) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_i16(self, _v: i16) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_i32(self, _v: i32) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_i64(self, _v: i64) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_u8(self, _v: u8) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_u16(self, _v: u16) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_u32(self, _v: u32) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_u64(self, _v: u64) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_f32(self, _v: f32) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_f64(self, _v: f64) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_char(self, _v: char) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_str(self, _value: &str) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_bytes(self, _value: &[u8]) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_unit(self) -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_unit_struct(self, - _name: &'static str) - -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_unit_variant(self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str) - -> Result { - Err(Error::top_level()) - } - - /// Serializes the inner value, ignoring the newtype name. - fn serialize_newtype_struct - (self, - _name: &'static str, - value: &T) - -> Result { - value.serialize(self) - } - - /// Returns an error. - fn serialize_newtype_variant - (self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _value: &T) - -> Result { - Err(Error::top_level()) - } - - /// Returns `Ok`. - fn serialize_none(self) -> Result { - Ok(self.urlencoder) - } - - /// Serializes the given value. - fn serialize_some - (self, - value: &T) - -> Result { - value.serialize(self) - } - - /// Serialize a sequence, given length (if any) is ignored. - fn serialize_seq(self, - _len: Option) - -> Result { - Err(Error::top_level()) - } - - - /// Returns an error. - fn serialize_tuple(self, - _len: usize) - -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_tuple_struct(self, - _name: &'static str, - _len: usize) - -> Result { - Err(Error::top_level()) - } - - /// Returns an error. - fn serialize_tuple_variant - (self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize) - -> Result { - Err(Error::top_level()) - } - - /// Serializes a map, given length is ignored. - fn serialize_map(self, - _len: Option) - -> Result { - Ok(MapSerializer { - urlencoder: self.urlencoder, - key: None, - }) - } - - /// Serializes a struct, given length is ignored. - fn serialize_struct(self, - _name: &'static str, - _len: usize) - -> Result { - Ok(StructSerializer { urlencoder: self.urlencoder }) - } - - /// Returns an error. - fn serialize_struct_variant - (self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize) - -> Result { - Err(Error::top_level()) - } -} - -impl<'output, Target> ser::SerializeSeq for SeqSerializer<'output, Target> - where Target: 'output + UrlEncodedTarget, -{ - type Ok = &'output mut UrlEncodedSerializer; - type Error = Error; - - fn serialize_element(&mut self, - value: &T) - -> Result<(), Error> { - self.inner.serialize_element(value) - } - - fn end(self) -> Result { - self.inner.end() - } -} - - -impl<'output, Target> ser::SerializeTuple for TupleSerializer<'output, Target> - where Target: 'output + UrlEncodedTarget, -{ - type Ok = &'output mut UrlEncodedSerializer; - type Error = Error; - - fn serialize_element(&mut self, - value: &T) - -> Result<(), Error> { - self.inner.serialize_element(value) - } - - fn end(self) -> Result { - self.inner.end() - } -} - -impl<'output, Target> ser::SerializeTupleStruct - for - TupleStructSerializer<'output, Target> - where Target: 'output + UrlEncodedTarget, -{ - type Ok = &'output mut UrlEncodedSerializer; - type Error = Error; - - fn serialize_field(&mut self, - value: &T) - -> Result<(), Error> { - self.inner.serialize_field(value) - } - - fn end(self) -> Result { - self.inner.end() - } -} - -impl<'output, Target> ser::SerializeTupleVariant - for - TupleVariantSerializer<'output, Target> - where Target: 'output + UrlEncodedTarget, -{ - type Ok = &'output mut UrlEncodedSerializer; - type Error = Error; - - fn serialize_field(&mut self, - value: &T) - -> Result<(), Error> { - self.inner.serialize_field(value) - } - - fn end(self) -> Result { - self.inner.end() - } -} - -impl<'output, Target> ser::SerializeMap for MapSerializer<'output, Target> - where Target: 'output + UrlEncodedTarget, -{ - type Ok = &'output mut UrlEncodedSerializer; - type Error = Error; - - fn serialize_entry - (&mut self, - key: &K, - value: &V) - -> Result<(), Error> { - let key_sink = key::KeySink::new(|key| { - let value_sink = value::ValueSink::new(self.urlencoder, &key); - value.serialize(part::PartSerializer::new(value_sink))?; - self.key = None; - Ok(()) - }); - let entry_serializer = part::PartSerializer::new(key_sink); - key.serialize(entry_serializer) - } - - fn serialize_key(&mut self, - key: &T) - -> Result<(), Error> { - let key_sink = key::KeySink::new(|key| Ok(key.into())); - let key_serializer = part::PartSerializer::new(key_sink); - self.key = Some(key.serialize(key_serializer)?); - Ok(()) - } - - fn serialize_value(&mut self, - value: &T) - -> Result<(), Error> { - { - let key = self.key.as_ref().ok_or_else(Error::no_key)?; - let value_sink = value::ValueSink::new(self.urlencoder, key); - value.serialize(part::PartSerializer::new(value_sink))?; - } - self.key = None; - Ok(()) - } - - fn end(self) -> Result { - Ok(self.urlencoder) - } -} - -impl<'output, Target> ser::SerializeStruct for StructSerializer<'output, Target> - where Target: 'output + UrlEncodedTarget, -{ - type Ok = &'output mut UrlEncodedSerializer; - type Error = Error; - - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), Error> { - let value_sink = value::ValueSink::new(self.urlencoder, key); - value.serialize(part::PartSerializer::new(value_sink)) - } - - fn end(self) -> Result { - Ok(self.urlencoder) - } -} - -impl<'output, Target> ser::SerializeStructVariant - for - StructVariantSerializer<'output, Target> - where Target: 'output + UrlEncodedTarget, -{ - type Ok = &'output mut UrlEncodedSerializer; - type Error = Error; - - fn serialize_field(&mut self, - key: &'static str, - value: &T) - -> Result<(), Error> { - self.inner.serialize_field(key, value) - } - - fn end(self) -> Result { - self.inner.end() - } -} - -impl Error { - fn top_level() -> Self { - let msg = "top-level serializer supports only maps and structs"; - Error::Custom(msg.into()) - } - - fn no_key() -> Self { - let msg = "tried to serialize a value before serializing key"; - Error::Custom(msg.into()) - } -} diff --git a/src/ser/part.rs b/src/ser/part.rs deleted file mode 100644 index ad2d9dd..0000000 --- a/src/ser/part.rs +++ /dev/null @@ -1,232 +0,0 @@ -use dtoa; -use itoa; -use ser::Error; -use serde; -use serde::ser; -use std::marker::PhantomData; -use std::str; - -pub struct PartSerializer> { - sink: S, - marker: PhantomData, -} - -impl> PartSerializer { - pub fn new(sink: S) -> Self { - PartSerializer { - sink: sink, - marker: PhantomData, - } - } -} - -pub trait Sink: Sized + ser::SerializeStruct - + ser::SerializeSeq - where E: serde::ser::Error -{ -// type Ok; -// type Error; - fn serialize_static_str(self, - value: &'static str) - -> Result; - - fn serialize_str(self, value: &str) -> Result; - fn serialize_string(self, value: String) -> Result; - fn serialize_none(self) -> Result; - - fn serialize_some - (self, - value: &T) - -> Result; - - fn unsupported(&self) -> Error; -} - -impl> ser::Serializer for PartSerializer { - type Ok = SO; - type Error = Error; - type SerializeSeq = S; - type SerializeTuple = ser::Impossible; - type SerializeTupleStruct = ser::Impossible; - type SerializeTupleVariant = ser::Impossible; - type SerializeMap = ser::Impossible; - type SerializeStruct = S; - type SerializeStructVariant = ser::Impossible; - - fn serialize_bool(self, v: bool) -> Result { - self.sink.serialize_static_str(if v { "true" } else { "false" }) - } - - fn serialize_i8(self, v: i8) -> Result { - self.serialize_integer(v) - } - - fn serialize_i16(self, v: i16) -> Result { - self.serialize_integer(v) - } - - fn serialize_i32(self, v: i32) -> Result { - self.serialize_integer(v) - } - - fn serialize_i64(self, v: i64) -> Result { - self.serialize_integer(v) - } - - fn serialize_u8(self, v: u8) -> Result { - self.serialize_integer(v) - } - - fn serialize_u16(self, v: u16) -> Result { - self.serialize_integer(v) - } - - fn serialize_u32(self, v: u32) -> Result { - self.serialize_integer(v) - } - - fn serialize_u64(self, v: u64) -> Result { - self.serialize_integer(v) - } - - fn serialize_f32(self, v: f32) -> Result { - self.serialize_floating(v) - } - - fn serialize_f64(self, v: f64) -> Result { - self.serialize_floating(v) - } - - fn serialize_char(self, v: char) -> Result { - self.sink.serialize_string(v.to_string()) - } - - fn serialize_str(self, value: &str) -> Result { - self.sink.serialize_str(value) - } - - fn serialize_bytes(self, value: &[u8]) -> Result { - match str::from_utf8(value) { - Ok(value) => self.sink.serialize_str(value), - Err(err) => Err(Error::Utf8(err)), - } - } - - fn serialize_unit(self) -> Result { - Err(self.sink.unsupported()) - } - - fn serialize_unit_struct(self, name: &'static str) -> Result { - self.sink.serialize_static_str(name.into()) - } - - fn serialize_unit_variant(self, - _name: &'static str, - _variant_index: u32, - variant: &'static str) - -> Result { - self.sink.serialize_static_str(variant.into()) - } - - fn serialize_newtype_struct - (self, - _name: &'static str, - value: &T) - -> Result { - value.serialize(self) - } - - fn serialize_newtype_variant - (self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _value: &T) - -> Result { - Err(self.sink.unsupported()) - } - - fn serialize_none(self) -> Result { - self.sink.serialize_none() - } - - fn serialize_some(self, - value: &T) - -> Result { - self.sink.serialize_some(value) - } - - fn serialize_seq(self, - _len: Option) - -> Result { - Ok(self.sink) - } - - fn serialize_tuple(self, - _len: usize) - -> Result { - Err(self.sink.unsupported()) - } - - fn serialize_tuple_struct(self, - _name: &'static str, - _len: usize) - -> Result { - Err(self.sink.unsupported()) - } - - fn serialize_tuple_variant - (self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize) - -> Result { - Err(self.sink.unsupported()) - } - - fn serialize_map(self, - _len: Option) - -> Result { - Err(self.sink.unsupported()) - } - - fn serialize_struct(self, - _name: &'static str, - _len: usize) - -> Result { - // Err(self.sink.unsupported()) - Ok(self.sink) - - } - - fn serialize_struct_variant - (self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize) - -> Result { - Err(self.sink.unsupported()) - } -} - -impl> PartSerializer { - fn serialize_integer(self, value: I) -> Result - where I: itoa::Integer, - { - let mut buf = [b'\0'; 20]; - let len = itoa::write(&mut buf[..], value).unwrap(); - let part = unsafe { str::from_utf8_unchecked(&buf[0..len]) }; - ser::Serializer::serialize_str(self, part) - } - - fn serialize_floating(self, value: F) -> Result - where F: dtoa::Floating, - { - let mut buf = [b'\0'; 24]; - let len = dtoa::write(&mut buf[..], value).unwrap(); - let part = unsafe { str::from_utf8_unchecked(&buf[0..len]) }; - ser::Serializer::serialize_str(self, part) - } -} diff --git a/src/ser/value.rs b/src/ser/value.rs deleted file mode 100644 index f2fc617..0000000 --- a/src/ser/value.rs +++ /dev/null @@ -1,102 +0,0 @@ -use ser::Error; -use ser::part::{PartSerializer, Sink}; -use serde::ser::{Serialize, SerializeSeq, SerializeStruct}; -use std::str; -use url::form_urlencoded::Serializer as UrlEncodedSerializer; -use url::form_urlencoded::Target as UrlEncodedTarget; - -pub struct ValueSink<'key, 'target, Target> - where Target: 'target + UrlEncodedTarget, -{ - urlencoder: &'target mut UrlEncodedSerializer, - key: &'key str, - idx: usize, -} - -impl<'key, 'target, Target> ValueSink<'key, 'target, Target> - where Target: 'target + UrlEncodedTarget, -{ - pub fn new(urlencoder: &'target mut UrlEncodedSerializer, - key: &'key str) - -> Self { - ValueSink { - urlencoder: urlencoder, - key: key, - idx: 0, - } - } -} - -impl<'key, 'target, Target> Sink<(), Error> for ValueSink<'key, 'target, Target> - where Target: 'target + UrlEncodedTarget, -{ - // type Ok = (); - - fn serialize_str(self, value: &str) -> Result<(), Error> { - self.urlencoder.append_pair(self.key, value); - Ok(()) - } - - fn serialize_static_str(self, value: &'static str) -> Result<(), Error> { - self.serialize_str(value) - } - - fn serialize_string(self, value: String) -> Result<(), Error> { - self.serialize_str(&value) - } - - fn serialize_none(self) -> Result<(), Error> { - Ok(()) - } - - fn serialize_some(self, - value: &T) - -> Result<(), Error> { - value.serialize(PartSerializer::new(self)) - } - - fn unsupported(&self) -> Error { - 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(&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 { - Ok(()) - } -} - -impl<'key, 'target, Target> SerializeSeq for ValueSink<'key, 'target, Target> - where Target: 'target + UrlEncodedTarget, -{ - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, - value: &T) - -> Result<(), Error> { - let newk = format!("{}[{}]", self.key, self.idx); - self.idx += 1; - let value_sink = ValueSink::new(self.urlencoder, &newk); - value.serialize(super::part::PartSerializer::new(value_sink)) - } - - fn end(self) -> Result { - Ok(()) - } -} diff --git a/tests/test_deserialize.rs b/tests/test_deserialize.rs index 569be0c..5d6d2c6 100644 --- a/tests/test_deserialize.rs +++ b/tests/test_deserialize.rs @@ -333,3 +333,38 @@ fn deserialize_enum_adjacently() { let rec_params: Query = qs::from_str(params).unwrap(); assert_eq!(rec_params, Query { e: E::S("other".to_string()), v: None }); } + +#[test] +fn deserialize_enum() { + #[derive(Deserialize, Debug, PartialEq)] + struct NewU8(u8); + + #[derive(Deserialize, Debug, PartialEq)] + enum E { + B, + S(String), + } + + #[derive(Deserialize, Debug, PartialEq)] + enum V { + V1 { x: u8, y: u16 }, + V2(String), + } + + #[derive(Deserialize, Debug, PartialEq)] + struct Query { + e: E, + v: Option, + u: NewU8, + } + + let params = "e=B&v[V1][x]=12&v[V1][y]=300&u=12"; + let rec_params: Query = qs::from_str(params).unwrap(); + assert_eq!(rec_params, + Query { e: E::B, v: Some(V::V1 { x: 12, y: 300 }), u: NewU8(12) } + ); + + let params = "e[S]=other&u=1"; + let rec_params: Query = qs::from_str(params).unwrap(); + assert_eq!(rec_params, Query { e: E::S("other".to_string()), v: None, u: NewU8(1) }); +} diff --git a/tests/test_serialize.rs b/tests/test_serialize.rs index 5751ff6..7d9c38f 100644 --- a/tests/test_serialize.rs +++ b/tests/test_serialize.rs @@ -63,3 +63,50 @@ fn serialize_option() { let rec_params = qs::to_string(&query).unwrap(); assert_eq!(rec_params, params); } + +#[test] +fn serialize_enum() { + #[derive(Debug,Serialize,Deserialize,PartialEq)] + #[serde(rename_all = "lowercase")] + enum TestEnum { + A, + B(bool), + C { x: u8, y: u8}, + D(u8, u8), + } + + #[derive(Debug,Serialize,Deserialize,PartialEq)] + struct Query { + e: TestEnum, + } + + let params = urlencode("e=a"); + let query = Query { + e: TestEnum::A, + }; + let rec_params = qs::to_string(&query).unwrap(); + assert_eq!(rec_params, params); + + let params = urlencode("e[b]=true"); + let query = Query { + e: TestEnum::B(true), + }; + let rec_params = qs::to_string(&query).unwrap(); + assert_eq!(rec_params, params); + + let params = urlencode("e[c][x]=2&e[c][y]=3"); + let query = Query { + e: TestEnum::C { x: 2, y: 3 }, + }; + let rec_params = qs::to_string(&query).unwrap(); + assert_eq!(rec_params, params); + + let params = urlencode("e[d][0]=128&e[d][1]=1"); + let query = Query { + e: TestEnum::D(128, 1), + }; + let rec_params = qs::to_string(&query).unwrap(); + assert_eq!(rec_params, params); + + +} \ No newline at end of file -- cgit v1.2.3