accounts/abi: Modified unpackAtomic to accept struct lvalues
This commit is contained in:
parent
13b566e06e
commit
60a999f238
@ -86,7 +86,7 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) {
|
|||||||
}
|
}
|
||||||
return method.Outputs.Unpack(v, output)
|
return method.Outputs.Unpack(v, output)
|
||||||
} else if event, ok := abi.Events[name]; ok {
|
} else if event, ok := abi.Events[name]; ok {
|
||||||
return event.Inputs.unpackTuple(v, output)
|
return event.Inputs.Unpack(v, output)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("abi: could not locate named method or event")
|
return fmt.Errorf("abi: could not locate named method or event")
|
||||||
}
|
}
|
||||||
|
@ -113,16 +113,8 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa
|
|||||||
}
|
}
|
||||||
// If the output interface is a struct, make sure names don't collide
|
// If the output interface is a struct, make sure names don't collide
|
||||||
if kind == reflect.Struct {
|
if kind == reflect.Struct {
|
||||||
exists := make(map[string]bool)
|
if err := requireUniqueStructFieldNames(arguments); err != nil {
|
||||||
for _, arg := range arguments {
|
return err
|
||||||
field := capitalise(arg.Name)
|
|
||||||
if field == "" {
|
|
||||||
return fmt.Errorf("abi: purely underscored output cannot unpack to struct")
|
|
||||||
}
|
|
||||||
if exists[field] {
|
|
||||||
return fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", field)
|
|
||||||
}
|
|
||||||
exists[field] = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, arg := range arguments.NonIndexed() {
|
for i, arg := range arguments.NonIndexed() {
|
||||||
@ -131,14 +123,9 @@ func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interfa
|
|||||||
|
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
name := capitalise(arg.Name)
|
err := unpackStruct(value, reflectValue, arg)
|
||||||
for j := 0; j < typ.NumField(); j++ {
|
if err != nil {
|
||||||
// TODO read tags: `abi:"fieldName"`
|
return err
|
||||||
if typ.Field(j).Name == name {
|
|
||||||
if err := set(value.Field(j), reflectValue, arg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
if value.Len() < i {
|
if value.Len() < i {
|
||||||
@ -165,8 +152,20 @@ func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interf
|
|||||||
return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues))
|
return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues))
|
||||||
}
|
}
|
||||||
elem := reflect.ValueOf(v).Elem()
|
elem := reflect.ValueOf(v).Elem()
|
||||||
|
kind := elem.Kind()
|
||||||
reflectValue := reflect.ValueOf(marshalledValues[0])
|
reflectValue := reflect.ValueOf(marshalledValues[0])
|
||||||
|
|
||||||
|
if kind == reflect.Struct {
|
||||||
|
//make sure names don't collide
|
||||||
|
if err := requireUniqueStructFieldNames(arguments); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unpackStruct(elem, reflectValue, arguments[0])
|
||||||
|
}
|
||||||
|
|
||||||
return set(elem, reflectValue, arguments.NonIndexed()[0])
|
return set(elem, reflectValue, arguments.NonIndexed()[0])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes the full size of an array;
|
// Computes the full size of an array;
|
||||||
@ -278,3 +277,18 @@ func capitalise(input string) string {
|
|||||||
}
|
}
|
||||||
return strings.ToUpper(input[:1]) + input[1:]
|
return strings.ToUpper(input[:1]) + input[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//unpackStruct extracts each argument into its corresponding struct field
|
||||||
|
func unpackStruct(value, reflectValue reflect.Value, arg Argument) error {
|
||||||
|
name := capitalise(arg.Name)
|
||||||
|
typ := value.Type()
|
||||||
|
for j := 0; j < typ.NumField(); j++ {
|
||||||
|
// TODO read tags: `abi:"fieldName"`
|
||||||
|
if typ.Field(j).Name == name {
|
||||||
|
if err := set(value.Field(j), reflectValue, arg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -110,3 +110,19 @@ func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind,
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// requireUniqueStructFieldNames makes sure field names don't collide
|
||||||
|
func requireUniqueStructFieldNames(args Arguments) error {
|
||||||
|
exists := make(map[string]bool)
|
||||||
|
for _, arg := range args {
|
||||||
|
field := capitalise(arg.Name)
|
||||||
|
if field == "" {
|
||||||
|
return fmt.Errorf("abi: purely underscored output cannot unpack to struct")
|
||||||
|
}
|
||||||
|
if exists[field] {
|
||||||
|
return fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", field)
|
||||||
|
}
|
||||||
|
exists[field] = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user