-module(murmur3a). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/murmur3a.gleam"). -export([int_digest/1, bit_array_digest/1, hex_digest/1, hash_bytes/2, hash_string/2, hash_ints/2]). -export_type([hash/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() :: {hash, integer(), integer(), integer()}. -file("src/murmur3a.gleam", 160). ?DOC( " Returns the 32 bit _signed_ integer digest of the hash.\n" "\n" " Keep in mind that these values may return negative numbers!\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " hash_ints([1, 2, 3], 0)\n" " |> int_digest\n" " // -> -2133732860\n" " ```\n" ). -spec int_digest(hash()) -> integer(). int_digest(Hash) -> erlang:element(4, Hash). -file("src/murmur3a.gleam", 173). ?DOC( " Returns 32 bit digest of the hash as a BitArray.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " hash_string(\"murmur3a\", 0)\n" " |> bit_array_digest\n" " // -> <<232, 177, 21, 28>>\n" " ```\n" ). -spec bit_array_digest(hash()) -> bitstring(). bit_array_digest(Hash) -> <<(int_digest(Hash)):32>>. -file("src/murmur3a.gleam", 186). ?DOC( " Returns a hexadecimal digest of the hash.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " hash_string(\"murmur3a\", 0)\n" " |> hex_digest\n" " // -> \"E8B1151C\"\n" " ```\n" ). -spec hex_digest(hash()) -> binary(). hex_digest(Hash) -> _pipe = Hash, _pipe@1 = bit_array_digest(_pipe), gleam_stdlib:base16_encode(_pipe@1). -file("src/murmur3a.gleam", 206). -spec rotate_left(integer(), integer()) -> integer(). rotate_left(N, Shift) -> N@1 = erlang:'band'(N, 16#ffffffff), _pipe = erlang:'bsl'(N@1, Shift), _pipe@1 = erlang:'band'(_pipe, 16#ffffffff), erlang:'bor'(_pipe@1, erlang:'bsr'(N@1, 32 - Shift)). -file("src/murmur3a.gleam", 197). -spec signed_multiply(integer(), integer()) -> integer(). signed_multiply(M, N) -> Result = erlang:'band'(M * N, 16#ffffffff), case Result > 16#7fffffff of true -> Result - 16#100000000; false -> Result end. -file("src/murmur3a.gleam", 107). -spec mix(integer(), integer()) -> integer(). mix(State, Seed) -> _pipe = State, _pipe@1 = signed_multiply(_pipe, 16#cc9e2d51), _pipe@2 = rotate_left(_pipe@1, 15), _pipe@3 = signed_multiply(_pipe@2, 16#1b873593), _pipe@4 = erlang:'bxor'(_pipe@3, Seed), _pipe@5 = rotate_left(_pipe@4, 13), _pipe@6 = signed_multiply(_pipe@5, 5), gleam@int:add(_pipe@6, 16#e6546b64). -file("src/murmur3a.gleam", 95). -spec hash_byte(hash(), integer()) -> hash(). hash_byte(Hash, Byte) -> State = begin _pipe = Byte, _pipe@1 = erlang:'bsl'(_pipe, erlang:element(3, Hash)), erlang:'bor'(_pipe@1, erlang:element(4, Hash)) end, case erlang:element(3, Hash) of 24 -> {hash, mix(State, erlang:element(2, Hash)), 0, 0}; _ -> {hash, erlang:element(2, Hash), erlang:element(3, Hash) + 8, State} end. -file("src/murmur3a.gleam", 53). -spec do_hash_bytes(hash(), bitstring()) -> {ok, hash()} | {error, nil}. do_hash_bytes(Hash, Key) -> case Key of <> -> Seed = begin _pipe = First, _pipe@1 = erlang:'bor'(_pipe, erlang:'bsl'(Second, 8)), _pipe@2 = erlang:'bor'(_pipe@1, erlang:'bsl'(Third, 16)), _pipe@3 = erlang:'bor'(_pipe@2, erlang:'bsl'(Fourth, 24)), mix(_pipe@3, erlang:element(2, Hash)) end, do_hash_bytes( {hash, Seed, erlang:element(3, Hash), erlang:element(4, Hash)}, Rest ); <> -> _pipe@4 = hash_byte(Hash, Byte), do_hash_bytes(_pipe@4, Rest@1); <<>> -> {ok, Hash}; _ -> {error, nil} end. -file("src/murmur3a.gleam", 118). -spec finalize(hash(), integer()) -> hash(). finalize(Hash, Length) -> State = begin _pipe@5 = case erlang:element(4, Hash) of 0 -> erlang:element(2, Hash); _ -> _pipe = erlang:element(4, Hash), _pipe@1 = signed_multiply(_pipe, 16#cc9e2d51), _pipe@2 = rotate_left(_pipe@1, 15), _pipe@3 = signed_multiply(_pipe@2, 16#1b873593), _pipe@4 = erlang:'bxor'(_pipe@3, erlang:element(2, Hash)), erlang:'band'(_pipe@4, 16#ffffffff) end, erlang:'bxor'(_pipe@5, Length) end, State@1 = begin _pipe@6 = erlang:'bsr'(State, 16), _pipe@7 = erlang:'bxor'(_pipe@6, State), _pipe@8 = signed_multiply(_pipe@7, 16#85ebca6b), erlang:'band'(_pipe@8, 16#ffffffff) end, State@2 = begin _pipe@9 = erlang:'bsr'(State@1, 13), _pipe@10 = erlang:'bxor'(_pipe@9, State@1), signed_multiply(_pipe@10, 16#c2b2ae35) end, {hash, erlang:element(2, Hash), erlang:element(3, Hash), begin _pipe@11 = erlang:'bsr'(State@2, 16), _pipe@12 = erlang:'band'(_pipe@11, 16#ffff), erlang:'bxor'(_pipe@12, State@2) end}. -file("src/murmur3a.gleam", 48). ?DOC( " Computes a 32 bit Murmur3 hash of the supplied bit array.\n" "\n" " Returns `Error(Nil)` if the bit array is not byte-aligned.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " hash_bytes(<<\"murmur3a\">>, 0)\n" " // -> Ok(Hash(3521997819, 0, -391047908))\n" " ```\n" ). -spec hash_bytes(bitstring(), integer()) -> {ok, hash()} | {error, nil}. hash_bytes(Key, Seed) -> _pipe = do_hash_bytes( {hash, Seed, erlang:element(3, {hash, 0, 0, 0}), erlang:element(4, {hash, 0, 0, 0})}, Key ), gleam@result:map( _pipe, fun(_capture) -> finalize(_capture, erlang:byte_size(Key)) end ). -file("src/murmur3a.gleam", 32). ?DOC( " Computes a 32 bit Murmur3 hash of the input string.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " hash_string(\"murmur3a\", 0)\n" " // -> Hash(3521997819, 0, -391047908)\n" " ```\n" ). -spec hash_string(binary(), integer()) -> hash(). hash_string(Key, Seed) -> Hash@1 = case hash_bytes(<>, Seed) of {ok, Hash} -> Hash; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"murmur3a"/utf8>>, function => <<"hash_string"/utf8>>, line => 33, value => _assert_fail, start => 755, 'end' => 807, pattern_start => 766, pattern_end => 774}) end, Hash@1. -file("src/murmur3a.gleam", 83). ?DOC( " Computes a 32 bit Murmur3 hash of the supplied list of integers.\n" "\n" " **Note:** Values outside the 0–255 range will be truncated to their lowest\n" " byte before hashing.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " hash_ints([1, 2, 3], 0)\n" " // -> Hash(0, 24, -2133732860)\n" " ```\n" ). -spec hash_ints(list(integer()), integer()) -> hash(). hash_ints(Key, Seed) -> {Hash@1, Length@1} = begin _pipe = Key, gleam@list:fold( _pipe, {{hash, Seed, erlang:element(3, {hash, 0, 0, 0}), erlang:element(4, {hash, 0, 0, 0})}, 0}, fun(Acc, I) -> {Hash, Length} = Acc, {hash_byte(Hash, erlang:'band'(I, 16#ff)), Length + 1} end ) end, finalize(Hash@1, Length@1).