Updates mitchellh/copystructure, mitchellh/mapstructure, and mitchellh/reflectwalk.

This commit is contained in:
James Phillips 2016-08-09 17:34:07 -07:00
parent 33ea18fb21
commit ce206323bb
No known key found for this signature in database
GPG Key ID: 77183E682AC5FC11
5 changed files with 76 additions and 29 deletions

View File

@ -95,8 +95,10 @@ func (w *walker) Exit(l reflectwalk.Location) error {
if v.IsValid() { if v.IsValid() {
s := w.cs[len(w.cs)-1] s := w.cs[len(w.cs)-1]
sf := reflect.Indirect(s).FieldByName(f.Name) sf := reflect.Indirect(s).FieldByName(f.Name)
if sf.CanSet() {
sf.Set(v) sf.Set(v)
} }
}
case reflectwalk.WalkLoc: case reflectwalk.WalkLoc:
// Clear out the slices for GC // Clear out the slices for GC
w.cs = nil w.cs = nil
@ -111,16 +113,12 @@ func (w *walker) Map(m reflect.Value) error {
return nil return nil
} }
// Get the type for the map
t := m.Type()
mapType := reflect.MapOf(t.Key(), t.Elem())
// Create the map. If the map itself is nil, then just make a nil map // Create the map. If the map itself is nil, then just make a nil map
var newMap reflect.Value var newMap reflect.Value
if m.IsNil() { if m.IsNil() {
newMap = reflect.Indirect(reflect.New(mapType)) newMap = reflect.Indirect(reflect.New(m.Type()))
} else { } else {
newMap = reflect.MakeMap(reflect.MapOf(t.Key(), t.Elem())) newMap = reflect.MakeMap(m.Type())
} }
w.cs = append(w.cs, newMap) w.cs = append(w.cs, newMap)
@ -155,8 +153,10 @@ func (w *walker) Primitive(v reflect.Value) error {
return nil return nil
} }
// IsValid verifies the v is non-zero and CanInterface verifies
// that we're allowed to read this value (unexported fields).
var newV reflect.Value var newV reflect.Value
if v.IsValid() { if v.IsValid() && v.CanInterface() {
newV = reflect.New(v.Type()) newV = reflect.New(v.Type())
reflect.Indirect(newV).Set(v) reflect.Indirect(newV).Set(v)
} }

View File

@ -1,7 +0,0 @@
language: go
go:
- 1.4
script:
- go test

View File

@ -72,7 +72,10 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
} }
// Modify the from kind to be correct with the new data // Modify the from kind to be correct with the new data
f = reflect.ValueOf(data).Type() f = nil
if val := reflect.ValueOf(data); val.IsValid() {
f = val.Type()
}
} }
return data, nil return data, nil

View File

@ -8,6 +8,7 @@
package mapstructure package mapstructure
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"reflect" "reflect"
@ -67,6 +68,7 @@ type DecoderConfig struct {
// FALSE, false, False. Anything else is an error) // FALSE, false, False. Anything else is an error)
// - empty array = empty map and vice versa // - empty array = empty map and vice versa
// - negative numbers to overflowed uint values (base 10) // - negative numbers to overflowed uint values (base 10)
// - slice of maps to a merged map
// //
WeaklyTypedInput bool WeaklyTypedInput bool
@ -245,6 +247,10 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
// value to "data" of that type. // value to "data" of that type.
func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
dataVal := reflect.ValueOf(data) dataVal := reflect.ValueOf(data)
if !dataVal.IsValid() {
dataVal = reflect.Zero(val.Type())
}
dataValType := dataVal.Type() dataValType := dataVal.Type()
if !dataValType.AssignableTo(val.Type()) { if !dataValType.AssignableTo(val.Type()) {
return fmt.Errorf( return fmt.Errorf(
@ -301,6 +307,7 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
dataVal := reflect.ValueOf(data) dataVal := reflect.ValueOf(data)
dataKind := getKind(dataVal) dataKind := getKind(dataVal)
dataType := dataVal.Type()
switch { switch {
case dataKind == reflect.Int: case dataKind == reflect.Int:
@ -322,6 +329,14 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
} else { } else {
return fmt.Errorf("cannot parse '%s' as int: %s", name, err) return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
} }
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
jn := data.(json.Number)
i, err := jn.Int64()
if err != nil {
return fmt.Errorf(
"error decoding json.Number into %s: %s", name, err)
}
val.SetInt(i)
default: default:
return fmt.Errorf( return fmt.Errorf(
"'%s' expected type '%s', got unconvertible type '%s'", "'%s' expected type '%s', got unconvertible type '%s'",
@ -408,6 +423,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
dataVal := reflect.ValueOf(data) dataVal := reflect.ValueOf(data)
dataKind := getKind(dataVal) dataKind := getKind(dataVal)
dataType := dataVal.Type()
switch { switch {
case dataKind == reflect.Int: case dataKind == reflect.Int:
@ -429,6 +445,14 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
} else { } else {
return fmt.Errorf("cannot parse '%s' as float: %s", name, err) return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
} }
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
jn := data.(json.Number)
i, err := jn.Float64()
if err != nil {
return fmt.Errorf(
"error decoding json.Number into %s: %s", name, err)
}
val.SetFloat(i)
default: default:
return fmt.Errorf( return fmt.Errorf(
"'%s' expected type '%s', got unconvertible type '%s'", "'%s' expected type '%s', got unconvertible type '%s'",
@ -456,15 +480,30 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er
// Check input type // Check input type
dataVal := reflect.Indirect(reflect.ValueOf(data)) dataVal := reflect.Indirect(reflect.ValueOf(data))
if dataVal.Kind() != reflect.Map { if dataVal.Kind() != reflect.Map {
// Accept empty array/slice instead of an empty map in weakly typed mode // In weak mode, we accept a slice of maps as an input...
if d.config.WeaklyTypedInput && if d.config.WeaklyTypedInput {
(dataVal.Kind() == reflect.Slice || dataVal.Kind() == reflect.Array) && switch dataVal.Kind() {
dataVal.Len() == 0 { case reflect.Array, reflect.Slice:
// Special case for BC reasons (covered by tests)
if dataVal.Len() == 0 {
val.Set(valMap) val.Set(valMap)
return nil return nil
} else {
return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
} }
for i := 0; i < dataVal.Len(); i++ {
err := d.decode(
fmt.Sprintf("%s[%d]", name, i),
dataVal.Index(i).Interface(), val)
if err != nil {
return err
}
}
return nil
}
}
return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
} }
// Accumulate errors // Accumulate errors
@ -607,11 +646,12 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
structs = structs[1:] structs = structs[1:]
structType := structVal.Type() structType := structVal.Type()
for i := 0; i < structType.NumField(); i++ { for i := 0; i < structType.NumField(); i++ {
fieldType := structType.Field(i) fieldType := structType.Field(i)
fieldKind := fieldType.Type.Kind()
if fieldType.Anonymous { if fieldType.Anonymous {
fieldKind := fieldType.Type.Kind()
if fieldKind != reflect.Struct { if fieldKind != reflect.Struct {
errors = appendErrors(errors, errors = appendErrors(errors,
fmt.Errorf("%s: unsupported type: %s", fieldType.Name, fieldKind)) fmt.Errorf("%s: unsupported type: %s", fieldType.Name, fieldKind))
@ -630,7 +670,12 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
} }
if squash { if squash {
if fieldKind != reflect.Struct {
errors = appendErrors(errors,
fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind))
} else {
structs = append(structs, val.FieldByName(fieldType.Name)) structs = append(structs, val.FieldByName(fieldType.Name))
}
continue continue
} }

12
vendor/vendor.json vendored
View File

@ -438,16 +438,22 @@
"revisionTime": "2016-03-23T17:07:00Z" "revisionTime": "2016-03-23T17:07:00Z"
}, },
{ {
"checksumSHA1": "86nE93o1VIND0Doe8PuhCXnhUx0=",
"path": "github.com/mitchellh/copystructure", "path": "github.com/mitchellh/copystructure",
"revision": "6fc66267e9da7d155a9d3bd489e00dad02666dc6" "revision": "cdac8253d00f2ecf0a0b19fbff173a9a72de4f82",
"revisionTime": "2016-08-04T03:23:30Z"
}, },
{ {
"checksumSHA1": "LUrnGREfnifW4WDMaavmc9MlLI0=",
"path": "github.com/mitchellh/mapstructure", "path": "github.com/mitchellh/mapstructure",
"revision": "281073eb9eb092240d33ef253c404f1cca550309" "revision": "ca63d7c062ee3c9f34db231e352b60012b4fd0c1",
"revisionTime": "2016-08-08T18:12:53Z"
}, },
{ {
"checksumSHA1": "mrqMlK6gqe//WsJSrJ1HgkPM0lM=",
"path": "github.com/mitchellh/reflectwalk", "path": "github.com/mitchellh/reflectwalk",
"revision": "eecf4c70c626c7cfbb95c90195bc34d386c74ac6" "revision": "eecf4c70c626c7cfbb95c90195bc34d386c74ac6",
"revisionTime": "2015-05-27T15:31:53Z"
}, },
{ {
"checksumSHA1": "3AoPMXlmVq2+iWMpsdJZkcUKHB8=", "checksumSHA1": "3AoPMXlmVq2+iWMpsdJZkcUKHB8=",