Current section
Files
Jump to
Current section
Files
src/outcome.erl
-module(outcome).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([new_defect/1, new_failure/1, error_with_defect/1, error_with_failure/1, into_defect/1, into_failure/1, map_into_defect/2, as_defect/2, as_failure/2, problem_with_defect/2, with_defect/2, problem_with_failure/2, with_failure/2, add_to_problem_stack/2, add_context_to_problem/2, with_context/2, add_failure_to_problem_stack/2, add_defect_to_problem_stack/2, unwrap_failure/2, outcome_to_lines/1, pretty_print/1, pretty_print_outcome/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 as_defect({ok, GJA} | {error, nil}, binary()) -> {ok, GJA} |
{error, problem()}.
as_defect(Result, E) ->
gleam@result:replace_error(Result, new_defect(E)).
-spec as_failure({ok, GJE} | {error, nil}, binary()) -> {ok, GJE} |
{error, problem()}.
as_failure(Result, E) ->
gleam@result:replace_error(Result, new_failure(E)).
-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 problem_with_defect(problem(), binary()) -> problem().
problem_with_defect(Problem, Defect_message) ->
case Problem of
{defect, Current_defect_message, Stack} ->
{defect,
Current_defect_message,
push_to_stack(Stack, {stack_entry_defect, Defect_message})};
{failure, _, Stack@1} ->
{defect,
Defect_message,
push_to_stack(Stack@1, {stack_entry_defect, Defect_message})}
end.
-spec with_defect({ok, GJL} | {error, problem()}, binary()) -> {ok, GJL} |
{error, problem()}.
with_defect(Outcome, Defect_message) ->
gleam@result:map_error(
Outcome,
fun(_capture) -> problem_with_defect(_capture, Defect_message) end
).
-spec problem_with_failure(problem(), binary()) -> problem().
problem_with_failure(Problem, Failure_message) ->
case Problem of
{defect, Current_defect_message, Stack} ->
{defect,
Current_defect_message,
push_to_stack(Stack, {stack_entry_failure, Failure_message})};
{failure, _, Stack@1} ->
{failure,
Failure_message,
push_to_stack(Stack@1, {stack_entry_failure, Failure_message})}
end.
-spec with_failure({ok, GJO} | {error, problem()}, binary()) -> {ok, GJO} |
{error, problem()}.
with_failure(Outcome, Failure_message) ->
gleam@result:map_error(
Outcome,
fun(_capture) -> problem_with_failure(_capture, Failure_message) end
).
-spec add_to_problem_stack(problem(), stack_entry()) -> problem().
add_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) ->
add_to_problem_stack(Problem, {stack_entry_context, Value}).
-spec with_context({ok, GJI} | {error, problem()}, binary()) -> {ok, GJI} |
{error, problem()}.
with_context(Outcome, Context) ->
gleam@result:map_error(
Outcome,
fun(Problem) -> add_context_to_problem(Problem, Context) end
).
-spec add_failure_to_problem_stack(problem(), binary()) -> problem().
add_failure_to_problem_stack(Problem, Failure) ->
add_to_problem_stack(Problem, {stack_entry_failure, Failure}).
-spec add_defect_to_problem_stack(problem(), binary()) -> problem().
add_defect_to_problem_stack(Problem, Failure) ->
add_to_problem_stack(Problem, {stack_entry_failure, Failure}).
-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} ->
<<"Context: "/utf8, Value/binary>>;
{stack_entry_defect, Value@1} ->
<<"Defect: "/utf8, Value@1/binary>>;
{stack_entry_failure, Value@2} ->
<<"Failure: "/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 pretty_print_outcome({ok, any()} | {error, problem()}) -> binary().
pretty_print_outcome(Outcome) ->
case Outcome of
{ok, _} ->
<<"Ok"/utf8>>;
{error, Problem} ->
pretty_print(Problem)
end.