github.com/sandwich-go/boost@v1.3.29/z/hash.go (about) 1 package z 2 3 import ( 4 "fmt" 5 "unsafe" 6 ) 7 8 type stringStruct struct { 9 str unsafe.Pointer 10 len int 11 } 12 13 //go:linkname memhash runtime.memhash 14 func memhash(p unsafe.Pointer, h, s uintptr) uintptr 15 16 //go:linkname typehash runtime.typehash 17 func typehash(t, p unsafe.Pointer, h uintptr) uintptr 18 19 // MemHash 不同进程内同一个值获取的可能不同,不能用作持久化的hash 20 func MemHash(data []byte) uint64 { 21 ss := (*stringStruct)(unsafe.Pointer(&data)) 22 return uint64(memhash(ss.str, 0, uintptr(ss.len))) 23 } 24 25 // AnyHash 不同进程内同一个值获取的可能不同,不能用作持久化的hash 26 func AnyHash(v any, h uintptr) uintptr { 27 s := (*[2]unsafe.Pointer)(unsafe.Pointer(&v)) 28 return typehash(s[0], s[1], h) 29 } 30 31 // MemHashString 不同进程内同一个值获取的可能不同,不能用作持久化的hash 32 func MemHashString(str string) uint64 { 33 ss := (*stringStruct)(unsafe.Pointer(&str)) 34 return uint64(memhash(ss.str, 0, uintptr(ss.len))) 35 } 36 37 // KeyToHash 38 // TODO: Figure out a way to re-use memhash for the second uint64 hash, we 39 // already know that appending bytes isn't reliable for generating a 40 // second hash (see Ristretto PR #88). 41 // 42 // We also know that while the Go runtime has a runtime memhash128 43 // function, it's not possible to use it to generate [2]uint64 or 44 // anything resembling a 128bit hash, even though that's exactly what 45 // we need in this situation. 46 47 type HashUint64 interface{ HashUint64() uint64 } 48 49 func KeyToHash(key interface{}) uint64 { 50 if key == nil { 51 return 0 52 } 53 switch k := key.(type) { 54 case uint64: 55 return k 56 case HashUint64: 57 return k.HashUint64() 58 case fmt.Stringer: 59 return MemHashString(k.String()) 60 case string: 61 return MemHashString(k) 62 case []byte: 63 return MemHash(k) 64 case byte: 65 return uint64(k) 66 case int: 67 return uint64(k) 68 case uint: 69 return uint64(k) 70 case int8: 71 return uint64(k) 72 case int16: 73 return uint64(k) 74 case uint16: 75 return uint64(k) 76 case int32: 77 return uint64(k) 78 case uint32: 79 return uint64(k) 80 case int64: 81 return uint64(k) 82 default: 83 panic("Key type not supported") 84 } 85 }