github.com/Nigel2392/go-datastructures@v1.1.5/hashmap/make_hasher.go (about)

     1  package hashmap
     2  
     3  import (
     4  	"fmt"
     5  	"unsafe"
     6  
     7  	"github.com/Nigel2392/go-datastructures"
     8  )
     9  
    10  type comparable interface {
    11  	~int | ~uint | ~string | ~int8 | ~int16 | ~int32 | ~int64 | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | ~complex64 | ~complex128 | ~bool
    12  }
    13  
    14  func Key[T comparable](v T) *MapKey[T] {
    15  	return makeHasher(v, getHashFunc[T]())
    16  }
    17  
    18  type MapKey[T comparable] struct {
    19  	_hash func(T) uint64
    20  	v     T
    21  }
    22  
    23  func (h *MapKey[T]) Hash() uint64 {
    24  	return h._hash(h.v)
    25  }
    26  
    27  func (h *MapKey[T]) Equals(other *MapKey[T]) bool {
    28  	return h.v == other.v
    29  }
    30  
    31  func (h *MapKey[T]) Value() T {
    32  	return h.v
    33  }
    34  
    35  func (h *MapKey[T]) String() string {
    36  	return fmt.Sprintf("%v", h.v)
    37  }
    38  
    39  func (h *MapKey[T]) GoString() string {
    40  	return fmt.Sprintf("%#v", h.v)
    41  }
    42  
    43  func makeHasher[T comparable](v T, hashfunc func(T) uint64) *MapKey[T] {
    44  	switch any(*new(T)).(type) {
    45  	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128:
    46  		return &MapKey[T]{_hash: hashfunc, v: v}
    47  	case string:
    48  		return &MapKey[T]{_hash: hashfunc, v: v}
    49  	case bool:
    50  		return &MapKey[T]{_hash: hashfunc, v: v}
    51  	case nil:
    52  		return &MapKey[T]{_hash: hashfunc, v: v}
    53  	}
    54  	panic("type is not comparable!")
    55  }
    56  
    57  func getHashFunc[T comparable]() func(T) uint64 {
    58  	return genericHashFunc[T]
    59  }
    60  
    61  func genericHashFunc[T comparable](v T) uint64 {
    62  	switch any(*new(T)).(type) {
    63  	case string:
    64  		return _hash_string(*(*string)(unsafe.Pointer(&v)))
    65  	case int:
    66  		return _hash_int(*(*int)(unsafe.Pointer(&v)))
    67  	case int8:
    68  		return _hash_int(*(*int8)(unsafe.Pointer(&v)))
    69  	case int16:
    70  		return _hash_int(*(*int16)(unsafe.Pointer(&v)))
    71  	case int32:
    72  		return _hash_int(*(*int32)(unsafe.Pointer(&v)))
    73  	case int64:
    74  		return _hash_int(*(*int64)(unsafe.Pointer(&v)))
    75  	case uint:
    76  		return _hash_int(*(*uint)(unsafe.Pointer(&v)))
    77  	case uint8:
    78  		return _hash_int(*(*uint8)(unsafe.Pointer(&v)))
    79  	case uint16:
    80  		return _hash_int(*(*uint16)(unsafe.Pointer(&v)))
    81  	case uint32:
    82  		return _hash_int(*(*uint32)(unsafe.Pointer(&v)))
    83  	case uint64:
    84  		return _hash_int(*(*uint64)(unsafe.Pointer(&v)))
    85  	case uintptr:
    86  		return _hash_int(*(*uintptr)(unsafe.Pointer(&v)))
    87  	case float32:
    88  		return _hash_float(*(*float32)(unsafe.Pointer(&v)))
    89  	case float64:
    90  		return _hash_float(*(*float64)(unsafe.Pointer(&v)))
    91  	case complex64:
    92  		return _hash_float(*(*float32)(unsafe.Pointer(&v)))
    93  	case complex128:
    94  		return _hash_float(*(*float64)(unsafe.Pointer(&v)))
    95  	case bool:
    96  		return _bool_hash(*(*bool)(unsafe.Pointer(&v)))
    97  	case nil:
    98  		return _hash_int(0)
    99  	}
   100  	panic("type is not comparable!")
   101  }
   102  
   103  type integer interface {
   104  	~int | ~int8 | ~int16 | ~int32 | ~int64
   105  }
   106  
   107  type uinteger interface {
   108  	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
   109  }
   110  
   111  type number interface {
   112  	integer | uinteger
   113  }
   114  
   115  func _hash_int[T number](v T) uint64 {
   116  	var x = uint64(v)
   117  	x = (x ^ (x >> 30)) * uint64(0xbf58476d1ce4e5b9)
   118  	x = (x ^ (x >> 27)) * uint64(0x94d049bb133111eb)
   119  	x = x ^ (x >> 31)
   120  	return x
   121  }
   122  
   123  type decimal interface {
   124  	~float32 | ~float64
   125  }
   126  
   127  func _hash_float[T decimal](v T) uint64 {
   128  	return _hash_int(uint64(v))
   129  }
   130  
   131  func _hash_string(v string) uint64 {
   132  	return datastructures.FastStrHash(v)
   133  }
   134  
   135  func _bool_hash(v bool) uint64 {
   136  	if v {
   137  		return 1
   138  	}
   139  	return 0
   140  }