-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathhasher.ts
More file actions
85 lines (74 loc) 路 2.16 KB
/
Copy pathhasher.ts
File metadata and controls
85 lines (74 loc) 路 2.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { xxh3 } from '@node-rs/xxhash';
export interface Hasher {
/**
* @param data - The data to hash (string or Buffer)
*/
update(data: string | Buffer): this;
/**
* @returns The hash value in hex format
*/
digest(encoding: 'hex'): string;
/**
* @returns The hash value as a Buffer
*/
digest(): Buffer;
}
class XxHasher implements Hasher {
private data: Buffer[] = [];
public update(data: string | Buffer): this {
if (typeof data === 'string') {
this.data.push(Buffer.from(data));
} else {
this.data.push(data);
}
return this;
}
public digest(): Buffer;
public digest(encoding: 'hex'): string;
public digest(encoding?: 'hex'): Buffer | string {
const combined = Buffer.concat(this.data);
const hash = xxh3.xxh128(combined);
if (encoding === 'hex') {
return hash.toString(16);
}
/*
* This ensures the Buffer format matches what the old MD5 implementation
* would have returned, maintaining compatibility with code that reads the
* digest as a Buffer.
*/
const buffer = Buffer.alloc(16);
const hashBigInt = BigInt(hash);
// eslint-disable-next-line no-bitwise
buffer.writeBigUInt64BE(hashBigInt >> BigInt(64), 0);
// eslint-disable-next-line no-bitwise
buffer.writeBigUInt64BE(hashBigInt & BigInt('0xFFFFFFFFFFFFFFFF'), 8);
return buffer;
}
}
/**
* Creates a new default hasher instance.
*
* This follows Rust's DefaultHasher pattern and provides a consistent
* hashing interface throughout the Cube.js codebase. The implementation
* uses xxHash (xxh128) for fast, non-cryptographic hashing.
*
* The hasher can be used as a drop-in replacement for crypto.createHash()
* in non-cryptographic contexts.
*
* @example
* ```typescript
* const hash = defaultHasher().update('data').digest('hex');
* ```
*
* @example
* ```typescript
* const buffer = defaultHasher().update(JSON.stringify(obj)).digest();
* ```
*
* @returns A new Hasher instance
*/
export function defaultHasher(): Hasher {
// Future: could check environment variable here to switch implementations
// e.g., process.env.CUBEJS_HASHER_ALGORITHM
return new XxHasher();
}