diff options
author | Ben Clayton <bclayton@google.com> | 2015-08-04 14:37:48 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2015-08-04 14:37:48 +0000 |
commit | 5a3e60cecae46ea74dc7ecf365927480dbf9a831 (patch) | |
tree | 3582e25313048af2795633b8f68609d0297112ce | |
parent | 1824dfeb2b854854feb259c8d0f293b8c1906f14 (diff) | |
parent | 73dbd04b293d46be9f2bb589b08aa4697a788cc3 (diff) | |
download | gpu-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.go | 18 | ||||
-rw-r--r-- | builder/resolve.go | 17 | ||||
-rw-r--r-- | builder/set.go | 36 |
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: |