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  }