Current section

Files

Jump to
outcome src outcome.erl
Raw

src/outcome.erl

-module(outcome).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([error_with_defect/1, error_with_failure/1, into_defect/1, into_failure/1, map_into_defect/2, map_into_failure/2, as_defect/2, as_failure/2, to_defect/1, to_failure/1, map_message/2, with_context/2, unwrap_failure/2, outcome_to_lines/1, pretty_print/1, print_line/1]).
-export_type([problem/0, stack_entry/0]).
-type problem() :: {defect,
binary(),
non_empty_list:non_empty_list(stack_entry())} |
{failure, binary(), non_empty_list:non_empty_list(stack_entry())}.
-type stack_entry() :: {stack_entry_context, binary()} |
{stack_entry_defect, binary()} |
{stack_entry_failure, binary()}.
-spec new_defect(binary()) -> problem().
new_defect(Message) ->
{defect, Message, non_empty_list:single({stack_entry_defect, Message})}.
-spec new_failure(binary()) -> problem().
new_failure(Message) ->
{failure, Message, non_empty_list:single({stack_entry_failure, Message})}.
-spec error_with_defect(binary()) -> {ok, any()} | {error, problem()}.
error_with_defect(Defect) ->
{error, new_defect(Defect)}.
-spec error_with_failure(binary()) -> {ok, any()} | {error, problem()}.
error_with_failure(Failure) ->
{error, new_failure(Failure)}.
-spec into_defect({ok, GIN} | {error, binary()}) -> {ok, GIN} |
{error, problem()}.
into_defect(Result) ->
gleam@result:map_error(Result, fun new_defect/1).
-spec into_failure({ok, GIR} | {error, binary()}) -> {ok, GIR} |
{error, problem()}.
into_failure(Result) ->
gleam@result:map_error(Result, fun new_failure/1).
-spec map_into_defect({ok, GIV} | {error, GIW}, fun((GIW) -> binary())) -> {ok,
GIV} |
{error, problem()}.
map_into_defect(Result, Mapper) ->
_pipe = Result,
_pipe@1 = gleam@result:map_error(_pipe, Mapper),
into_defect(_pipe@1).
-spec map_into_failure({ok, GJA} | {error, GJB}, fun((GJB) -> binary())) -> {ok,
GJA} |
{error, problem()}.
map_into_failure(Result, Mapper) ->
_pipe = Result,
_pipe@1 = gleam@result:map_error(_pipe, Mapper),
into_failure(_pipe@1).
-spec as_defect({ok, GJF} | {error, nil}, binary()) -> {ok, GJF} |
{error, problem()}.
as_defect(Result, E) ->
gleam@result:replace_error(Result, new_defect(E)).
-spec as_failure({ok, GJJ} | {error, nil}, binary()) -> {ok, GJJ} |
{error, problem()}.
as_failure(Result, E) ->
gleam@result:replace_error(Result, new_failure(E)).
-spec to_defect({ok, GJQ} | {error, problem()}) -> {ok, GJQ} |
{error, problem()}.
to_defect(Outcome) ->
_pipe = Outcome,
gleam@result:map_error(
_pipe,
fun(Problem) ->
{defect, erlang:element(2, Problem), erlang:element(3, Problem)}
end
).
-spec to_failure({ok, GJT} | {error, problem()}) -> {ok, GJT} |
{error, problem()}.
to_failure(Outcome) ->
_pipe = Outcome,
gleam@result:map_error(
_pipe,
fun(Problem) ->
{failure, erlang:element(2, Problem), erlang:element(3, Problem)}
end
).
-spec map_message_in_problem(problem(), fun((binary()) -> binary())) -> problem().
map_message_in_problem(Problem, Mapper) ->
case Problem of
{defect, Message, Stack} ->
{defect, Mapper(Message), Stack};
{failure, Message@1, Stack@1} ->
{failure, Mapper(Message@1), Stack@1}
end.
-spec map_message({ok, GJW} | {error, problem()}, fun((binary()) -> binary())) -> {ok,
GJW} |
{error, problem()}.
map_message(Outcome, Mapper) ->
_pipe = Outcome,
gleam@result:map_error(
_pipe,
fun(_capture) -> map_message_in_problem(_capture, Mapper) end
).
-spec push_to_stack(non_empty_list:non_empty_list(stack_entry()), stack_entry()) -> non_empty_list:non_empty_list(stack_entry()).
push_to_stack(Stack, Entry) ->
non_empty_list:prepend(Stack, Entry).
-spec push_to_problem_stack(problem(), stack_entry()) -> problem().
push_to_problem_stack(Problem, Stack_entry) ->
case Problem of
{defect, Problem@1, Stack} ->
{defect, Problem@1, push_to_stack(Stack, Stack_entry)};
{failure, Problem@2, Stack@1} ->
{failure, Problem@2, push_to_stack(Stack@1, Stack_entry)}
end.
-spec add_context_to_problem(problem(), binary()) -> problem().
add_context_to_problem(Problem, Value) ->
push_to_problem_stack(Problem, {stack_entry_context, Value}).
-spec with_context({ok, GJN} | {error, problem()}, binary()) -> {ok, GJN} |
{error, problem()}.
with_context(Outcome, Context) ->
gleam@result:map_error(
Outcome,
fun(_capture) -> add_context_to_problem(_capture, Context) end
).
-spec unwrap_failure(problem(), binary()) -> binary().
unwrap_failure(Problem, Default_message) ->
case Problem of
{defect, _, _} ->
Default_message;
{failure, Message, _} ->
Message
end.
-spec prettry_print_problem_value(problem()) -> binary().
prettry_print_problem_value(Problem) ->
case Problem of
{defect, Value, _} ->
<<"Defect: "/utf8, Value/binary>>;
{failure, Value@1, _} ->
<<"Failure: "/utf8, Value@1/binary>>
end.
-spec pretty_print_stack_entry(stack_entry()) -> binary().
pretty_print_stack_entry(Entry) ->
case Entry of
{stack_entry_context, Value} ->
<<"c: "/utf8, Value/binary>>;
{stack_entry_defect, Value@1} ->
<<"d: "/utf8, Value@1/binary>>;
{stack_entry_failure, Value@2} ->
<<"f: "/utf8, Value@2/binary>>
end.
-spec stack_to_lines(non_empty_list:non_empty_list(stack_entry())) -> list(binary()).
stack_to_lines(Stack) ->
_pipe = Stack,
_pipe@1 = non_empty_list:to_list(_pipe),
gleam@list:map(_pipe@1, fun pretty_print_stack_entry/1).
-spec outcome_to_lines({ok, any()} | {error, problem()}) -> list(binary()).
outcome_to_lines(Outcome) ->
case Outcome of
{ok, _} ->
[];
{error, Problem} ->
stack_to_lines(erlang:element(3, Problem))
end.
-spec pretty_print(problem()) -> binary().
pretty_print(Problem) ->
Stack = begin
_pipe = erlang:element(3, Problem),
_pipe@1 = stack_to_lines(_pipe),
gleam@string:join(_pipe@1, <<"\n "/utf8>>)
end,
<<<<(prettry_print_problem_value(Problem))/binary, "\n\nstack:\n "/utf8>>/binary,
Stack/binary>>.
-spec print_line(problem()) -> binary().
print_line(Problem) ->
Stack = begin
_pipe = erlang:element(3, Problem),
_pipe@1 = stack_to_lines(_pipe),
gleam@string:join(_pipe@1, <<" < "/utf8>>)
end,
<<<<(prettry_print_problem_value(Problem))/binary, " < "/utf8>>/binary,
Stack/binary>>.