mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-05 04:11:59 +00:00
util/deephash: add canMemHash func + typeInfo property
Currently unused. (breaking up a bigger change) Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
7b9a901489
commit
35782f891d
@@ -180,6 +180,7 @@ var uint8Type = reflect.TypeOf(byte(0))
|
||||
// typeInfo describes properties of a type.
|
||||
type typeInfo struct {
|
||||
rtype reflect.Type
|
||||
canMemHash bool
|
||||
isRecursive bool
|
||||
|
||||
// elemTypeInfo is the element type's typeInfo.
|
||||
@@ -218,6 +219,7 @@ func getTypeInfoLocked(t reflect.Type, incomplete map[reflect.Type]*typeInfo) *t
|
||||
ti := &typeInfo{
|
||||
rtype: t,
|
||||
isRecursive: typeIsRecursive(t),
|
||||
canMemHash: canMemHash(t),
|
||||
}
|
||||
incomplete[t] = ti
|
||||
|
||||
@@ -311,6 +313,34 @@ func typeIsRecursive(t reflect.Type) bool {
|
||||
return visitType(t)
|
||||
}
|
||||
|
||||
// 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)
|
||||
func canMemHash(t reflect.Type) bool {
|
||||
switch t.Kind() {
|
||||
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float64, reflect.Float32, reflect.Complex128, reflect.Complex64:
|
||||
return true
|
||||
case reflect.Array:
|
||||
return canMemHash(t.Elem())
|
||||
case reflect.Struct:
|
||||
var sumFieldSize uintptr
|
||||
for i, numField := 0, t.NumField(); i < numField; i++ {
|
||||
sf := t.Field(i)
|
||||
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
|
||||
}
|
||||
sumFieldSize += sf.Type.Size()
|
||||
}
|
||||
return sumFieldSize == t.Size() // else there are gaps
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *hasher) hashValue(v reflect.Value, forceCycleChecking bool) {
|
||||
if !v.IsValid() {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user