-
Notifications
You must be signed in to change notification settings - Fork 246
/
hasher_ristretto.go
90 lines (72 loc) · 2.4 KB
/
hasher_ristretto.go
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
90
//go:build !wasm
// +build !wasm
package keys
import (
"fmt"
"unsafe"
"github.com/cespare/xxhash/v2"
)
type dispatchCacheKeyHashComputeOption int
const (
computeOnlyStableHash dispatchCacheKeyHashComputeOption = 0
computeBothHashes dispatchCacheKeyHashComputeOption = 1
)
// dispatchCacheKeyHash computres a DispatchCheckKey for the given prefix and any hashable values.
func dispatchCacheKeyHash(prefix cachePrefix, atRevision string, computeOption dispatchCacheKeyHashComputeOption, args ...hashableValue) DispatchCacheKey {
hasher := newDispatchCacheKeyHasher(prefix, computeOption)
for _, arg := range args {
arg.AppendToHash(hasher)
hasher.WriteString("@")
}
hasher.WriteString(atRevision)
return hasher.BuildKey()
}
type dispatchCacheKeyHasher struct {
stableHasher *xxhash.Digest
computeOption dispatchCacheKeyHashComputeOption
processSpecificSum uint64
}
func newDispatchCacheKeyHasher(prefix cachePrefix, computeOption dispatchCacheKeyHashComputeOption) *dispatchCacheKeyHasher {
h := &dispatchCacheKeyHasher{
stableHasher: xxhash.New(),
computeOption: computeOption,
}
prefixString := string(prefix)
h.WriteString(prefixString)
h.WriteString("/")
return h
}
// WriteString writes a single string to the hasher.
func (h *dispatchCacheKeyHasher) WriteString(value string) {
h.mustWriteString(value)
}
func (h *dispatchCacheKeyHasher) mustWriteString(value string) {
// NOTE: xxhash doesn't seem to ever return an error for WriteString, but we check it just
// to be on the safe side.
_, err := h.stableHasher.WriteString(value)
if err != nil {
panic(fmt.Errorf("got an error from writing to the stable hasher: %w", err))
}
if h.computeOption == computeBothHashes {
h.processSpecificSum = runMemHash(h.processSpecificSum, []byte(value))
}
}
// From: https://github.com/outcaste-io/ristretto/blob/master/z/rtutil.go
type stringStruct struct {
str unsafe.Pointer
len int
}
//go:noescape
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptr
func runMemHash(seed uint64, data []byte) uint64 {
ss := (*stringStruct)(unsafe.Pointer(&data))
return uint64(memhash(ss.str, uintptr(seed), uintptr(ss.len)))
}
// BuildKey returns the constructed DispatchCheckKey.
func (h *dispatchCacheKeyHasher) BuildKey() DispatchCacheKey {
return DispatchCacheKey{
stableSum: h.stableHasher.Sum64(),
processSpecificSum: h.processSpecificSum,
}
}