mirror of https://github.com/golang/go.git
parent
02df413842
commit
76684949a2
|
|
@ -286,7 +286,7 @@ func (h *Hash) BlockSize() int { return len(h.buf) }
|
|||
// If v contains a floating-point NaN, then the hash is non-deterministically random.
|
||||
func Comparable[T comparable](seed Seed, v T) uint64 {
|
||||
abi.Escape(v)
|
||||
t := abi.TypeOf(v)
|
||||
t := abi.TypeFor[T]()
|
||||
len := t.Size()
|
||||
if len == 0 {
|
||||
return seed.s
|
||||
|
|
@ -297,7 +297,7 @@ func Comparable[T comparable](seed Seed, v T) uint64 {
|
|||
// WriteComparable adds x to the data hashed by h.
|
||||
func WriteComparable[T comparable](h *Hash, x T) {
|
||||
v := Comparable(h.seed, x)
|
||||
var buf []byte
|
||||
var buf [8]byte
|
||||
byteorder.LePutUint64(buf[:], v)
|
||||
h.Write(buf[:])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,17 +95,12 @@ func mix(a, b uint64) uint64 {
|
|||
return hi ^ lo
|
||||
}
|
||||
|
||||
var byteSliceTyp = reflect.TypeFor[[]byte]()
|
||||
|
||||
var strSliceTyp = reflect.TypeFor[string]()
|
||||
var strTyp = reflect.TypeFor[string]()
|
||||
|
||||
func comparableF[T comparable](seed uint64, v T, t *abi.Type) uint64 {
|
||||
vv := reflect.ValueOf(v)
|
||||
typ := vv.Type()
|
||||
if typ == byteSliceTyp {
|
||||
return wyhash(vv.Bytes(), seed, uint64(vv.Len()))
|
||||
}
|
||||
if typ == strSliceTyp {
|
||||
if typ == strTyp {
|
||||
return rthashString(vv.String(), seed)
|
||||
}
|
||||
buf := make([]byte, 0, typ.Size())
|
||||
|
|
@ -119,7 +114,7 @@ func appendT(buf []byte, v reflect.Value) []byte {
|
|||
return byteorder.LeAppendUint64(buf, uint64(v.Int()))
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr:
|
||||
return byteorder.LeAppendUint64(buf, v.Uint())
|
||||
case reflect.Array, reflect.Slice:
|
||||
case reflect.Array:
|
||||
for i := range v.Len() {
|
||||
buf = appendT(buf, v.Index(i))
|
||||
}
|
||||
|
|
@ -142,6 +137,8 @@ func appendT(buf []byte, v reflect.Value) []byte {
|
|||
case reflect.UnsafePointer, reflect.Pointer:
|
||||
return byteorder.LeAppendUint64(buf, uint64(v.Pointer()))
|
||||
case reflect.Interface:
|
||||
// There is no need to check comparability here,
|
||||
// because !purego also treats it as a piece of memory.
|
||||
a := v.InterfaceData()
|
||||
buf = byteorder.LeAppendUint64(buf, uint64(a[0]))
|
||||
return byteorder.LeAppendUint64(buf, uint64(a[1]))
|
||||
|
|
|
|||
|
|
@ -48,11 +48,7 @@ func comparableF[T comparable](seed uint64, v T, t *abi.Type) uint64 {
|
|||
k := t.Kind()
|
||||
len := t.Size()
|
||||
ptr := unsafe.Pointer(&v)
|
||||
switch k {
|
||||
case abi.Slice:
|
||||
len = uintptr(((*unsafeheader.Slice)(unsafe.Pointer(&v))).Len) * t.Elem().Size()
|
||||
ptr = ((*unsafeheader.Slice)(unsafe.Pointer(&v))).Data
|
||||
case abi.String:
|
||||
if k == abi.String {
|
||||
len = uintptr(((*unsafeheader.String)(unsafe.Pointer(&v))).Len)
|
||||
ptr = ((*unsafeheader.String)(unsafe.Pointer(&v))).Data
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"hash"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
@ -210,19 +211,36 @@ func TestSeedFromReset(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCompare(t *testing.T) {
|
||||
var a, b int = 2, 2
|
||||
var pa *int = &a
|
||||
seed := MakeSeed()
|
||||
if Comparable(seed, a) != Comparable(seed, b) {
|
||||
t.Fatal("Comparable(seed, 2) != Comparable(seed, 2)")
|
||||
}
|
||||
old := Comparable(seed, pa)
|
||||
stackGrow(8192)
|
||||
new := Comparable(seed, pa)
|
||||
if old != new {
|
||||
t.Fatal("Comparable(seed, ptr) != Comparable(seed, ptr)")
|
||||
}
|
||||
func TestComparable(t *testing.T) {
|
||||
testComparable(t, int64(2))
|
||||
testComparable(t, uint64(8))
|
||||
testComparable(t, uintptr(12))
|
||||
testComparable(t, any("s"))
|
||||
testComparable(t, "s")
|
||||
testComparable(t, new(float64))
|
||||
testComparable(t, float64(9))
|
||||
testComparable(t, complex128(9i+1))
|
||||
testComparable(t, struct {
|
||||
i int
|
||||
f float64
|
||||
}{i: 9, f: 9.9})
|
||||
}
|
||||
|
||||
func testComparable[T comparable](t *testing.T, v T) {
|
||||
t.Run(reflect.TypeFor[T]().Name(), func(t *testing.T) {
|
||||
var a, b T = v, v
|
||||
var pa *T = &a
|
||||
seed := MakeSeed()
|
||||
if Comparable(seed, a) != Comparable(seed, b) {
|
||||
t.Fatalf("Comparable(seed, %v) != Comparable(seed, %v)", a, b)
|
||||
}
|
||||
old := Comparable(seed, pa)
|
||||
stackGrow(8192)
|
||||
new := Comparable(seed, pa)
|
||||
if old != new {
|
||||
t.Fatal("Comparable(seed, ptr) != Comparable(seed, ptr)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
|
|
@ -236,25 +254,42 @@ func stackGrow(dep int) {
|
|||
}
|
||||
|
||||
func TestWriteComparable(t *testing.T) {
|
||||
var a, b int = 2, 2
|
||||
var pa *int = &a
|
||||
h1 := Hash{}
|
||||
h2 := Hash{}
|
||||
h1.seed = MakeSeed()
|
||||
h2.seed = h1.seed
|
||||
WriteComparable(&h1, a)
|
||||
WriteComparable(&h2, b)
|
||||
if h1.Sum64() != h1.Sum64() {
|
||||
t.Fatal("WriteComparable(h, 2) != WriteComparable(h, 2)")
|
||||
}
|
||||
WriteComparable(&h1, pa)
|
||||
old := h1.Sum64()
|
||||
stackGrow(8192)
|
||||
WriteComparable(&h2, pa)
|
||||
new := h2.Sum64()
|
||||
if old != new {
|
||||
t.Fatal("WriteComparable(seed, ptr) != WriteComparable(seed, ptr)")
|
||||
}
|
||||
testWriteComparable(t, int64(2))
|
||||
testWriteComparable(t, uint64(8))
|
||||
testWriteComparable(t, uintptr(12))
|
||||
testWriteComparable(t, any("s"))
|
||||
testWriteComparable(t, "s")
|
||||
testWriteComparable(t, new(float64))
|
||||
testWriteComparable(t, float64(9))
|
||||
testWriteComparable(t, complex128(9i+1))
|
||||
testWriteComparable(t, struct {
|
||||
i int
|
||||
f float64
|
||||
}{i: 9, f: 9.9})
|
||||
}
|
||||
|
||||
func testWriteComparable[T comparable](t *testing.T, v T) {
|
||||
t.Run(reflect.TypeFor[T]().Name(), func(t *testing.T) {
|
||||
var a, b T = v, v
|
||||
var pa *T = &a
|
||||
h1 := Hash{}
|
||||
h2 := Hash{}
|
||||
h1.seed = MakeSeed()
|
||||
h2.seed = h1.seed
|
||||
WriteComparable(&h1, a)
|
||||
WriteComparable(&h2, b)
|
||||
if h1.Sum64() != h1.Sum64() {
|
||||
t.Fatalf("WriteComparable(h, %v) != WriteComparable(h, %v)", a, b)
|
||||
}
|
||||
WriteComparable(&h1, pa)
|
||||
old := h1.Sum64()
|
||||
stackGrow(8192)
|
||||
WriteComparable(&h2, pa)
|
||||
new := h2.Sum64()
|
||||
if old != new {
|
||||
t.Fatal("WriteComparable(seed, ptr) != WriteComparable(seed, ptr)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Make sure a Hash implements the hash.Hash and hash.Hash64 interfaces.
|
||||
|
|
|
|||
Loading…
Reference in New Issue