-
Notifications
You must be signed in to change notification settings - Fork 0
/
hash.go
116 lines (98 loc) · 1.85 KB
/
hash.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package gymbol
import (
"encoding/binary"
"hash"
"math"
"github.com/dchest/siphash"
)
var SIPHASH_KEY = []byte{
0x5a,
0x52,
0xff,
0x2e,
0x4e,
0x09,
0x8e,
0x62,
0x0b,
0x61,
0x46,
0x6e,
0x7a,
0xf9,
0x64,
0x93,
}
type Hasher struct {
hash.Hash64
vm *VM
}
func NewHasher(vm *VM) *Hasher {
sip := siphash.New(SIPHASH_KEY)
return &Hasher{sip, vm}
}
func (hasher *Hasher) Sum() uint32 {
sum64 := hasher.Hash64.Sum64()
return uint32(sum64)
}
func (hasher *Hasher) WriteBytes(b []byte) {
hasher.Write(b)
}
func (hasher *Hasher) WriteUint32(n uint32) {
var b [4]byte
binary.BigEndian.PutUint32(b[:], n)
hasher.Write(b[:])
}
func (hasher *Hasher) WriteUint64(n uint64) {
var b [8]byte
binary.BigEndian.PutUint64(b[:], n)
hasher.Write(b[:])
}
func (hasher *Hasher) WriteFloat64(f float64) {
n := math.Float64bits(f)
hasher.WriteUint64(n)
}
func (hasher *Hasher) WriteType(sym Symbol) {
hasher.WriteUint32(sym.Index)
}
func (hasher *Hasher) WriteNumber(num Number) {
f := float64(num)
hasher.WriteType(NUMBER)
hasher.WriteFloat64(f)
}
func (hasher *Hasher) WriteSymbol(sym Symbol) {
hasher.WriteType(SYMBOL)
hasher.WriteUint32(sym.Index)
}
func (hasher *Hasher) WriteString(str String) {
bytes := []byte(str)
hasher.WriteBytes(bytes)
}
func (hasher *Hasher) WriteRef(ref Ref) {
type_, values := hasher.vm.Heap.Load(ref)
hasher.WriteType(type_)
for i := range values {
value := values[i]
hasher.WriteValue(value)
}
}
func (hasher *Hasher) WriteQuoted(quoted Quoted) {
hasher.WriteUint32(quoted.Type.Index)
hasher.WriteValue(quoted.Value)
}
func (hasher *Hasher) WriteValue(val Value) {
switch val := val.(type) {
case Number:
hasher.WriteNumber(val)
case Symbol:
hasher.WriteSymbol(val)
case String:
hasher.WriteString(val)
case Ref:
hasher.WriteRef(val)
case Quoted:
hasher.WriteQuoted(val)
default:
panic(val)
}
}