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 }