Current section

Files

Jump to
distribute src distribute@codec@tagged.erl
Raw

src/distribute@codec@tagged.erl

-module(distribute@codec@tagged).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/distribute/codec/tagged.gleam").
-export([new/3, payload/1, tag/1, version/1, encoder/1, decoder/3, encode_tagged/4, decode_tagged/4]).
-export_type([tagged_message/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-opaque tagged_message(HLL) :: {tagged_message, binary(), integer(), HLL}.
-file("src/distribute/codec/tagged.gleam", 13).
?DOC(" Create a tagged message.\n").
-spec new(binary(), integer(), HLM) -> tagged_message(HLM).
new(Tag, Version, Payload) ->
{tagged_message, Tag, Version, Payload}.
-file("src/distribute/codec/tagged.gleam", 22).
?DOC(" Extract the payload.\n").
-spec payload(tagged_message(HLO)) -> HLO.
payload(Msg) ->
erlang:element(4, Msg).
-file("src/distribute/codec/tagged.gleam", 27).
?DOC(" Get the tag.\n").
-spec tag(tagged_message(any())) -> binary().
tag(Msg) ->
erlang:element(2, Msg).
-file("src/distribute/codec/tagged.gleam", 32).
?DOC(" Get the version.\n").
-spec version(tagged_message(any())) -> integer().
version(Msg) ->
erlang:element(3, Msg).
-file("src/distribute/codec/tagged.gleam", 39).
?DOC(
" Encoder for tagged messages.\n"
"\n"
" Format: `[tag_len:32][tag:utf8][version:32][payload]`\n"
).
-spec encoder(
fun((HLU) -> {ok, bitstring()} | {error, distribute@codec:encode_error()})
) -> fun((tagged_message(HLU)) -> {ok, bitstring()} |
{error, distribute@codec:encode_error()}).
encoder(Payload_encoder) ->
fun(Msg) ->
Tag_bytes = gleam_stdlib:identity(erlang:element(2, Msg)),
Tag_len = erlang:byte_size(Tag_bytes),
gleam@result:'try'(
distribute@codec:encode(Payload_encoder, erlang:element(4, Msg)),
fun(Payload_bytes) ->
{ok,
<<Tag_len:32,
Tag_bytes/bitstring,
(erlang:element(3, Msg)):32,
Payload_bytes/bitstring>>}
end
)
end.
-file("src/distribute/codec/tagged.gleam", 53).
?DOC(
" Decoder for tagged messages with tag and version validation.\n"
"\n"
" Returns `TagMismatch` or `VersionMismatch` errors for protocol mismatches.\n"
).
-spec decoder(
binary(),
integer(),
fun((bitstring()) -> {ok, HLY} | {error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, tagged_message(HLY)} |
{error, distribute@codec:decode_error()}).
decoder(Expected_tag, Expected_version, Payload_decoder) ->
fun(Binary) -> case Binary of
<<Tag_len:32, Rest/bitstring>> ->
gleam@result:'try'(
begin
_pipe = gleam_stdlib:bit_array_slice(Rest, 0, Tag_len),
gleam@result:replace_error(
_pipe,
{insufficient_data, <<"tag truncated"/utf8>>}
)
end,
fun(Tag_bytes) ->
gleam@result:'try'(
begin
_pipe@1 = gleam@bit_array:to_string(Tag_bytes),
gleam@result:replace_error(
_pipe@1,
{invalid_binary,
<<"tag not valid UTF-8"/utf8>>}
)
end,
fun(Tag_string) ->
case Tag_string =:= Expected_tag of
false ->
{error,
{tag_mismatch,
Expected_tag,
Tag_string}};
true ->
gleam@result:'try'(
begin
_pipe@2 = gleam_stdlib:bit_array_slice(
Rest,
Tag_len,
erlang:byte_size(Rest) - Tag_len
),
gleam@result:replace_error(
_pipe@2,
{insufficient_data,
<<"missing version"/utf8>>}
)
end,
fun(Remaining) -> case Remaining of
<<Ver:32,
Payload_bytes/bitstring>> ->
case Ver =:= Expected_version of
false ->
{error,
{version_mismatch,
Expected_version,
Ver}};
true ->
gleam@result:'try'(
distribute@codec:decode(
Payload_decoder,
Payload_bytes
),
fun(Payload) ->
{ok,
{tagged_message,
Tag_string,
Ver,
Payload}}
end
)
end;
_ ->
{error,
{insufficient_data,
<<"missing version or payload"/utf8>>}}
end end
)
end
end
)
end
);
_ ->
{error, {invalid_binary, <<"missing tag length"/utf8>>}}
end end.
-file("src/distribute/codec/tagged.gleam", 109).
?DOC(" Convenience: encode a value as a tagged message in one step.\n").
-spec encode_tagged(
binary(),
integer(),
fun((HMC) -> {ok, bitstring()} | {error, distribute@codec:encode_error()}),
HMC
) -> {ok, bitstring()} | {error, distribute@codec:encode_error()}.
encode_tagged(Tag, Version, Payload_encoder, Value) ->
Msg = new(Tag, Version, Value),
distribute@codec:encode(encoder(Payload_encoder), Msg).
-file("src/distribute/codec/tagged.gleam", 120).
?DOC(" Convenience: decode binary as a tagged message and extract the payload.\n").
-spec decode_tagged(
binary(),
integer(),
fun((bitstring()) -> {ok, HMG} | {error, distribute@codec:decode_error()}),
bitstring()
) -> {ok, HMG} | {error, distribute@codec:decode_error()}.
decode_tagged(Expected_tag, Expected_version, Payload_decoder, Data) ->
gleam@result:'try'(
distribute@codec:decode(
decoder(Expected_tag, Expected_version, Payload_decoder),
Data
),
fun(Msg) -> {ok, payload(Msg)} end
).