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()
typ = value.Type()
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 {
case reflect.Struct:
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)
k := 0
for i := 0; i < len(arguments); i++ {
// 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
}
k++
}
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())
for i := 0; i < value.Len(); i++ {
// Skip indexed fields
if arguments[i].Indexed {
continue
}
v := value.Index(i)
if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil {
if err := set(value.Index(i), reflect.ValueOf(marshalledValues[i])); err != nil {
return err
}
if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil {
return err
}
default:
return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
}
}
return nil
}
// 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) {
type EventTransfer struct {
From common.Address
To common.Address
Value *big.Int
}

View file

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