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([defect/1, failure/1, error_with_defect/1, new_stack/1, new_stack_with_defect/1, new_stack_with_failure/1, error_with_failure/1, stack_to_problems/1, unwrap_failure/2, into_defect/1, into_failure/1, map_into_defect/2, as_defect/2, as_failure/2, add_to_stack/2, add_context_to_stack/2, add_context/2, add_defect_to_stack/2, add_failure_to_stack/2, stack_to_lines/1, outcome_to_lines/1, pretty_print/1]).
-export_type([problem/0, stack/0]).
-type problem() :: {context, binary()} |
{defect, binary()} |
{failure, binary()}.
-type stack() :: {stack, problem(), list(problem())}.
-spec defect(binary()) -> problem().
defect(Value) ->
{defect, Value}.
-spec failure(binary()) -> problem().
failure(Value) ->
{failure, Value}.
-spec problem_is_error(problem()) -> boolean().
problem_is_error(Problem) ->
case Problem of
{context, _} ->
false;
{defect, _} ->
true;
{failure, _} ->
true
end.
-spec error_with_defect(binary()) -> {ok, any()} | {error, stack()}.
error_with_defect(Defect) ->
{error, {stack, {defect, Defect}, []}}.
-spec new_stack(problem()) -> stack().
new_stack(Error) ->
{stack, Error, []}.
-spec new_stack_with_defect(binary()) -> stack().
new_stack_with_defect(Failure) ->
new_stack({defect, Failure}).
-spec new_stack_with_failure(binary()) -> stack().
new_stack_with_failure(Failure) ->
new_stack({failure, Failure}).
-spec error_with_failure(binary()) -> {ok, any()} | {error, stack()}.
error_with_failure(Failure) ->
{error, new_stack_with_failure(Failure)}.
-spec stack_to_problems(stack()) -> list(problem()).
stack_to_problems(Stack) ->
[erlang:element(2, Stack) | erlang:element(3, Stack)].
-spec top_problem(list(problem())) -> {ok, problem()} | {error, nil}.
top_problem(Problems) ->
gleam@list:find(Problems, fun problem_is_error/1).
-spec unwrap_failure(stack(), binary()) -> binary().
unwrap_failure(Stack, Default) ->
_pipe = Stack,
_pipe@1 = stack_to_problems(_pipe),
gleam@list:fold_until(
_pipe@1,
Default,
fun(Message, Problem) -> case Problem of
{context, _} ->
{continue, Message};
{defect, _} ->
{stop, Message};
{failure, Failure_message} ->
{stop, Failure_message}
end end
).
-spec into_defect({ok, FWR} | {error, binary()}) -> {ok, FWR} | {error, stack()}.
into_defect(Result) ->
gleam@result:map_error(Result, fun(E) -> {stack, {defect, E}, []} end).
-spec into_failure({ok, FWV} | {error, binary()}) -> {ok, FWV} |
{error, stack()}.
into_failure(Result) ->
gleam@result:map_error(Result, fun(E) -> {stack, {failure, E}, []} end).
-spec map_into_defect({ok, FWZ} | {error, FXA}, fun((FXA) -> binary())) -> {ok,
FWZ} |
{error, stack()}.
map_into_defect(Result, Mapper) ->
_pipe = Result,
_pipe@1 = gleam@result:map_error(_pipe, Mapper),
into_defect(_pipe@1).
-spec as_defect({ok, FXE} | {error, nil}, binary()) -> {ok, FXE} |
{error, stack()}.
as_defect(Result, E) ->
gleam@result:replace_error(Result, {stack, {defect, E}, []}).
-spec as_failure({ok, FXI} | {error, nil}, binary()) -> {ok, FXI} |
{error, stack()}.
as_failure(Result, E) ->
gleam@result:replace_error(Result, {stack, {failure, E}, []}).
-spec add_to_stack(stack(), problem()) -> stack().
add_to_stack(Stack, New_problem) ->
{stack, New_problem, [erlang:element(2, Stack) | erlang:element(3, Stack)]}.
-spec add_context_to_stack(stack(), binary()) -> stack().
add_context_to_stack(Stack, Value) ->
add_to_stack(Stack, {context, Value}).
-spec add_context({ok, FXM} | {error, stack()}, binary()) -> {ok, FXM} |
{error, stack()}.
add_context(Outcome, Context) ->
gleam@result:map_error(
Outcome,
fun(Stack) -> add_context_to_stack(Stack, Context) end
).
-spec add_defect_to_stack(stack(), binary()) -> stack().
add_defect_to_stack(Stack, Value) ->
add_to_stack(Stack, {defect, Value}).
-spec add_failure_to_stack(stack(), binary()) -> stack().
add_failure_to_stack(Stack, Value) ->
add_to_stack(Stack, {failure, Value}).
-spec pretty_print_problem(problem()) -> binary().
pretty_print_problem(Problem) ->
case Problem of
{context, Value} ->
<<"Context: "/utf8, Value/binary>>;
{defect, Value@1} ->
<<"Defect: "/utf8, Value@1/binary>>;
{failure, Value@2} ->
<<"Failure: "/utf8, Value@2/binary>>
end.
-spec stack_to_lines(stack()) -> list(binary()).
stack_to_lines(Stack) ->
_pipe = stack_to_problems(Stack),
gleam@list:map(_pipe, fun pretty_print_problem/1).
-spec outcome_to_lines({ok, any()} | {error, stack()}) -> list(binary()).
outcome_to_lines(Outcome) ->
case Outcome of
{ok, _} ->
[];
{error, Stack} ->
stack_to_lines(Stack)
end.
-spec pretty_print(stack()) -> binary().
pretty_print(Stack) ->
Problem = begin
_pipe = Stack,
_pipe@1 = stack_to_problems(_pipe),
_pipe@2 = top_problem(_pipe@1),
_pipe@3 = gleam@result:map(_pipe@2, fun pretty_print_problem/1),
gleam@result:unwrap(_pipe@3, <<"Error"/utf8>>)
end,
Stack@1 = begin
_pipe@4 = stack_to_lines(Stack),
gleam@string:join(_pipe@4, <<"\n "/utf8>>)
end,
<<<<Problem/binary, "\n\nstack:\n "/utf8>>/binary, Stack@1/binary>>.