-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 <> -> 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}; <> -> {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); <> -> 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; <> -> 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}; <> -> 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 <> -> 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)).