Allow properties to have unsettable int and uint fields

Allow properties structs to contain exported int and uint fields,
but only if they are tagged with blueprint:"mutated".  These fields
will be copied by CopyProperties in order to propagate through
cloning during mutations, but can only be set by Mutators and not
by Blueprint files.

Change-Id: Ic462385799c77667e392f4928d02d424c8f8d900
This commit is contained in:
Colin Cross 2014-12-17 16:46:09 -08:00
parent bbfa51a229
commit 11a114f454
2 changed files with 30 additions and 3 deletions

View file

@ -40,7 +40,7 @@ func CopyProperties(dstValue, srcValue reflect.Value) {
dstFieldValue := dstValue.Field(i)
switch srcFieldValue.Kind() {
case reflect.Bool, reflect.String:
case reflect.Bool, reflect.String, reflect.Int, reflect.Uint:
dstFieldValue.Set(srcFieldValue)
case reflect.Struct:
CopyProperties(dstFieldValue, srcFieldValue)
@ -104,7 +104,7 @@ func ZeroProperties(structValue reflect.Value) {
fieldValue := structValue.Field(i)
switch fieldValue.Kind() {
case reflect.Bool, reflect.String, reflect.Struct, reflect.Slice:
case reflect.Bool, reflect.String, reflect.Struct, reflect.Slice, reflect.Int, reflect.Uint:
fieldValue.Set(reflect.Zero(fieldValue.Type()))
case reflect.Ptr, reflect.Interface:
if !fieldValue.IsNil() {

View file

@ -5,6 +5,7 @@ import (
"blueprint/proptools"
"fmt"
"reflect"
"strings"
)
type packedProperty struct {
@ -154,6 +155,11 @@ func unpackStructValue(namePrefix string, structValue reflect.Value,
panic(fmt.Errorf("field %s contains a non-struct pointer",
field.Name))
}
case reflect.Int, reflect.Uint:
if !hasTag(field, "blueprint", "mutated") {
panic(fmt.Errorf(`int field %s must be tagged blueprint:"mutated"`, field.Name))
}
default:
panic(fmt.Errorf("unsupported kind for field %s: %s",
field.Name, kind))
@ -167,9 +173,19 @@ func unpackStructValue(namePrefix string, structValue reflect.Value,
continue
}
var newErrs []error
if hasTag(field, "blueprint", "mutated") {
errs = append(errs,
fmt.Errorf("mutated field %s cannot be set in a Blueprint file", propertyName))
if len(errs) >= maxErrors {
return errs
}
continue
}
packedProperty.unpacked = true
var newErrs []error
switch kind := fieldValue.Kind(); kind {
case reflect.Bool:
newErrs = unpackBool(fieldValue, packedProperty.property)
@ -261,3 +277,14 @@ func unpackStruct(namePrefix string, structValue reflect.Value,
return unpackStructValue(namePrefix, structValue, propertyMap)
}
func hasTag(field reflect.StructField, name, value string) bool {
tag := field.Tag.Get(name)
for _, entry := range strings.Split(tag, ",") {
if entry == value {
return true
}
}
return false
}