//! Deserialization support for querystrings. use serde::de; #[doc(inline)] pub use serde::de::value::Error; use serde::de::value::MapDeserializer; use std::collections::btree_map::{BTreeMap, Entry, IntoIter}; use std::io::Read; use url::percent_encoding; /// To override the default serialization parameters, first construct a new /// Config. /// /// A `max_depth` of 0 implies no nesting: the result will be a flat map. /// This is mostly useful when the maximum nested depth is known beforehand, /// to prevent denial of service attacks by providing incredibly deeply nested /// inputs. /// /// ``` /// use serde_qs::de::Config; /// use std::collections::HashMap; /// /// let mut config = Config::default(); /// config.max_depth(0); /// let map: HashMap = config.deserialize_str("a[b][c]=1") /// .unwrap(); /// assert_eq!(map.get("a[b][c]").unwrap(), "1"); /// /// config.max_depth(10); /// let map: HashMap>> = /// config.deserialize_str("a[b][c]=1").unwrap(); /// assert_eq!(map.get("a").unwrap().get("b").unwrap().get("c").unwrap(), "1"); /// ``` /// pub struct Config { /// Specifies the maximum depth key that `serde_qs` will attempt to /// deserialize. Default is 5. max_depth: usize, } impl Default for Config { fn default() -> Self { Config { max_depth: 5 } } } impl Config { pub fn max_depth(&mut self, depth: usize) { self.max_depth = depth; } } impl Config { pub fn deserialize_bytes<'de, T: de::Deserialize<'de>>(&self, input: &[u8]) -> Result { T::deserialize(Deserializer::with_config(self, input)) } pub fn deserialize_str<'de, T: de::Deserialize<'de>>(&self, input: &str) -> Result { self.deserialize_bytes(input.as_bytes()) } pub fn deserialize_reader<'de, T, R>(&self, mut reader: R) -> Result where T: de::Deserialize<'de>, R: Read, { let mut buf = vec![]; reader.read_to_end(&mut buf) .map_err(|e| { de::Error::custom(format_args!("could not read input: {}", e)) })?; self.deserialize_bytes(&buf) // from_bytes(&buf) // T::deserialize(Deserializer::with_config(self, input.as_bytes())) } } /// Deserializes a querystring from a `&[u8]`. /// /// ``` /// # #[macro_use] /// # extern crate serde_derive; /// # extern crate serde_qs; /// #[derive(Debug, Deserialize, PartialEq, 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::from_bytes::( /// "name=Alice&age=24&occupation=Student".as_bytes() /// ), /// Ok(q)); /// # } /// ``` pub fn from_bytes<'de, T: de::Deserialize<'de>>(input: &[u8]) -> Result { Config::default().deserialize_bytes(input) } /// Deserializes a querystring from a `&str`. /// /// ``` /// # #[macro_use] /// # extern crate serde_derive; /// # extern crate serde_qs; /// #[derive(Debug, Deserialize, PartialEq, 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::from_str::("name=Alice&age=24&occupation=Student"), /// Ok(q)); /// # } /// ``` pub fn from_str<'de, T: de::Deserialize<'de>>(input: &str) -> Result { from_bytes(input.as_bytes()) } /// Convenience function that reads all bytes from `reader` and deserializes /// them with `from_bytes`. pub fn from_reader<'de, T, R>(mut reader: R) -> Result where T: de::Deserialize<'de>, R: Read, { let mut buf = vec![]; reader.read_to_end(&mut buf) .map_err(|e| { de::Error::custom(format_args!("could not read input: {}", e)) })?; from_bytes(&buf) } /// A deserializer for the querystring format. /// /// Supported top-level outputs are structs and maps. pub struct Deserializer { iter: IntoIter, value: Option, } #[derive(Debug)] enum Level { Nested(BTreeMap), Sequence(Vec), Flat(String), Invalid(&'static str), } macro_rules! tu { ($x:expr) => ( match $x { Some(x) => x, None => return Err( de::Error::custom("query string ended before expected")) } ) } use std::iter::Iterator; use std::str; struct Parser> { inner: I, acc: Vec, peeked: Option, depth: usize, } impl> Iterator for Parser { type Item = u8; #[inline] fn next(&mut self) -> Option { self.inner.next() } } fn insert_into_map(node: &mut Level, key: String, value: String) { if let Level::Nested(ref mut map) = *node { match map.entry(key) { Entry::Occupied(mut o) => { o.insert(Level::Invalid("Multiple values for one key")); }, Entry::Vacant(vm) => { vm.insert(Level::Flat(value)); }, } } else { let mut map = BTreeMap::default(); map.insert(key, Level::Flat(value)); *node = Level::Nested(map); } } impl> Parser { #[inline] fn peek(&mut self) -> Option<::Item> { if !self.acc.is_empty() { self.peeked } else if let Some(x) = self.inner.next() { self.acc.push(x); self.peeked = Some(x); Some(x) } else { None } } fn parse_key(&mut self, end_on: u8, consume: bool) -> Result { loop { if let Some(x) = self.next() { match x { x if x == end_on => { let res = String::from_utf8(self.acc.split_off(0)); self.acc.clear(); // Add this character back to the buffer for peek. if !consume { self.acc.push(x); self.peeked = Some(x); } return res.map_err(|_| de::Error::custom("blah")); }, b'=' => { // Allow the '=' byte when parsing keys within [] if end_on == b']' { self.acc.push(b'='); } else { let res = String::from_utf8(self.acc.split_off(0)); self.acc.clear(); // Add this character back to the buffer for peek. self.acc.push(b'='); self.peeked = Some(b'='); return res.map_err(|_| de::Error::custom("blah")); } }, b' ' => { self.acc.push(b' '); }, b'&' => { let res = String::from_utf8(self.acc.split_off(0)); self.acc.clear(); self.acc.push(b'&'); self.peeked = Some(b'&'); return res.map_err(|_| de::Error::custom("blah")); }, x @ 0x20...0x7e => { self.acc.push(x); }, _ => { return Err(de::Error::custom("unexpected character \ in query string.")); }, } } else { // End of string. let res = String::from_utf8(self.acc.split_off(0)); self.acc.clear(); return res.map_err(|_| de::Error::custom("blah")); } } } fn parse_map_value(&mut self, key: String, node: &mut Level) -> Result<(), Error> { if let Some(x) = self.peek() { match x { b'=' => { self.acc.clear(); for b in self.inner.by_ref().take_while(|b| b != &b'&') { if b == b'+' { self.acc.push(b' '); } else { self.acc.push(b); } } let value = String::from_utf8(self.acc.split_off(0)); let value = value.map_err(|_e| de::Error::custom("blah"))?; // Reached the end of the key string insert_into_map(node, key, value); Ok(()) }, b'&' => { insert_into_map(node, key, "".to_string()); Ok(()) }, b'[' => { if let Level::Invalid(_) = *node { *node = Level::Nested(BTreeMap::default()); } if let Level::Nested(ref mut map) = *node { self.depth -= 1; self.parse(map.entry(key) .or_insert(Level::Invalid("uninitialised")))?; Ok(()) } else { Err(de::Error::custom(format!("tried to insert a \ new key into {:?}", node))) } }, _ => { panic!("Unexpected character"); }, } } else { insert_into_map(node, key, "".to_string()); Ok(()) } } fn parse_seq_value(&mut self, node: &mut Level) -> Result<(), Error> { match tu!(self.peek()) { b'=' => { self.acc.clear(); for b in self.inner.by_ref().take_while(|b| b != &b'&') { self.acc.push(b); } let value = String::from_utf8(self.acc.split_off(0)) .map(|s| s.into()); let value = value.map_err(|e| de::Error::custom(e.to_string()))?; // Reached the end of the key string if let Level::Sequence(ref mut seq) = *node { seq.push(Level::Flat(value)); } else { let mut seq = Vec::new(); seq.push(Level::Flat(value)); *node = Level::Sequence(seq); } Ok(()) }, _ => { Err(de::Error::custom("non-indexed sequence of structs not \ supported")) }, } } fn parse(&mut self, node: &mut Level) -> Result { // First character determines parsing type if self.depth == 0 { let key = self.parse_key(b'\x00', true)?; self.parse_map_value(key.into(), node)?; self.depth += 1; return Ok(true); } match self.peek() { Some(x) => { match x { b'[' => { self.acc.clear(); // let _ = self.next(); match tu!(self.peek()) { // key is of the form "[...", not really allowed. b'[' => { panic!(""); }, // 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) }, // 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) }, _ => { panic!(""); }, } }, // This means the key should be a root key // of the form "abc" or "abc[...]" 0x20...0x7e => { let key = self.parse_key(b'[', false)?; self.parse_map_value(key.into(), node)?; self.depth += 1; Ok(true) }, _ => { panic!(""); }, } }, // Ran out of characters to parse None => Ok(false), } } } impl Deserializer { fn with_map(map: BTreeMap) -> Self { Deserializer { iter: map.into_iter(), value: None, } } /// Returns a new `Deserializer`. fn with_config(config: &Config, input: &[u8]) -> Self { let map = BTreeMap::default(); let mut root = Level::Nested(map); let decoded = percent_encoding::percent_decode(input); let mut parser = Parser { inner: decoded, acc: Vec::new(), peeked: None, depth: config.max_depth, }; while let Ok(x) = parser.parse(&mut root) { if !x { break; } } let iter = match root { Level::Nested(map) => map.into_iter(), _ => panic!(""), }; Deserializer { iter: iter, value: None, } } } impl<'de> de::Deserializer<'de> for Deserializer { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { self.deserialize_map(visitor) } fn deserialize_map(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_map(self) } fn deserialize_struct(self, _name: &'static str, _fields: &'static [&'static str], visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_map(self) } fn deserialize_seq(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_seq(MapDeserializer::new(self.iter)) } forward_to_deserialize_any! { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bytes byte_buf unit_struct // seq // seq_fixed_size newtype_struct tuple_struct // struct identifier // struct_field tuple enum ignored_any } } use serde::de::IntoDeserializer; use serde::de::value::SeqDeserializer; impl<'de> de::MapAccess<'de> for Deserializer { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result, 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); }; Ok(None) } fn next_value_seed(&mut self, seed: V) -> Result where V: de::DeserializeSeed<'de>, { if let Some(v) = self.value.take() { seed.deserialize(v.into_deserializer()) } else { Err(de::Error::custom("Somehow the list was empty after a \ non-empty key was returned")) } } } struct LevelDeserializer(Level); macro_rules! deserialize_primitive { ($ty:ident, $method:ident, $visit_method:ident) => ( fn $method(self, visitor: V) -> Result where V: de::Visitor<'de>, { match self.0 { Level::Nested(_) => { Err(de::Error::custom(format!("Expected: {:?}, got a Map", stringify!($ty)))) }, Level::Sequence(_) => { Err(de::Error::custom(format!("Expected: {:?}, got a Sequence", stringify!($ty)))) }, Level::Flat(x) => { let val = str::FromStr::from_str(&x) .map_err(|e| de::Error::custom(e))?; visitor.$visit_method(val) }, Level::Invalid(e) => { Err(de::Error::custom(e)) } } } ) } impl<'de> de::Deserializer<'de> for LevelDeserializer { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { match self.0 { Level::Nested(map) => { Deserializer::with_map(map).deserialize_map(visitor) }, Level::Sequence(seq) => { SeqDeserializer::new(seq.into_iter()).deserialize_any(visitor) }, Level::Flat(x) => { visitor.visit_string(x) }, Level::Invalid(e) => { Err(de::Error::custom(e)) } } } 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) }, Level::Sequence(x) => { SeqDeserializer::new(x.into_iter()).deserialize_any(visitor) }, Level::Flat(x) => { SeqDeserializer::new(vec![x].into_iter()).deserialize_any(visitor) }, _ => { Err(de::Error::custom("value does not appear to be a sequence")) }, } } fn deserialize_option(self, visitor: V) -> Result where V: de::Visitor<'de>, { match self.0 { Level::Flat(ref x) if x == "" => { visitor.visit_none() }, _ => { visitor.visit_some(self) }, } } deserialize_primitive!(bool, deserialize_bool, visit_bool); deserialize_primitive!(i8, deserialize_i8, visit_i8); deserialize_primitive!(i16, deserialize_i16, visit_i16); deserialize_primitive!(i32, deserialize_i32, visit_i32); deserialize_primitive!(i64, deserialize_i64, visit_i64); deserialize_primitive!(u8, deserialize_u8, visit_u8); deserialize_primitive!(u16, deserialize_u16, visit_u16); deserialize_primitive!(u32, deserialize_u32, visit_u32); deserialize_primitive!(u64, deserialize_u64, visit_u64); deserialize_primitive!(f32, deserialize_f32, visit_f32); deserialize_primitive!(f64, deserialize_f64, visit_f64); forward_to_deserialize_any! { char str string unit bytes byte_buf unit_struct newtype_struct tuple_struct identifier tuple enum ignored_any } } impl<'de> IntoDeserializer<'de> for Level { type Deserializer = LevelDeserializer; fn into_deserializer(self) -> Self::Deserializer { LevelDeserializer(self) } }