aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2021-09-04 23:06:09 +0100
committerLouis Pilfold <louis@lpil.uk>2021-09-04 23:06:09 +0100
commit7a52f1356fe39475b7576ca5f105a10ae975e7ff (patch)
tree26aaef910ccba182d38474630bb904af732934f2 /src
parenta54b1986daf44ebfd941849584175215306ad6d9 (diff)
downloadgleam_stdlib-7a52f1356fe39475b7576ca5f105a10ae975e7ff.tar.gz
gleam_stdlib-7a52f1356fe39475b7576ca5f105a10ae975e7ff.zip
JS parse query
Diffstat (limited to 'src')
-rw-r--r--src/gleam/uri.gleam55
-rw-r--r--src/gleam_stdlib.erl15
-rw-r--r--src/gleam_stdlib.js18
3 files changed, 56 insertions, 32 deletions
diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam
index e67837e..5482478 100644
--- a/src/gleam/uri.gleam
+++ b/src/gleam/uri.gleam
@@ -189,39 +189,34 @@ fn extra_required(list: List(a), remaining: Int) -> Int {
}
}
-if erlang {
- import gleam/io
-
- external fn erl_parse_query(String) -> Dynamic =
- "uri_string" "dissect_query"
+/// Parses an urlencoded query string into a list of key value pairs.
+/// Returns an error for invalid encoding.
+///
+/// The opposite operation is `uri.query_to_string`.
+///
+/// ## Examples
+///
+/// ```
+/// > parse_query("a=1&b=2")
+///
+/// Ok([#("a", "1"), #("b", "2")])
+/// ```
+///
+pub fn parse_query(query: String) -> Result(List(#(String, String)), Nil) {
+ do_parse_query(query)
+}
- /// Parses an urlencoded query string into a list of key value pairs.
- /// Returns an error for invalid encoding.
- ///
- /// The opposite operation is `uri.query_to_string`.
- ///
- /// ## Examples
- ///
- /// ```
- /// > parse_query("a=1&b=2")
- ///
- /// Ok([#("a", "1"), #("b", "2")])
- /// ```
- ///
- pub fn parse_query(query: String) -> Result(List(#(String, String)), Nil) {
- let bool_value = fn(x) { result.map(dynamic.bool(x), fn(_) { "" }) }
- let query_param = dynamic.typed_tuple2(
- _,
- dynamic.string,
- dynamic.any(_, of: [dynamic.string, bool_value]),
- )
+if erlang {
+ external fn do_parse_query(String) -> Result(List(#(String, String)), Nil) =
+ "gleam_stdlib" "parse_query"
+}
- query
- |> erl_parse_query
- |> dynamic.typed_list(of: query_param)
- |> result.nil_error
- }
+if javascript {
+ external fn do_parse_query(String) -> Result(List(#(String, String)), Nil) =
+ "../gleam_stdlib.js" "parse_query"
+}
+if erlang {
type Encoding {
Utf8
}
diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl
index 408853a..f8f6851 100644
--- a/src/gleam_stdlib.erl
+++ b/src/gleam_stdlib.erl
@@ -5,13 +5,13 @@
map_get/2, iodata_append/2, identity/1, decode_int/1, decode_bool/1,
decode_float/1, decode_thunk/1, decode_list/1, decode_optional/2,
decode_field/2, decode_element/2, parse_int/1, parse_float/1,
- less_than/2, string_pop_grapheme/1, string_starts_with/2,
+ less_than/2, string_pop_grapheme/1, string_starts_with/2, wrap_list/1,
string_ends_with/2, string_pad/4, decode_tuple2/1, decode_tuple3/1,
decode_tuple4/1, decode_tuple5/1, decode_tuple6/1, decode_map/1,
bit_string_int_to_u32/1, bit_string_int_from_u32/1, decode_result/1,
bit_string_slice/3, decode_bit_string/1, compile_regex/2,
regex_check/2, regex_split/2, regex_scan/2, base_decode64/1,
- wrap_list/1, bit_string_concat/1]).
+ parse_query/1, bit_string_concat/1]).
should_equal(Actual, Expected) ->
?assertEqual(Expected, Actual),
@@ -234,3 +234,14 @@ base_decode64(S) ->
wrap_list(X) when is_list(X) -> X;
wrap_list(X) -> [X].
+
+parse_query(Query) ->
+ case uri_string:dissect_query(Query) of
+ {error, _, _} -> {error, nil};
+ Pairs ->
+ Pairs1 = lists:map(fun
+ ({K, true}) -> {K, <<"">>};
+ (Pair) -> Pair
+ end, Pairs),
+ {ok, Pairs1}
+ end.
diff --git a/src/gleam_stdlib.js b/src/gleam_stdlib.js
index 360de75..082e661 100644
--- a/src/gleam_stdlib.js
+++ b/src/gleam_stdlib.js
@@ -352,3 +352,21 @@ export function map_get(map, key) {
export function map_insert(key, value, map) {
return map.insert(key, value);
}
+
+function decode_query_component(string) {
+ return decodeURIComponent((string || "").replace("+", " "));
+}
+
+export function parse_query(query) {
+ try {
+ let pairs = [];
+ for (let section of query.split("&")) {
+ let [key, value] = section.split("=");
+ if (!key) continue;
+ pairs.push([decode_query_component(key), decode_query_component(value)]);
+ }
+ return new Ok(List.fromArray(pairs));
+ } catch (error) {
+ return new Error(Nil);
+ }
+}