Current section

Files

Jump to
clad src clad.erl
Raw

src/clad.erl

-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.