Current section
Files
Jump to
Current section
Files
src/tenthash.erl
-module(tenthash).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/tenthash.gleam").
-export([new/0, update/2, update_bitarray/2, finalise/1, hash_bitarray/1, hash/1]).
-export_type([hash_state/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.
-opaque hash_state() :: {hash_state,
bigi:big_int(),
bigi:big_int(),
bigi:big_int(),
bigi:big_int(),
bigi:big_int(),
bitstring(),
integer()}.
-file("src/tenthash.gleam", 217).
-spec bitmask(integer()) -> bigi:big_int().
bitmask(Size) ->
Bitmask@1 = case bigi_ffi:power(bigi_ffi:from(2), bigi_ffi:from(Size)) of
{ok, Bitmask} -> Bitmask;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"tenthash"/utf8>>,
function => <<"bitmask"/utf8>>,
line => 218,
value => _assert_fail,
start => 5807,
'end' => 5881,
pattern_start => 5818,
pattern_end => 5829})
end,
bigi_ffi:subtract(Bitmask@1, bigi_ffi:from(1)).
-file("src/tenthash.gleam", 222).
-spec rot_left(bigi:big_int(), integer(), bigi:big_int()) -> bigi:big_int().
rot_left(I, Count, Bitmask) ->
P1 = bigi_ffi:bitwise_and(bigi_ffi:bitwise_shift_left(I, Count), Bitmask),
P2 = bigi_ffi:bitwise_shift_right(I, 64 - Count),
bigi_ffi:bitwise_or(P1, P2).
-file("src/tenthash.gleam", 93).
-spec initial_state() -> {ok, hash_state()} | {error, nil}.
initial_state() ->
{A@1, B@1, C@1, D@1} = case [<<93, 109, 175, 252, 68, 17, 169, 103>>,
<<226, 45, 77, 234, 104, 87, 127, 52>>,
<<202, 80, 134, 77, 129, 76, 188, 46>>,
<<137, 78, 41, 185, 97, 30, 177, 115>>] of
[A, B, C, D] -> {A, B, C, D};
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"tenthash"/utf8>>,
function => <<"initial_state"/utf8>>,
line => 94,
value => _assert_fail,
start => 2199,
'end' => 2236,
pattern_start => 2210,
pattern_end => 2222})
end,
gleam@result:'try'(
bigi_ffi:from_bytes(A@1, big_endian, unsigned),
fun(A@2) ->
gleam@result:'try'(
bigi_ffi:from_bytes(B@1, big_endian, unsigned),
fun(B@2) ->
gleam@result:'try'(
bigi_ffi:from_bytes(C@1, big_endian, unsigned),
fun(C@2) ->
gleam@result:'try'(
bigi_ffi:from_bytes(D@1, big_endian, unsigned),
fun(D@2) ->
{ok,
{hash_state,
A@2,
B@2,
C@2,
D@2,
bitmask(64),
<<>>,
0}}
end
)
end
)
end
)
end
).
-file("src/tenthash.gleam", 36).
?DOC(" Returns a HashState to allow creating a hash using streaming\n").
-spec new() -> {ok, hash_state()} | {error, nil}.
new() ->
initial_state().
-file("src/tenthash.gleam", 203).
-spec mix_hash(hash_state()) -> hash_state().
mix_hash(State) ->
gleam@list:fold(
[{16, 28}, {14, 57}, {11, 22}, {35, 34}, {57, 16}, {59, 40}, {44, 13}],
State,
fun(State@1, Rc) ->
A = bigi_ffi:add(
erlang:element(2, State@1),
erlang:element(4, State@1)
),
A@1 = bigi_ffi:bitwise_and(A, erlang:element(6, State@1)),
B = bigi_ffi:add(
erlang:element(3, State@1),
erlang:element(5, State@1)
),
B@1 = bigi_ffi:bitwise_and(B, erlang:element(6, State@1)),
C = rot_left(
erlang:element(4, State@1),
erlang:element(1, Rc),
erlang:element(6, State@1)
),
C@1 = bigi_ffi:bitwise_exclusive_or(C, A@1),
D = rot_left(
erlang:element(5, State@1),
erlang:element(2, Rc),
erlang:element(6, State@1)
),
D@1 = bigi_ffi:bitwise_exclusive_or(D, B@1),
_record = State@1,
{hash_state,
B@1,
A@1,
C@1,
D@1,
erlang:element(6, _record),
erlang:element(7, _record),
erlang:element(8, _record)}
end
).
-file("src/tenthash.gleam", 131).
-spec hash_bits(
bitstring(),
bitstring(),
bitstring(),
bitstring(),
hash_state()
) -> {ok, hash_state()} | {error, nil}.
hash_bits(A, B, C, D, State) ->
A@1 = bigi_ffi:from_bytes(A, little_endian, unsigned),
B@1 = bigi_ffi:from_bytes(B, little_endian, unsigned),
C@1 = bigi_ffi:from_bytes(C, little_endian, unsigned),
D@1 = bigi_ffi:from_bytes(D, little_endian, unsigned),
case {A@1, B@1, C@1, D@1} of
{{ok, A@2}, {ok, B@2}, {ok, C@2}, {ok, D@2}} ->
{ok,
mix_hash(
begin
_record = State,
{hash_state,
bigi_ffi:bitwise_exclusive_or(
erlang:element(2, State),
A@2
),
bigi_ffi:bitwise_exclusive_or(
erlang:element(3, State),
B@2
),
bigi_ffi:bitwise_exclusive_or(
erlang:element(4, State),
C@2
),
bigi_ffi:bitwise_exclusive_or(
erlang:element(5, State),
D@2
),
erlang:element(6, _record),
erlang:element(7, _record),
erlang:element(8, _record)}
end
)};
{_, _, _, _} ->
{error, nil}
end.
-file("src/tenthash.gleam", 102).
-spec do_hash(bitstring(), hash_state()) -> {ok, hash_state()} | {error, nil}.
do_hash(Data, State) ->
case Data of
<<A:8/binary, B:8/binary, C:8/binary, D:8/binary, Rest/bitstring>> ->
gleam@result:'try'(
hash_bits(
A,
B,
C,
D,
begin
_record = State,
{hash_state,
erlang:element(2, _record),
erlang:element(3, _record),
erlang:element(4, _record),
erlang:element(5, _record),
erlang:element(6, _record),
Rest,
erlang:element(8, State) + 32}
end
),
fun(Hashed_bits) -> do_hash(Rest, Hashed_bits) end
);
<<>> ->
{ok, State};
<<A@1/bitstring>> ->
{ok,
begin
_record@1 = State,
{hash_state,
erlang:element(2, _record@1),
erlang:element(3, _record@1),
erlang:element(4, _record@1),
erlang:element(5, _record@1),
erlang:element(6, _record@1),
A@1,
erlang:element(8, _record@1)}
end};
_ ->
{error, nil}
end.
-file("src/tenthash.gleam", 41).
?DOC(" Updates the HashState using the provided String\n").
-spec update(hash_state(), binary()) -> {ok, hash_state()} | {error, nil}.
update(State, Data) ->
Data@1 = case erlang:element(7, State) of
<<>> ->
gleam_stdlib:identity(Data);
<<A/bitstring>> ->
gleam@bit_array:append(A, gleam_stdlib:identity(Data));
_ ->
gleam_stdlib:identity(Data)
end,
do_hash(Data@1, State).
-file("src/tenthash.gleam", 51).
?DOC(" Updates the HashState using the provided BitArray\n").
-spec update_bitarray(hash_state(), bitstring()) -> {ok, hash_state()} |
{error, nil}.
update_bitarray(State, Data) ->
Data@1 = case erlang:element(7, State) of
<<>> ->
Data;
<<A/bitstring>> ->
gleam@bit_array:append(A, Data);
_ ->
Data
end,
do_hash(Data@1, State).
-file("src/tenthash.gleam", 157).
-spec finalise_hash(hash_state()) -> {ok, bigi:big_int()} | {error, nil}.
finalise_hash(State) ->
gleam@result:'try'(case erlang:element(7, State) of
<<>> ->
{ok, State};
<<A/bitstring>> ->
Size = erlang:byte_size(A),
Extra_bits = 32 - Size,
A@1 = gleam_stdlib:bit_array_concat(
[A, <<0:(lists:max([((Extra_bits * 8)), 0]))>>]
),
case A@1 of
<<A@2:8/binary, B:8/binary, C:8/binary, D:8/binary>> ->
gleam@result:'try'(
hash_bits(
A@2,
B,
C,
D,
begin
_record = State,
{hash_state,
erlang:element(2, _record),
erlang:element(3, _record),
erlang:element(4, _record),
erlang:element(5, _record),
erlang:element(6, _record),
<<>>,
erlang:element(8, State) + Size}
end
),
fun(Hashed_bits) -> {ok, Hashed_bits} end
);
_ ->
{error, nil}
end;
_ ->
{error, nil}
end, fun(State@1) ->
State@2 = begin
_record@1 = State@1,
{hash_state,
bigi_ffi:bitwise_exclusive_or(
erlang:element(2, State@1),
bigi_ffi:from(erlang:element(8, State@1) * 8)
),
erlang:element(3, _record@1),
erlang:element(4, _record@1),
erlang:element(5, _record@1),
erlang:element(6, _record@1),
erlang:element(7, _record@1),
erlang:element(8, _record@1)}
end,
Final_state = mix_hash(mix_hash(State@2)),
A@4 = case bigi_ffi:to_bytes(
erlang:element(2, Final_state),
little_endian,
unsigned,
8
) of
{ok, A@3} -> A@3;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"tenthash"/utf8>>,
function => <<"finalise_hash"/utf8>>,
line => 192,
value => _assert_fail,
start => 4857,
'end' => 4945,
pattern_start => 4868,
pattern_end => 4873})
end,
B@2 = case bigi_ffi:to_bytes(
erlang:element(3, Final_state),
little_endian,
unsigned,
8
) of
{ok, B@1} -> B@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"tenthash"/utf8>>,
function => <<"finalise_hash"/utf8>>,
line => 194,
value => _assert_fail@1,
start => 4948,
'end' => 5036,
pattern_start => 4959,
pattern_end => 4964})
end,
C@2 = case bigi_ffi:to_bytes(
erlang:element(4, Final_state),
little_endian,
unsigned,
8
) of
{ok, C@1} -> C@1;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"tenthash"/utf8>>,
function => <<"finalise_hash"/utf8>>,
line => 196,
value => _assert_fail@2,
start => 5039,
'end' => 5127,
pattern_start => 5050,
pattern_end => 5055})
end,
Ba = gleam_stdlib:bit_array_concat([A@4, B@2, C@2]),
Slice@1 = case gleam_stdlib:bit_array_slice(Ba, 0, 20) of
{ok, Slice} -> Slice;
_assert_fail@3 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"tenthash"/utf8>>,
function => <<"finalise_hash"/utf8>>,
line => 199,
value => _assert_fail@3,
start => 5169,
'end' => 5218,
pattern_start => 5180,
pattern_end => 5189})
end,
bigi_ffi:from_bytes(Slice@1, big_endian, unsigned)
end).
-file("src/tenthash.gleam", 64).
?DOC(" Finalises the hash and returns the resulting BigInt\n").
-spec finalise(hash_state()) -> {ok, bigi:big_int()} | {error, nil}.
finalise(State) ->
finalise_hash(State).
-file("src/tenthash.gleam", 85).
?DOC(
" Takes a BitArray and returns a BigInt result \n"
" or Error(Nil) if hash failed for some reason\n"
).
-spec hash_bitarray(bitstring()) -> {ok, bigi:big_int()} | {error, nil}.
hash_bitarray(Data) ->
gleam@result:'try'(
initial_state(),
fun(Init_state) ->
gleam@result:'try'(
do_hash(Data, Init_state),
fun(Final_state) -> finalise_hash(Final_state) end
)
end
).
-file("src/tenthash.gleam", 78).
?DOC(
" Takes a String and returns a BigInt result \n"
" or Error(Nil) if hash failed for some reason\n"
" \n"
" ## Examples\n"
"\n"
" ```gleam\n"
" let assert Ok(h) = hash(\"abcdefghijklmnopqrstuvwxyz\")\n"
" bigi.to_String(h)\n"
" // -> \"1380110527555217708541196361393927539963735354394\"\n"
" ```\n"
).
-spec hash(binary()) -> {ok, bigi:big_int()} | {error, nil}.
hash(Data) ->
hash_bitarray(gleam_stdlib:identity(Data)).