Packages

A Gleam implementation of the CBOR standard

Current section

Files

Jump to
gbor src gbor@encode.erl
Raw

src/gbor@encode.erl

-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, <<Major:3, V@2:5, Value@1/bitstring>>};
V@3 when V@3 < 16#100 ->
{ok, <<Major:3, 24:5, V@3:8, Value@1/bitstring>>};
V@4 when V@4 < 16#10000 ->
{ok, <<Major:3, 25:5, V@4:16, Value@1/bitstring>>};
V@5 when V@5 < 16#100000000 ->
{ok, <<Major:3, 26:5, V@5:32, Value@1/bitstring>>};
V@6 when V@6 < 16#10000000000000000 ->
{ok, <<Major:3, 27:5, V@6:64, Value@1/bitstring>>};
_ ->
{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).