-module(qs_adv). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([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, 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]). -type one_or_many() :: {one, binary()} | {many, list(binary())}. -spec add_key_value( gleam@dict:dict(binary(), one_or_many()), {binary(), binary()} ) -> gleam@dict:dict(binary(), one_or_many()). add_key_value(Query, Key_value) -> List_suffix = <<"[]"/utf8>>, {Raw_key, Raw_value} = Key_value, {Is_list, Key} = case gleam@string:ends_with(Raw_key, List_suffix) of true -> {true, gleam@string:replace(Raw_key, List_suffix, <<""/utf8>>)}; false -> {false, Raw_key} end, Updater = fun(Res) -> case Res of {some, Existing} -> case Is_list of true -> case Existing of {one, _} -> {many, [Raw_value]}; {many, Existing_list} -> {many, lists:append(Existing_list, [Raw_value])} end; false -> {one, Raw_value} end; none -> case Is_list of true -> {many, [Raw_value]}; false -> {one, Raw_value} end end end, gleam@dict:upsert(Query, Key, Updater). -spec serialize_key_value({binary(), one_or_many()}) -> list(binary()). serialize_key_value(Key_value) -> {Key, One_or_many} = Key_value, case One_or_many of {one, Value} -> [qs:join_key_value(Key, Value, <<"="/utf8>>)]; {many, Values} -> _pipe = Values, gleam@list:map( _pipe, fun(_capture) -> qs:join_key_value(Key, _capture, <<"[]="/utf8>>) end ) end. -spec serialize(gleam@dict:dict(binary(), one_or_many())) -> binary(). serialize(Query) -> qs:serialize_with(Query, fun serialize_key_value/1). -spec empty() -> gleam@dict:dict(binary(), one_or_many()). empty() -> qs:empty(). -spec parse(binary()) -> {ok, gleam@dict:dict(binary(), one_or_many())} | {error, binary()}. parse(Qs) -> gleam@result:then( qs:split_and_parse(Qs), fun(Key_values) -> _pipe = gleam@list:fold(Key_values, empty(), fun add_key_value/2), {ok, _pipe} end ). -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).