aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Clayton <bclayton@google.com>2015-08-04 14:37:48 +0000
committerandroid-build-merger <android-build-merger@google.com>2015-08-04 14:37:48 +0000
commit5a3e60cecae46ea74dc7ecf365927480dbf9a831 (patch)
tree3582e25313048af2795633b8f68609d0297112ce
parent1824dfeb2b854854feb259c8d0f293b8c1906f14 (diff)
parent73dbd04b293d46be9f2bb589b08aa4697a788cc3 (diff)
downloadgpu-5a3e60cecae46ea74dc7ecf365927480dbf9a831.tar.gz
Merge "Fix resolving of slices / arrays / maps where keys need converting." into studio-1.4-dev
automerge: 73dbd04 * commit '73dbd04b293d46be9f2bb589b08aa4697a788cc3': Fix resolving of slices / arrays / maps where keys need converting.
-rw-r--r--builder/get_set_test.go18
-rw-r--r--builder/resolve.go17
-rw-r--r--builder/set.go36
3 files changed, 57 insertions, 14 deletions
diff --git a/builder/get_set_test.go b/builder/get_set_test.go
index 42c23ad3f..c27a946a0 100644
--- a/builder/get_set_test.go
+++ b/builder/get_set_test.go
@@ -103,6 +103,7 @@ func TestGet(t *testing.T) {
{p.Atoms().Index(1).Field("Str").ArrayIndex(1), byte('y'), nil},
{p.Atoms().Index(1).Field("Str").Slice(1, 3), "yz", nil},
{p.Atoms().Index(1).Field("Map").MapIndex("bird"), "tweet", nil},
+ {p.Atoms().Index(1).Field("Map").MapIndex([]rune("bird")), "tweet", nil},
// Test invalid paths
{p.Atoms().Index(5), nil, fmt.Errorf(
@@ -125,8 +126,8 @@ func TestGet(t *testing.T) {
"Index at Capture(%v).Atoms[1].Str[4] is out of bounds [0-2]", p.ID)},
{p.Atoms().Index(1).Field("Ptr").ArrayIndex(4), nil, fmt.Errorf(
"Type *builder.testStruct at Capture(%v).Atoms[1].Ptr is not an array, slice or string", p.ID)},
- {p.Atoms().Index(1).Field("Map").MapIndex(10), nil, fmt.Errorf(
- "Map at Capture(%v).Atoms[1].Map has key of type string, got type int", p.ID)},
+ {p.Atoms().Index(1).Field("Map").MapIndex(10.0), nil, fmt.Errorf(
+ "Map at Capture(%v).Atoms[1].Map has key of type string, got type float64", p.ID)},
{p.Atoms().Index(1).Field("Map").MapIndex("rabbit"), nil, fmt.Errorf(
"Map at Capture(%v).Atoms[1].Map does not contain key rabbit", p.ID)},
{p.Atoms().Index(1).Field("Ptr").MapIndex("foo"), nil, fmt.Errorf(
@@ -155,6 +156,9 @@ func TestGet(t *testing.T) {
{path: p.Atoms().Index(0).Field("Any"), val: 0.123},
{path: p.Atoms().Index(0).Field("Ptr"), val: &testStruct{Str: "ddd"}},
{path: p.Atoms().Index(0).Field("Ptr").Field("Str"), val: "purr"},
+ {path: p.Atoms().Index(1).Field("Sli").ArrayIndex(1), val: false},
+ {path: p.Atoms().Index(1).Field("Map").MapIndex("bird"), val: "churp"},
+ {path: p.Atoms().Index(1).Field("Map").MapIndex([]rune("bird")), val: "churp"},
// Test invalid paths
{p.Atoms().Index(5), nil, fmt.Errorf(
@@ -175,12 +179,18 @@ func TestGet(t *testing.T) {
"Index at Capture(%v).Atoms[1].Str[4] is out of bounds [0-2]", p.ID)},
{p.Atoms().Index(1).Field("Ptr").ArrayIndex(4), nil, fmt.Errorf(
"Type *builder.testStruct at Capture(%v).Atoms[1].Ptr is not an array, slice or string", p.ID)},
- {p.Atoms().Index(1).Field("Map").MapIndex(10), nil, fmt.Errorf(
- "Map at Capture(%v).Atoms[1].Map has key of type string, got type int", p.ID)},
+ {p.Atoms().Index(1).Field("Map").MapIndex(10.0), nil, fmt.Errorf(
+ "Map at Capture(%v).Atoms[1].Map has key of type string, got type float64", p.ID)},
{p.Atoms().Index(1).Field("Map").MapIndex("rabbit"), nil, fmt.Errorf(
"Map at Capture(%v).Atoms[1].Map does not contain key rabbit", p.ID)},
{p.Atoms().Index(1).Field("Ptr").MapIndex("foo"), nil, fmt.Errorf(
"Type *builder.testStruct at Capture(%v).Atoms[1].Ptr is not a map", p.ID)},
+
+ // Test invalid sets
+ {p.Atoms().Index(1).Field("Sli").ArrayIndex(2), "blah", fmt.Errorf(
+ "Slice or array at Capture(%v).Atoms[1].Sli has element of type bool, got type string", p.ID)},
+ {p.Atoms().Index(1).Field("Map").MapIndex("bird"), 10.0, fmt.Errorf(
+ "Map at Capture(%v).Atoms[1].Map has value of type string, got type float64", p.ID)},
} {
res, err := database.Build(&Set{Path: test.path, Value: test.val}, d, l)
if expected := test.err; !reflect.DeepEqual(err, expected) {
diff --git a/builder/resolve.go b/builder/resolve.go
index 16613a35a..aaea59152 100644
--- a/builder/resolve.go
+++ b/builder/resolve.go
@@ -215,12 +215,12 @@ func resolveChain(paths []path.Path, d database.Database, l log.Logger) ([]inter
m := reflect.ValueOf(v[i-1])
switch m.Kind() {
case reflect.Map:
- key := reflect.ValueOf(p.Key)
- if key.Type() != m.Type().Key() {
+ key, ok := convert(reflect.ValueOf(p.Key), m.Type().Key())
+ if !ok {
return nil, fmt.Errorf("Map at %s has key of type %v, got type %v",
paths[i-1].Path(), m.Type().Key(), key.Type())
}
- val := m.MapIndex(reflect.ValueOf(p.Key))
+ val := m.MapIndex(key)
if !val.IsValid() {
return nil, fmt.Errorf("Map at %s does not contain key %v",
paths[i-1].Path(), p.Key)
@@ -239,3 +239,14 @@ func resolveChain(paths []path.Path, d database.Database, l log.Logger) ([]inter
return v, nil
}
+
+func convert(val reflect.Value, ty reflect.Type) (reflect.Value, bool) {
+ if valTy := val.Type(); valTy != ty {
+ if valTy.ConvertibleTo(ty) {
+ val = val.Convert(ty)
+ } else {
+ return val, false
+ }
+ }
+ return val, true
+}
diff --git a/builder/set.go b/builder/set.go
index 3bbf6c702..092b5f1d6 100644
--- a/builder/set.go
+++ b/builder/set.go
@@ -29,8 +29,8 @@ import (
// with the object, value or memory at p replaced with v. The path returned is
// identical to p, but with the base changed to refer to the new capture.
func (request *Set) BuildLazy(c interface{}, d database.Database, l log.Logger) (interface{}, error) {
- p := path.Flatten(request.Path)
- v, err := resolveChain(p, d, l)
+ paths := path.Flatten(request.Path)
+ v, err := resolveChain(paths, d, l)
if err != nil {
return nil, err
}
@@ -40,7 +40,7 @@ func (request *Set) BuildLazy(c interface{}, d database.Database, l log.Logger)
// Propagate changes back down to the root
for i := len(v) - 1; i >= 0; i-- {
- switch p := p[i].(type) {
+ switch p := paths[i].(type) {
case *path.Capture:
id, err := database.Store(v[i], d, l)
if err != nil {
@@ -101,6 +101,11 @@ func (request *Set) BuildLazy(c interface{}, d database.Database, l log.Logger)
if err != nil {
return nil, err
}
+ val, ok := convert(reflect.ValueOf(v[i]), a.Type().Elem())
+ if !ok {
+ return nil, fmt.Errorf("Slice or array at %s has element of type %v, got type %v",
+ paths[i-1].Path(), a.Type().Elem(), val.Type())
+ }
if err := assign(a.Index(int(p.Index)), reflect.ValueOf(v[i])); err != nil {
return nil, err
}
@@ -111,9 +116,17 @@ func (request *Set) BuildLazy(c interface{}, d database.Database, l log.Logger)
if err != nil {
return nil, err
}
- if err := assign(m.MapIndex(reflect.ValueOf(p.Key)), reflect.ValueOf(v[i])); err != nil {
- return nil, err
+ key, ok := convert(reflect.ValueOf(p.Key), m.Type().Key())
+ if !ok {
+ return nil, fmt.Errorf("Map at %s has key of type %v, got type %v",
+ paths[i-1].Path(), m.Type().Key(), key.Type())
+ }
+ val, ok := convert(reflect.ValueOf(v[i]), m.Type().Elem())
+ if !ok {
+ return nil, fmt.Errorf("Map at %s has value of type %v, got type %v",
+ paths[i-1].Path(), m.Type().Elem(), val.Type())
}
+ m.SetMapIndex(key, val)
v[i-1] = m.Interface()
default:
@@ -125,7 +138,15 @@ func (request *Set) BuildLazy(c interface{}, d database.Database, l log.Logger)
}
func clone(v reflect.Value) (reflect.Value, error) {
- o := reflect.New(v.Type()).Elem()
+ var o reflect.Value
+ switch v.Kind() {
+ case reflect.Slice:
+ o = reflect.MakeSlice(v.Type(), v.Len(), v.Len())
+ case reflect.Map:
+ o = reflect.MakeMap(v.Type())
+ default:
+ o = reflect.New(v.Type()).Elem()
+ }
return o, shallowCopy(o, v)
}
@@ -143,7 +164,8 @@ func shallowCopy(dst, src reflect.Value) error {
case reflect.Map:
for _, k := range src.MapKeys() {
- dst.SetMapIndex(k, src.MapIndex(k))
+ val := src.MapIndex(k)
+ dst.SetMapIndex(k, val)
}
default: