| |
| |
|
|
| type XXHash<T> = { |
| update(input: string | Uint8Array): XXHash<T>; |
| digest(): T; |
| }; |
|
|
| type XXHashAPI = { |
| h32(input: string, seed?: number): number; |
| h32ToString(input: string, seed?: number): string; |
| h32Raw(inputBuffer: Uint8Array, seed?: number): number; |
| create32(seed?: number): XXHash<number>; |
| h64(input: string, seed?: bigint): bigint; |
| h64ToString(input: string, seed?: bigint): string; |
| h64Raw(inputBuffer: Uint8Array, seed?: bigint): bigint; |
| create64(seed?: bigint): XXHash<bigint>; |
| }; |
|
|
| const encoder = new TextEncoder(); |
|
|
| |
| const simpleHash32 = (input: Uint8Array, seed = 0): number => { |
| let hash = seed; |
| for (const byte of input) { |
| hash = Math.trunc((hash << 5) - hash + byte); |
| } |
| return hash >>> 0; |
| }; |
|
|
| function xxhash(): Promise<XXHashAPI> { |
| return { |
| h32: (input: string, seed?: number): number => simpleHash32(encoder.encode(input), seed), |
| h32ToString: (input: string, seed?: number): string => simpleHash32(encoder.encode(input), seed).toString(16).padStart(8, '0'), |
| h32Raw: (inputBuffer: Uint8Array, seed?: number): number => simpleHash32(inputBuffer, seed), |
| create32: (seed?: number): XXHash<number> => { |
| const chunks: Uint8Array[] = []; |
| return { |
| update(input: string | Uint8Array) { |
| chunks.push(typeof input === 'string' ? encoder.encode(input) : input); |
| return this; |
| }, |
| digest() { |
| const totalLength = chunks.reduce((sum, arr) => sum + arr.length, 0); |
| const combined = new Uint8Array(totalLength); |
| let offset = 0; |
| for (const chunk of chunks) { |
| combined.set(chunk, offset); |
| offset += chunk.length; |
| } |
| return simpleHash32(combined, seed); |
| }, |
| }; |
| }, |
| |
| |
| h64: (_input: string, _seed?: bigint): bigint => { |
| throw new Error('h64 is not supported in Worker shim, use h64ToString instead'); |
| }, |
| h64ToString: (input: string, _seed?: bigint): string => { |
| |
| |
| let hash = 0n; |
| const data = encoder.encode(input); |
| for (const byte of data) { |
| hash = ((hash << 5n) - hash + BigInt(byte)) & 0xff_ff_ff_ff_ff_ff_ff_ffn; |
| } |
| return hash.toString(16).padStart(16, '0'); |
| }, |
| h64Raw: (_inputBuffer: Uint8Array, _seed?: bigint): bigint => { |
| throw new Error('h64Raw is not supported in Worker shim'); |
| }, |
| create64: (_seed?: bigint): XXHash<bigint> => { |
| throw new Error('create64 is not supported in Worker shim'); |
| }, |
| }; |
| } |
|
|
| export default xxhash; |
|
|