-module(tenthash). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([hash_bitarray/1, hash/1]). -export_type([hash_state/0]). -type hash_state() :: {hash_state, bigi:big_int(), bigi:big_int(), bigi:big_int(), bigi:big_int()}. -file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 167). -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 => 168}) end, bigi_ffi:subtract(Bitmask, bigi_ffi:from(1)). -file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 172). -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", 62). -spec initial_state() -> {ok, hash_state()} | {error, nil}. initial_state() -> [A, B, C, D] = case [<<"6732230515997387111"/utf8>>, <<"16297768295691943732"/utf8>>, <<"14578299661238189102"/utf8>>, <<"9893891307554648435"/utf8>>] of [_, _, _, _] -> [<<"6732230515997387111"/utf8>>, <<"16297768295691943732"/utf8>>, <<"14578299661238189102"/utf8>>, <<"9893891307554648435"/utf8>>]; _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 => 63}) end, gleam@result:'try'( bigi_ffi:from_string(A), fun(A@1) -> gleam@result:'try'( bigi_ffi:from_string(B), fun(B@1) -> gleam@result:'try'( bigi_ffi:from_string(C), fun(C@1) -> gleam@result:'try'( bigi_ffi:from_string(D), fun(D@1) -> {ok, {hash_state, A@1, B@1, C@1, D@1}} end ) end ) end ) end ). -file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 147). -spec mix_hash(hash_state()) -> hash_state(). mix_hash(State) -> Bitmask = bitmask(64), gleam@list:fold( [[16, 28], [14, 57], [11, 22], [35, 34], [57, 16], [59, 40], [44, 13]], State, fun(State@1, C) -> [C1, C2] = case C of [_, _] -> C; _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 => <<"mix_hash"/utf8>>, line => 150}) end, A = bigi_ffi:add( erlang:element(2, State@1), erlang:element(4, State@1) ), A@1 = bigi_ffi:bitwise_and(A, Bitmask), B = bigi_ffi:add( erlang:element(3, State@1), erlang:element(5, State@1) ), B@1 = bigi_ffi:bitwise_and(B, Bitmask), C@1 = rot_left(erlang:element(4, State@1), C1, Bitmask), C@2 = bigi_ffi:bitwise_exclusive_or(C@1, A@1), D = rot_left(erlang:element(5, State@1), C2, Bitmask), D@1 = bigi_ffi:bitwise_exclusive_or(D, B@1), A2 = A@1, A@2 = B@1, B@2 = A2, {hash_state, A@2, B@2, C@2, D@1} end ). -file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 104). -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( {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 )} )}; {_, _, _, _} -> {error, nil} end. -file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 71). -spec do_hash(bitstring(), hash_state()) -> {ok, hash_state()} | {error, nil}. do_hash(Data, State) -> case Data of <> -> gleam@result:'try'( hash_bits(A, B, C, D, State), fun(Hashed_bits) -> do_hash(Rest, Hashed_bits) end ); <<>> -> {ok, State}; <> -> Extra_bits = 32 - erlang:byte_size(A@1), A@2 = gleam_stdlib:bit_array_concat( [A@1, <<0:(lists:max([((Extra_bits * 8)), 0]))>>] ), case A@2 of <> -> gleam@result:'try'( hash_bits(A@3, B@1, C@1, D@1, State), fun(Hashed_bits@1) -> do_hash(<<>>, Hashed_bits@1) end ); _ -> {error, nil} end; _ -> {error, nil} end. -file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 129). -spec finalise_hash(hash_state(), integer()) -> {ok, bigi:big_int()} | {error, nil}. finalise_hash(State, Len) -> State@1 = erlang:setelement( 2, State, bigi_ffi:bitwise_exclusive_or( erlang:element(2, State), bigi_ffi:from(Len) ) ), Final_state = mix_hash(mix_hash(State@1)), _assert_subject = bigi_ffi:to_bytes( erlang:element(2, Final_state), little_endian, unsigned, 8 ), {ok, A} = 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 => 136}) end, _assert_subject@1 = bigi_ffi:to_bytes( erlang:element(3, Final_state), little_endian, unsigned, 8 ), {ok, B} = 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 => 138}) end, _assert_subject@2 = bigi_ffi:to_bytes( erlang:element(4, Final_state), little_endian, unsigned, 8 ), {ok, C} = 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 => 140}) end, Ba = gleam@bit_array:append(A, gleam@bit_array:append(B, C)), _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 => 143}) end, bigi_ffi:from_bytes(Slice, big_endian, unsigned). -file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 54). -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, erlang:byte_size(Data) * 8) end ) end ). -file("/Users/gareth/Development/gleam/tenthash/src/tenthash.gleam", 47). -spec hash(binary()) -> {ok, bigi:big_int()} | {error, nil}. hash(Data) -> hash_bitarray(gleam_stdlib:identity(Data)).