Packages

Parse and encode URL query strings

Current section

Files

Jump to
qs src qs_adv.erl
Raw

src/qs_adv.erl

-module(qs_adv).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([scheme_rails_like/0, default_config/0, with_scheme/2, serialize/2, default_serialize/1, empty/0, parse/2, default_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, merge/2, delete/2, maybe_get_as_list/2, get_as_list/2, get_as_list_of_int/2, get_as_list_of_float/2, get_as_bool/2, get_as_list_of_bool/2]).
-export_type([one_or_many/0, scheme/0, config/0]).
-type one_or_many() :: {one, binary()} | {many, list(binary())}.
-type scheme() :: {scheme_list_as_multiple_values, binary()} |
{scheme_list_as_single_value, binary(), binary()}.
-type config() :: {config, boolean(), scheme()}.
-spec map_one_or_many(one_or_many(), fun((binary()) -> binary())) -> one_or_many().
map_one_or_many(One_or_many, Mapper) ->
case One_or_many of
{one, Value} ->
{one, Mapper(Value)};
{many, Values} ->
{many, gleam@list:map(Values, Mapper)}
end.
-spec scheme_rails_like() -> scheme().
scheme_rails_like() ->
{scheme_list_as_multiple_values, <<"[]"/utf8>>}.
-spec default_config() -> config().
default_config() ->
{config, false, scheme_rails_like()}.
-spec with_scheme(config(), scheme()) -> config().
with_scheme(Config, Scheme) ->
erlang:setelement(3, Config, Scheme).
-spec get_list_value(binary(), scheme()) -> list(binary()).
get_list_value(Raw_value, Scheme) ->
case Scheme of
{scheme_list_as_single_value, _, Separator} ->
gleam@string:split(Raw_value, Separator);
{scheme_list_as_multiple_values, _} ->
[Raw_value]
end.
-spec value_as_many(binary(), list(binary()), scheme()) -> one_or_many().
value_as_many(Raw_value, Existing_values, Scheme) ->
Added_values = get_list_value(Raw_value, Scheme),
Next_values = lists:append(Existing_values, Added_values),
{many, Next_values}.
-spec add_key_value(
scheme(),
gleam@dict:dict(binary(), one_or_many()),
{binary(), binary()}
) -> gleam@dict:dict(binary(), one_or_many()).
add_key_value(Scheme, Query, Key_value) ->
{Raw_key, Raw_value} = Key_value,
List_suffix = erlang:element(2, Scheme),
Key_without_suffix = gleam@string:replace(Raw_key, List_suffix, <<""/utf8>>),
Is_list = Raw_key /= Key_without_suffix,
Updater = fun(Res) -> case {Is_list, Res} of
{true, {some, Existing}} ->
case Existing of
{one, _} ->
value_as_many(Raw_value, [], Scheme);
{many, Existing_values} ->
value_as_many(Raw_value, Existing_values, Scheme)
end;
{true, none} ->
value_as_many(Raw_value, [], Scheme);
{false, _} ->
{one, Raw_value}
end end,
gleam@dict:upsert(Query, Key_without_suffix, Updater).
-spec encode_key_and_values({binary(), one_or_many()}) -> {binary(),
one_or_many()}.
encode_key_and_values(Key_value) ->
{Key, One_or_many} = Key_value,
{qs:encode(Key), map_one_or_many(One_or_many, fun qs:encode/1)}.
-spec add_list_suffix_or_key(binary(), scheme()) -> binary().
add_list_suffix_or_key(Key, Scheme) ->
<<Key/binary, (erlang:element(2, Scheme))/binary>>.
-spec add_key_suffix({binary(), one_or_many()}, scheme()) -> {binary(),
one_or_many()}.
add_key_suffix(Key_value, Scheme) ->
{Key, One_or_many} = Key_value,
case One_or_many of
{one, _} ->
Key_value;
{many, Values} ->
{add_list_suffix_or_key(Key, Scheme), {many, Values}}
end.
-spec unfold_key_value_many(binary(), list(binary()), scheme()) -> list({binary(),
binary()}).
unfold_key_value_many(Key, Values, Scheme) ->
case Scheme of
{scheme_list_as_single_value, _, Separator} ->
[{Key, gleam@string:join(Values, Separator)}];
{scheme_list_as_multiple_values, _} ->
gleam@list:map(Values, fun(Value) -> {Key, Value} end)
end.
-spec unfold_values({binary(), one_or_many()}, scheme()) -> list({binary(),
binary()}).
unfold_values(Key_value, Scheme) ->
{Key, One_or_many} = Key_value,
case One_or_many of
{one, Value} ->
[{Key, Value}];
{many, Values} ->
unfold_key_value_many(Key, Values, Scheme)
end.
-spec join_key_value({binary(), binary()}) -> binary().
join_key_value(Tuple) ->
{Key, Value} = Tuple,
<<<<Key/binary, "="/utf8>>/binary, Value/binary>>.
-spec serialize(gleam@dict:dict(binary(), one_or_many()), config()) -> binary().
serialize(Input, Config) ->
_pipe = Input,
_pipe@1 = maps:to_list(_pipe),
_pipe@2 = gleam@list:map(_pipe@1, fun encode_key_and_values/1),
_pipe@3 = gleam@list:map(
_pipe@2,
fun(_capture) -> add_key_suffix(_capture, erlang:element(3, Config)) end
),
_pipe@4 = gleam@list:flat_map(
_pipe@3,
fun(_capture@1) ->
unfold_values(_capture@1, erlang:element(3, Config))
end
),
_pipe@5 = gleam@list:map(_pipe@4, fun join_key_value/1),
_pipe@6 = gleam@string:join(_pipe@5, <<"&"/utf8>>),
qs:add_question_mark(_pipe@6).
-spec default_serialize(gleam@dict:dict(binary(), one_or_many())) -> binary().
default_serialize(Query) ->
serialize(Query, default_config()).
-spec empty() -> gleam@dict:dict(binary(), one_or_many()).
empty() ->
qs:empty().
-spec parse(binary(), config()) -> {ok,
gleam@dict:dict(binary(), one_or_many())} |
{error, binary()}.
parse(Input, Config) ->
gleam@result:then(
qs:split_and_parse(Input, erlang:element(2, Config)),
fun(Key_values) ->
_pipe = gleam@list:fold(
Key_values,
empty(),
fun(Query, Key_value) ->
add_key_value(erlang:element(3, Config), Query, Key_value)
end
),
{ok, _pipe}
end
).
-spec default_parse(binary()) -> {ok, gleam@dict:dict(binary(), one_or_many())} |
{error, binary()}.
default_parse(Qs) ->
parse(Qs, default_config()).
-spec get(gleam@dict:dict(binary(), one_or_many()), binary()) -> {ok,
one_or_many()} |
{error, binary()}.
get(Query, Key) ->
qs:get(Query, Key).
-spec get_as_string(gleam@dict:dict(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@dict:dict(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@dict:dict(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@dict:dict(binary(), one_or_many()), binary()) -> boolean().
has_key(Query, Key) ->
qs:has_key(Query, Key).
-spec insert(gleam@dict:dict(binary(), one_or_many()), binary(), one_or_many()) -> gleam@dict:dict(binary(), one_or_many()).
insert(Query, Key, Value) ->
qs:insert(Query, Key, Value).
-spec insert_one(gleam@dict:dict(binary(), one_or_many()), binary(), binary()) -> gleam@dict:dict(binary(), one_or_many()).
insert_one(Query, Key, Value) ->
insert(Query, Key, {one, Value}).
-spec insert_list(
gleam@dict:dict(binary(), one_or_many()),
binary(),
list(binary())
) -> gleam@dict:dict(binary(), one_or_many()).
insert_list(Query, Key, Values) ->
insert(Query, Key, {many, Values}).
-spec merge(
gleam@dict:dict(binary(), one_or_many()),
gleam@dict:dict(binary(), one_or_many())
) -> gleam@dict:dict(binary(), one_or_many()).
merge(A, B) ->
qs:merge(A, B).
-spec delete(gleam@dict:dict(binary(), one_or_many()), binary()) -> gleam@dict:dict(binary(), one_or_many()).
delete(Query, Key) ->
qs:delete(Query, Key).
-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@dict:dict(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@dict:dict(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_int(gleam@dict:dict(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@dict:dict(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>>).
-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@dict:dict(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 get_as_list_of_bool(gleam@dict:dict(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).