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