-module(distribute@codec). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/distribute/codec.gleam"). -export([encode/2, decode/2, decode_sized/2, to_decoder/1, string_sized_decoder/0, string_decoder/0, int_encoder/0, int_sized_decoder/0, int_decoder/0, float_encoder/0, float_sized_decoder/0, float_decoder/0, bool_encoder/0, bool_sized_decoder/0, bool_decoder/0, bitarray_encoder/0, bitarray_sized_decoder/0, bitarray_decoder/0, nil_encoder/0, nil_sized_decoder/0, nil_decoder/0, subject_encoder/0, subject_sized_decoder/0, subject_decoder/0, int/0, string_encoder/0, string/0, float/0, bool/0, bitarray/0, nil/0, subject/0, map/3, decode_error_to_string/1, encode_error_to_string/1, list/1, list_decoder/1, list_sized_decoder/1, list_encoder/1]). -export_type([encode_error/0, decode_error/0, codec/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. -type encode_error() :: {invalid_value, binary()} | {encode_failed, binary()} | {value_too_large, binary()}. -type decode_error() :: {invalid_binary, binary()} | {type_mismatch, binary()} | {decode_failed, binary()} | {insufficient_data, binary()} | decode_timeout | {tag_mismatch, binary(), binary()} | {version_mismatch, integer(), integer()}. -type codec(FLQ) :: {codec, fun((FLQ) -> {ok, bitstring()} | {error, encode_error()}), fun((bitstring()) -> {ok, FLQ} | {error, decode_error()}), fun((bitstring()) -> {ok, {FLQ, bitstring()}} | {error, decode_error()})}. -file("src/distribute/codec.gleam", 55). -spec encode(fun((FMA) -> {ok, bitstring()} | {error, encode_error()}), FMA) -> {ok, bitstring()} | {error, encode_error()}. encode(Encoder, Value) -> Encoder(Value). -file("src/distribute/codec.gleam", 59). -spec decode( fun((bitstring()) -> {ok, FME} | {error, decode_error()}), bitstring() ) -> {ok, FME} | {error, decode_error()}. decode(Decoder, Data) -> Decoder(Data). -file("src/distribute/codec.gleam", 63). -spec decode_sized( fun((bitstring()) -> {ok, {FMI, bitstring()}} | {error, decode_error()}), bitstring() ) -> {ok, {FMI, bitstring()}} | {error, decode_error()}. decode_sized(Decoder, Data) -> Decoder(Data). -file("src/distribute/codec.gleam", 71). ?DOC(" Turn a `SizedDecoder` into a `Decoder` (drops remaining bytes).\n"). -spec to_decoder( fun((bitstring()) -> {ok, {FMM, bitstring()}} | {error, decode_error()}) ) -> fun((bitstring()) -> {ok, FMM} | {error, decode_error()}). to_decoder(Sized) -> fun(Data) -> case Sized(Data) of {ok, {Value, _}} -> {ok, Value}; {error, E} -> {error, E} end end. -file("src/distribute/codec.gleam", 95). -spec string_sized_decoder() -> fun((bitstring()) -> {ok, {binary(), bitstring()}} | {error, decode_error()}). string_sized_decoder() -> fun(Data) -> case Data of <> -> Rest_size = erlang:byte_size(Rest), case Rest_size >= Len of false -> {error, {insufficient_data, <<"string"/utf8>>}}; true -> gleam@result:'try'( begin _pipe = gleam_stdlib:bit_array_slice( Rest, 0, Len ), gleam@result:replace_error( _pipe, {insufficient_data, <<"string slice"/utf8>>} ) end, fun(Str_bytes) -> gleam@result:'try'( begin _pipe@1 = gleam@bit_array:to_string( Str_bytes ), gleam@result:replace_error( _pipe@1, {invalid_binary, <<"invalid UTF-8"/utf8>>} ) end, fun(S) -> Remaining = case gleam_stdlib:bit_array_slice( Rest, Len, Rest_size - Len ) of {ok, R} -> R; {error, _} -> <<>> end, {ok, {S, Remaining}} end ) end ) end; _ -> {error, {invalid_binary, <<"missing string length prefix"/utf8>>}} end end. -file("src/distribute/codec.gleam", 124). -spec string_decoder() -> fun((bitstring()) -> {ok, binary()} | {error, decode_error()}). string_decoder() -> to_decoder(string_sized_decoder()). -file("src/distribute/codec.gleam", 132). -spec int_encoder() -> fun((integer()) -> {ok, bitstring()} | {error, encode_error()}). int_encoder() -> fun(I) -> {ok, <>} end. -file("src/distribute/codec.gleam", 136). -spec int_sized_decoder() -> fun((bitstring()) -> {ok, {integer(), bitstring()}} | {error, decode_error()}). int_sized_decoder() -> fun(Data) -> case Data of <> -> {ok, {I, Rest}}; _ -> {error, {invalid_binary, <<"int64"/utf8>>}} end end. -file("src/distribute/codec.gleam", 145). -spec int_decoder() -> fun((bitstring()) -> {ok, integer()} | {error, decode_error()}). int_decoder() -> to_decoder(int_sized_decoder()). -file("src/distribute/codec.gleam", 153). -spec float_encoder() -> fun((float()) -> {ok, bitstring()} | {error, encode_error()}). float_encoder() -> fun(F) -> {ok, <>} end. -file("src/distribute/codec.gleam", 157). -spec float_sized_decoder() -> fun((bitstring()) -> {ok, {float(), bitstring()}} | {error, decode_error()}). float_sized_decoder() -> fun(Data) -> case Data of <> -> {ok, {F, Rest}}; _ -> {error, {invalid_binary, <<"float64"/utf8>>}} end end. -file("src/distribute/codec.gleam", 166). -spec float_decoder() -> fun((bitstring()) -> {ok, float()} | {error, decode_error()}). float_decoder() -> to_decoder(float_sized_decoder()). -file("src/distribute/codec.gleam", 174). -spec bool_encoder() -> fun((boolean()) -> {ok, bitstring()} | {error, encode_error()}). bool_encoder() -> fun(B) -> case B of true -> {ok, <<1>>}; false -> {ok, <<0>>} end end. -file("src/distribute/codec.gleam", 183). -spec bool_sized_decoder() -> fun((bitstring()) -> {ok, {boolean(), bitstring()}} | {error, decode_error()}). bool_sized_decoder() -> fun(Data) -> case Data of <<1, Rest/binary>> -> {ok, {true, Rest}}; <<0, Rest@1/binary>> -> {ok, {false, Rest@1}}; _ -> {error, {invalid_binary, <<"bool"/utf8>>}} end end. -file("src/distribute/codec.gleam", 193). -spec bool_decoder() -> fun((bitstring()) -> {ok, boolean()} | {error, decode_error()}). bool_decoder() -> to_decoder(bool_sized_decoder()). -file("src/distribute/codec.gleam", 201). -spec bitarray_encoder() -> fun((bitstring()) -> {ok, bitstring()} | {error, encode_error()}). bitarray_encoder() -> fun(Bytes) -> Len = erlang:byte_size(Bytes), {ok, <>} end. -file("src/distribute/codec.gleam", 208). -spec bitarray_sized_decoder() -> fun((bitstring()) -> {ok, {bitstring(), bitstring()}} | {error, decode_error()}). bitarray_sized_decoder() -> fun(Data) -> case Data of <> -> Rest_size = erlang:byte_size(Rest), case Rest_size >= Len of false -> {error, {insufficient_data, <<"bitarray"/utf8>>}}; true -> gleam@result:'try'( begin _pipe = gleam_stdlib:bit_array_slice( Rest, 0, Len ), gleam@result:replace_error( _pipe, {insufficient_data, <<"bitarray slice"/utf8>>} ) end, fun(Bytes) -> Remaining = case gleam_stdlib:bit_array_slice( Rest, Len, Rest_size - Len ) of {ok, R} -> R; {error, _} -> <<>> end, {ok, {Bytes, Remaining}} end ) end; _ -> {error, {invalid_binary, <<"bitarray length prefix"/utf8>>}} end end. -file("src/distribute/codec.gleam", 233). -spec bitarray_decoder() -> fun((bitstring()) -> {ok, bitstring()} | {error, decode_error()}). bitarray_decoder() -> to_decoder(bitarray_sized_decoder()). -file("src/distribute/codec.gleam", 272). -spec encode_list_elements( list(FNQ), fun((FNQ) -> {ok, bitstring()} | {error, encode_error()}), bitstring() ) -> {ok, bitstring()} | {error, encode_error()}. encode_list_elements(Items, Enc, Acc) -> case Items of [] -> {ok, Acc}; [Head | Tail] -> gleam@result:'try'( Enc(Head), fun(Bytes) -> encode_list_elements( Tail, Enc, gleam@bit_array:append(Acc, Bytes) ) end ) end. -file("src/distribute/codec.gleam", 308). -spec nil_encoder() -> fun((nil) -> {ok, bitstring()} | {error, encode_error()}). nil_encoder() -> fun(_) -> {ok, <<>>} end. -file("src/distribute/codec.gleam", 312). -spec nil_sized_decoder() -> fun((bitstring()) -> {ok, {nil, bitstring()}} | {error, decode_error()}). nil_sized_decoder() -> fun(Data) -> {ok, {nil, Data}} end. -file("src/distribute/codec.gleam", 316). -spec nil_decoder() -> fun((bitstring()) -> {ok, nil} | {error, decode_error()}). nil_decoder() -> fun(_) -> {ok, nil} end. -file("src/distribute/codec.gleam", 332). ?DOC( " Encode a `Subject(BitArray)` via `term_to_binary`. The PID\n" " inside carries node info, so it routes back cross-node.\n" ). -spec subject_encoder() -> fun((gleam@erlang@process:subject(bitstring())) -> {ok, bitstring()} | {error, encode_error()}). subject_encoder() -> fun(Sub) -> Bytes = distribute_ffi_utils:encode_subject(Sub), Len = erlang:byte_size(Bytes), {ok, <>} end. -file("src/distribute/codec.gleam", 340). -spec subject_sized_decoder() -> fun((bitstring()) -> {ok, {gleam@erlang@process:subject(bitstring()), bitstring()}} | {error, decode_error()}). subject_sized_decoder() -> fun(Data) -> case Data of <> -> Rest_size = erlang:byte_size(Rest), case Rest_size >= Len of false -> {error, {insufficient_data, <<"subject"/utf8>>}}; true -> case gleam_stdlib:bit_array_slice(Rest, 0, Len) of {ok, Subject_bytes} -> case distribute_ffi_utils:decode_subject_safe( Subject_bytes ) of {ok, Sub} -> Remaining = case gleam_stdlib:bit_array_slice( Rest, Len, Rest_size - Len ) of {ok, R} -> R; {error, _} -> <<>> end, {ok, {Sub, Remaining}}; {error, nil} -> {error, {decode_failed, <<"invalid subject binary"/utf8>>}} end; {error, _} -> {error, {insufficient_data, <<"subject slice"/utf8>>}} end end; _ -> {error, {invalid_binary, <<"subject length prefix"/utf8>>}} end end. -file("src/distribute/codec.gleam", 372). -spec subject_decoder() -> fun((bitstring()) -> {ok, gleam@erlang@process:subject(bitstring())} | {error, decode_error()}). subject_decoder() -> to_decoder(subject_sized_decoder()). -file("src/distribute/codec.gleam", 388). -spec int() -> codec(integer()). int() -> {codec, int_encoder(), int_decoder(), int_sized_decoder()}. -file("src/distribute/codec.gleam", 84). -spec string_encoder() -> fun((binary()) -> {ok, bitstring()} | {error, encode_error()}). string_encoder() -> fun(S) -> Bytes = gleam_stdlib:identity(S), Len = erlang:byte_size(Bytes), case Len > 65535 of true -> {error, {value_too_large, <<"string length "/utf8, (erlang:integer_to_binary(Len))/binary>>}}; false -> {ok, <>} end end. -file("src/distribute/codec.gleam", 380). -spec string() -> codec(binary()). string() -> {codec, string_encoder(), string_decoder(), string_sized_decoder()}. -file("src/distribute/codec.gleam", 396). -spec float() -> codec(float()). float() -> {codec, float_encoder(), float_decoder(), float_sized_decoder()}. -file("src/distribute/codec.gleam", 404). -spec bool() -> codec(boolean()). bool() -> {codec, bool_encoder(), bool_decoder(), bool_sized_decoder()}. -file("src/distribute/codec.gleam", 412). -spec bitarray() -> codec(bitstring()). bitarray() -> {codec, bitarray_encoder(), bitarray_decoder(), bitarray_sized_decoder()}. -file("src/distribute/codec.gleam", 420). -spec nil() -> codec(nil). nil() -> {codec, nil_encoder(), nil_decoder(), nil_sized_decoder()}. -file("src/distribute/codec.gleam", 437). ?DOC(" Subject codec, for the request/response pattern.\n"). -spec subject() -> codec(gleam@erlang@process:subject(bitstring())). subject() -> {codec, subject_encoder(), subject_decoder(), subject_sized_decoder()}. -file("src/distribute/codec.gleam", 455). ?DOC( " Transform a codec. `wrap` runs after decoding, `unwrap` before encoding.\n" "\n" " ```gleam\n" " type UserId { UserId(Int) }\n" "\n" " let user_id = codec.map(codec.int(), UserId, fn(uid) {\n" " let UserId(n) = uid\n" " n\n" " })\n" " ```\n" ). -spec map(codec(FPA), fun((FPA) -> FPC), fun((FPC) -> FPA)) -> codec(FPC). map(C, Wrap, Unwrap) -> {codec, fun(Value) -> (erlang:element(2, C))(Unwrap(Value)) end, fun(Data) -> case (erlang:element(3, C))(Data) of {ok, Val} -> {ok, Wrap(Val)}; {error, E} -> {error, E} end end, fun(Data@1) -> case (erlang:element(4, C))(Data@1) of {ok, {Val@1, Rest}} -> {ok, {Wrap(Val@1), Rest}}; {error, E@1} -> {error, E@1} end end}. -file("src/distribute/codec.gleam", 477). -spec decode_error_to_string(decode_error()) -> binary(). decode_error_to_string(Error) -> case Error of {invalid_binary, Msg} -> <<"Invalid binary: "/utf8, Msg/binary>>; {type_mismatch, Msg@1} -> <<"Type mismatch: "/utf8, Msg@1/binary>>; {decode_failed, Msg@2} -> <<"Decode failed: "/utf8, Msg@2/binary>>; {insufficient_data, Msg@3} -> <<"Insufficient data: "/utf8, Msg@3/binary>>; decode_timeout -> <<"Decode timeout"/utf8>>; {tag_mismatch, Expected, Got} -> <<<<<<<<"Tag mismatch: expected '"/utf8, Expected/binary>>/binary, "', got '"/utf8>>/binary, Got/binary>>/binary, "'"/utf8>>; {version_mismatch, Expected@1, Got@1} -> <<<<<<"Version mismatch: expected "/utf8, (erlang:integer_to_binary(Expected@1))/binary>>/binary, ", got "/utf8>>/binary, (erlang:integer_to_binary(Got@1))/binary>> end. -file("src/distribute/codec.gleam", 494). -spec encode_error_to_string(encode_error()) -> binary(). encode_error_to_string(Error) -> case Error of {invalid_value, Msg} -> <<"Invalid value: "/utf8, Msg/binary>>; {encode_failed, Msg@1} -> <<"Encode failed: "/utf8, Msg@1/binary>>; {value_too_large, Msg@2} -> <<"Value too large: "/utf8, Msg@2/binary>> end. -file("src/distribute/codec.gleam", 428). -spec list(codec(FOU)) -> codec(list(FOU)). list(Element) -> {codec, list_encoder(erlang:element(2, Element)), list_decoder(erlang:element(4, Element)), list_sized_decoder(erlang:element(4, Element))}. -file("src/distribute/codec.gleam", 268). -spec list_decoder( fun((bitstring()) -> {ok, {FNM, bitstring()}} | {error, decode_error()}) ) -> fun((bitstring()) -> {ok, list(FNM)} | {error, decode_error()}). list_decoder(Element_decoder) -> to_decoder(list_sized_decoder(Element_decoder)). -file("src/distribute/codec.gleam", 256). -spec list_sized_decoder( fun((bitstring()) -> {ok, {FNI, bitstring()}} | {error, decode_error()}) ) -> fun((bitstring()) -> {ok, {list(FNI), bitstring()}} | {error, decode_error()}). list_sized_decoder(Element_decoder) -> fun(Data) -> case Data of <> -> decode_list_elements(Rest, Element_decoder, Count, []); _ -> {error, {invalid_binary, <<"list length prefix"/utf8>>}} end end. -file("src/distribute/codec.gleam", 286). -spec decode_list_elements( bitstring(), fun((bitstring()) -> {ok, {FNV, bitstring()}} | {error, decode_error()}), integer(), list(FNV) ) -> {ok, {list(FNV), bitstring()}} | {error, decode_error()}. decode_list_elements(Data, Dec, Remaining, Acc) -> case Remaining of 0 -> {ok, {lists:reverse(Acc), Data}}; _ -> case Dec(Data) of {ok, {Element, Rest}} -> decode_list_elements( Rest, Dec, Remaining - 1, [Element | Acc] ); {error, E} -> {error, E} end end. -file("src/distribute/codec.gleam", 241). -spec list_encoder(fun((FNE) -> {ok, bitstring()} | {error, encode_error()})) -> fun((list(FNE)) -> {ok, bitstring()} | {error, encode_error()}). list_encoder(Element_encoder) -> fun(Items) -> Len = erlang:length(Items), case Len > 65535 of true -> {error, {value_too_large, <<"list length "/utf8, (erlang:integer_to_binary(Len))/binary>>}}; false -> gleam@result:'try'( encode_list_elements(Items, Element_encoder, <<>>), fun(Body) -> {ok, <>} end ) end end.