-module(gbor@encode). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/gbor/encode.gleam"). -export([to_bit_array/1]). -export_type([encode_error/0, binary_encoding/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(" Module where we can find the functions used for getting the CBOR binary representation of a value\n"). -type encode_error() :: {encode_error, binary()}. -type binary_encoding() :: {binary_encoding, bitstring()} | {string_encoding, binary()}. -file("src/gbor/encode.gleam", 34). -spec uint_encode(integer()) -> {ok, bitstring()} | {error, encode_error()}. uint_encode(Value) -> case Value of V when V < 24 -> {ok, <<0:3, V:5>>}; V@1 when V@1 < 16#100 -> {ok, <<0:3, 24:5, V@1:8>>}; V@2 when V@2 < 16#10000 -> {ok, <<0:3, 25:5, V@2:16>>}; V@3 when V@3 < 16#100000000 -> {ok, <<0:3, 26:5, V@3:32>>}; V@4 when V@4 < 16#10000000000000000 -> {ok, <<0:3, 27:5, V@4:64>>}; V@5 -> {error, {encode_error, <<"Int value too large: "/utf8, (gleam@string:inspect(V@5))/binary>>}} end. -file("src/gbor/encode.gleam", 46). -spec int_encode(integer()) -> {ok, bitstring()} | {error, encode_error()}. int_encode(Value) -> Value@1 = (Value * -1) - 1, case Value@1 of V when V < 24 -> {ok, <<1:3, V:5>>}; V@1 when V@1 < 16#100 -> {ok, <<1:3, 24:5, V@1:8>>}; V@2 when V@2 < 16#10000 -> {ok, <<1:3, 25:5, V@2:16>>}; V@3 when V@3 < 16#100000000 -> {ok, <<1:3, 26:5, V@3:32>>}; V@4 when V@4 < 16#10000000000000000 -> {ok, <<1:3, 27:5, V@4:64>>}; V@5 -> {error, {encode_error, <<"Int value too large: "/utf8, (gleam@string:inspect(V@5))/binary>>}} end. -file("src/gbor/encode.gleam", 59). -spec float_encode(float()) -> bitstring(). float_encode(Value) -> Bytes = begin _pipe = Value, _pipe@1 = ieee_float:finite(_pipe), ieee_float:to_bytes_64_be(_pipe@1) end, <<7:3, 27:5, Bytes/bitstring>>. -file("src/gbor/encode.gleam", 73). -spec binary_encode(binary_encoding()) -> {ok, bitstring()} | {error, encode_error()}. binary_encode(Value) -> {Value@1, Major} = case Value of {binary_encoding, V} -> {gleam_stdlib:bit_array_pad_to_bytes(V), 2}; {string_encoding, V@1} -> {gleam_stdlib:identity(V@1), 3} end, Length = erlang:byte_size(Value@1), case Length of V@2 when V@2 < 24 -> {ok, <>}; V@3 when V@3 < 16#100 -> {ok, <>}; V@4 when V@4 < 16#10000 -> {ok, <>}; V@5 when V@5 < 16#100000000 -> {ok, <>}; V@6 when V@6 < 16#10000000000000000 -> {ok, <>}; _ -> {error, {encode_error, <<"Binary length too large"/utf8>>}} end. -file("src/gbor/encode.gleam", 109). -spec bool_encode(boolean()) -> bitstring(). bool_encode(Value) -> case Value of false -> <<16#f4>>; true -> <<16#f5>> end. -file("src/gbor/encode.gleam", 116). -spec null_encode() -> bitstring(). null_encode() -> <<16#f6>>. -file("src/gbor/encode.gleam", 120). -spec undefined_encode() -> bitstring(). undefined_encode() -> <<16#f7>>. -file("src/gbor/encode.gleam", 93). -spec array_encode(list(gbor:c_b_o_r())) -> {ok, bitstring()} | {error, encode_error()}. array_encode(Value) -> Length = erlang:length(Value), gleam@result:'try'( gleam@list:try_map(Value, fun to_bit_array/1), fun(Data) -> Data@1 = gleam_stdlib:bit_array_concat(Data), case Length of V when V < 24 -> {ok, <<4:3, V:5, Data@1/bitstring>>}; V@1 when V@1 < 16#100 -> {ok, <<4:3, 24:5, V@1:8, Data@1/bitstring>>}; V@2 when V@2 < 16#10000 -> {ok, <<4:3, 25:5, V@2:16, Data@1/bitstring>>}; V@3 when V@3 < 16#100000000 -> {ok, <<4:3, 26:5, V@3:32, Data@1/bitstring>>}; V@4 when V@4 < 16#10000000000000000 -> {ok, <<4:3, 27:5, V@4:64, Data@1/bitstring>>}; _ -> {error, {encode_error, <<"Array length too large"/utf8>>}} end end ). -file("src/gbor/encode.gleam", 17). ?DOC(" Encode a CBOR value to a bit array\n"). -spec to_bit_array(gbor:c_b_o_r()) -> {ok, bitstring()} | {error, encode_error()}. to_bit_array(Value) -> case Value of {c_b_int, V} when V >= 0 -> uint_encode(V); {c_b_int, V@1} when V@1 < 0 -> int_encode(V@1); {c_b_int, V@2} -> uint_encode(V@2); {c_b_float, V@3} -> {ok, float_encode(V@3)}; {c_b_binary, V@4} -> binary_encode({binary_encoding, V@4}); {c_b_string, V@5} -> binary_encode({string_encoding, V@5}); {c_b_array, V@6} -> array_encode(V@6); {c_b_map, V@7} -> map_encode(V@7); {c_b_bool, V@8} -> {ok, bool_encode(V@8)}; {c_b_tagged, T, V@9} -> tagged_encode(T, V@9); c_b_null -> {ok, null_encode()}; c_b_undefined -> {ok, undefined_encode()} end. -file("src/gbor/encode.gleam", 124). -spec map_encode(list({gbor:c_b_o_r(), gbor:c_b_o_r()})) -> {ok, bitstring()} | {error, encode_error()}. map_encode(Value) -> N_pairs = erlang:length(Value), gleam@result:'try'( gleam@list:try_fold( Value, <<>>, fun(Acc, A) -> gleam@result:'try'( to_bit_array(erlang:element(1, A)), fun(K_data) -> gleam@result:'try'( to_bit_array(erlang:element(2, A)), fun(V_data) -> {ok, gleam_stdlib:bit_array_concat( [Acc, K_data, V_data] )} end ) end ) end ), fun(Data) -> case N_pairs of V when V < 24 -> {ok, <<5:3, V:5, Data/bitstring>>}; V@1 when V@1 < 16#100 -> {ok, <<5:3, 25:5, V@1:8, Data/bitstring>>}; V@2 when V@2 < 16#10000 -> {ok, <<5:3, 26:5, V@2:16, Data/bitstring>>}; V@3 when V@3 < 16#100000000 -> {ok, <<5:3, 27:5, V@3:32, Data/bitstring>>}; V@4 when V@4 < 16#10000000000000000 -> {ok, <<5:3, 28:5, V@4:64, Data/bitstring>>}; _ -> {error, {encode_error, <<"N pairs size too large"/utf8>>}} end end ). -file("src/gbor/encode.gleam", 145). -spec tagged_encode(integer(), gbor:c_b_o_r()) -> {ok, bitstring()} | {error, encode_error()}. tagged_encode(T, V) -> gleam@result:'try'(case T of T@1 when T@1 < 24 -> {ok, <<6:3, T@1:5>>}; T@2 when T@2 < 16#100 -> {ok, <<6:3, 24:5, T@2:8>>}; T@3 when T@3 < 16#10000 -> {ok, <<6:3, 25:5, T@3:16>>}; T@4 when T@4 < 16#100000000 -> {ok, <<6:3, 26:5, T@4:32>>}; T@5 when T@5 < 16#10000000000000000 -> {ok, <<6:3, 27:5, T@5:64>>}; _ -> {error, {encode_error, <<"Tagged tag too large"/utf8>>}} end, fun(Bin_tag) -> gleam@result:'try'( to_bit_array(V), fun(Bin_value) -> {ok, gleam_stdlib:bit_array_concat([Bin_tag, Bin_value])} end ) end).