Packages

Parse and encode URL query strings

Current section

Files

Jump to
gleam_qs src qs.erl
Raw

src/qs.erl

-module(qs).
-compile([no_auto_import, nowarn_unused_vars]).
-export([parse_key_value/1, serialize/1, empty/0, parse/1, get/2, get_as_string/2, get_as_int/2, get_as_float/2, has_key/2, insert/3, insert_one/3, insert_list/3, push/3, merge/2, delete/2, get_as_bool/2, maybe_get_as_list/2, get_as_list/2, get_as_list_of_bool/2, get_as_list_of_int/2, get_as_list_of_float/2]).
-export_type([one_or_many/0]).
-type one_or_many() :: {one, binary()} | {many, list(binary())}.
-spec parse_key_value(binary()) -> {ok, {binary(), binary(), boolean()}} |
{error, binary()}.
parse_key_value(Segment) ->
_pipe = Segment,
_pipe@1 = gleam@uri:percent_decode(_pipe),
_pipe@2 = gleam@result:unwrap(_pipe@1, Segment),
_pipe@3 = gleam@string:split_once(_pipe@2, <<"="/utf8>>),
_pipe@4 = gleam@result:map(
_pipe@3,
fun(Pair) ->
{K, V} = Pair,
case gleam@string:ends_with(K, <<"[]"/utf8>>) of
true ->
{gleam@string:replace(K, <<"[]"/utf8>>, <<""/utf8>>),
V,
true};
false ->
{K, V, false}
end
end
),
gleam@result:replace_error(
_pipe@4,
begin
_pipe@5 = <<"Unable to parse "/utf8>>,
gleam@string:append(_pipe@5, Segment)
end
).
-spec split_and_parse(binary()) -> {ok, list({binary(), binary(), boolean()})} |
{error, binary()}.
split_and_parse(Qs) ->
_pipe = Qs,
_pipe@1 = gleam@string:replace(_pipe, <<"?"/utf8>>, <<""/utf8>>),
_pipe@2 = gleam@string:split(_pipe@1, <<"&"/utf8>>),
_pipe@3 = gleam@list:map(_pipe@2, fun parse_key_value/1),
gleam@result:all(_pipe@3).
-spec add_segment(
gleam@map:map_(binary(), one_or_many()),
{binary(), binary(), boolean()}
) -> gleam@map:map_(binary(), one_or_many()).
add_segment(Query, Segment) ->
{Key, Value, Is_list} = Segment,
Updater = fun(Res) -> case Res of
{some, Existing} ->
case Is_list of
true ->
case Existing of
{one, _} ->
{many, [Value]};
{many, Existing_list} ->
{many, [Value | Existing_list]}
end;
false ->
{one, Value}
end;
none ->
case Is_list of
true ->
{many, [Value]};
false ->
{one, Value}
end
end end,
gleam@map:update(Query, Key, Updater).
-spec reverse_many(binary(), one_or_many()) -> one_or_many().
reverse_many(_, V) ->
case V of
{many, Values} ->
{many, gleam@list:reverse(Values)};
_ ->
V
end.
-spec join_key_value(binary(), binary(), binary()) -> binary().
join_key_value(Key, Value, Join) ->
_pipe = Key,
_pipe@1 = gleam@uri:percent_encode(_pipe),
_pipe@2 = gleam@string:append(_pipe@1, Join),
gleam@string:append(
_pipe@2,
begin
_pipe@3 = Value,
gleam@uri:percent_encode(_pipe@3)
end
).
-spec serialize_key({binary(), one_or_many()}) -> list(binary()).
serialize_key(Input) ->
{Key, One_or_many} = Input,
case One_or_many of
{one, Value} ->
[join_key_value(Key, Value, <<"="/utf8>>)];
{many, Values} ->
_pipe = Values,
gleam@list:map(
_pipe,
fun(_capture) ->
join_key_value(Key, _capture, <<"[]="/utf8>>)
end
)
end.
-spec add_question_mark(binary()) -> binary().
add_question_mark(Query) ->
_pipe = <<"?"/utf8>>,
gleam@string:append(_pipe, Query).
-spec serialize(gleam@map:map_(binary(), one_or_many())) -> binary().
serialize(Query) ->
_pipe = Query,
_pipe@1 = gleam@map:to_list(_pipe),
_pipe@2 = gleam@list:map(_pipe@1, fun serialize_key/1),
_pipe@3 = gleam@list:flatten(_pipe@2),
_pipe@4 = gleam@string:join(_pipe@3, <<"&"/utf8>>),
add_question_mark(_pipe@4).
-spec empty() -> gleam@map:map_(binary(), one_or_many()).
empty() ->
gleam@map:new().
-spec parse(binary()) -> {ok, gleam@map:map_(binary(), one_or_many())} |
{error, binary()}.
parse(Qs) ->
gleam@result:then(
split_and_parse(Qs),
fun(Segments) ->
_pipe = gleam@list:fold(Segments, empty(), fun add_segment/2),
_pipe@1 = gleam@map:map_values(_pipe, fun reverse_many/2),
{ok, _pipe@1}
end
).
-spec get(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
one_or_many()} |
{error, binary()}.
get(Query, Key) ->
Error = begin
_pipe = <<"Invalid key "/utf8>>,
gleam@string:append(_pipe, Key)
end,
_pipe@1 = gleam@map:get(Query, Key),
gleam@result:replace_error(_pipe@1, Error).
-spec get_as_string(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
binary()} |
{error, binary()}.
get_as_string(Query, Key) ->
gleam@result:then(get(Query, Key), fun(One_or_many) -> case One_or_many of
{one, Value} ->
{ok, Value};
{many, _} ->
{error,
begin
_pipe = Key,
gleam@string:append(_pipe, <<" is a list"/utf8>>)
end}
end end).
-spec get_as_int(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
integer()} |
{error, binary()}.
get_as_int(Query, Key) ->
gleam@result:then(get_as_string(Query, Key), fun(Value) -> _pipe = Value,
_pipe@1 = gleam@int:parse(_pipe),
gleam@result:replace_error(
_pipe@1,
begin
_pipe@2 = <<"Invalid Int "/utf8>>,
gleam@string:append(_pipe@2, Value)
end
) end).
-spec get_as_float(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
float()} |
{error, binary()}.
get_as_float(Query, Key) ->
gleam@result:then(get_as_string(Query, Key), fun(Value) -> _pipe = Value,
_pipe@1 = gleam@float:parse(_pipe),
gleam@result:replace_error(
_pipe@1,
begin
_pipe@2 = <<"Invalid Float "/utf8>>,
gleam@string:append(_pipe@2, Value)
end
) end).
-spec has_key(gleam@map:map_(binary(), one_or_many()), binary()) -> boolean().
has_key(Query, Key) ->
gleam@map:has_key(Query, Key).
-spec insert(gleam@map:map_(binary(), one_or_many()), binary(), one_or_many()) -> gleam@map:map_(binary(), one_or_many()).
insert(Query, Key, Value) ->
gleam@map:insert(Query, Key, Value).
-spec insert_one(gleam@map:map_(binary(), one_or_many()), binary(), binary()) -> gleam@map:map_(binary(), one_or_many()).
insert_one(Query, Key, Value) ->
insert(Query, Key, {one, Value}).
-spec insert_list(
gleam@map:map_(binary(), one_or_many()),
binary(),
list(binary())
) -> gleam@map:map_(binary(), one_or_many()).
insert_list(Query, Key, Values) ->
insert(Query, Key, {many, Values}).
-spec push(gleam@map:map_(binary(), one_or_many()), binary(), binary()) -> gleam@map:map_(binary(), one_or_many()).
push(Query, Key, Value) ->
gleam@map:update(Query, Key, fun(Res) -> case Res of
{some, Current} ->
case Current of
{one, One} ->
{many, [One, Value]};
{many, Many} ->
{many, gleam@list:append(Many, [Value])}
end;
none ->
{many, [Value]}
end end).
-spec merge(
gleam@map:map_(binary(), one_or_many()),
gleam@map:map_(binary(), one_or_many())
) -> gleam@map:map_(binary(), one_or_many()).
merge(A, B) ->
gleam@map:merge(A, B).
-spec delete(gleam@map:map_(binary(), one_or_many()), binary()) -> gleam@map:map_(binary(), one_or_many()).
delete(Query, Key) ->
gleam@map:delete(Query, Key).
-spec parse_bool(binary()) -> {ok, boolean()} | {error, binary()}.
parse_bool(S) ->
case S of
<<"true"/utf8>> ->
{ok, true};
<<"false"/utf8>> ->
{ok, false};
_ ->
{error,
begin
_pipe = <<"Invalid "/utf8>>,
gleam@string:append(_pipe, S)
end}
end.
-spec get_as_bool(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
boolean()} |
{error, binary()}.
get_as_bool(Query, Key) ->
_pipe = get_as_string(Query, Key),
gleam@result:then(_pipe, fun parse_bool/1).
-spec to_list(one_or_many()) -> list(binary()).
to_list(One_or_many) ->
case One_or_many of
{one, Value} ->
[Value];
{many, Values} ->
Values
end.
-spec maybe_get_as_list(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
list(binary())} |
{error, binary()}.
maybe_get_as_list(Query, Key) ->
_pipe = get(Query, Key),
gleam@result:map(_pipe, fun to_list/1).
-spec get_as_list(gleam@map:map_(binary(), one_or_many()), binary()) -> list(binary()).
get_as_list(Query, Key) ->
_pipe = maybe_get_as_list(Query, Key),
gleam@result:unwrap(_pipe, []).
-spec get_as_list_of_bool(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
list(boolean())} |
{error, binary()}.
get_as_list_of_bool(Query, Key) ->
_pipe = get_as_list(Query, Key),
_pipe@1 = gleam@list:map(_pipe, fun parse_bool/1),
gleam@result:all(_pipe@1).
-spec get_as_list_of_int(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
list(integer())} |
{error, binary()}.
get_as_list_of_int(Query, Key) ->
_pipe = get_as_list(Query, Key),
_pipe@1 = gleam@list:map(_pipe, fun gleam@int:parse/1),
_pipe@2 = gleam@result:all(_pipe@1),
gleam@result:replace_error(_pipe@2, <<"Couldn't parse all values"/utf8>>).
-spec get_as_list_of_float(gleam@map:map_(binary(), one_or_many()), binary()) -> {ok,
list(float())} |
{error, binary()}.
get_as_list_of_float(Query, Key) ->
_pipe = get_as_list(Query, Key),
_pipe@1 = gleam@list:map(_pipe, fun gleam@float:parse/1),
_pipe@2 = gleam@result:all(_pipe@1),
gleam@result:replace_error(_pipe@2, <<"Couldn't parse all values"/utf8>>).