-module(clad). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([decoded/1, decode/2, arg/4, arg_with_default/5, toggle/3, short_name/3, long_name/3]). -export_type([arg/0, arg_results/0]). -type arg() :: {arg, binary(), binary()} | {long_name, binary()} | {short_name, binary()}. -type arg_results() :: {arg_results, binary(), binary(), {ok, gleam@option:option(list(gleam@dynamic:dynamic_()))} | {error, list(gleam@dynamic:decode_error())}, {ok, gleam@option:option(list(gleam@dynamic:dynamic_()))} | {error, list(gleam@dynamic:decode_error())}} | {long_name_results, binary(), {ok, gleam@option:option(list(gleam@dynamic:dynamic_()))} | {error, list(gleam@dynamic:decode_error())}} | {short_name_results, binary(), {ok, gleam@option:option(list(gleam@dynamic:dynamic_()))} | {error, list(gleam@dynamic:decode_error())}}. -spec decoded(FYQ) -> fun((gleam@dynamic:dynamic_()) -> {ok, FYQ} | {error, list(gleam@dynamic:decode_error())}). decoded(Value) -> fun(_) -> {ok, Value} end. -spec do_list( binary(), fun((gleam@dynamic:dynamic_()) -> {ok, GAB} | {error, list(gleam@dynamic:decode_error())}) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, GAB} | {error, list(gleam@dynamic:decode_error())}). do_list(Name, Decoder) -> fun(Data) -> gleam@result:map_error(Decoder(Data), fun(Error) -> case Error of [{decode_error, _, _, _} = E] -> [erlang:setelement(4, E, [Name | erlang:element(4, E)])]; _ -> Error end end) end. -spec do_single( binary(), fun((gleam@dynamic:dynamic_()) -> {ok, FZY} | {error, list(gleam@dynamic:decode_error())}) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, FZY} | {error, list(gleam@dynamic:decode_error())}). do_single(Name, Decoder) -> fun(Data) -> gleam@result:try_recover( Decoder(Data), fun(First_error) -> Decoder@1 = do_list(Name, Decoder), gleam@result:map_error( Decoder@1(gleam_stdlib:identity([Data])), fun(Second_error) -> case First_error of [{decode_error, _, _, _} = E] -> [erlang:setelement( 4, E, [Name | erlang:element(4, E)] )]; _ -> Second_error end end ) end ) end. -spec fail(binary(), binary()) -> {ok, any()} | {error, list(gleam@dynamic:decode_error())}. fail(Expected, Found) -> {error, [{decode_error, Expected, Found, []}]}. -spec try_parse_float(binary()) -> {ok, gleam@dynamic:dynamic_()} | {error, nil}. try_parse_float(Input) -> _pipe = gleam@float:parse(Input), gleam@result:map(_pipe, fun gleam_stdlib:identity/1). -spec try_parse_int(binary()) -> {ok, gleam@dynamic:dynamic_()} | {error, nil}. try_parse_int(Input) -> _pipe = gleam@int:parse(Input), gleam@result:map(_pipe, fun gleam_stdlib:identity/1). -spec try_parse_bool(binary()) -> {ok, gleam@dynamic:dynamic_()} | {error, nil}. try_parse_bool(Input) -> case Input of <<"true"/utf8>> -> {ok, gleam_stdlib:identity(true)}; <<"True"/utf8>> -> {ok, gleam_stdlib:identity(true)}; <<"false"/utf8>> -> {ok, gleam_stdlib:identity(false)}; <<"False"/utf8>> -> {ok, gleam_stdlib:identity(false)}; _ -> {error, nil} end. -spec parse(binary()) -> gleam@dynamic:dynamic_(). parse(Input) -> _pipe = try_parse_float(Input), _pipe@1 = gleam@result:'or'(_pipe, try_parse_int(Input)), _pipe@2 = gleam@result:'or'(_pipe@1, try_parse_bool(Input)), gleam@result:unwrap(_pipe@2, gleam_stdlib:identity(Input)). -spec prepare_arguments(list(binary())) -> {ok, list({binary(), gleam@dynamic:dynamic_()})} | {error, list(gleam@dynamic:decode_error())}. prepare_arguments(Arguments) -> Arguments@1 = begin _pipe = Arguments, _pipe@1 = clad@internal@args:split_equals(_pipe), clad@internal@args:add_bools(_pipe@1) end, Chunked = gleam@list:sized_chunk(Arguments@1, 2), Chunked@1 = gleam@list:map(Chunked, fun(Chunk) -> case Chunk of [K, V] -> {ok, {K, parse(V)}}; _ -> fail(<<"key/value pairs"/utf8>>, <<"dangling arg"/utf8>>) end end), gleam@result:all(Chunked@1). -spec do_object_list( list({binary(), gleam@dynamic:dynamic_()}), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()) ) -> gleam@dynamic:dynamic_(). do_object_list(Entries, Acc) -> case Entries of [] -> gleam_stdlib:identity(Acc); [{K, _} | Rest] -> case gleam@dict:has_key(Acc, K) of true -> do_object_list(Rest, Acc); false -> Values = gleam@list:key_filter(Entries, K), do_object_list( Rest, gleam@dict:insert(Acc, K, gleam_stdlib:identity(Values)) ) end end. -spec object(list({binary(), gleam@dynamic:dynamic_()})) -> gleam@dynamic:dynamic_(). object(Entries) -> do_object_list(Entries, gleam@dict:new()). -spec decode( fun((gleam@dynamic:dynamic_()) -> {ok, FYH} | {error, list(gleam@dynamic:decode_error())}), list(binary()) ) -> {ok, FYH} | {error, list(gleam@dynamic:decode_error())}. decode(Decoder, Arguments) -> gleam@result:'try'( prepare_arguments(Arguments), fun(Arguments@1) -> _pipe = object(Arguments@1), Decoder(_pipe) end ). -spec missing_field(binary()) -> list(gleam@dynamic:decode_error()). missing_field(Name) -> [{decode_error, <<"field"/utf8>>, <<"nothing"/utf8>>, [Name]}]. -spec do_arg_results( binary(), binary(), {ok, gleam@option:option(list(gleam@dynamic:dynamic_()))} | {error, list(gleam@dynamic:decode_error())}, {ok, gleam@option:option(list(gleam@dynamic:dynamic_()))} | {error, list(gleam@dynamic:decode_error())}, fun((gleam@dynamic:dynamic_()) -> {ok, FZS} | {error, list(gleam@dynamic:decode_error())}) ) -> {ok, FZS} | {error, list(gleam@dynamic:decode_error())}. do_arg_results(Long_name, Short_name, Long_result, Short_result, Decoder) -> case {Long_result, Short_result} of {{ok, {some, A}}, {ok, {some, B}}} -> (do_list(Long_name, Decoder))( gleam_stdlib:identity(lists:append(A, B)) ); {{ok, {some, [A@1]}}, {ok, none}} -> (do_single(Long_name, Decoder))(A@1); {{ok, none}, {ok, {some, [A@2]}}} -> (do_single(Short_name, Decoder))(A@2); {{ok, {some, A@3}}, {ok, none}} -> (do_list(Long_name, Decoder))(gleam_stdlib:identity(A@3)); {{ok, none}, {ok, {some, A@4}}} -> (do_list(Short_name, Decoder))(gleam_stdlib:identity(A@4)); {{ok, none}, {ok, none}} -> _pipe = (do_single(Long_name, Decoder))(gleam_stdlib:identity(none)), gleam@result:replace_error(_pipe, missing_field(Long_name)); {{error, E1}, {error, E2}} -> {error, lists:append(E1, E2)}; {{error, E}, _} -> {error, E}; {_, {error, E}} -> {error, E} end. -spec do_single_name_results( binary(), {ok, gleam@option:option(list(gleam@dynamic:dynamic_()))} | {error, list(gleam@dynamic:decode_error())}, fun((gleam@dynamic:dynamic_()) -> {ok, FZV} | {error, list(gleam@dynamic:decode_error())}) ) -> {ok, FZV} | {error, list(gleam@dynamic:decode_error())}. do_single_name_results(Name, Decode_result, Decoder) -> case Decode_result of {ok, {some, [A]}} -> (do_single(Name, Decoder))(A); {ok, {some, A@1}} -> (do_list(Name, Decoder))(gleam_stdlib:identity(A@1)); {ok, none} -> _pipe = (do_single(Name, Decoder))(gleam_stdlib:identity(none)), gleam@result:replace_error(_pipe, missing_field(Name)); {error, E} -> {error, E} end. -spec do_arg( arg(), fun((gleam@dynamic:dynamic_()) -> {ok, FZP} | {error, list(gleam@dynamic:decode_error())}) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, FZP} | {error, list(gleam@dynamic:decode_error())}). do_arg(Arg, Decoder) -> fun(Data) -> Arg_res = case Arg of {arg, Long_name, Short_name} -> {arg_results, Long_name, Short_name, (gleam@dynamic:optional_field( Long_name, fun gleam@dynamic:shallow_list/1 ))(Data), (gleam@dynamic:optional_field( Short_name, fun gleam@dynamic:shallow_list/1 ))(Data)}; {long_name, Name} -> {long_name_results, Name, (gleam@dynamic:optional_field( Name, fun gleam@dynamic:shallow_list/1 ))(Data)}; {short_name, Name@1} -> {short_name_results, Name@1, (gleam@dynamic:optional_field( Name@1, fun gleam@dynamic:shallow_list/1 ))(Data)} end, case Arg_res of {arg_results, L, S, Lr, Sr} -> do_arg_results(L, S, Lr, Sr, Decoder); {long_name_results, N, R} -> do_single_name_results(N, R, Decoder); {short_name_results, N@1, R@1} -> do_single_name_results(N@1, R@1, Decoder) end end. -spec arg( binary(), binary(), fun((gleam@dynamic:dynamic_()) -> {ok, FZA} | {error, list(gleam@dynamic:decode_error())}), fun((FZA) -> fun((gleam@dynamic:dynamic_()) -> {ok, FZC} | {error, list(gleam@dynamic:decode_error())})) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, FZC} | {error, list(gleam@dynamic:decode_error())}). arg(Long_name, Short_name, Decoder, Next) -> fun(Data) -> Long_name@1 = <<"--"/utf8, Long_name/binary>>, Short_name@1 = <<"-"/utf8, Short_name/binary>>, First = do_arg({arg, Long_name@1, Short_name@1}, Decoder), gleam@result:'try'(First(Data), fun(A) -> (Next(A))(Data) end) end. -spec arg_with_default( binary(), binary(), fun((gleam@dynamic:dynamic_()) -> {ok, FYV} | {error, list(gleam@dynamic:decode_error())}), FYV, fun((FYV) -> fun((gleam@dynamic:dynamic_()) -> {ok, FYX} | {error, list(gleam@dynamic:decode_error())})) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, FYX} | {error, list(gleam@dynamic:decode_error())}). arg_with_default(Long_name, Short_name, Decoder, Default, Next) -> arg( Long_name, Short_name, gleam@dynamic:optional(Decoder), fun(Res) -> Next(gleam@option:unwrap(Res, Default)) end ). -spec toggle( binary(), binary(), fun((boolean()) -> fun((gleam@dynamic:dynamic_()) -> {ok, FYS} | {error, list(gleam@dynamic:decode_error())})) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, FYS} | {error, list(gleam@dynamic:decode_error())}). toggle(Long_name, Short_name, Next) -> arg_with_default( Long_name, Short_name, fun gleam@dynamic:bool/1, false, Next ). -spec short_name( binary(), fun((gleam@dynamic:dynamic_()) -> {ok, FZF} | {error, list(gleam@dynamic:decode_error())}), fun((FZF) -> fun((gleam@dynamic:dynamic_()) -> {ok, FZH} | {error, list(gleam@dynamic:decode_error())})) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, FZH} | {error, list(gleam@dynamic:decode_error())}). short_name(Short_name, Decoder, Next) -> fun(Data) -> First = do_arg({short_name, <<"-"/utf8, Short_name/binary>>}, Decoder), gleam@result:'try'(First(Data), fun(A) -> (Next(A))(Data) end) end. -spec long_name( binary(), fun((gleam@dynamic:dynamic_()) -> {ok, FZK} | {error, list(gleam@dynamic:decode_error())}), fun((FZK) -> fun((gleam@dynamic:dynamic_()) -> {ok, FZM} | {error, list(gleam@dynamic:decode_error())})) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, FZM} | {error, list(gleam@dynamic:decode_error())}). long_name(Long_name, Decoder, Next) -> fun(Data) -> First = do_arg({long_name, <<"--"/utf8, Long_name/binary>>}, Decoder), gleam@result:'try'(First(Data), fun(A) -> (Next(A))(Data) end) end.