summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-structr/hash.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-structr/hash.go')
-rw-r--r--vendor/codeberg.org/gruf/go-structr/hash.go370
1 files changed, 370 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-structr/hash.go b/vendor/codeberg.org/gruf/go-structr/hash.go
new file mode 100644
index 000000000..84f0e62fc
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-structr/hash.go
@@ -0,0 +1,370 @@
+package structr
+
+import (
+ "reflect"
+ "unsafe"
+
+ "github.com/zeebo/xxh3"
+)
+
+func hasher(t reflect.Type) func(*xxh3.Hasher, any) bool {
+ switch t.Kind() {
+ case reflect.Int,
+ reflect.Uint,
+ reflect.Uintptr:
+ switch unsafe.Sizeof(int(0)) {
+ case 4:
+ return hash32bit
+ case 8:
+ return hash64bit
+ default:
+ panic("unexpected platform int size")
+ }
+
+ case reflect.Int8,
+ reflect.Uint8:
+ return hash8bit
+
+ case reflect.Int16,
+ reflect.Uint16:
+ return hash16bit
+
+ case reflect.Int32,
+ reflect.Uint32,
+ reflect.Float32:
+ return hash32bit
+
+ case reflect.Int64,
+ reflect.Uint64,
+ reflect.Float64,
+ reflect.Complex64:
+ return hash64bit
+
+ case reflect.String:
+ return hashstring
+
+ case reflect.Pointer:
+ switch t.Elem().Kind() {
+ case reflect.Int,
+ reflect.Uint,
+ reflect.Uintptr:
+ switch unsafe.Sizeof(int(0)) {
+ case 4:
+ return hash32bitptr
+ case 8:
+ return hash64bitptr
+ default:
+ panic("unexpected platform int size")
+ }
+
+ case reflect.Int8,
+ reflect.Uint8:
+ return hash8bitptr
+
+ case reflect.Int16,
+ reflect.Uint16:
+ return hash16bitptr
+
+ case reflect.Int32,
+ reflect.Uint32,
+ reflect.Float32:
+ return hash32bitptr
+
+ case reflect.Int64,
+ reflect.Uint64,
+ reflect.Float64,
+ reflect.Complex64:
+ return hash64bitptr
+
+ case reflect.String:
+ return hashstringptr
+ }
+
+ case reflect.Slice:
+ switch t.Elem().Kind() {
+ case reflect.Int,
+ reflect.Uint,
+ reflect.Uintptr:
+ switch unsafe.Sizeof(int(0)) {
+ case 4:
+ return hash32bitslice
+ case 8:
+ return hash64bitslice
+ default:
+ panic("unexpected platform int size")
+ }
+
+ case reflect.Int8,
+ reflect.Uint8:
+ return hash8bitslice
+
+ case reflect.Int16,
+ reflect.Uint16:
+ return hash16bitslice
+
+ case reflect.Int32,
+ reflect.Uint32,
+ reflect.Float32:
+ return hash32bitslice
+
+ case reflect.Int64,
+ reflect.Uint64,
+ reflect.Float64,
+ reflect.Complex64:
+ return hash64bitslice
+
+ case reflect.String:
+ return hashstringslice
+ }
+ }
+ switch {
+ case t.Implements(reflect.TypeOf((*interface{ MarshalBinary() ([]byte, error) })(nil)).Elem()):
+ return hashbinarymarshaler
+
+ case t.Implements(reflect.TypeOf((*interface{ Bytes() []byte })(nil)).Elem()):
+ return hashbytesmethod
+
+ case t.Implements(reflect.TypeOf((*interface{ String() string })(nil)).Elem()):
+ return hashstringmethod
+
+ case t.Implements(reflect.TypeOf((*interface{ MarshalText() ([]byte, error) })(nil)).Elem()):
+ return hashtextmarshaler
+
+ case t.Implements(reflect.TypeOf((*interface{ MarshalJSON() ([]byte, error) })(nil)).Elem()):
+ return hashjsonmarshaler
+ }
+ panic("unhashable type")
+}
+
+func hash8bit(h *xxh3.Hasher, a any) bool {
+ u := *(*uint8)(iface_value(a))
+ _, _ = h.Write([]byte{u})
+ return u == 0
+}
+
+func hash8bitptr(h *xxh3.Hasher, a any) bool {
+ u := (*uint8)(iface_value(a))
+ if u == nil {
+ _, _ = h.Write([]byte{
+ 0,
+ })
+ return true
+ } else {
+ _, _ = h.Write([]byte{
+ 1,
+ byte(*u),
+ })
+ return false
+ }
+}
+
+func hash8bitslice(h *xxh3.Hasher, a any) bool {
+ b := *(*[]byte)(iface_value(a))
+ _, _ = h.Write(b)
+ return b == nil
+}
+
+func hash16bit(h *xxh3.Hasher, a any) bool {
+ u := *(*uint16)(iface_value(a))
+ _, _ = h.Write([]byte{
+ byte(u),
+ byte(u >> 8),
+ })
+ return u == 0
+}
+
+func hash16bitptr(h *xxh3.Hasher, a any) bool {
+ u := (*uint16)(iface_value(a))
+ if u == nil {
+ _, _ = h.Write([]byte{
+ 0,
+ })
+ return true
+ } else {
+ _, _ = h.Write([]byte{
+ 1,
+ byte(*u),
+ byte(*u >> 8),
+ })
+ return false
+ }
+}
+
+func hash16bitslice(h *xxh3.Hasher, a any) bool {
+ u := *(*[]uint16)(iface_value(a))
+ for i := range u {
+ _, _ = h.Write([]byte{
+ byte(u[i]),
+ byte(u[i] >> 8),
+ })
+ }
+ return u == nil
+}
+
+func hash32bit(h *xxh3.Hasher, a any) bool {
+ u := *(*uint32)(iface_value(a))
+ _, _ = h.Write([]byte{
+ byte(u),
+ byte(u >> 8),
+ byte(u >> 16),
+ byte(u >> 24),
+ })
+ return u == 0
+}
+
+func hash32bitptr(h *xxh3.Hasher, a any) bool {
+ u := (*uint32)(iface_value(a))
+ if u == nil {
+ _, _ = h.Write([]byte{
+ 0,
+ })
+ return true
+ } else {
+ _, _ = h.Write([]byte{
+ 1,
+ byte(*u),
+ byte(*u >> 8),
+ byte(*u >> 16),
+ byte(*u >> 24),
+ })
+ return false
+ }
+}
+
+func hash32bitslice(h *xxh3.Hasher, a any) bool {
+ u := *(*[]uint32)(iface_value(a))
+ for i := range u {
+ _, _ = h.Write([]byte{
+ byte(u[i]),
+ byte(u[i] >> 8),
+ byte(u[i] >> 16),
+ byte(u[i] >> 24),
+ })
+ }
+ return u == nil
+}
+
+func hash64bit(h *xxh3.Hasher, a any) bool {
+ u := *(*uint64)(iface_value(a))
+ _, _ = h.Write([]byte{
+ byte(u),
+ byte(u >> 8),
+ byte(u >> 16),
+ byte(u >> 24),
+ byte(u >> 32),
+ byte(u >> 40),
+ byte(u >> 48),
+ byte(u >> 56),
+ })
+ return u == 0
+}
+
+func hash64bitptr(h *xxh3.Hasher, a any) bool {
+ u := (*uint64)(iface_value(a))
+ if u == nil {
+ _, _ = h.Write([]byte{
+ 0,
+ })
+ return true
+ } else {
+ _, _ = h.Write([]byte{
+ 1,
+ byte(*u),
+ byte(*u >> 8),
+ byte(*u >> 16),
+ byte(*u >> 24),
+ byte(*u >> 32),
+ byte(*u >> 40),
+ byte(*u >> 48),
+ byte(*u >> 56),
+ })
+ return false
+ }
+}
+
+func hash64bitslice(h *xxh3.Hasher, a any) bool {
+ u := *(*[]uint64)(iface_value(a))
+ for i := range u {
+ _, _ = h.Write([]byte{
+ byte(u[i]),
+ byte(u[i] >> 8),
+ byte(u[i] >> 16),
+ byte(u[i] >> 24),
+ byte(u[i] >> 32),
+ byte(u[i] >> 40),
+ byte(u[i] >> 48),
+ byte(u[i] >> 56),
+ })
+ }
+ return u == nil
+}
+
+func hashstring(h *xxh3.Hasher, a any) bool {
+ s := *(*string)(iface_value(a))
+ _, _ = h.WriteString(s)
+ return s == ""
+}
+
+func hashstringptr(h *xxh3.Hasher, a any) bool {
+ s := (*string)(iface_value(a))
+ if s == nil {
+ _, _ = h.Write([]byte{
+ 0,
+ })
+ return true
+ } else {
+ _, _ = h.Write([]byte{
+ 1,
+ })
+ _, _ = h.WriteString(*s)
+ return false
+ }
+}
+
+func hashstringslice(h *xxh3.Hasher, a any) bool {
+ s := *(*[]string)(iface_value(a))
+ for i := range s {
+ _, _ = h.WriteString(s[i])
+ }
+ return s == nil
+}
+
+func hashbinarymarshaler(h *xxh3.Hasher, a any) bool {
+ i := a.(interface{ MarshalBinary() ([]byte, error) })
+ b, _ := i.MarshalBinary()
+ _, _ = h.Write(b)
+ return b == nil
+}
+
+func hashbytesmethod(h *xxh3.Hasher, a any) bool {
+ i := a.(interface{ Bytes() []byte })
+ b := i.Bytes()
+ _, _ = h.Write(b)
+ return b == nil
+}
+
+func hashstringmethod(h *xxh3.Hasher, a any) bool {
+ i := a.(interface{ String() string })
+ s := i.String()
+ _, _ = h.WriteString(s)
+ return s == ""
+}
+
+func hashtextmarshaler(h *xxh3.Hasher, a any) bool {
+ i := a.(interface{ MarshalText() ([]byte, error) })
+ b, _ := i.MarshalText()
+ _, _ = h.Write(b)
+ return b == nil
+}
+
+func hashjsonmarshaler(h *xxh3.Hasher, a any) bool {
+ i := a.(interface{ MarshalJSON() ([]byte, error) })
+ b, _ := i.MarshalJSON()
+ _, _ = h.Write(b)
+ return b == nil
+}
+
+func iface_value(a any) unsafe.Pointer {
+ type eface struct{ _, v unsafe.Pointer }
+ return (*eface)(unsafe.Pointer(&a)).v
+}