summaryrefslogtreecommitdiff
path: root/src/de
diff options
context:
space:
mode:
authorSam Scott <sam.scott89@gmail.com>2017-05-22 10:49:22 +0100
committerSam Scott <sam.scott89@gmail.com>2017-05-23 09:22:22 +0100
commit6f22cff63ad58c722293f8d74c978a0bf616be67 (patch)
tree8cdf62226bb51742ed1bcb03ad6047d4fa332f19 /src/de
parent071affd963ed88bfdcede6aa7b20626d3cf0f368 (diff)
Add detection of indexed sequences.
Clean up the code in places.
Diffstat (limited to 'src/de')
-rw-r--r--src/de/mod.rs126
-rw-r--r--src/de/parse.rs100
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)
},