Add isStruct and isStructPtr helpers
Test: proptools tests
Change-Id: I7814b2138cd19b538a3a33036a15119e118d7644
diff --git a/proptools/clone.go b/proptools/clone.go
index fe4e115..1de432b 100644
--- a/proptools/clone.go
+++ b/proptools/clone.go
@@ -67,13 +67,9 @@
srcFieldValue = srcFieldValue.Elem()
- if srcFieldValue.Kind() != reflect.Ptr {
- panic(fmt.Errorf("can't clone field %q: interface refers to a non-pointer",
- field.Name))
- }
- if srcFieldValue.Type().Elem().Kind() != reflect.Struct {
- panic(fmt.Errorf("can't clone field %q: interface points to a non-struct",
- field.Name))
+ if !isStructPtr(srcFieldValue.Type()) {
+ panic(fmt.Errorf("can't clone field %q: expected interface to contain *struct, found %s",
+ field.Name, srcFieldValue.Type()))
}
if dstFieldValue.IsNil() || dstFieldValue.Elem().Type() != srcFieldValue.Type() {
@@ -146,13 +142,9 @@
// We leave the pointer intact and zero out the struct that's
// pointed to.
fieldValue = fieldValue.Elem()
- if fieldValue.Kind() != reflect.Ptr {
- panic(fmt.Errorf("can't zero field %q: interface refers to a non-pointer",
- field.Name))
- }
- if fieldValue.Type().Elem().Kind() != reflect.Struct {
- panic(fmt.Errorf("can't zero field %q: interface points to a non-struct",
- field.Name))
+ if !isStructPtr(fieldValue.Type()) {
+ panic(fmt.Errorf("can't zero field %q: expected interface to contain *struct, found %s",
+ field.Name, fieldValue.Type()))
}
fallthrough
case reflect.Ptr:
@@ -206,13 +198,9 @@
}
srcFieldValue = srcFieldValue.Elem()
- if srcFieldValue.Kind() != reflect.Ptr {
- panic(fmt.Errorf("can't clone empty field %q: interface refers to a non-pointer",
- field.Name))
- }
- if srcFieldValue.Type().Elem().Kind() != reflect.Struct {
- panic(fmt.Errorf("can't clone empty field %q: interface points to a non-struct",
- field.Name))
+ if !isStructPtr(srcFieldValue.Type()) {
+ panic(fmt.Errorf("can't clone empty field %q: expected interface to contain *struct, found %s",
+ field.Name, srcFieldValue.Type()))
}
newValue := reflect.New(srcFieldValue.Type()).Elem()
diff --git a/proptools/extend.go b/proptools/extend.go
index b0c7459..d3c2b79 100644
--- a/proptools/extend.go
+++ b/proptools/extend.go
@@ -274,7 +274,7 @@
}
// Step into source pointers to structs
- if srcFieldValue.Kind() == reflect.Ptr && srcFieldValue.Type().Elem().Kind() == reflect.Struct {
+ if isStructPtr(srcFieldValue.Type()) {
if srcFieldValue.IsNil() {
continue
}
@@ -323,7 +323,7 @@
}
// Step into destination pointers to structs
- if dstFieldValue.Kind() == reflect.Ptr && dstFieldValue.Type().Elem().Kind() == reflect.Struct {
+ if isStructPtr(dstFieldValue.Type()) {
if dstFieldValue.IsNil() {
dstFieldValue = reflect.New(dstFieldValue.Type().Elem())
origDstFieldValue.Set(dstFieldValue)
@@ -501,11 +501,8 @@
func getStruct(in interface{}) (reflect.Value, error) {
value := reflect.ValueOf(in)
- if value.Kind() != reflect.Ptr {
- return reflect.Value{}, fmt.Errorf("expected pointer to struct, got %T", in)
- }
- if value.Type().Elem().Kind() != reflect.Struct {
- return reflect.Value{}, fmt.Errorf("expected pointer to struct, got %T", in)
+ if !isStructPtr(value.Type()) {
+ return reflect.Value{}, fmt.Errorf("expected pointer to struct, got %s", value.Type())
}
if value.IsNil() {
return reflect.Value{}, getStructEmptyError{}
diff --git a/proptools/filter.go b/proptools/filter.go
index 59eca5a..e6b3336 100644
--- a/proptools/filter.go
+++ b/proptools/filter.go
@@ -50,8 +50,7 @@
if maxTypeNameSize > 0 && structNameSize+fieldTypeNameSize > maxTypeNameSize {
if len(filteredFields) == 0 {
- if field.Type.Kind() == reflect.Struct ||
- field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
+ if isStruct(field.Type) || isStructPtr(field.Type) {
// An error fitting the nested struct should have been caught when recursing
// into the nested struct.
panic(fmt.Errorf("Shouldn't happen: can't fit nested struct %q (%d) into %d",
@@ -82,12 +81,12 @@
}
ptrToStruct := false
- if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
+ if isStructPtr(field.Type) {
ptrToStruct = true
}
// Recurse into structs
- if ptrToStruct || field.Type.Kind() == reflect.Struct {
+ if ptrToStruct || isStruct(field.Type) {
subMaxTypeNameSize := maxTypeNameSize
if maxTypeNameSize > 0 {
// In the worst case where only this nested struct will fit in the outer struct, the
diff --git a/proptools/proptools.go b/proptools/proptools.go
index 6881828..b91c92a 100644
--- a/proptools/proptools.go
+++ b/proptools/proptools.go
@@ -15,6 +15,7 @@
package proptools
import (
+ "reflect"
"unicode"
"unicode/utf8"
)
@@ -97,3 +98,11 @@
func Int(i *int64) int {
return IntDefault(i, 0)
}
+
+func isStruct(t reflect.Type) bool {
+ return t.Kind() == reflect.Struct
+}
+
+func isStructPtr(t reflect.Type) bool {
+ return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
+}
diff --git a/proptools/tag.go b/proptools/tag.go
index af5b97e..d69853a 100644
--- a/proptools/tag.go
+++ b/proptools/tag.go
@@ -36,7 +36,7 @@
// are tagged with the given key and value, including ones found in embedded structs or pointers to structs.
func PropertyIndexesWithTag(ps interface{}, key, value string) [][]int {
t := reflect.TypeOf(ps)
- if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
+ if !isStructPtr(t) {
panic(fmt.Errorf("type %s is not a pointer to a struct", t))
}
t = t.Elem()
@@ -49,7 +49,7 @@
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
ft := field.Type
- if ft.Kind() == reflect.Struct || (ft.Kind() == reflect.Ptr && ft.Elem().Kind() == reflect.Struct) {
+ if isStruct(ft) || isStructPtr(ft) {
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
}
diff --git a/proptools/unpack.go b/proptools/unpack.go
index e7d4fff..344327f 100644
--- a/proptools/unpack.go
+++ b/proptools/unpack.go
@@ -49,14 +49,11 @@
for _, properties := range propertiesStructs {
propertiesValue := reflect.ValueOf(properties)
- if propertiesValue.Kind() != reflect.Ptr {
- panic("properties must be a pointer to a struct")
+ if !isStructPtr(propertiesValue.Type()) {
+ panic(fmt.Errorf("properties must be *struct, got %s",
+ propertiesValue.Type()))
}
-
propertiesValue = propertiesValue.Elem()
- if propertiesValue.Kind() != reflect.Struct {
- panic("properties must be a pointer to a struct")
- }
newErrs := unpackStructValue("", propertiesValue, propertyMap)
errs = append(errs, newErrs...)
@@ -212,7 +209,7 @@
panic(fmt.Errorf("unsupported kind for field %s: %s", propertyName, kind))
}
- if field.Anonymous && fieldValue.Kind() == reflect.Struct {
+ if field.Anonymous && isStruct(fieldValue.Type()) {
newErrs := unpackStructValue(namePrefix, fieldValue, propertyMap)
errs = append(errs, newErrs...)
continue
@@ -239,7 +236,7 @@
var newErrs []error
- if fieldValue.Kind() == reflect.Struct {
+ if isStruct(fieldValue.Type()) {
newErrs = unpackStruct(propertyName+".", fieldValue,
packedProperty.property, propertyMap)