|
|
@@ -122,149 +122,55 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-// unpack sets the unmarshalled value to go format.
|
|
|
-// Note the dst here must be settable.
|
|
|
-func unpack(t *Type, dst interface{}, src interface{}) error {
|
|
|
- var (
|
|
|
- dstVal = reflect.ValueOf(dst).Elem()
|
|
|
- srcVal = reflect.ValueOf(src)
|
|
|
- )
|
|
|
- tuple, typ := false, t
|
|
|
- for {
|
|
|
- if typ.T == SliceTy || typ.T == ArrayTy {
|
|
|
- typ = typ.Elem
|
|
|
- continue
|
|
|
- }
|
|
|
- tuple = typ.T == TupleTy
|
|
|
- break
|
|
|
- }
|
|
|
- if !tuple {
|
|
|
- return set(dstVal, srcVal)
|
|
|
- }
|
|
|
-
|
|
|
- // Dereferences interface or pointer wrapper
|
|
|
- dstVal = indirectInterfaceOrPtr(dstVal)
|
|
|
-
|
|
|
- switch t.T {
|
|
|
- case TupleTy:
|
|
|
- if dstVal.Kind() != reflect.Struct {
|
|
|
- return fmt.Errorf("abi: invalid dst value for unpack, want struct, got %s", dstVal.Kind())
|
|
|
- }
|
|
|
- fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, dstVal)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- for i, elem := range t.TupleElems {
|
|
|
- fname := fieldmap[t.TupleRawNames[i]]
|
|
|
- field := dstVal.FieldByName(fname)
|
|
|
- if !field.IsValid() {
|
|
|
- return fmt.Errorf("abi: field %s can't found in the given value", t.TupleRawNames[i])
|
|
|
- }
|
|
|
- if err := unpack(elem, field.Addr().Interface(), srcVal.Field(i).Interface()); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
- return nil
|
|
|
- case SliceTy:
|
|
|
- if dstVal.Kind() != reflect.Slice {
|
|
|
- return fmt.Errorf("abi: invalid dst value for unpack, want slice, got %s", dstVal.Kind())
|
|
|
- }
|
|
|
- slice := reflect.MakeSlice(dstVal.Type(), srcVal.Len(), srcVal.Len())
|
|
|
- for i := 0; i < slice.Len(); i++ {
|
|
|
- if err := unpack(t.Elem, slice.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
- dstVal.Set(slice)
|
|
|
- case ArrayTy:
|
|
|
- if dstVal.Kind() != reflect.Array {
|
|
|
- return fmt.Errorf("abi: invalid dst value for unpack, want array, got %s", dstVal.Kind())
|
|
|
- }
|
|
|
- array := reflect.New(dstVal.Type()).Elem()
|
|
|
- for i := 0; i < array.Len(); i++ {
|
|
|
- if err := unpack(t.Elem, array.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
- dstVal.Set(array)
|
|
|
- }
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
// unpackAtomic unpacks ( hexdata -> go ) a single value
|
|
|
func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
|
|
|
- nonIndexedArgs := arguments.NonIndexed()
|
|
|
- if len(nonIndexedArgs) == 0 {
|
|
|
- return nil
|
|
|
- }
|
|
|
- argument := nonIndexedArgs[0]
|
|
|
- elem := reflect.ValueOf(v).Elem()
|
|
|
+ dst := reflect.ValueOf(v).Elem()
|
|
|
+ src := reflect.ValueOf(marshalledValues)
|
|
|
|
|
|
- if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy {
|
|
|
- fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- field := elem.FieldByName(fieldmap[argument.Name])
|
|
|
- if !field.IsValid() {
|
|
|
- return fmt.Errorf("abi: field %s can't be found in the given value", argument.Name)
|
|
|
- }
|
|
|
- return unpack(&argument.Type, field.Addr().Interface(), marshalledValues)
|
|
|
+ if dst.Kind() == reflect.Struct && src.Kind() != reflect.Struct {
|
|
|
+ return set(dst.Field(0), src)
|
|
|
}
|
|
|
- return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues)
|
|
|
+ return set(dst, src)
|
|
|
}
|
|
|
|
|
|
// unpackTuple unpacks ( hexdata -> go ) a batch of values.
|
|
|
func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
|
|
|
- var (
|
|
|
- value = reflect.ValueOf(v).Elem()
|
|
|
- typ = value.Type()
|
|
|
- kind = value.Kind()
|
|
|
- nonIndexedArgs = arguments.NonIndexed()
|
|
|
- )
|
|
|
- if err := requireUnpackKind(value, len(nonIndexedArgs), arguments); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
+ value := reflect.ValueOf(v).Elem()
|
|
|
+ nonIndexedArgs := arguments.NonIndexed()
|
|
|
|
|
|
- // If the interface is a struct, get of abi->struct_field mapping
|
|
|
- var abi2struct map[string]string
|
|
|
- if kind == reflect.Struct {
|
|
|
+ switch value.Kind() {
|
|
|
+ case reflect.Struct:
|
|
|
argNames := make([]string, len(nonIndexedArgs))
|
|
|
for i, arg := range nonIndexedArgs {
|
|
|
argNames[i] = arg.Name
|
|
|
}
|
|
|
var err error
|
|
|
- if abi2struct, err = mapArgNamesToStructFields(argNames, value); err != nil {
|
|
|
+ abi2struct, err := mapArgNamesToStructFields(argNames, value)
|
|
|
+ if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- }
|
|
|
- for i, arg := range nonIndexedArgs {
|
|
|
- switch kind {
|
|
|
- case reflect.Struct:
|
|
|
+ for i, arg := range nonIndexedArgs {
|
|
|
field := value.FieldByName(abi2struct[arg.Name])
|
|
|
if !field.IsValid() {
|
|
|
return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name)
|
|
|
}
|
|
|
- if err := unpack(&arg.Type, field.Addr().Interface(), marshalledValues[i]); err != nil {
|
|
|
+ if err := set(field, reflect.ValueOf(marshalledValues[i])); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- case reflect.Slice, reflect.Array:
|
|
|
- if value.Len() < i {
|
|
|
- return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len())
|
|
|
- }
|
|
|
- v := value.Index(i)
|
|
|
- if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil {
|
|
|
+ }
|
|
|
+ case reflect.Slice, reflect.Array:
|
|
|
+ if value.Len() < len(marshalledValues) {
|
|
|
+ return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len())
|
|
|
+ }
|
|
|
+ for i := range nonIndexedArgs {
|
|
|
+ if err := set(value.Index(i), reflect.ValueOf(marshalledValues[i])); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- default:
|
|
|
- return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
|
|
|
}
|
|
|
+ default:
|
|
|
+ return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", value.Type())
|
|
|
}
|
|
|
return nil
|
|
|
-
|
|
|
}
|
|
|
|
|
|
// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
|