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  }