@ -122,149 +122,55 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
return nil
}
// unpack sets the unmarshalled value to go format.
// Note the dst here must be settable.
func unpack ( t * Type , dst interface { } , src interface { } ) error {
var (
dstVal = reflect . ValueOf ( dst ) . Elem ( )
srcVal = reflect . ValueOf ( src )
)
tuple , typ := false , t
for {
if typ . T == SliceTy || typ . T == ArrayTy {
typ = typ . Elem
continue
}
tuple = typ . T == TupleTy
break
}
if ! tuple {
return set ( dstVal , srcVal )
}
// Dereferences interface or pointer wrapper
dstVal = indirectInterfaceOrPtr ( dstVal )
switch t . T {
case TupleTy :
if dstVal . Kind ( ) != reflect . Struct {
return fmt . Errorf ( "abi: invalid dst value for unpack, want struct, got %s" , dstVal . Kind ( ) )
}
fieldmap , err := mapArgNamesToStructFields ( t . TupleRawNames , dstVal )
if err != nil {
return err
}
for i , elem := range t . TupleElems {
fname := fieldmap [ t . TupleRawNames [ i ] ]
field := dstVal . FieldByName ( fname )
if ! field . IsValid ( ) {
return fmt . Errorf ( "abi: field %s can't found in the given value" , t . TupleRawNames [ i ] )
}
if err := unpack ( elem , field . Addr ( ) . Interface ( ) , srcVal . Field ( i ) . Interface ( ) ) ; err != nil {
return err
}
}
return nil
case SliceTy :
if dstVal . Kind ( ) != reflect . Slice {
return fmt . Errorf ( "abi: invalid dst value for unpack, want slice, got %s" , dstVal . Kind ( ) )
}
slice := reflect . MakeSlice ( dstVal . Type ( ) , srcVal . Len ( ) , srcVal . Len ( ) )
for i := 0 ; i < slice . Len ( ) ; i ++ {
if err := unpack ( t . Elem , slice . Index ( i ) . Addr ( ) . Interface ( ) , srcVal . Index ( i ) . Interface ( ) ) ; err != nil {
return err
}
}
dstVal . Set ( slice )
case ArrayTy :
if dstVal . Kind ( ) != reflect . Array {
return fmt . Errorf ( "abi: invalid dst value for unpack, want array, got %s" , dstVal . Kind ( ) )
}
array := reflect . New ( dstVal . Type ( ) ) . Elem ( )
for i := 0 ; i < array . Len ( ) ; i ++ {
if err := unpack ( t . Elem , array . Index ( i ) . Addr ( ) . Interface ( ) , srcVal . Index ( i ) . Interface ( ) ) ; err != nil {
return err
}
}
dstVal . Set ( array )
}
return nil
}
// unpackAtomic unpacks ( hexdata -> go ) a single value
func ( arguments Arguments ) unpackAtomic ( v interface { } , marshalledValues interface { } ) error {
nonIndexedArgs := arguments . NonIndexed ( )
if len ( nonIndexedArgs ) == 0 {
return nil
}
argument := nonIndexedArgs [ 0 ]
elem := reflect . ValueOf ( v ) . Elem ( )
dst := reflect . ValueOf ( v ) . Elem ( )
src := reflect . ValueOf ( marshalledValues )
if elem . Kind ( ) == reflect . Struct && argument . Type . T != TupleTy {
fieldmap , err := mapArgNamesToStructFields ( [ ] string { argument . Name } , elem )
if err != nil {
return err
}
field := elem . FieldByName ( fieldmap [ argument . Name ] )
if ! field . IsValid ( ) {
return fmt . Errorf ( "abi: field %s can't be found in the given value" , argument . Name )
}
return unpack ( & argument . Type , field . Addr ( ) . Interface ( ) , marshalledValues )
if dst . Kind ( ) == reflect . Struct && src . Kind ( ) != reflect . Struct {
return set ( dst . Field ( 0 ) , src )
}
return unpack ( & argument . Type , elem . Addr ( ) . Interface ( ) , marshalledValues )
return set ( dst , src )
}
// unpackTuple unpacks ( hexdata -> go ) a batch of values.
func ( arguments Arguments ) unpackTuple ( v interface { } , marshalledValues [ ] interface { } ) error {
var (
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
}
value := reflect . ValueOf ( v ) . Elem ( )
nonIndexedArgs := arguments . NonIndexed ( )
// If the interface is a struct, get of abi->struct_field mapping
var abi2struct map [ string ] string
if kind == reflect . Struct {
switch value . Kind ( ) {
case 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 {
abi2struct , err := mapArgNamesToStructFields ( argNames , value )
if err != nil {
return err
}
}
for i , arg := range nonIndexedArgs {
switch kind {
case reflect . Struct :
for i , arg := range nonIndexedArgs {
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 )
}
if err := unpack ( & arg . Type , field . Addr ( ) . Interface ( ) , marshalledValues [ i ] ) ; err != nil {
if err := set ( field , reflect . ValueOf ( marshalledValues [ i ] ) ) ; err != nil {
return err
}
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 ( ) )
}
v := value . Index ( i )
if err := requireAssignable ( v , reflect . ValueOf ( marshalledValues [ i ] ) ) ; err != nil {
return err
}
if err := unpack ( & arg . Type , v . Addr ( ) . Interface ( ) , marshalledValues [ i ] ) ; err != nil {
}
case reflect . Slice , reflect . Array :
if value . Len ( ) < len ( marshalledValues ) {
return fmt . Errorf ( "abi: insufficient number of arguments for unpack, want %d, got %d" , len ( arguments ) , value . Len ( ) )
}
for i := range nonIndexedArgs {
if err := set ( value . Index ( i ) , reflect . ValueOf ( marshalledValues [ i ] ) ) ; err != nil {
return err
}
default :
return fmt . Errorf ( "abi:[2] cannot unmarshal tuple in to %v" , typ )
}
default :
return fmt . Errorf ( "abi:[2] cannot unmarshal tuple in to %v" , value . Type ( ) )
}
return nil
}
// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,