Skip to main content

src/aion@codec.erl

-module(aion@codec).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aion/codec.gleam").
-export([json_codec/2]).
-export_type([codec/1, decode_error/0]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(" Typed codecs for values crossing the Aion workflow boundary.\n").

-type codec(DNJ) :: {codec,
        fun((DNJ) -> binary()),
        fun((binary()) -> {ok, DNJ} | {error, decode_error()})}.

-type decode_error() :: {decode_error, binary(), list(binary())}.

-file("src/aion/codec.gleam", 52).
-spec dynamic_decode_error(list(gleam@dynamic@decode:decode_error())) -> decode_error().
dynamic_decode_error(Errors) ->
    case Errors of
        [] ->
            {decode_error, <<"Unable to decode value"/utf8>>, []};

        [{decode_error, Expected, Found, Path} | _] ->
            {decode_error,
                <<<<<<"Expected "/utf8, Expected/binary>>/binary,
                        ", found "/utf8>>/binary,
                    Found/binary>>,
                Path}
    end.

-file("src/aion/codec.gleam", 42).
-spec json_decode_error(gleam@json:decode_error()) -> decode_error().
json_decode_error(Error) ->
    case Error of
        unexpected_end_of_input ->
            {decode_error, <<"Unexpected end of input"/utf8>>, []};

        {unexpected_byte, Byte} ->
            {decode_error, <<"Unexpected byte: "/utf8, Byte/binary>>, []};

        {unexpected_sequence, Sequence} ->
            {decode_error,
                <<"Unexpected sequence: "/utf8, Sequence/binary>>,
                []};

        {unable_to_decode, Errors} ->
            dynamic_decode_error(Errors)
    end.

-file("src/aion/codec.gleam", 60).
-spec result_map_error({ok, DNO} | {error, DNP}, fun((DNP) -> DNS)) -> {ok, DNO} |
    {error, DNS}.
result_map_error(Result, Mapper) ->
    case Result of
        {ok, Value} ->
            {ok, Value};

        {error, Error} ->
            {error, Mapper(Error)}
    end.

-file("src/aion/codec.gleam", 28).
?DOC(
    " Build a `Codec` from a `gleam_json` encoder and decoder.\n"
    "\n"
    " Malformed JSON and decoder mismatches are mapped to `DecodeError` values;\n"
    " decode failures are returned as data.\n"
).
-spec json_codec(
    fun((DNK) -> gleam@json:json()),
    gleam@dynamic@decode:decoder(DNK)
) -> codec(DNK).
json_codec(Encoder, Decoder) ->
    {codec, fun(Value) -> _pipe = Value,
            _pipe@1 = Encoder(_pipe),
            gleam@json:to_string(_pipe@1) end, fun(Input) -> _pipe@2 = Input,
            _pipe@3 = gleam@json:parse(_pipe@2, Decoder),
            result_map_error(_pipe@3, fun json_decode_error/1) end}.