@ -238,8 +238,16 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
return fmt . Errorf ( "abi: unmarshalling empty output" )
return fmt . Errorf ( "abi: unmarshalling empty output" )
}
}
value := reflect . ValueOf ( v ) . Elem ( )
// make sure the passed value is a pointer
typ := value . Type ( )
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 {
if len ( method . Outputs ) > 1 {
switch value . Kind ( ) {
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 )
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
// create a new slice and start appending the unmarshalled
// values to the new interface slice.
// values to the new interface slice.
z := reflect . MakeSlice ( typ , 0 , len ( method . Outputs ) )
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
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 {
func ( abi * ABI ) UnmarshalJSON ( data [ ] byte ) error {
var fields [ ] struct {
var fields [ ] struct {
Type string
Type string