summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--src/de/parse.rs44
-rw-r--r--tests/test_deserialize.rs5
3 files changed, 38 insertions, 13 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 859497a..2f10a29 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT/Apache-2.0"
name = "serde_qs"
repository = "https://github.com/samscott89/serde_qs"
readme = "README.md"
-version = "0.4.0-rc.1"
+version = "0.4.0-rc.2"
[badges]
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);
diff --git a/tests/test_deserialize.rs b/tests/test_deserialize.rs
index a9f2dd7..946a8f3 100644
--- a/tests/test_deserialize.rs
+++ b/tests/test_deserialize.rs
@@ -474,3 +474,8 @@ fn strict_mode() {
assert!(rec_params.is_err());
println!("{}", rec_params.unwrap_err());
}
+
+#[test]
+fn square_brackets_in_values() {
+ map_test!("foo=%5BHello%5D", "foo"["[Hello]"]);
+}