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]).
-export([new/0, update/2, update_bitarray/2, finalise/1, hash_bitarray/1, hash/1]).
-export_type([hash_state/0]).
-opaque hash_state() :: {hash_state,
bigi:big_int(),
bigi:big_int(),
bigi:big_int(),
bigi:big_int(),
bigi:big_int(),
bitstring(),
integer()}.
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 210).
-spec bitmask(integer()) -> bigi:big_int().
bitmask(Size) ->
_assert_subject = bigi_ffi:power(bigi_ffi:from(2), bigi_ffi:from(Size)),
{ok, Bitmask} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail,
module => <<"tenthash"/utf8>>,
function => <<"bitmask"/utf8>>,
line => 211})
end,
bigi_ffi:subtract(Bitmask, bigi_ffi:from(1)).
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 215).
-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("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 86).
-spec initial_state() -> {ok, hash_state()} | {error, nil}.
initial_state() ->
[A, B, C, D] = 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
[_, _, _, _] -> [<<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>>];
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail,
module => <<"tenthash"/utf8>>,
function => <<"initial_state"/utf8>>,
line => 87})
end,
gleam@result:'try'(
bigi_ffi:from_bytes(A, big_endian, unsigned),
fun(A@1) ->
gleam@result:'try'(
bigi_ffi:from_bytes(B, big_endian, unsigned),
fun(B@1) ->
gleam@result:'try'(
bigi_ffi:from_bytes(C, big_endian, unsigned),
fun(C@1) ->
gleam@result:'try'(
bigi_ffi:from_bytes(D, big_endian, unsigned),
fun(D@1) ->
{ok,
{hash_state,
A@1,
B@1,
C@1,
D@1,
bitmask(64),
<<>>,
0}}
end
)
end
)
end
)
end
).
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 29).
-spec new() -> {ok, hash_state()} | {error, nil}.
new() ->
initial_state().
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 196).
-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),
erlang:setelement(
5,
erlang:setelement(
4,
erlang:setelement(
3,
erlang:setelement(2, State@1, B@1),
A@1
),
C@1
),
D@1
)
end
).
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 124).
-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(
erlang:setelement(
5,
erlang:setelement(
4,
erlang:setelement(
3,
erlang:setelement(
2,
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
)
)
)};
{_, _, _, _} ->
{error, nil}
end.
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 95).
-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,
erlang:setelement(
8,
erlang:setelement(7, State, Rest),
erlang:element(8, State) + 32
)
),
fun(Hashed_bits) -> do_hash(Rest, Hashed_bits) end
);
<<>> ->
{ok, State};
<<A@1/bitstring>> ->
{ok, erlang:setelement(7, State, A@1)};
_ ->
{error, nil}
end.
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 34).
-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("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 44).
-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("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 150).
-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,
erlang:setelement(
8,
erlang:setelement(7, State, <<>>),
erlang:element(8, State) + Size
)
),
fun(Hashed_bits) -> {ok, Hashed_bits} end
);
_ ->
{error, nil}
end;
_ ->
{error, nil}
end, fun(State@1) ->
State@2 = erlang:setelement(
2,
State@1,
bigi_ffi:bitwise_exclusive_or(
erlang:element(2, State@1),
bigi_ffi:from(erlang:element(8, State@1) * 8)
)
),
Final_state = mix_hash(mix_hash(State@2)),
_assert_subject = bigi_ffi:to_bytes(
erlang:element(2, Final_state),
little_endian,
unsigned,
8
),
{ok, A@3} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail,
module => <<"tenthash"/utf8>>,
function => <<"finalise_hash"/utf8>>,
line => 185})
end,
_assert_subject@1 = bigi_ffi:to_bytes(
erlang:element(3, Final_state),
little_endian,
unsigned,
8
),
{ok, B@1} = case _assert_subject@1 of
{ok, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail@1,
module => <<"tenthash"/utf8>>,
function => <<"finalise_hash"/utf8>>,
line => 187})
end,
_assert_subject@2 = bigi_ffi:to_bytes(
erlang:element(4, Final_state),
little_endian,
unsigned,
8
),
{ok, C@1} = case _assert_subject@2 of
{ok, _} -> _assert_subject@2;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail@2,
module => <<"tenthash"/utf8>>,
function => <<"finalise_hash"/utf8>>,
line => 189})
end,
Ba = gleam_stdlib:bit_array_concat([A@3, B@1, C@1]),
_assert_subject@3 = gleam_stdlib:bit_array_slice(Ba, 0, 20),
{ok, Slice} = case _assert_subject@3 of
{ok, _} -> _assert_subject@3;
_assert_fail@3 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail@3,
module => <<"tenthash"/utf8>>,
function => <<"finalise_hash"/utf8>>,
line => 192})
end,
bigi_ffi:from_bytes(Slice, big_endian, unsigned)
end).
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 57).
-spec finalise(hash_state()) -> {ok, bigi:big_int()} | {error, nil}.
finalise(State) ->
finalise_hash(State).
-file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 78).
-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("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 71).
-spec hash(binary()) -> {ok, bigi:big_int()} | {error, nil}.
hash(Data) ->
hash_bitarray(gleam_stdlib:identity(Data)).