mirror of
https://github.com/Instadapp/Swap-Aggregator-Subgraph.git
synced 2024-07-29 21:57:12 +00:00
118 lines
2.9 KiB
TypeScript
118 lines
2.9 KiB
TypeScript
export function HASH<T>(key: T): u32 {
|
|
if (isString<T>()) {
|
|
return hashStr(changetype<string>(key));
|
|
} else if (isReference<T>()) {
|
|
if (sizeof<T>() == 4) return hash32(changetype<u32>(key));
|
|
if (sizeof<T>() == 8) return hash64(changetype<u64>(key));
|
|
} else if (isFloat<T>()) {
|
|
if (sizeof<T>() == 4) return hash32(reinterpret<u32>(f32(key)));
|
|
if (sizeof<T>() == 8) return hash64(reinterpret<u64>(f64(key)));
|
|
} else {
|
|
if (sizeof<T>() <= 4) return hash32(u32(key), sizeof<T>());
|
|
if (sizeof<T>() == 8) return hash64(u64(key));
|
|
}
|
|
return unreachable();
|
|
}
|
|
|
|
// XXHash 32-bit as a starting point, see: https://cyan4973.github.io/xxHash
|
|
|
|
// primes
|
|
// @ts-ignore: decorator
|
|
@inline const XXH32_P1: u32 = 2654435761;
|
|
// @ts-ignore: decorator
|
|
@inline const XXH32_P2: u32 = 2246822519;
|
|
// @ts-ignore: decorator
|
|
@inline const XXH32_P3: u32 = 3266489917;
|
|
// @ts-ignore: decorator
|
|
@inline const XXH32_P4: u32 = 668265263;
|
|
// @ts-ignore: decorator
|
|
@inline const XXH32_P5: u32 = 374761393;
|
|
// @ts-ignore: decorator
|
|
@inline const XXH32_SEED: u32 = 0;
|
|
|
|
// @ts-ignore: decorator
|
|
@inline
|
|
function hash32(key: u32, len: u32 = 4): u32 {
|
|
var h: u32 = XXH32_SEED + XXH32_P5 + len;
|
|
h += key * XXH32_P3;
|
|
h = rotl(h, 17) * XXH32_P4;
|
|
h ^= h >> 15;
|
|
h *= XXH32_P2;
|
|
h ^= h >> 13;
|
|
h *= XXH32_P3;
|
|
h ^= h >> 16;
|
|
return h;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@inline
|
|
function hash64(key: u64): u32 {
|
|
var h: u32 = XXH32_SEED + XXH32_P5 + 8;
|
|
h += <u32>key * XXH32_P3;
|
|
h = rotl(h, 17) * XXH32_P4;
|
|
h += <u32>(key >> 32) * XXH32_P3;
|
|
h = rotl(h, 17) * XXH32_P4;
|
|
h ^= h >> 15;
|
|
h *= XXH32_P2;
|
|
h ^= h >> 13;
|
|
h *= XXH32_P3;
|
|
h ^= h >> 16;
|
|
return h;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@inline
|
|
function mix(h: u32, key: u32): u32 {
|
|
return rotl(h + key * XXH32_P2, 13) * XXH32_P1;
|
|
}
|
|
|
|
// @ts-ignore: decorator
|
|
@inline
|
|
function hashStr(key: string): u32 {
|
|
if (key === null) return XXH32_SEED;
|
|
|
|
var h: u32 = key.length << 1;
|
|
var len: usize = h;
|
|
var pos = changetype<usize>(key);
|
|
|
|
if (len >= 16) {
|
|
let s1 = XXH32_SEED + XXH32_P1 + XXH32_P2;
|
|
let s2 = XXH32_SEED + XXH32_P2;
|
|
let s3 = XXH32_SEED;
|
|
let s4 = XXH32_SEED - XXH32_P1;
|
|
|
|
let end = len + pos - 16;
|
|
while (pos <= end) {
|
|
s1 = mix(s1, load<u32>(pos ));
|
|
s2 = mix(s2, load<u32>(pos, 4));
|
|
s3 = mix(s3, load<u32>(pos, 8));
|
|
s4 = mix(s4, load<u32>(pos, 12));
|
|
pos += 16;
|
|
}
|
|
h += rotl(s1, 1) + rotl(s2, 7) + rotl(s3, 12) + rotl(s4, 18);
|
|
} else {
|
|
h += XXH32_SEED + XXH32_P5;
|
|
}
|
|
|
|
var end = changetype<usize>(key) + len - 4;
|
|
while (pos <= end) {
|
|
h += load<u32>(pos) * XXH32_P3;
|
|
h = rotl(h, 17) * XXH32_P4;
|
|
pos += 4;
|
|
}
|
|
|
|
end = changetype<usize>(key) + len;
|
|
while (pos < end) {
|
|
h += <u32>load<u8>(pos) * XXH32_P5;
|
|
h = rotl(h, 11) * XXH32_P1;
|
|
pos++;
|
|
}
|
|
|
|
h ^= h >> 15;
|
|
h *= XXH32_P2;
|
|
h ^= h >> 13;
|
|
h *= XXH32_P3;
|
|
h ^= h >> 16;
|
|
return h;
|
|
}
|