Created
April 17, 2023 09:39
-
-
Save jsnanigans/a4a4d80ab29f04260703b0681477986f to your computer and use it in GitHub Desktop.
murmur3_32 TS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function hashText(text: string, seed = 42): number { | |
const encoder = new TextEncoder(); | |
const inputUint8Array = encoder.encode(text); | |
return murmur3_32(inputUint8Array, inputUint8Array.length, seed); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function murmur3_32(key: Uint8Array, len: number, seed: number): number { | |
const c1 = 0xcc9e2d51; | |
const c2 = 0x1b873593; | |
const r1 = 15; | |
const r2 = 13; | |
const m = 5; | |
const n = 0xe6546b64; | |
let hash = seed; | |
function rol(value: number, shift: number): number { | |
return (value << shift) | (value >>> (32 - shift)); | |
} | |
for (let i = 0; i < len - (len % 4); i += 4) { | |
let k = | |
key[i] | (key[i + 1] << 8) | (key[i + 2] << 16) | (key[i + 3] << 24); | |
k = (k * c1) | 0; | |
k = rol(k, r1); | |
k = (k * c2) | 0; | |
hash ^= k; | |
hash = rol(hash, r2); | |
hash = (hash * m + n) | 0; | |
} | |
let remainingBytes = 0; | |
switch (len % 4) { | |
case 3: | |
remainingBytes ^= key[len - 3] << 16; | |
break; | |
case 2: | |
remainingBytes ^= key[len - 2] << 8; | |
break; | |
case 1: | |
remainingBytes ^= key[len - 1]; | |
remainingBytes = (remainingBytes * c1) | 0; | |
remainingBytes = rol(remainingBytes, r1); | |
remainingBytes = (remainingBytes * c2) | 0; | |
hash ^= remainingBytes; | |
} | |
hash ^= len; | |
hash ^= hash >>> 16; | |
hash = (hash * 0x85ebca6b) | 0; | |
hash ^= hash >>> 13; | |
hash = (hash * 0xc2b2ae35) | 0; | |
hash ^= hash >>> 16; | |
return hash >>> 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hashText from "src/lib/hashText"; | |
// mock "new TextEncoder()" and set it on the global.TextEncoder is not defined | |
class TextEncoder { | |
encode(input: string): Uint8Array { | |
return new Uint8Array(input.split("").map((char) => char.charCodeAt(0))); | |
} | |
} | |
(globalThis as any).TextEncoder = TextEncoder; | |
describe('hashText', () => { | |
it('should return the same hash for the same input and seed', () => { | |
const input = 'Hello, world!'; | |
const hash1 = hashText(input); | |
const hash2 = hashText(input); | |
expect(hash1).toStrictEqual(hash2); | |
}); | |
it('should return different hashes for different inputs with the same seed', () => { | |
const input1 = 'Hello, world!'; | |
const input2 = 'Second String'; | |
const hash1 = hashText(input1); | |
const hash2 = hashText(input2); | |
expect(hash1).not.toStrictEqual(hash2); | |
}); | |
it('should return different hashes for the same input with different seeds', () => { | |
const input = 'Hello, world!'; | |
const seed1 = 42; | |
const seed2 = 84; | |
const hash1 = hashText(input, seed1); | |
const hash2 = hashText(input, seed2); | |
expect(hash1).not.toStrictEqual(hash2); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment