mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
util/deephash: simplify canMemHash (#5384)
Put the t.Size() == 0 check first since this is applicable in all cases. Drop the last struct field conditional since this is covered by the sumFieldSize check at the end. Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
parent
766ea96adf
commit
c200229f9e
@ -722,10 +722,15 @@ func typeIsRecursive(t reflect.Type) bool {
|
|||||||
// canMemHash reports whether a slice of t can be hashed by looking at its
|
// canMemHash reports whether a slice of t can be hashed by looking at its
|
||||||
// contiguous bytes in memory alone. (e.g. structs with gaps aren't memhashable)
|
// contiguous bytes in memory alone. (e.g. structs with gaps aren't memhashable)
|
||||||
func canMemHash(t reflect.Type) bool {
|
func canMemHash(t reflect.Type) bool {
|
||||||
|
if t.Size() == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
case reflect.Bool,
|
||||||
reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||||
reflect.Float64, reflect.Float32, reflect.Complex128, reflect.Complex64:
|
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
|
||||||
|
reflect.Float32, reflect.Float64,
|
||||||
|
reflect.Complex64, reflect.Complex128:
|
||||||
return true
|
return true
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
return canMemHash(t.Elem())
|
return canMemHash(t.Elem())
|
||||||
@ -734,15 +739,11 @@ func canMemHash(t reflect.Type) bool {
|
|||||||
for i, numField := 0, t.NumField(); i < numField; i++ {
|
for i, numField := 0, t.NumField(); i < numField; i++ {
|
||||||
sf := t.Field(i)
|
sf := t.Field(i)
|
||||||
if !canMemHash(sf.Type) {
|
if !canMemHash(sf.Type) {
|
||||||
// Special case for 0-width fields that aren't at the end.
|
|
||||||
if sf.Type.Size() == 0 && i < numField-1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
sumFieldSize += sf.Type.Size()
|
sumFieldSize += sf.Type.Size()
|
||||||
}
|
}
|
||||||
return sumFieldSize == t.Size() // else there are gaps
|
return sumFieldSize == t.Size() // ensure no gaps
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -379,20 +379,18 @@ func TestCanMemHash(t *testing.T) {
|
|||||||
_ uint8
|
_ uint8
|
||||||
_ int
|
_ int
|
||||||
}{}, false}, // gap
|
}{}, false}, // gap
|
||||||
{
|
{struct {
|
||||||
struct {
|
|
||||||
_ structs.Incomparable // if not last, zero-width
|
_ structs.Incomparable // if not last, zero-width
|
||||||
x int
|
x int
|
||||||
}{},
|
}{}, true},
|
||||||
true,
|
{struct {
|
||||||
},
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
x int
|
x int
|
||||||
_ structs.Incomparable // zero-width last: has space, can't memhash
|
_ structs.Incomparable // zero-width last: has space, can't memhash
|
||||||
}{},
|
}{},
|
||||||
false,
|
false},
|
||||||
}}
|
{[0]chan bool{}, true},
|
||||||
|
{struct{ f [0]func() }{}, true},
|
||||||
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
got := canMemHash(reflect.TypeOf(tt.val))
|
got := canMemHash(reflect.TypeOf(tt.val))
|
||||||
if got != tt.want {
|
if got != tt.want {
|
||||||
|
Loading…
Reference in New Issue
Block a user