/
v2.ts
50 lines (45 loc) · 1.52 KB
/
v2.ts
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
import { doubleToByteArrayJSBI } from "./encoding/number";
import { BytePrefix } from "./encoding/prefix";
import MurmurHash from "./murmurHash";
type v2Key = string | number | null | {} | undefined;
export function hashV2PartitionKey(partitionKey: v2Key): string {
const toHash = prefixKeyByType(partitionKey);
const hash = MurmurHash.x64.hash128(toHash);
const reverseBuff: Buffer = reverse(Buffer.from(hash, "hex"));
reverseBuff[0] &= 0x3f;
return reverseBuff.toString("hex").toUpperCase();
}
function prefixKeyByType(key: v2Key) {
let bytes: Buffer;
switch (typeof key) {
case "string":
bytes = Buffer.concat([
Buffer.from(BytePrefix.String, "hex"),
Buffer.from(key),
Buffer.from(BytePrefix.Infinity, "hex")
]);
return bytes;
case "number":
const numberBytes = doubleToByteArrayJSBI(key);
bytes = Buffer.concat([Buffer.from(BytePrefix.Number, "hex"), numberBytes]);
return bytes;
case "boolean":
const prefix = key ? BytePrefix.True : BytePrefix.False;
return Buffer.from(prefix, "hex");
case "object":
if (key === null) {
return Buffer.from(BytePrefix.Null, "hex");
}
return Buffer.from(BytePrefix.Undefined, "hex");
case "undefined":
return Buffer.from(BytePrefix.Undefined, "hex");
}
}
export function reverse(buff: Buffer) {
const buffer = Buffer.allocUnsafe(buff.length);
for (let i = 0, j = buff.length - 1; i <= j; ++i, --j) {
buffer[i] = buff[j];
buffer[j] = buff[i];
}
return buffer;
}