From 820fa3c43a2d20e140bc4525e0a1405e7420bb66 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 17 Mar 2024 17:50:33 +0100 Subject: [PATCH] `Location::query_map`: support repeated key (#4183) This adds support for parsing e.g. `?foo=hello&foo=world`, returning both "hello" and "world" in `Location::query_map` --- crates/eframe/src/epi.rs | 4 ++-- crates/eframe/src/web/backend.rs | 29 ++++++++++++++++------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index a27a3733..5ee29e45 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -758,8 +758,8 @@ pub struct Location { /// The parsed "query" part of "www.example.com/index.html?query#fragment". /// - /// "foo=42&bar%20" is parsed as `{"foo": "42", "bar ": ""}` - pub query_map: std::collections::BTreeMap, + /// "foo=hello&bar%20&foo=world" is parsed as `{"bar ": [""], "foo": ["hello", "world"]}` + pub query_map: std::collections::BTreeMap>, /// `location.origin` /// diff --git a/crates/eframe/src/web/backend.rs b/crates/eframe/src/web/backend.rs index 1121cb43..041fe420 100644 --- a/crates/eframe/src/web/backend.rs +++ b/crates/eframe/src/web/backend.rs @@ -117,21 +117,24 @@ pub fn web_location() -> epi::Location { } /// query is percent-encoded -fn parse_query_map(query: &str) -> BTreeMap { - query - .split('&') - .filter_map(|pair| { - if pair.is_empty() { - None +fn parse_query_map(query: &str) -> BTreeMap> { + let mut map: BTreeMap> = Default::default(); + + for pair in query.split('&') { + if !pair.is_empty() { + if let Some((key, value)) = pair.split_once('=') { + map.entry(percent_decode(key)) + .or_default() + .push(percent_decode(value)); } else { - Some(if let Some((key, value)) = pair.split_once('=') { - (percent_decode(key), percent_decode(value)) - } else { - (percent_decode(pair), String::new()) - }) + map.entry(percent_decode(pair)) + .or_default() + .push(String::new()); } - }) - .collect() + } + } + + map } // TODO(emilk): this test is never acgtually run, because this whole module is wasm32 only 🤦‍♂️