accounts/abi: simplified reflection logic

This commit is contained in:
Marius van der Wijden 2020-05-07 17:02:35 +02:00
parent a10793e412
commit d0a25e1967
3 changed files with 30 additions and 41 deletions

View file

@ -220,51 +220,38 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa
value = reflect.ValueOf(v).Elem() value = reflect.ValueOf(v).Elem()
typ = value.Type() typ = value.Type()
kind = value.Kind() kind = value.Kind()
nonIndexedArgs = arguments.NonIndexed()
) )
if err := requireUnpackKind(value, len(nonIndexedArgs), arguments); err != nil {
return err
}
// If the interface is a struct, get of abi->struct_field mapping
var abi2struct map[string]string
if kind == 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 {
return err
}
}
for i, arg := range nonIndexedArgs {
switch kind { switch kind {
case reflect.Struct: case reflect.Struct:
field := value.FieldByName(abi2struct[arg.Name]) k := 0
if !field.IsValid() { for i := 0; i < len(arguments); i++ {
return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name) // Skip indexed fields
if arguments[i].Indexed {
continue
} }
if err := unpack(&arg.Type, field.Addr().Interface(), marshalledValues[i]); err != nil { if i >= value.NumField() {
return fmt.Errorf("Invalid field length while unpacking: %v", i)
}
if err := set(value.Field(i), reflect.ValueOf(marshalledValues[k])); err != nil {
return err return err
} }
k++
}
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
if value.Len() < i { for i := 0; i < value.Len(); i++ {
return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) // Skip indexed fields
if arguments[i].Indexed {
continue
} }
v := value.Index(i) if err := set(value.Index(i), reflect.ValueOf(marshalledValues[i])); err != nil {
if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil {
return err return err
} }
if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil {
return err
} }
default: default:
return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ) return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
} }
}
return nil return nil
} }
// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification, // UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,

View file

@ -167,6 +167,8 @@ func TestEventMultiValueWithArrayUnpack(t *testing.T) {
func TestEventTupleUnpack(t *testing.T) { func TestEventTupleUnpack(t *testing.T) {
type EventTransfer struct { type EventTransfer struct {
From common.Address
To common.Address
Value *big.Int Value *big.Int
} }

View file

@ -91,7 +91,7 @@ func set(dst, src reflect.Value) error {
dst.Set(src) dst.Set(src)
case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice && dst.CanSet(): case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice && dst.CanSet():
return setSlice(dst, src) return setSlice(dst, src)
case dstType.Kind() == reflect.Array: case dstType.Kind() == reflect.Array && dst.CanSet():
return setArray(dst, src) return setArray(dst, src)
case dstType.Kind() == reflect.Struct: case dstType.Kind() == reflect.Struct:
return setStruct(dst, src) return setStruct(dst, src)