diff options
author | Sam Scott <sam.scott89@gmail.com> | 2018-01-03 22:27:33 +0000 |
---|---|---|
committer | Sam Scott <sam.scott89@gmail.com> | 2018-01-03 22:27:33 +0000 |
commit | 93d0f47e2aa0fc31a196726163001e31f4824722 (patch) | |
tree | 87611daa95111845f01a841fbfb5998be7792f04 /src/de | |
parent | 2bf6ecb32c11deaaa4f569d4082d6b350ab2ffaf (diff) |
Tweak parsing logic of encoded brackets in non-strict mode.
When parsing a value, always just consume all the text, and ignore
special encoded of brackets.
(Hence non-strict mode only applies to keys)
Diffstat (limited to 'src/de')
-rw-r--r-- | src/de/parse.rs | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/src/de/parse.rs b/src/de/parse.rs index 1c13aaf..a99e96d 100644 --- a/src/de/parse.rs +++ b/src/de/parse.rs @@ -105,22 +105,27 @@ pub struct Parser<'a> { peeked: Option<&'a u8>, depth: usize, // stores the current depth, for use in bounded-depth parsing strict: bool, + state: ParsingState, +} + +/// The parsing logic varies slightly based on whether it is a key or a value +/// (determines how encoded brackets are parse in non-strict mode) +/// This tracks the state. +enum ParsingState { + Init, + Key, + Value, } impl<'a> Iterator for Parser<'a> { type Item = &'a u8; #[inline] fn next(&mut self) -> Option<Self::Item> { - if self.strict { - match self.peeked.take() { - Some(v) => Some(v), - None => { - self.index += 1; - self.acc.1 += 1; - self.iter.next() - }, - } - } else { + let preparse_brackets = match self.state { + ParsingState::Value => false, + _ => !self.strict, + }; + if preparse_brackets { // in non-strict mode, we will happily decode any bracket match self.peeked.take() { Some(v) => Some(v), @@ -152,6 +157,15 @@ impl<'a> Iterator for Parser<'a> { } }, } + } else { + match self.peeked.take() { + Some(v) => Some(v), + None => { + self.index += 1; + self.acc.1 += 1; + self.iter.next() + }, + } } } } @@ -199,6 +213,7 @@ impl<'a> Parser<'a> { peeked: None, depth: depth, strict: strict, + state: ParsingState::Init, } } @@ -228,7 +243,6 @@ impl<'a> Parser<'a> { // Parses all top level nodes into the `root` map. while self.parse(&mut root)? {} - let iter = match root { Level::Nested(map) => map.into_iter(), _ => BTreeMap::default().into_iter(), @@ -331,6 +345,7 @@ impl<'a> Parser<'a> { /// parsing keys like `abc[def][ghi]` since the `'['` character is /// needed to for the next iteration of `parse`. fn parse_key(&mut self, end_on: u8, consume: bool) -> Result<Cow<'a, str>> { + self.state = ParsingState::Key; loop { if let Some(x) = self.next() { match *x { @@ -339,7 +354,6 @@ impl<'a> Parser<'a> { if !consume { self.peeked = Some(x); } - return self.collect_str(); }, b'=' => { @@ -377,12 +391,14 @@ impl<'a> Parser<'a> { key: Cow<'a, str>, node: &mut Level<'a>) -> Result<()> { + self.state = ParsingState::Key; let res = loop { if let Some(x) = self.peek() { match *x { b'=' => { // Key is finished, parse up until the '&' as the value self.clear_acc(); + self.state = ParsingState::Value; for _ in self.take_while(|b| *b != &b'&') {} let value: Cow<'a, str> = self.collect_str()?; node.insert_map_value(key, value); @@ -445,12 +461,14 @@ impl<'a> Parser<'a> { key: usize, node: &mut Level<'a>) -> Result<()> { + self.state = ParsingState::Key; let res = loop { if let Some(x) = self.peek() { match *x { b'=' => { // Key is finished, parse up until the '&' as the value self.clear_acc(); + self.state = ParsingState::Value; for _ in self.take_while(|b| *b != &b'&') {} let value = self.collect_str()?; // Reached the end of the key string @@ -512,12 +530,14 @@ impl<'a> Parser<'a> { /// unordered sequence. /// This must be the final level of nesting, so assume we have a value fn parse_seq_value(&mut self, node: &mut Level<'a>) -> Result<()> { + self.state = ParsingState::Key; let res = match self.peek() { Some(x) => { match *x { b'=' => { // Key is finished, parse up until the '&' as the value self.clear_acc(); + self.state = ParsingState::Value; for _ in self.take_while(|b| *b != &b'&') {} let value = self.collect_str()?; node.insert_seq_value(value); |