-
Notifications
You must be signed in to change notification settings - Fork 581
/
fnv64.ts
89 lines (72 loc) · 1.98 KB
/
fnv64.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
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
86
87
88
89
// Ported from Go:
// https://github.com/golang/go/tree/go1.13.10/src/hash/fnv/fnv.go
// Copyright 2011 The Go Authors. All rights reserved. BSD license.
// https://github.com/golang/go/blob/master/LICENSE
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
import { mul64 } from "./util.ts";
const offset64Lo = 2216829733;
const offset64Hi = 3421674724;
const prime64Lo = 435;
const prime64Hi = 256;
abstract class Fnv64Base<T> {
#stateHi: number;
#stateLo: number;
constructor() {
this.#stateHi = offset64Hi;
this.#stateLo = offset64Lo;
}
protected _updateState([newStateHi, newStateLo]: [number, number]): void {
this.#stateHi = newStateHi;
this.#stateLo = newStateLo;
}
reset(): void {
this.#stateHi = offset64Hi;
this.#stateLo = offset64Lo;
}
abstract write(data: Uint8Array): T;
size(): number {
return 8;
}
blockSize(): number {
return 1;
}
sum64(): [number, number] {
return [this.#stateHi, this.#stateLo];
}
sum(): Uint8Array {
return Uint8Array.from([
(this.#stateHi >> 24) & 0xff,
(this.#stateHi >> 16) & 0xff,
(this.#stateHi >> 8) & 0xff,
this.#stateHi & 0xff,
(this.#stateLo >> 24) & 0xff,
(this.#stateLo >> 16) & 0xff,
(this.#stateLo >> 8) & 0xff,
this.#stateLo & 0xff,
]);
}
}
/** Fnv64 hash */
export class Fnv64 extends Fnv64Base<Fnv64> {
write(data: Uint8Array): Fnv64 {
let [hashHi, hashLo] = this.sum64();
data.forEach((c) => {
[hashHi, hashLo] = mul64([hashHi, hashLo], [prime64Hi, prime64Lo]);
hashLo ^= c;
});
this._updateState([hashHi, hashLo]);
return this;
}
}
/** Fnv64a hash */
export class Fnv64a extends Fnv64Base<Fnv64a> {
write(data: Uint8Array): Fnv64 {
let [hashHi, hashLo] = this.sum64();
data.forEach((c) => {
hashLo ^= c;
[hashHi, hashLo] = mul64([hashHi, hashLo], [prime64Hi, prime64Lo]);
});
this._updateState([hashHi, hashLo]);
return this;
}
}