Current section
Files
Jump to
Current section
Files
src/gleb128.erl
-module(gleb128).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([encode_unsigned/1, encode_signed/1, decode_unsigned/1, decode_signed/1, fast_decode_unsigned/1, fast_decode_signed/1]).
-spec do_encode_unsigned(integer(), gleam@bytes_builder:bytes_builder()) -> {ok,
gleam@bytes_builder:bytes_builder()} |
{error, binary()}.
do_encode_unsigned(Value, Builder) ->
case Value >= 0 of
true ->
Current_chunk = erlang:'band'(Value, 2#01111111),
Next_chunk = erlang:'bsr'(Value, 7),
case Next_chunk of
0 ->
{ok, gleam@bytes_builder:append(Builder, <<Current_chunk>>)};
_ ->
Current_chunk@1 = erlang:'bor'(Current_chunk, 2#10000000),
do_encode_unsigned(
Next_chunk,
gleam@bytes_builder:append(Builder, <<Current_chunk@1>>)
)
end;
false ->
{error,
<<"Can't encode a negative value with an unsigned function"/utf8>>}
end.
-spec do_encode_signed(integer(), gleam@bytes_builder:bytes_builder()) -> gleam@bytes_builder:bytes_builder().
do_encode_signed(Value, Builder) ->
Current_chunk = erlang:'band'(Value, 2#01111111),
Next_chunk = erlang:'bsr'(Value, 7),
Sign = erlang:'band'(Value, 2#01000000),
Sign@1 = erlang:'bsr'(Sign, 6),
case ((Next_chunk =:= 0) andalso (Sign@1 =:= 0)) orelse ((Next_chunk =:= erlang:'bnot'(
0
))
andalso (Sign@1 =:= 1)) of
true ->
gleam@bytes_builder:append(Builder, <<Current_chunk>>);
_ ->
Current_chunk@1 = erlang:'bor'(Current_chunk, 2#10000000),
do_encode_signed(
Next_chunk,
gleam@bytes_builder:append(Builder, <<Current_chunk@1>>)
)
end.
-spec do_decode_unsigned(bitstring(), integer(), integer(), integer()) -> {ok,
{integer(), integer()}} |
{error, binary()}.
do_decode_unsigned(
Data,
Position_accumulator,
Result_accumulator,
Shift_accumulator
) ->
case gleam_stdlib:bit_array_slice(Data, Position_accumulator, 1) of
{ok, Slice} ->
case Slice of
<<Byte/integer>> ->
Current_chunk = erlang:'band'(Byte, 2#01111111),
Current_chunk@1 = erlang:'bsl'(
Current_chunk,
Shift_accumulator
),
Result_accumulator@1 = erlang:'bor'(
Result_accumulator,
Current_chunk@1
),
Next_chunk = erlang:'bsr'(Byte, 7),
case Next_chunk of
0 ->
{ok,
{Result_accumulator@1, Position_accumulator + 1}};
_ ->
do_decode_unsigned(
Data,
Position_accumulator + 1,
Result_accumulator@1,
Shift_accumulator + 7
)
end;
_ ->
{error,
<<"Can't decode the bit array slice into a byte"/utf8>>}
end;
_ ->
{error, <<"Invalid LEB128 integer"/utf8>>}
end.
-spec do_decode_signed(bitstring(), integer(), integer(), integer()) -> {ok,
{integer(), integer()}} |
{error, binary()}.
do_decode_signed(
Data,
Position_accumulator,
Result_accumulator,
Shift_accumulator
) ->
case gleam_stdlib:bit_array_slice(Data, Position_accumulator, 1) of
{ok, Slice} ->
case Slice of
<<Byte/integer>> ->
Current_chunk = erlang:'band'(Byte, 2#01111111),
Current_chunk@1 = erlang:'bsl'(
Current_chunk,
Shift_accumulator
),
Result_accumulator@1 = erlang:'bor'(
Result_accumulator,
Current_chunk@1
),
Shift_accumulator@1 = Shift_accumulator + 7,
Next_chunk = erlang:'bsr'(Byte, 7),
case Next_chunk of
0 ->
Sign = erlang:'band'(Byte, 2#01000000),
Sign@1 = erlang:'bsr'(Sign, 6),
case Sign@1 of
1 ->
{ok,
{erlang:'bor'(
Result_accumulator@1,
erlang:'bsl'(
erlang:'bnot'(0),
Shift_accumulator@1
)
),
Position_accumulator + 1}};
_ ->
{ok,
{Result_accumulator@1,
Position_accumulator + 1}}
end;
_ ->
do_decode_signed(
Data,
Position_accumulator + 1,
Result_accumulator@1,
Shift_accumulator@1
)
end;
_ ->
{error,
<<"Can't decode the bit array slice into a byte"/utf8>>}
end;
_ ->
{error, <<"Invalid LEB128 integer"/utf8>>}
end.
-spec do_fast_decode_unsigned(integer(), integer(), integer(), integer()) -> {ok,
{integer(), integer()}} |
{error, binary()}.
do_fast_decode_unsigned(
Data,
Position_accumulator,
Result_accumulator,
Shift_accumulator
) ->
Byte = erlang:'bsr'(Data, 8 * Position_accumulator),
Byte@1 = erlang:'band'(Byte, 16#ff),
Current_chunk = erlang:'band'(Byte@1, 2#01111111),
Current_chunk@1 = erlang:'bsl'(Current_chunk, Shift_accumulator),
Result_accumulator@1 = erlang:'bor'(Result_accumulator, Current_chunk@1),
Next_chunk = erlang:'bsr'(Byte@1, 7),
case Next_chunk of
0 ->
{ok, {Result_accumulator@1, Position_accumulator + 1}};
_ ->
do_fast_decode_unsigned(
Data,
Position_accumulator + 1,
Result_accumulator@1,
Shift_accumulator + 7
)
end.
-spec do_fast_decode_signed(integer(), integer(), integer(), integer()) -> {ok,
{integer(), integer()}} |
{error, binary()}.
do_fast_decode_signed(
Data,
Position_accumulator,
Result_accumulator,
Shift_accumulator
) ->
Byte = erlang:'bsr'(Data, 8 * Position_accumulator),
Byte@1 = erlang:'band'(Byte, 16#ff),
Current_chunk = erlang:'band'(Byte@1, 2#01111111),
Current_chunk@1 = erlang:'bsl'(Current_chunk, Shift_accumulator),
Result_accumulator@1 = erlang:'bor'(Result_accumulator, Current_chunk@1),
Shift_accumulator@1 = Shift_accumulator + 7,
Next_chunk = erlang:'bsr'(Byte@1, 7),
case Next_chunk of
0 ->
Sign = erlang:'band'(Byte@1, 2#01000000),
Sign@1 = erlang:'bsr'(Sign, 6),
case Sign@1 of
1 ->
{ok,
{erlang:'bor'(
Result_accumulator@1,
erlang:'bsl'(
erlang:'bnot'(0),
Shift_accumulator@1
)
),
Position_accumulator + 1}};
_ ->
{ok, {Result_accumulator@1, Position_accumulator + 1}}
end;
_ ->
do_fast_decode_signed(
Data,
Position_accumulator + 1,
Result_accumulator@1,
Shift_accumulator@1
)
end.
-spec encode_unsigned(integer()) -> {ok, bitstring()} | {error, binary()}.
encode_unsigned(Value) ->
case do_encode_unsigned(Value, gleam@bytes_builder:new()) of
{ok, Result} ->
{ok, erlang:list_to_bitstring(Result)};
{error, E} ->
{error, E}
end.
-spec encode_signed(integer()) -> bitstring().
encode_signed(Value) ->
_pipe = do_encode_signed(Value, gleam@bytes_builder:new()),
erlang:list_to_bitstring(_pipe).
-spec decode_unsigned(bitstring()) -> {ok, {integer(), integer()}} |
{error, binary()}.
decode_unsigned(Data) ->
do_decode_unsigned(Data, 0, 0, 0).
-spec decode_signed(bitstring()) -> {ok, {integer(), integer()}} |
{error, binary()}.
decode_signed(Data) ->
do_decode_signed(Data, 0, 0, 0).
-spec fast_decode_unsigned(bitstring()) -> {ok, {integer(), integer()}} |
{error, binary()}.
fast_decode_unsigned(Data) ->
case erlang:byte_size(Data) of
S when S =< 8 ->
case gleb128@internal@native:get_cpu_endianness() of
{ok, Endianness} ->
do_fast_decode_unsigned(
binary:decode_unsigned(Data, Endianness),
0,
0,
0
);
{error, Reason} ->
{error, Reason}
end;
_ ->
do_decode_unsigned(Data, 0, 0, 0)
end.
-spec fast_decode_signed(bitstring()) -> {ok, {integer(), integer()}} |
{error, binary()}.
fast_decode_signed(Data) ->
case erlang:byte_size(Data) of
S when S =< 8 ->
case gleb128@internal@native:get_cpu_endianness() of
{ok, Endianness} ->
do_fast_decode_signed(
gleb128@internal@native:decode_native_signed_integer(
Data,
Endianness
),
0,
0,
0
);
{error, Reason} ->
{error, Reason}
end;
_ ->
do_decode_signed(Data, 0, 0, 0)
end.