github.com/arr-ai/hash@v0.8.0/hash.go (about) 1 package hash 2 3 import ( 4 "fmt" 5 "reflect" 6 "unsafe" 7 ) 8 9 // Interface returns a hash for i. 10 //nolint:gocyclo,funlen 11 func Interface(i interface{}, seed uintptr) uintptr { 12 switch k := i.(type) { 13 case Hashable: 14 return k.Hash(seed) 15 case bool: 16 return Bool(k, seed) 17 case int: 18 return Int(k, seed) 19 case int8: 20 return Int8(k, seed) 21 case int16: 22 return Int16(k, seed) 23 case int32: 24 return Int32(k, seed) 25 case int64: 26 return Int64(k, seed) 27 case uint: 28 return Uint(k, seed) 29 case uint8: 30 return Uint8(k, seed) 31 case uint16: 32 return Uint16(k, seed) 33 case uint32: 34 return Uint32(k, seed) 35 case uint64: 36 return Uint64(k, seed) 37 case uintptr: 38 return Uintptr(k, seed) 39 case float32: 40 return Float32(k, seed) 41 case float64: 42 return Float64(k, seed) 43 case complex64: 44 return Complex64(k, seed) 45 case complex128: 46 return Complex128(k, seed) 47 case string: 48 return String(k, seed) 49 case struct{}: 50 return seed 51 case []interface{}: 52 return sliceInterfaceHash(k, seed) 53 default: 54 return Value(reflect.ValueOf(k), seed) 55 } 56 } 57 58 // Bool returns a hash for b. 59 func Bool(b bool, seed uintptr) uintptr { 60 return algarray[algMEM8](noescape(unsafe.Pointer(&b)), seed) 61 } 62 63 // Int returns a hash for x. 64 func Int(x int, seed uintptr) uintptr { 65 return algarray[algINT](noescape(unsafe.Pointer(&x)), seed) 66 } 67 68 // Int8 returns a hash for x. 69 func Int8(x int8, seed uintptr) uintptr { 70 return algarray[algMEM8](noescape(unsafe.Pointer(&x)), seed) 71 } 72 73 // Int16 returns a hash for x. 74 func Int16(x int16, seed uintptr) uintptr { 75 return algarray[algMEM16](noescape(unsafe.Pointer(&x)), seed) 76 } 77 78 // Int32 returns a hash for x. 79 func Int32(x int32, seed uintptr) uintptr { 80 return algarray[algMEM32](noescape(unsafe.Pointer(&x)), seed) 81 } 82 83 // Int64 returns a hash for x. 84 func Int64(x int64, seed uintptr) uintptr { 85 return algarray[algMEM64](noescape(unsafe.Pointer(&x)), seed) 86 } 87 88 // Uint returns a hash for x. 89 func Uint(x uint, seed uintptr) uintptr { 90 return algarray[algUINT](noescape(unsafe.Pointer(&x)), seed) 91 } 92 93 // Uint8 returns a hash for x. 94 func Uint8(x uint8, seed uintptr) uintptr { 95 return algarray[algMEM8](noescape(unsafe.Pointer(&x)), seed) 96 } 97 98 // Uint16 returns a hash for x. 99 func Uint16(x uint16, seed uintptr) uintptr { 100 return algarray[algMEM16](noescape(unsafe.Pointer(&x)), seed) 101 } 102 103 // Uint32 returns a hash for x. 104 func Uint32(x uint32, seed uintptr) uintptr { 105 return algarray[algMEM32](noescape(unsafe.Pointer(&x)), seed) 106 } 107 108 // Uint64 returns a hash for x. 109 func Uint64(x uint64, seed uintptr) uintptr { 110 return algarray[algMEM64](noescape(unsafe.Pointer(&x)), seed) 111 } 112 113 // Uintptr returns a hash for x. 114 func Uintptr(x, seed uintptr) uintptr { 115 return algarray[algPTR](noescape(unsafe.Pointer(&x)), seed) 116 } 117 118 // Float32 returns a hash for f. 119 func Float32(f float32, seed uintptr) uintptr { 120 return algarray[algFLOAT32](noescape(unsafe.Pointer(&f)), seed) 121 } 122 123 // Float64 returns a hash for f. 124 func Float64(f float64, seed uintptr) uintptr { 125 return algarray[algFLOAT64](noescape(unsafe.Pointer(&f)), seed) 126 } 127 128 // Complex64 returns a hash for c. 129 func Complex64(c complex64, seed uintptr) uintptr { 130 return algarray[algCPLX64](noescape(unsafe.Pointer(&c)), seed) 131 } 132 133 // Complex128 returns a hash for c. 134 func Complex128(c complex128, seed uintptr) uintptr { 135 return algarray[algCPLX128](noescape(unsafe.Pointer(&c)), seed) 136 } 137 138 // String returns a hash for s. 139 func String(s string, seed uintptr) uintptr { 140 return algarray[algSTRING](noescape(unsafe.Pointer(&s)), seed) 141 } 142 143 // UnsafePointer returns a hash for p 144 func UnsafePointer(p unsafe.Pointer, seed uintptr) uintptr { 145 return Uintptr(uintptr(p), seed) 146 } 147 148 // Value returns a hash for v. 149 //nolint:funlen 150 func Value(v reflect.Value, seed uintptr) uintptr { 151 switch v.Kind() { 152 case reflect.Bool: 153 return Bool(v.Bool(), seed) 154 case reflect.Int: 155 return Int(int(v.Int()), seed) 156 case reflect.Int8: 157 return Int8(int8(v.Int()), seed) 158 case reflect.Int16: 159 return Int16(int16(v.Int()), seed) 160 case reflect.Int32: 161 return Int32(int32(v.Int()), seed) 162 case reflect.Int64: 163 return Int64(v.Int(), seed) 164 case reflect.Uint: 165 return Uint(uint(v.Uint()), seed) 166 case reflect.Uint8: 167 return Uint8(uint8(v.Uint()), seed) 168 case reflect.Uint16: 169 return Uint16(uint16(v.Uint()), seed) 170 case reflect.Uint32: 171 return Uint32(uint32(v.Uint()), seed) 172 case reflect.Uint64: 173 return Uint64(v.Uint(), seed) 174 case reflect.Uintptr: 175 return Uintptr(uintptr(v.Uint()), seed) 176 case reflect.UnsafePointer: 177 return UnsafePointer(unsafe.Pointer(v.Pointer()), seed) 178 case reflect.Float32: 179 return Float32(float32(v.Float()), seed) 180 case reflect.Float64: 181 return Float64(v.Float(), seed) 182 case reflect.Complex64: 183 return Complex64(complex64(v.Complex()), seed) 184 case reflect.Complex128: 185 return Complex128(v.Complex(), seed) 186 case reflect.String: 187 return String(v.String(), seed) 188 case reflect.Struct: 189 return structHash(v, seed) 190 case reflect.Array: 191 return arrayHash(v, seed) 192 case reflect.Ptr: 193 return Uintptr(v.Pointer(), seed) 194 } 195 panic(fmt.Sprintf("value %v has unhashable type %v", v, v.Type())) 196 } 197 198 func structHash(v reflect.Value, seed uintptr) uintptr { 199 t := v.Type() 200 h := seed 201 for i := v.NumField(); i > 0; { 202 i-- 203 h = String(t.Field(i).Name, h) 204 h = Interface(v.Field(i).Interface(), h) 205 } 206 return h 207 } 208 209 func arrayHash(v reflect.Value, seed uintptr) uintptr { 210 h := seed 211 for i := v.Len(); i > 0; { 212 i-- 213 h = Value(v.Index(i), h) 214 } 215 return h 216 } 217 218 func sliceInterfaceHash(slice []interface{}, seed uintptr) uintptr { 219 h := seed 220 for _, elem := range slice { 221 h = Interface(elem, h) 222 } 223 return h 224 }