Current section

Files

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

src/distribute@codec@composite.erl

-module(distribute@codec@composite).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/distribute/codec/composite.gleam").
-export([result_sized_decoder/2, result_decoder/2, result_encoder/2, result/2, option_encoder/1, option_decoder/1, option/1, option_sized_decoder/1, tuple2_encoder/2, tuple2_sized_decoder/2, tuple2_decoder/2, tuple3_encoder/3, tuple3_sized_decoder/3, tuple3_decoder/3, tuple2/2, tuple3/3]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/distribute/codec/composite.gleam", 85).
-spec result_sized_decoder(
fun((bitstring()) -> {ok, {IFG, bitstring()}} |
{error, distribute@codec:decode_error()}),
fun((bitstring()) -> {ok, {IFI, bitstring()}} |
{error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, {{ok, IFG} | {error, IFI}, bitstring()}} |
{error, distribute@codec:decode_error()}).
result_sized_decoder(Ok_decoder, Error_decoder) ->
fun(Data) -> case Data of
<<0, Rest/binary>> ->
gleam@result:'try'(
Ok_decoder(Rest),
fun(_use0) ->
{Value, Remaining} = _use0,
{ok, {{ok, Value}, Remaining}}
end
);
<<1, Rest@1/binary>> ->
gleam@result:'try'(
Error_decoder(Rest@1),
fun(_use0@1) ->
{Err, Remaining@1} = _use0@1,
{ok, {{error, Err}, Remaining@1}}
end
);
_ ->
{error, {invalid_binary, <<"invalid result tag"/utf8>>}}
end end.
-file("src/distribute/codec/composite.gleam", 104).
-spec result_decoder(
fun((bitstring()) -> {ok, IFN} | {error, distribute@codec:decode_error()}),
fun((bitstring()) -> {ok, IFP} | {error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, {ok, IFN} | {error, IFP}} |
{error, distribute@codec:decode_error()}).
result_decoder(Ok_decoder, Error_decoder) ->
fun(Data) -> case Data of
<<0, Rest/binary>> ->
gleam@result:'try'(
Ok_decoder(Rest),
fun(Value) -> {ok, {ok, Value}} end
);
<<1, Rest@1/binary>> ->
gleam@result:'try'(
Error_decoder(Rest@1),
fun(Err) -> {ok, {error, Err}} end
);
_ ->
{error, {invalid_binary, <<"invalid result tag"/utf8>>}}
end end.
-file("src/distribute/codec/composite.gleam", 67).
?DOC(" Encoder for Result(a, e). Ok is 0x00 + encoded, Error is 0x01 + encoded.\n").
-spec result_encoder(
fun((IEZ) -> {ok, bitstring()} | {error, distribute@codec:encode_error()}),
fun((IFB) -> {ok, bitstring()} | {error, distribute@codec:encode_error()})
) -> fun(({ok, IEZ} | {error, IFB}) -> {ok, bitstring()} |
{error, distribute@codec:encode_error()}).
result_encoder(Ok_encoder, Error_encoder) ->
fun(Res) -> case Res of
{ok, Value} ->
gleam@result:'try'(
Ok_encoder(Value),
fun(Encoded) ->
{ok, gleam@bit_array:append(<<0>>, Encoded)}
end
);
{error, Err} ->
gleam@result:'try'(
Error_encoder(Err),
fun(Encoded@1) ->
{ok, gleam@bit_array:append(<<1>>, Encoded@1)}
end
)
end end.
-file("src/distribute/codec/composite.gleam", 304).
-spec result(distribute@codec:codec(IHG), distribute@codec:codec(IHI)) -> distribute@codec:codec({ok,
IHG} |
{error, IHI}).
result(Ok_codec, Error_codec) ->
{codec,
result_encoder(
erlang:element(2, Ok_codec),
erlang:element(2, Error_codec)
),
result_decoder(
erlang:element(3, Ok_codec),
erlang:element(3, Error_codec)
),
result_sized_decoder(
erlang:element(4, Ok_codec),
erlang:element(4, Error_codec)
)}.
-file("src/distribute/codec/composite.gleam", 14).
?DOC(" Encoder for Option(a). None is 0x00, Some(v) is 0x01 + encoded value.\n").
-spec option_encoder(
fun((IEN) -> {ok, bitstring()} | {error, distribute@codec:encode_error()})
) -> fun((gleam@option:option(IEN)) -> {ok, bitstring()} |
{error, distribute@codec:encode_error()}).
option_encoder(Inner) ->
fun(Opt) -> case Opt of
none ->
{ok, <<0>>};
{some, Value} ->
gleam@result:'try'(
Inner(Value),
fun(Encoded) ->
{ok, gleam@bit_array:append(<<1>>, Encoded)}
end
)
end end.
-file("src/distribute/codec/composite.gleam", 47).
?DOC(
" Strict top-level `Option(a)` decoder. `None` is one byte (`0`)\n"
" followed by EOF; `Some(a)` is `1` followed by `a`'s encoded form.\n"
"\n"
" The earlier `<<0, _:bytes>>` pattern matched a `None` tag plus any\n"
" number of trailing bytes, mirroring the smuggling vector that we\n"
" closed inside `tuple2`/`tuple3`. The `Some` branch is already strict\n"
" because `inner` is itself a top-level `Decoder(a)` (built via\n"
" `to_decoder`).\n"
).
-spec option_decoder(
fun((bitstring()) -> {ok, IEV} | {error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, gleam@option:option(IEV)} |
{error, distribute@codec:decode_error()}).
option_decoder(Inner) ->
fun(Data) -> case Data of
<<0>> ->
{ok, none};
<<0, _, _/binary>> ->
{error,
{invalid_binary,
<<"trailing bytes after option None tag"/utf8>>}};
<<1, Rest/binary>> ->
gleam@result:'try'(
Inner(Rest),
fun(Value) -> {ok, {some, Value}} end
);
_ ->
{error, {invalid_binary, <<"invalid option tag"/utf8>>}}
end end.
-file("src/distribute/codec/composite.gleam", 318).
-spec option(distribute@codec:codec(IHN)) -> distribute@codec:codec(gleam@option:option(IHN)).
option(Inner) ->
{codec,
option_encoder(erlang:element(2, Inner)),
option_decoder(erlang:element(3, Inner)),
option_sized_decoder(erlang:element(4, Inner))}.
-file("src/distribute/codec/composite.gleam", 26).
-spec option_sized_decoder(
fun((bitstring()) -> {ok, {IER, bitstring()}} |
{error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, {gleam@option:option(IER), bitstring()}} |
{error, distribute@codec:decode_error()}).
option_sized_decoder(Inner) ->
fun(Data) -> case Data of
<<0, Rest/binary>> ->
{ok, {none, Rest}};
<<1, Rest@1/binary>> ->
gleam@result:'try'(
Inner(Rest@1),
fun(_use0) ->
{Value, Remaining} = _use0,
{ok, {{some, Value}, Remaining}}
end
);
_ ->
{error, {invalid_binary, <<"invalid option tag"/utf8>>}}
end end.
-file("src/distribute/codec/composite.gleam", 134).
?DOC(
" Encoder for `#(a, b)`. First element is length-prefixed (32-bit).\n"
"\n"
" The length prefix is validated against the unsigned-32 bound. A\n"
" first element larger than 4 GiB would silently truncate the prefix\n"
" and corrupt the wire frame. Mirrors the bound enforced by\n"
" `string_encoder` / `bitarray_encoder` / `list_encoder` /\n"
" `subject_encoder` / `tagged.encoder`.\n"
).
-spec tuple2_encoder(
fun((IFU) -> {ok, bitstring()} | {error, distribute@codec:encode_error()}),
fun((IFW) -> {ok, bitstring()} | {error, distribute@codec:encode_error()})
) -> fun(({IFU, IFW}) -> {ok, bitstring()} |
{error, distribute@codec:encode_error()}).
tuple2_encoder(First, Second) ->
fun(Tuple) ->
{A, B} = Tuple,
gleam@result:'try'(
First(A),
fun(Encoded_a) ->
gleam@result:'try'(
Second(B),
fun(Encoded_b) ->
Len_a = erlang:byte_size(Encoded_a),
gleam@result:'try'(
distribute@codec:check_32bit_length(
Len_a,
<<"tuple2 first element"/utf8>>
),
fun(_) ->
{ok,
gleam_stdlib:bit_array_concat(
[<<Len_a:32>>, Encoded_a, Encoded_b]
)}
end
)
end
)
end
)
end.
-file("src/distribute/codec/composite.gleam", 279).
?DOC(
" Reject data smuggled past the inner decoder. The slice we hand to the\n"
" inner decoder is sized exactly to `len_a`/`len_b`; if the decoder\n"
" returned remaining bytes, the encoder declared a slice longer than\n"
" the value consumed. A hostile sender hiding payload inside the\n"
" length-prefixed envelope. Surface as `InvalidBinary` instead of\n"
" silently passing bytes through.\n"
).
-spec reject_inner_trailing(bitstring(), binary()) -> {ok, nil} |
{error, distribute@codec:decode_error()}.
reject_inner_trailing(Rest, Where_label) ->
case Rest of
<<>> ->
{ok, nil};
_ ->
{error,
{invalid_binary,
<<<<"trailing bytes smuggled inside "/utf8,
Where_label/binary>>/binary,
" element"/utf8>>}}
end.
-file("src/distribute/codec/composite.gleam", 148).
-spec tuple2_sized_decoder(
fun((bitstring()) -> {ok, {IFZ, bitstring()}} |
{error, distribute@codec:decode_error()}),
fun((bitstring()) -> {ok, {IGB, bitstring()}} |
{error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, {{IFZ, IGB}, bitstring()}} |
{error, distribute@codec:decode_error()}).
tuple2_sized_decoder(First, Second) ->
fun(Data) -> case Data of
<<Len_a:32, Rest/binary>> ->
Rest_size = erlang:byte_size(Rest),
gleam@result:'try'(
begin
_pipe = gleam_stdlib:bit_array_slice(Rest, 0, Len_a),
gleam@result:replace_error(
_pipe,
{insufficient_data, <<"tuple2 first"/utf8>>}
)
end,
fun(First_data) ->
gleam@result:'try'(
First(First_data),
fun(_use0) ->
{A, First_leftover} = _use0,
gleam@result:'try'(
reject_inner_trailing(
First_leftover,
<<"tuple2 first"/utf8>>
),
fun(_) ->
gleam@result:'try'(
begin
_pipe@1 = gleam_stdlib:bit_array_slice(
Rest,
Len_a,
Rest_size - Len_a
),
gleam@result:replace_error(
_pipe@1,
{insufficient_data,
<<"tuple2 second"/utf8>>}
)
end,
fun(After_first) ->
gleam@result:'try'(
Second(After_first),
fun(_use0@1) ->
{B, Remaining} = _use0@1,
{ok,
{{A, B}, Remaining}}
end
)
end
)
end
)
end
)
end
);
_ ->
{error,
{invalid_binary, <<"missing tuple2 length prefix"/utf8>>}}
end end.
-file("src/distribute/codec/composite.gleam", 183).
-spec tuple2_decoder(
fun((bitstring()) -> {ok, {IGE, bitstring()}} |
{error, distribute@codec:decode_error()}),
fun((bitstring()) -> {ok, {IGG, bitstring()}} |
{error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, {IGE, IGG}} |
{error, distribute@codec:decode_error()}).
tuple2_decoder(First, Second) ->
distribute@codec:to_decoder(tuple2_sized_decoder(First, Second)).
-file("src/distribute/codec/composite.gleam", 198).
?DOC(
" Encoder for `#(a, b, c)`. First two elements are length-prefixed (32-bit).\n"
"\n"
" Both length prefixes are validated against the unsigned-32 bound;\n"
" see `tuple2_encoder` for the rationale.\n"
).
-spec tuple3_encoder(
fun((IGJ) -> {ok, bitstring()} | {error, distribute@codec:encode_error()}),
fun((IGL) -> {ok, bitstring()} | {error, distribute@codec:encode_error()}),
fun((IGN) -> {ok, bitstring()} | {error, distribute@codec:encode_error()})
) -> fun(({IGJ, IGL, IGN}) -> {ok, bitstring()} |
{error, distribute@codec:encode_error()}).
tuple3_encoder(First, Second, Third) ->
fun(Tuple) ->
{A, B, C} = Tuple,
gleam@result:'try'(
First(A),
fun(Encoded_a) ->
gleam@result:'try'(
Second(B),
fun(Encoded_b) ->
gleam@result:'try'(
Third(C),
fun(Encoded_c) ->
Len_a = erlang:byte_size(Encoded_a),
Len_b = erlang:byte_size(Encoded_b),
gleam@result:'try'(
distribute@codec:check_32bit_length(
Len_a,
<<"tuple3 first element"/utf8>>
),
fun(_) ->
gleam@result:'try'(
distribute@codec:check_32bit_length(
Len_b,
<<"tuple3 second element"/utf8>>
),
fun(_) ->
{ok,
gleam_stdlib:bit_array_concat(
[<<Len_a:32>>,
Encoded_a,
<<Len_b:32>>,
Encoded_b,
Encoded_c]
)}
end
)
end
)
end
)
end
)
end
)
end.
-file("src/distribute/codec/composite.gleam", 224).
-spec tuple3_sized_decoder(
fun((bitstring()) -> {ok, {IGQ, bitstring()}} |
{error, distribute@codec:decode_error()}),
fun((bitstring()) -> {ok, {IGS, bitstring()}} |
{error, distribute@codec:decode_error()}),
fun((bitstring()) -> {ok, {IGU, bitstring()}} |
{error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, {{IGQ, IGS, IGU}, bitstring()}} |
{error, distribute@codec:decode_error()}).
tuple3_sized_decoder(First, Second, Third) ->
fun(Data) -> case Data of
<<Len_a:32, Rest/binary>> ->
Rest_size = erlang:byte_size(Rest),
gleam@result:'try'(
begin
_pipe = gleam_stdlib:bit_array_slice(Rest, 0, Len_a),
gleam@result:replace_error(
_pipe,
{insufficient_data, <<"tuple3 first"/utf8>>}
)
end,
fun(First_data) ->
gleam@result:'try'(
First(First_data),
fun(_use0) ->
{A, First_leftover} = _use0,
gleam@result:'try'(
reject_inner_trailing(
First_leftover,
<<"tuple3 first"/utf8>>
),
fun(_) ->
gleam@result:'try'(
begin
_pipe@1 = gleam_stdlib:bit_array_slice(
Rest,
Len_a,
Rest_size - Len_a
),
gleam@result:replace_error(
_pipe@1,
{insufficient_data,
<<"tuple3 after first"/utf8>>}
)
end,
fun(After_first) ->
case After_first of
<<Len_b:32, Rest2/binary>> ->
Rest2_size = erlang:byte_size(
Rest2
),
gleam@result:'try'(
begin
_pipe@2 = gleam_stdlib:bit_array_slice(
Rest2,
0,
Len_b
),
gleam@result:replace_error(
_pipe@2,
{insufficient_data,
<<"tuple3 second"/utf8>>}
)
end,
fun(Second_data) ->
gleam@result:'try'(
Second(
Second_data
),
fun(_use0@1) ->
{B,
Second_leftover} = _use0@1,
gleam@result:'try'(
reject_inner_trailing(
Second_leftover,
<<"tuple3 second"/utf8>>
),
fun(
_
) ->
gleam@result:'try'(
begin
_pipe@3 = gleam_stdlib:bit_array_slice(
Rest2,
Len_b,
Rest2_size
- Len_b
),
gleam@result:replace_error(
_pipe@3,
{insufficient_data,
<<"tuple3 third"/utf8>>}
)
end,
fun(
Third_data
) ->
gleam@result:'try'(
Third(
Third_data
),
fun(
_use0@2
) ->
{C,
Remaining} = _use0@2,
{ok,
{{A,
B,
C},
Remaining}}
end
)
end
)
end
)
end
)
end
);
_ ->
{error,
{invalid_binary,
<<"tuple3 missing second length"/utf8>>}}
end
end
)
end
)
end
)
end
);
_ ->
{error, {invalid_binary, <<"tuple3 missing length"/utf8>>}}
end end.
-file("src/distribute/codec/composite.gleam", 292).
-spec tuple3_decoder(
fun((bitstring()) -> {ok, {IGZ, bitstring()}} |
{error, distribute@codec:decode_error()}),
fun((bitstring()) -> {ok, {IHB, bitstring()}} |
{error, distribute@codec:decode_error()}),
fun((bitstring()) -> {ok, {IHD, bitstring()}} |
{error, distribute@codec:decode_error()})
) -> fun((bitstring()) -> {ok, {IGZ, IHB, IHD}} |
{error, distribute@codec:decode_error()}).
tuple3_decoder(First, Second, Third) ->
distribute@codec:to_decoder(tuple3_sized_decoder(First, Second, Third)).
-file("src/distribute/codec/composite.gleam", 326).
-spec tuple2(distribute@codec:codec(IHR), distribute@codec:codec(IHT)) -> distribute@codec:codec({IHR,
IHT}).
tuple2(First, Second) ->
{codec,
tuple2_encoder(erlang:element(2, First), erlang:element(2, Second)),
tuple2_decoder(erlang:element(4, First), erlang:element(4, Second)),
tuple2_sized_decoder(
erlang:element(4, First),
erlang:element(4, Second)
)}.
-file("src/distribute/codec/composite.gleam", 340).
-spec tuple3(
distribute@codec:codec(IHW),
distribute@codec:codec(IHY),
distribute@codec:codec(IIA)
) -> distribute@codec:codec({IHW, IHY, IIA}).
tuple3(First, Second, Third) ->
{codec,
tuple3_encoder(
erlang:element(2, First),
erlang:element(2, Second),
erlang:element(2, Third)
),
tuple3_decoder(
erlang:element(4, First),
erlang:element(4, Second),
erlang:element(4, Third)
),
tuple3_sized_decoder(
erlang:element(4, First),
erlang:element(4, Second),
erlang:element(4, Third)
)}.