|
@@ -1,6 +1,7 @@
|
|
|
package reflect
|
|
|
|
|
|
import (
|
|
|
+ "errors"
|
|
|
"fmt"
|
|
|
"reflect"
|
|
|
"strconv"
|
|
@@ -11,6 +12,10 @@ var (
|
|
|
allowTags = []string{"json", "yaml", "xml", "name"}
|
|
|
)
|
|
|
|
|
|
+var (
|
|
|
+ ErrValueAssociated = errors.New("value cannot be associated")
|
|
|
+)
|
|
|
+
|
|
|
func findField(v reflect.Value, field string) reflect.Value {
|
|
|
var (
|
|
|
pos int
|
|
@@ -64,7 +69,7 @@ func safeAssignment(variable reflect.Value, value interface{}) (err error) {
|
|
|
variable.SetInt(n)
|
|
|
}
|
|
|
default:
|
|
|
- err = fmt.Errorf("unsupported kind %s", rv.Kind())
|
|
|
+ err = fmt.Errorf("integer value can not assign %s", rv.Kind())
|
|
|
}
|
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
|
switch rv.Kind() {
|
|
@@ -79,7 +84,7 @@ func safeAssignment(variable reflect.Value, value interface{}) (err error) {
|
|
|
variable.SetUint(un)
|
|
|
}
|
|
|
default:
|
|
|
- err = fmt.Errorf("unsupported kind %s", rv.Kind())
|
|
|
+ err = fmt.Errorf("unsigned integer value can not assign %s", rv.Kind())
|
|
|
}
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
switch rv.Kind() {
|
|
@@ -94,7 +99,7 @@ func safeAssignment(variable reflect.Value, value interface{}) (err error) {
|
|
|
variable.SetFloat(fn)
|
|
|
}
|
|
|
default:
|
|
|
- err = fmt.Errorf("unsupported kind %s", rv.Kind())
|
|
|
+ err = fmt.Errorf("decimal value can not assign %s", rv.Kind())
|
|
|
}
|
|
|
case reflect.String:
|
|
|
switch rv.Kind() {
|
|
@@ -139,10 +144,30 @@ func Set(hacky interface{}, field string, value interface{}) (err error) {
|
|
|
}
|
|
|
switch fieldKind {
|
|
|
case reflect.Struct:
|
|
|
- switch rv.Kind() {
|
|
|
- case reflect.Map:
|
|
|
+ if rv.Kind() != reflect.Map {
|
|
|
+ return ErrValueAssociated
|
|
|
+ }
|
|
|
+ keys := rv.MapKeys()
|
|
|
+ subVal := reflect.New(refField.Type())
|
|
|
+ for _, key := range keys {
|
|
|
+ pv := rv.MapIndex(key)
|
|
|
+ if key.Kind() == reflect.String {
|
|
|
+ if err = Set(subVal.Interface(), key.String(), pv.Interface()); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ refField.Set(subVal.Elem())
|
|
|
+ case reflect.Ptr:
|
|
|
+ elemType := refField.Type()
|
|
|
+ if elemType.Elem().Kind() != reflect.Struct {
|
|
|
+ return ErrValueAssociated
|
|
|
+ } else {
|
|
|
+ if rv.Kind() != reflect.Map {
|
|
|
+ return ErrValueAssociated
|
|
|
+ }
|
|
|
keys := rv.MapKeys()
|
|
|
- subVal := reflect.New(refField.Type())
|
|
|
+ subVal := reflect.New(elemType.Elem())
|
|
|
for _, key := range keys {
|
|
|
pv := rv.MapIndex(key)
|
|
|
if key.Kind() == reflect.String {
|
|
@@ -151,46 +176,102 @@ func Set(hacky interface{}, field string, value interface{}) (err error) {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- refField.Set(subVal.Elem())
|
|
|
- default:
|
|
|
- err = fmt.Errorf("struct unsupported assign kind %s", rv.Kind())
|
|
|
+ refField.Set(subVal)
|
|
|
}
|
|
|
- case reflect.Ptr:
|
|
|
- elemType := refField.Type()
|
|
|
- if elemType.Elem().Kind() == reflect.Struct {
|
|
|
- switch rv.Kind() {
|
|
|
- case reflect.Map:
|
|
|
- keys := rv.MapKeys()
|
|
|
- subVal := reflect.New(elemType.Elem())
|
|
|
- for _, key := range keys {
|
|
|
- pv := rv.MapIndex(key)
|
|
|
- if key.Kind() == reflect.String {
|
|
|
- if err = Set(subVal.Interface(), key.String(), pv.Interface()); err != nil {
|
|
|
+ case reflect.Map:
|
|
|
+ if rv.Kind() != reflect.Map {
|
|
|
+ return ErrValueAssociated
|
|
|
+ }
|
|
|
+ targetValue := reflect.MakeMap(refField.Type())
|
|
|
+ keys := rv.MapKeys()
|
|
|
+ for _, key := range keys {
|
|
|
+ pv := rv.MapIndex(key)
|
|
|
+ kVal := reflect.New(refField.Type().Key())
|
|
|
+ eVal := reflect.New(refField.Type().Elem())
|
|
|
+ if err = safeAssignment(kVal.Elem(), key.Interface()); err != nil {
|
|
|
+ return ErrValueAssociated
|
|
|
+ }
|
|
|
+ if refField.Type().Elem().Kind() == reflect.Struct {
|
|
|
+ if pv.Elem().Kind() != reflect.Map {
|
|
|
+ return ErrValueAssociated
|
|
|
+ }
|
|
|
+ subKeys := pv.Elem().MapKeys()
|
|
|
+ for _, subKey := range subKeys {
|
|
|
+ subVal := pv.Elem().MapIndex(subKey)
|
|
|
+ if subKey.Kind() == reflect.String {
|
|
|
+ if err = Set(eVal.Interface(), subKey.String(), subVal.Interface()); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- refField.Set(subVal)
|
|
|
- default:
|
|
|
- err = fmt.Errorf("struct unsupported assign kind %s", rv.Kind())
|
|
|
+ targetValue.SetMapIndex(kVal.Elem(), eVal.Elem())
|
|
|
+ } else {
|
|
|
+ if err = safeAssignment(eVal.Elem(), pv.Interface()); err != nil {
|
|
|
+ return ErrValueAssociated
|
|
|
+ }
|
|
|
+ targetValue.SetMapIndex(kVal.Elem(), eVal.Elem())
|
|
|
}
|
|
|
- } else {
|
|
|
- err = fmt.Errorf("ptr can't set kind %s", elemType.Elem().Kind())
|
|
|
}
|
|
|
+ refField.Set(targetValue)
|
|
|
case reflect.Array, reflect.Slice:
|
|
|
+ n = 0
|
|
|
innerType := refField.Type().Elem()
|
|
|
if rv.Kind() == reflect.Array || rv.Kind() == reflect.Slice {
|
|
|
- sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
|
|
|
- n = 0
|
|
|
- for i := 0; i < rv.Len(); i++ {
|
|
|
- srcVal := rv.Index(i)
|
|
|
- dstVal := reflect.New(innerType).Elem()
|
|
|
- if err = safeAssignment(dstVal, srcVal); err == nil {
|
|
|
+ if innerType.Kind() == reflect.Struct {
|
|
|
+ sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
|
|
|
+ for i := 0; i < rv.Len(); i++ {
|
|
|
+ srcVal := rv.Index(i)
|
|
|
+ if srcVal.Kind() != reflect.Map {
|
|
|
+ return ErrValueAssociated
|
|
|
+ }
|
|
|
+ dstVal := reflect.New(innerType)
|
|
|
+ keys := srcVal.MapKeys()
|
|
|
+ for _, key := range keys {
|
|
|
+ kv := srcVal.MapIndex(key)
|
|
|
+ if key.Kind() == reflect.String {
|
|
|
+ if err = Set(dstVal.Interface(), key.String(), kv.Interface()); err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sliceVar.Index(n).Set(dstVal.Elem())
|
|
|
+ n++
|
|
|
+ }
|
|
|
+ refField.Set(sliceVar.Slice(0, n))
|
|
|
+ } else if innerType.Kind() == reflect.Ptr {
|
|
|
+ sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
|
|
|
+ for i := 0; i < rv.Len(); i++ {
|
|
|
+ srcVal := rv.Index(i)
|
|
|
+ if srcVal.Kind() != reflect.Map {
|
|
|
+ return ErrValueAssociated
|
|
|
+ }
|
|
|
+ dstVal := reflect.New(innerType.Elem())
|
|
|
+ keys := srcVal.MapKeys()
|
|
|
+ for _, key := range keys {
|
|
|
+ kv := srcVal.MapIndex(key)
|
|
|
+ if key.Kind() == reflect.String {
|
|
|
+ if err = Set(dstVal.Interface(), key.String(), kv.Interface()); err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sliceVar.Index(n).Set(dstVal)
|
|
|
+ n++
|
|
|
+ }
|
|
|
+ refField.Set(sliceVar.Slice(0, n))
|
|
|
+ } else {
|
|
|
+ sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
|
|
|
+ for i := 0; i < rv.Len(); i++ {
|
|
|
+ srcVal := rv.Index(i)
|
|
|
+ dstVal := reflect.New(innerType).Elem()
|
|
|
+ if err = safeAssignment(dstVal, srcVal.Interface()); err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
sliceVar.Index(n).Set(dstVal)
|
|
|
n++
|
|
|
}
|
|
|
+ refField.Set(sliceVar.Slice(0, n))
|
|
|
}
|
|
|
- refField.Set(sliceVar.Slice(0, n))
|
|
|
}
|
|
|
default:
|
|
|
err = safeAssignment(refField, value)
|