v8.run/go/exp@v0.0.26-0.20230226010534-afcdbd3f782d/hash/hashutil/hasher.go (about)

     1  package hashutil
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  
     7  	"v8.run/go/exp/hash/wyhash"
     8  )
     9  
    10  func Hasher[T comparable](seed uint64) func(T) uint64 {
    11  	var v T
    12  	t := reflect.TypeOf(v)
    13  
    14  	// Mix Seed
    15  	wyhash.WYRAND(&seed)
    16  	wyhash.WYRAND(&seed)
    17  
    18  	switch t.Kind() {
    19  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
    20  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
    21  		reflect.Float32, reflect.Float64, reflect.Bool,
    22  		reflect.Complex64, reflect.Complex128,
    23  		reflect.Pointer, reflect.UnsafePointer, reflect.Uintptr:
    24  		return func(v T) uint64 {
    25  			return wyhash.WYHASH_RAW(
    26  				unsafe.Pointer(&v),
    27  				unsafe.Sizeof(v),
    28  				seed,
    29  			)
    30  		}
    31  	case reflect.String:
    32  		return func(v T) uint64 {
    33  			return wyhash.HashString(*(*string)(unsafe.Pointer(&v)), seed)
    34  		}
    35  	case reflect.Slice:
    36  		switch t.Elem().Kind() {
    37  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
    38  			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
    39  			reflect.Float32, reflect.Float64, reflect.Bool,
    40  			reflect.Complex64, reflect.Complex128,
    41  			reflect.Pointer, reflect.UnsafePointer, reflect.Uintptr:
    42  			return func(v T) uint64 {
    43  				sh := (*reflect.SliceHeader)(unsafe.Pointer(&v))
    44  				return wyhash.WYHASH_RAW(
    45  					unsafe.Pointer(sh.Data),
    46  					unsafe.Sizeof(v)*uintptr(sh.Len),
    47  					seed,
    48  				)
    49  			}
    50  		}
    51  	}
    52  
    53  	return nil
    54  }