|
|
|
@ -238,8 +238,16 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error { |
|
|
|
|
return fmt.Errorf("abi: unmarshalling empty output") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
value := reflect.ValueOf(v).Elem() |
|
|
|
|
typ := value.Type() |
|
|
|
|
// make sure the passed value is a pointer
|
|
|
|
|
valueOf := reflect.ValueOf(v) |
|
|
|
|
if reflect.Ptr != valueOf.Kind() { |
|
|
|
|
return fmt.Errorf("abi: Unpack(non-pointer %T)", v) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
value = valueOf.Elem() |
|
|
|
|
typ = value.Type() |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if len(method.Outputs) > 1 { |
|
|
|
|
switch value.Kind() { |
|
|
|
@ -268,6 +276,25 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error { |
|
|
|
|
return fmt.Errorf("abi: cannot marshal tuple in to slice %T (only []interface{} is supported)", v) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// if the slice already contains values, set those instead of the interface slice itself.
|
|
|
|
|
if value.Len() > 0 { |
|
|
|
|
if len(method.Outputs) > value.Len() { |
|
|
|
|
return fmt.Errorf("abi: cannot marshal in to slices of unequal size (require: %v, got: %v)", len(method.Outputs), value.Len()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for i := 0; i < len(method.Outputs); i++ { |
|
|
|
|
marshalledValue, err := toGoType(i, method.Outputs[i], output) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
reflectValue := reflect.ValueOf(marshalledValue) |
|
|
|
|
if err := set(value.Index(i).Elem(), reflectValue, method.Outputs[i]); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// create a new slice and start appending the unmarshalled
|
|
|
|
|
// values to the new interface slice.
|
|
|
|
|
z := reflect.MakeSlice(typ, 0, len(method.Outputs)) |
|
|
|
@ -296,34 +323,6 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// set attempts to assign src to dst by either setting, copying or otherwise.
|
|
|
|
|
//
|
|
|
|
|
// set is a bit more lenient when it comes to assignment and doesn't force an as
|
|
|
|
|
// strict ruleset as bare `reflect` does.
|
|
|
|
|
func set(dst, src reflect.Value, output Argument) error { |
|
|
|
|
dstType := dst.Type() |
|
|
|
|
srcType := src.Type() |
|
|
|
|
|
|
|
|
|
switch { |
|
|
|
|
case dstType.AssignableTo(src.Type()): |
|
|
|
|
dst.Set(src) |
|
|
|
|
case dstType.Kind() == reflect.Array && srcType.Kind() == reflect.Slice: |
|
|
|
|
if !dstType.Elem().AssignableTo(r_byte) { |
|
|
|
|
return fmt.Errorf("abi: cannot unmarshal %v in to array of elem %v", src.Type(), dstType.Elem()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if dst.Len() < output.Type.SliceSize { |
|
|
|
|
return fmt.Errorf("abi: cannot unmarshal src (len=%d) in to dst (len=%d)", output.Type.SliceSize, dst.Len()) |
|
|
|
|
} |
|
|
|
|
reflect.Copy(dst, src) |
|
|
|
|
case dstType.Kind() == reflect.Interface: |
|
|
|
|
dst.Set(src) |
|
|
|
|
default: |
|
|
|
|
return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type()) |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (abi *ABI) UnmarshalJSON(data []byte) error { |
|
|
|
|
var fields []struct { |
|
|
|
|
Type string |
|
|
|
|