summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Grinman <alex@krypt.co>2019-02-15 13:07:25 -0500
committerAlex Grinman <alex@krypt.co>2019-02-15 13:11:11 -0500
commit00862926b8cb7db48f60654d984dd11001ad3c95 (patch)
tree6eab35891b67644b16e344bab5e5dc23faf61394 /src
parent65c7f89ad4a4281aea4ea0115c27dbd54d339b15 (diff)
fix: replace pluses before percent decoding
Diffstat (limited to 'src')
-rw-r--r--src/de/parse.rs41
1 files changed, 26 insertions, 15 deletions
diff --git a/src/de/parse.rs b/src/de/parse.rs
index 5d84512..3718c57 100644
--- a/src/de/parse.rs
+++ b/src/de/parse.rs
@@ -193,22 +193,20 @@ impl<'a> Parser<'a> {
/// Replace b'+' with b' '
/// Copied from [`form_urlencoded`](https://github.com/servo/rust-url/blob/380be29859adb859e861c2d765897c22ec878e01/src/form_urlencoded.rs#L125).
-fn replace_plus(input: Cow<str>) -> Cow<str> {
- match input.as_bytes().iter().position(|&b| b == b'+') {
- None => input,
+fn replace_plus(input: &[u8]) -> Cow<[u8]> {
+ match input.iter().position(|&b| b == b'+') {
+ None => Cow::Borrowed(input),
Some(first_position) => {
- let mut replaced = input.as_bytes().to_owned();
+ let mut replaced = input.to_owned();
replaced[first_position] = b' ';
for byte in &mut replaced[first_position + 1..] {
if *byte == b'+' {
*byte = b' ';
}
}
- Cow::Owned(
- String::from_utf8(replaced)
- .expect("replacing '+' with ' ' cannot panic"),
- )
- },
+
+ Cow::Owned(replaced)
+ }
}
}
@@ -236,13 +234,26 @@ impl<'a> Parser<'a> {
/// Avoids allocations when neither percent encoded, nor `'+'` values are
/// present.
fn collect_str(&mut self) -> Result<Cow<'a, str>> {
- let res: Cow<'a, str> = percent_encoding::percent_decode(
- &self.inner[self.acc.0..self.acc.1 - 1],
- )
- .decode_utf8()?;
- let res: Result<Cow<'a, str>> = Ok(replace_plus(res));
+ let replaced = replace_plus(&self.inner[self.acc.0..self.acc.1 - 1]);
+ let ret:Result<Cow<'a, str>> = match percent_encoding::percent_decode(&replaced).decode_utf8()? {
+ Cow::Borrowed(_) => {
+ match replaced {
+ Cow::Borrowed(_) => {
+ let res = str::from_utf8(&self.inner[self.acc.0..self.acc.1 - 1])?;
+ Ok(Cow::Borrowed(res))
+ },
+ Cow::Owned(owned) => {
+ let res = String::from_utf8(owned)?;
+ Ok(Cow::Owned(res))
+ }
+ }
+ },
+ Cow::Owned(owned) => {
+ Ok(Cow::Owned(owned))
+ }
+ };
self.clear_acc();
- res.map_err(Error::from)
+ ret.map_err(Error::from)
}
/// In some ways the main way to use a `Parser`, this runs the parsing step