diff options
author | Sam Scott <sam.scott89@gmail.com> | 2017-05-22 10:49:22 +0100 |
---|---|---|
committer | Sam Scott <sam.scott89@gmail.com> | 2017-05-23 09:22:22 +0100 |
commit | 6f22cff63ad58c722293f8d74c978a0bf616be67 (patch) | |
tree | 8cdf62226bb51742ed1bcb03ad6047d4fa332f19 /src/de | |
parent | 071affd963ed88bfdcede6aa7b20626d3cf0f368 (diff) |
Add detection of indexed sequences.
Clean up the code in places.
Diffstat (limited to 'src/de')
-rw-r--r-- | src/de/mod.rs | 126 | ||||
-rw-r--r-- | src/de/parse.rs | 100 |
2 files changed, 118 insertions, 108 deletions
diff --git a/src/de/mod.rs b/src/de/mod.rs index cf32c5e..ce4124a 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -32,8 +32,8 @@ //! be thought of as similar to the `serde_json::Value` enum. //! //! Each `Level` can be deserialized through `LevelDeserializer`. This will -//! recursively call back to the top level `QsDeserializer`, or when `Level` is -//! a flat value it will attempt to deserialize it to a primitive via +//! recursively call back to the top level `QsDeserializer` for maps, or when +//! `Level` is a flat value it will attempt to deserialize it to a primitive via //! `ParsableStringDeserializer`. @@ -43,8 +43,6 @@ mod parse; pub use de::parse::Config; use error::*; -use data_encoding::base64url as base64; - use serde::de; use serde::de::IntoDeserializer; @@ -135,6 +133,7 @@ pub struct QsDeserializer { #[derive(Debug)] enum Level { Nested(BTreeMap<String, Level>), + OrderedSeq(BTreeMap<usize, Level>), Sequence(Vec<Level>), Flat(String), Invalid(&'static str), @@ -436,6 +435,10 @@ macro_rules! deserialize_primitive { Err(de::Error::custom(format!("Expected: {:?}, got a Map", stringify!($ty)))) }, + Level::OrderedSeq(_) => { + Err(de::Error::custom(format!("Expected: {:?}, got an OrderedSequence", + stringify!($ty)))) + }, Level::Sequence(_) => { Err(de::Error::custom(format!("Expected: {:?}, got a Sequence", stringify!($ty)))) @@ -459,7 +462,7 @@ impl LevelDeserializer { }, Level::Invalid(e) => { Err(de::Error::custom(e)) - } + }, l => { Err(de::Error::custom(format!("could not convert {:?} to QsDeserializer", l))) }, @@ -475,11 +478,13 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { { match self.0 { Level::Nested(_) => { - self.deserialize_map(visitor) + self.into_deserializer()?.deserialize_map(visitor) }, - Level::Sequence(_) => { - self.deserialize_seq(visitor) - + Level::OrderedSeq(map) => { + visitor.visit_seq(LevelSeq(map.into_iter().map(|(_k, v)| v))) + }, + Level::Sequence(seq) => { + visitor.visit_seq(LevelSeq(seq.into_iter())) }, Level::Flat(x) => { visitor.visit_string(x) @@ -490,25 +495,6 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { } } - fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value> - where V: de::Visitor<'de>, - { - match self.0 { - Level::Nested(map) => { - visitor.visit_seq(LevelSeq(map.into_iter().map(|(_k, v)| v))) - }, - Level::Sequence(x) => { - visitor.visit_seq(LevelSeq(x.into_iter())) - }, - Level::Invalid(e) => { - Err(de::Error::custom(e)) - }, - x => { - visitor.visit_seq(LevelSeq(vec![x].into_iter())) - }, - } - } - fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>, { @@ -543,23 +529,6 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { } } - fn deserialize_map<V>(self, visitor: V) -> Result<V::Value> - where V: de::Visitor<'de>, - { - self.into_deserializer()?.deserialize_map(visitor) - - } - - fn deserialize_struct<V>(self, - name: &'static str, - fields: &'static [&'static str], - visitor: V) - -> Result<V::Value> - where V: de::Visitor<'de>, - { - self.into_deserializer()?.deserialize_struct(name, fields, visitor) - } - fn deserialize_newtype_struct<V>( self, _name: &'static str, @@ -567,60 +536,20 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { ) -> Result<V::Value> where V: de::Visitor<'de> { - self.deserialize_seq(visitor) - } - - fn deserialize_tuple<V>( - self, - _len: usize, - visitor: V - ) -> Result<V::Value> - where V: de::Visitor<'de> - { - self.deserialize_seq(visitor) - } - fn deserialize_tuple_struct<V>( - self, - _name: &'static str, - _len: usize, - visitor: V - ) -> Result<V::Value> - where V: de::Visitor<'de> - { - self.deserialize_seq(visitor) - } - - fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value> - where V: de::Visitor<'de> - { match self.0 { Level::Nested(_) => { - Err(de::Error::custom("Expected: base64-encoded string, got a Map")) - }, - Level::Sequence(_) => { - Err(de::Error::custom("Expected: base64-encoded string, got a Sequence")) + self.into_deserializer()?.deserialize_map(visitor) }, - Level::Flat(x) => { - visitor.visit_byte_buf(base64::decode_nopad(x.as_bytes())?) - }, - Level::Invalid(e) => { - Err(de::Error::custom(e)) - } - } - } - - fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value> - where V: de::Visitor<'de> - { - match self.0 { - Level::Nested(_) => { - Err(de::Error::custom("Expected: base64-encoded string, got a Map")) + Level::OrderedSeq(map) => { + visitor.visit_seq(LevelSeq(map.into_iter().map(|(_k, v)| v))) }, - Level::Sequence(_) => { - Err(de::Error::custom("Expected: base64-encoded string, got a Sequence")) + Level::Sequence(seq) => { + visitor.visit_seq(LevelSeq(seq.into_iter())) }, - Level::Flat(x) => { - visitor.visit_byte_buf(base64::decode_nopad(x.as_bytes())?) + Level::Flat(_) => { + // For a newtype_struct, attempt to deserialize a flat value as a + // single element sequence. + visitor.visit_seq(LevelSeq(vec![self.0].into_iter())) }, Level::Invalid(e) => { Err(de::Error::custom(e)) @@ -628,6 +557,7 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { } } + deserialize_primitive!(bool, deserialize_bool, visit_bool); deserialize_primitive!(i8, deserialize_i8, visit_i8); deserialize_primitive!(i16, deserialize_i16, visit_i16); @@ -645,10 +575,18 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { char str string + bytes + byte_buf unit unit_struct + // newtype_struct + tuple_struct + struct identifier + tuple ignored_any + seq + map } } diff --git a/src/de/parse.rs b/src/de/parse.rs index 74d31a5..b9f2b35 100644 --- a/src/de/parse.rs +++ b/src/de/parse.rs @@ -121,13 +121,34 @@ fn insert_into_map(node: &mut Level, key: String, value: String) { let _ = vm.insert(Level::Flat(value)); }, } - } else { + } else { + // To reach here, node is either an Nested or nothing. let mut map = BTreeMap::default(); let _ = map.insert(key, Level::Flat(value)); *node = Level::Nested(map); } } +fn insert_into_ord_seq(node: &mut Level, key: usize, value: String) { + if let Level::OrderedSeq(ref mut map) = *node { + match map.entry(key) { + Entry::Occupied(mut o) => { + // Throw away old result; map is now invalid anyway. + let _ = o.insert(Level::Invalid("Multiple values for one key")); + }, + Entry::Vacant(vm) => { + // Map is empty, result is None + let _ = vm.insert(Level::Flat(value)); + }, + } + } else { + // To reach here, node is either an OrderedSeq or nothing. + let mut map = BTreeMap::default(); + let _ = map.insert(key, Level::Flat(value)); + *node = Level::OrderedSeq(map); + } +} + impl<I: Iterator<Item = u8>> Parser<I> { pub fn new(inner: I, acc: Vec<u8>, peeked: Option<u8>, depth: usize) -> Self { Parser { @@ -182,7 +203,7 @@ impl<I: Iterator<Item = u8>> Parser<I> { self.acc.push(x); self.peeked = Some(x); } - return res.map_err(|_| de::Error::custom("blah")); + return res.map_err(Error::from); }, b'=' => { // Allow the '=' byte when parsing keys within [] @@ -196,7 +217,7 @@ impl<I: Iterator<Item = u8>> Parser<I> { self.acc.push(b'='); self.peeked = Some(b'='); - return res.map_err(|_| de::Error::custom("blah")); + return res.map_err(Error::from); } }, b' ' => { @@ -207,7 +228,7 @@ impl<I: Iterator<Item = u8>> Parser<I> { self.acc.clear(); self.acc.push(b'&'); self.peeked = Some(b'&'); - return res.map_err(|_| de::Error::custom("blah")); + return res.map_err(Error::from); }, x @ 0x20...0x7e => { self.acc.push(x); @@ -218,10 +239,9 @@ impl<I: Iterator<Item = u8>> Parser<I> { }, } } 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")); + return res.map_err(Error::from); } } } @@ -283,8 +303,7 @@ impl<I: Iterator<Item = u8>> Parser<I> { 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 = String::from_utf8(self.acc.split_off(0)); let value = value.map_err(Error::from)?; // Reached the end of the key string if let Level::Sequence(ref mut seq) = *node { @@ -303,12 +322,59 @@ impl<I: Iterator<Item = u8>> Parser<I> { } } + fn parse_ord_seq_value(&mut self, key: usize, node: &mut Level) -> Result<()> { + 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(Error::from)?; + // Reached the end of the key string + insert_into_ord_seq(node, key, value); + Ok(()) + }, + b'&' => { + insert_into_ord_seq(node, key, "".to_string()); + Ok(()) + }, + b'[' => { + if let Level::Invalid(_) = *node { + *node = Level::Nested(BTreeMap::default()); + } + if let Level::OrderedSeq(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))) + } + }, + _ => { + Err(de::Error::custom("Unexpected character found when parsing")) + }, + } + } else { + insert_into_ord_seq(node, key, "".to_string()); + Ok(()) + } + } + fn parse(&mut self, node: &mut Level) -> Result<bool> { // 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.parse_map_value(key, node)?; self.depth += 1; return Ok(true); } @@ -317,7 +383,6 @@ impl<I: Iterator<Item = u8>> Parser<I> { match x { b'[' => { self.acc.clear(); - // let _ = self.next(); match tu!(self.peek()) { // key is of the form "[...", not really allowed. b'[' => { @@ -332,13 +397,20 @@ impl<I: Iterator<Item = u8>> Parser<I> { Ok(true) }, + // First character is an integer, attempt to parse it as an integer key + 0x30...0x39 => { + let key = self.parse_key(b']', true)?; + let key = usize::from_str_radix(&key, 10).map_err(Error::from)?; + self.parse_ord_seq_value(key, node)?; + self.depth += 1; + Ok(true) + } // Key is "[a..." so parse up to the closing "]" - 0x20...0x5a | 0x5c | 0x5e...0x7e => { + 0x20...0x2f | 0x3a...0x5a | 0x5c | 0x5e...0x7e => { let key = self.parse_key(b']', true)?; - self.parse_map_value(key.into(), node)?; + self.parse_map_value(key, node)?; self.depth += 1; Ok(true) - }, c => { Err(de::Error::custom(format!("unexpected character: {}", c))) @@ -349,7 +421,7 @@ impl<I: Iterator<Item = u8>> Parser<I> { // of the form "abc" or "abc[...]" 0x20...0x5a | 0x5c...0x7e => { let key = self.parse_key(b'[', false)?; - self.parse_map_value(key.into(), node)?; + self.parse_map_value(key, node)?; self.depth += 1; Ok(true) }, |