Current section
Files
Jump to
Current section
Files
src/gpkm@utils@bytes.erl
-module(gpkm@utils@bytes).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([bits_to_bytes/1, bytes_to_bits/1, slice/3, at/2, ordered_slice/4, chunked_slice/5, to_int/1, take_upper_16_bits/1, i16_to_i8_bytes/2, is_bit_set/2]).
-export_type([endian/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.
-type endian() :: big_endian | little_endian.
-file("src/gpkm/utils/bytes.gleam", 17).
-spec bits_to_bytes(bitstring()) -> list(integer()).
bits_to_bytes(Bits) ->
erlang:binary_to_list(Bits).
-file("src/gpkm/utils/bytes.gleam", 20).
-spec bytes_to_bits(list(integer())) -> bitstring().
bytes_to_bits(Bytes) ->
erlang:list_to_binary(Bytes).
-file("src/gpkm/utils/bytes.gleam", 32).
?DOC(
" Extracts a slice from a bytes list\n"
"\n"
" ```gleam\n"
" [0,1,2,3,4,5] |> slice(1, 4)\n"
" // -> [1,2,3,4]\n"
"\n"
" [0,1,2,3,4,5] |> slice(2, 2)\n"
" // -> [2]\n"
" ```\n"
).
-spec slice(list(integer()), integer(), integer()) -> list(integer()).
slice(Bs, Start, End) ->
_pipe = Bs,
_pipe@1 = gleam@list:take(_pipe, End + 1),
gleam@list:drop(_pipe@1, Start).
-file("src/gpkm/utils/bytes.gleam", 52).
?DOC(
" Makes a single-element slice from a bytes list\n"
" at a given index\n"
"\n"
" If the index is out of bounds, an empty bytes list is returned\n"
" \n"
" ```gleam\n"
" [0,1,2,3,4,5] |> at(2)\n"
" // -> [2]\n"
"\n"
" [0,1,2,3,4,5] |> at(42)\n"
" // -> []\n"
"\n"
" [] |> at(42)\n"
" // -> []\n"
" ```\n"
).
-spec at(list(integer()), integer()) -> list(integer()).
at(Xs, Index) ->
slice(Xs, Index, Index).
-file("src/gpkm/utils/bytes.gleam", 56).
-spec reorder_slice(list(integer()), endian()) -> list(integer()).
reorder_slice(Xs, Endian) ->
case Endian of
big_endian ->
Xs;
little_endian ->
lists:reverse(Xs)
end.
-file("src/gpkm/utils/bytes.gleam", 74).
?DOC(
" Extracts a slice from a bytes list\n"
" reordering it according to a target endian\n"
"\n"
" ```gleam\n"
" [0,1,2,3,4,5] |> ordered_slice(1, 4, BigEndian)\n"
" // -> [1,2,3,4]\n"
"\n"
" [0,1,2,3,4,5] |> ordered_slice(1, 4, LittleEndian)\n"
" // -> [4,3,2,1]\n"
" ```\n"
).
-spec ordered_slice(list(integer()), integer(), integer(), endian()) -> list(integer()).
ordered_slice(Xs, Start, End, Endian) ->
_pipe = Xs,
_pipe@1 = slice(_pipe, Start, End),
reorder_slice(_pipe@1, Endian).
-file("src/gpkm/utils/bytes.gleam", 89).
?DOC(
" Makes sized chunks from a slice of a bytes list,\n"
" reordering each chunk according to the target endian\n"
"\n"
" ```gleam\n"
" [0,1,2,3,4,5,6,7,8,9] |> chunked_slice(1, 8, 2, BigEndian)\n"
" // -> [[1,2], [3,4], [5,6], [7,8]]\n"
"\n"
" [0,1,2,3,4,5,6,7,8,9] |> chunked_slice(1, 8, 4, LittleEndian)\n"
" // -> [[4,3,2,1], [8,7,6,5]]\n"
" ```\n"
).
-spec chunked_slice(list(integer()), integer(), integer(), integer(), endian()) -> list(list(integer())).
chunked_slice(Xs, Start, End, Chunk_size, Endian) ->
_pipe = Xs,
_pipe@1 = slice(_pipe, Start, End),
_pipe@2 = gleam@list:sized_chunk(_pipe@1, Chunk_size),
gleam@list:map(
_pipe@2,
fun(_capture) -> reorder_slice(_capture, Endian) end
).
-file("src/gpkm/utils/bytes.gleam", 114).
?DOC(
" Converts a bytes list to a number, by concatenating the bytes\n"
"\n"
" ```gleam\n"
" // example when: max_byte_value = 0xff\n"
"\n"
" [0x42, 0xff] |> int.undigits(0xff + 1)\n"
" // -> 0x42ff\n"
"\n"
" [0xde, 0xad, 0xbe, 0xef] |> int.undigits(0xff + 1)\n"
" // -> 0xdeadbeef\n"
" ```\n"
).
-spec to_int(list(integer())) -> integer().
to_int(Xs) ->
Max_byte_value = 16#ff,
_pipe = Xs,
_pipe@1 = gleam@int:undigits(_pipe, Max_byte_value + 1),
gleam@result:unwrap(_pipe@1, 0).
-file("src/gpkm/utils/bytes.gleam", 147).
?DOC(
" Takes the 16 leftmost bits from the 32 rightmost bits of a numbe\n"
"\n"
" To return the \"upper 16 bits\" of the rand number (that may be bigger than 32bits)\n"
" the number should first be cast as a 32bits integer (using a 32bits bitmask)\n"
" then we can take its first 16 bits (by shifting 16bits to the right)\n"
"\n"
" ```gleam\n"
" take_upper_16_bits(0xdeadbeef)\n"
" // -> 0xdead\n"
"\n"
" take_upper_16_bits(0xf00d1337deadbeef)\n"
" // -> 0xdead\n"
"\n"
" take_upper_16_bits(0b00001111000011110000000000000000)\n"
" // -> 0b0000111100001111\n"
" ```\n"
"\n"
" A very uneffective implementation could also be:\n"
"\n"
" ```gleam\n"
" number\n"
" |> int.to_base2\n"
" |> string.slice(-32, 16)\n"
" |> int.base_parse(2)\n"
" |> result.unwrap(0)\n"
" ```\n"
).
-spec take_upper_16_bits(integer()) -> integer().
take_upper_16_bits(Number) ->
As_i32 = fun(_capture) -> erlang:'band'(_capture, 16#ffffffff) end,
Get_first_16_bits = fun(_capture@1) -> erlang:'bsr'(_capture@1, 16) end,
_pipe = Number,
_pipe@1 = As_i32(_pipe),
Get_first_16_bits(_pipe@1).
-file("src/gpkm/utils/bytes.gleam", 164).
?DOC(
" Converts a 16 bits int, to an 8 bits int, as a bytes list\n"
"\n"
" ```gleam\n"
" 0x0123 |> i16_to_i8_bytes(BigEndian)\n"
" // -> [0x01, 0x23]\n"
"\n"
" 0x0123 |> i16_to_i8_bytes(LittleEndian)\n"
" // -> [0x23, 0x01]\n"
" ```\n"
).
-spec i16_to_i8_bytes(integer(), endian()) -> list(integer()).
i16_to_i8_bytes(I16, Endian) ->
I8_left = erlang:'bsr'(I16, 8),
I8_right = erlang:'band'(I16, 16#ff),
case Endian of
little_endian ->
[I8_right, I8_left];
big_endian ->
[I8_left, I8_right]
end.
-file("src/gpkm/utils/bytes.gleam", 191).
?DOC(
" Checks if nth bit (from right to left) of a number,\n"
" is set (!= 0) using bitwise\n"
" ```gleam\n"
" let num = 10 // 10 == 0 b 1 0 1 0 // number (as bits)\n"
" // ^ ^ ^ ^\n"
" // 3 2 1 0 // bit_position\n"
"\n"
" is_bit_set(num, 3)\n"
" // -> True\n"
" \n"
" is_bit_set(num, 2)\n"
" // -> False\n"
" \n"
" is_bit_set(num, 1)\n"
" // -> True\n"
" ```\n"
).
-spec is_bit_set(integer(), integer()) -> boolean().
is_bit_set(X, N) ->
Mask = begin
_pipe = 1,
erlang:'bsl'(_pipe, N)
end,
Masked_nth_bit = begin
_pipe@1 = X,
erlang:'band'(_pipe@1, Mask)
end,
Masked_nth_bit /= 0.