@@ -8,8 +8,10 @@ package maphash
8
8
9
9
import (
10
10
"crypto/rand"
11
+ "internal/abi"
11
12
"internal/byteorder"
12
13
"math/bits"
14
+ "reflect"
13
15
)
14
16
15
17
func rthash (buf []byte , seed uint64 ) uint64 {
@@ -92,3 +94,62 @@ func mix(a, b uint64) uint64 {
92
94
hi , lo := bits .Mul64 (a , b )
93
95
return hi ^ lo
94
96
}
97
+
98
+ var byteSliceTyp = reflect .TypeFor [[]byte ]()
99
+
100
+ var strSliceTyp = reflect .TypeFor [string ]()
101
+
102
+ func comparableF [T comparable ](seed uint64 , v T , t * abi.Type ) uint64 {
103
+ vv := reflect .ValueOf (v )
104
+ typ := vv .Type ()
105
+ if typ == byteSliceTyp {
106
+ return wyhash (vv .Bytes (), seed , uint64 (vv .Len ()))
107
+ }
108
+ if typ == strSliceTyp {
109
+ return rthashString (vv .String (), seed )
110
+ }
111
+ buf := make ([]byte , 0 , typ .Size ())
112
+ appendT (buf , vv )
113
+ return wyhash (buf , seed , uint64 (len (buf )))
114
+ }
115
+
116
+ func appendT (buf []byte , v reflect.Value ) []byte {
117
+ switch v .Kind () {
118
+ case reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 , reflect .Int :
119
+ return byteorder .LeAppendUint64 (buf , uint64 (v .Int ()))
120
+ case reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 , reflect .Uint , reflect .Uintptr :
121
+ return byteorder .LeAppendUint64 (buf , v .Uint ())
122
+ case reflect .Array , reflect .Slice :
123
+ for i := range v .Len () {
124
+ buf = appendT (buf , v .Index (i ))
125
+ }
126
+ case reflect .String :
127
+ return append (buf , v .String ()... )
128
+ case reflect .Struct :
129
+ for i := range v .NumField () {
130
+ buf = appendT (buf , v .Field (i ))
131
+ }
132
+ case reflect .Complex64 , reflect .Complex128 :
133
+ c := v .Complex ()
134
+ buf = byteorder .LeAppendUint64 (buf , uint64 (real (c )))
135
+ return byteorder .LeAppendUint64 (buf , uint64 (imag (c )))
136
+ case reflect .Float32 , reflect .Float64 :
137
+ return byteorder .LeAppendUint64 (buf , uint64 (v .Float ()))
138
+ case reflect .Bool :
139
+ return byteorder .LeAppendUint16 (buf , btoi (v .Bool ()))
140
+ case reflect .UnsafePointer , reflect .Pointer :
141
+ return byteorder .LeAppendUint64 (buf , uint64 (v .Pointer ()))
142
+ case reflect .Interface :
143
+ a := v .InterfaceData ()
144
+ buf = byteorder .LeAppendUint64 (buf , uint64 (a [0 ]))
145
+ return byteorder .LeAppendUint64 (buf , uint64 (a [1 ]))
146
+ }
147
+ panic ("unreachable" )
148
+ }
149
+
150
+ func btoi (b bool ) uint16 {
151
+ if b {
152
+ return 1
153
+ }
154
+ return 0
155
+ }
0 commit comments