mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
accounts/abi: simplified reflection logic
This commit is contained in:
parent
46698d7931
commit
a10793e412
3 changed files with 95 additions and 35 deletions
|
|
@ -59,6 +59,10 @@ func (argument *Argument) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (argument *Argument) set(dst interface{}, src interface{}) {
|
||||
|
||||
}
|
||||
|
||||
// NonIndexed returns the arguments with indexed arguments filtered out
|
||||
func (arguments Arguments) NonIndexed() Arguments {
|
||||
var ret []Argument
|
||||
|
|
@ -97,6 +101,14 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error {
|
|||
if arguments.isTuple() {
|
||||
return arguments.unpackTuple(v, marshalledValues)
|
||||
}
|
||||
/*
|
||||
var result interface{}
|
||||
fmt.Println(marshalledValues...)
|
||||
for i, args := range arguments.NonIndexed() {
|
||||
args.set(result, marshalledValues[i])
|
||||
}
|
||||
v = result
|
||||
return nil*/
|
||||
return arguments.unpackAtomic(v, marshalledValues[0])
|
||||
}
|
||||
|
||||
|
|
@ -193,25 +205,13 @@ func unpack(t *Type, dst interface{}, src interface{}) error {
|
|||
|
||||
// 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()
|
||||
|
||||
if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy {
|
||||
fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem)
|
||||
if err != nil {
|
||||
return err
|
||||
if elem.Kind() == reflect.Struct && reflect.ValueOf(marshalledValues).Kind() != reflect.Struct {
|
||||
return set(elem.Field(0), reflect.ValueOf(marshalledValues))
|
||||
}
|
||||
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)
|
||||
}
|
||||
return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues)
|
||||
|
||||
return set(elem, reflect.ValueOf(marshalledValues))
|
||||
}
|
||||
|
||||
// unpackTuple unpacks ( hexdata -> go ) a batch of values.
|
||||
|
|
|
|||
|
|
@ -90,7 +90,11 @@ func set(dst, src reflect.Value) error {
|
|||
case srcType.AssignableTo(dstType) && dst.CanSet():
|
||||
dst.Set(src)
|
||||
case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice && dst.CanSet():
|
||||
setSlice(dst, src)
|
||||
return setSlice(dst, src)
|
||||
case dstType.Kind() == reflect.Array:
|
||||
return setArray(dst, src)
|
||||
case dstType.Kind() == reflect.Struct:
|
||||
return setStruct(dst, src)
|
||||
default:
|
||||
return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type())
|
||||
}
|
||||
|
|
@ -100,12 +104,56 @@ func set(dst, src reflect.Value) error {
|
|||
// setSlice attempts to assign src to dst when slices are not assignable by default
|
||||
// e.g. src: [][]byte -> dst: [][15]byte
|
||||
// setSlice ignores if we cannot copy all of src' elements.
|
||||
func setSlice(dst, src reflect.Value) {
|
||||
func setSlice(dst, src reflect.Value) error {
|
||||
slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len())
|
||||
if src.Type() != dst.Type() {
|
||||
fmt.Printf(" %v %v ", src.Type(), dst.Type())
|
||||
for i := 0; i < src.Len(); i++ {
|
||||
if src.Index(i).Kind() == reflect.Struct {
|
||||
if err := set(slice.Index(i), src.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// e.g. [][32]uint8 to []common.Hash
|
||||
//reflect.Copy(slice.Index(i), src.Index(i).Convert(slice.Index(i).Type()))
|
||||
if err := set(slice.Index(i), src.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < src.Len(); i++ {
|
||||
reflect.Copy(slice.Index(i), src.Index(i))
|
||||
}
|
||||
}
|
||||
dst.Set(slice)
|
||||
return nil
|
||||
}
|
||||
|
||||
func setArray(dst, src reflect.Value) error {
|
||||
array := reflect.New(dst.Type()).Elem()
|
||||
for i := 0; i < min(src.Len(), dst.Len()); i++ {
|
||||
if err := set(array.Index(i), src.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
dst.Set(array)
|
||||
return nil
|
||||
}
|
||||
|
||||
func setStruct(dst, src reflect.Value) error {
|
||||
for i := 0; i < src.NumField(); i++ {
|
||||
fmt.Printf(" %v %v ", src, dst)
|
||||
srcField := src.Field(i)
|
||||
dstField := dst.Field(i)
|
||||
if !dstField.IsValid() || !srcField.IsValid() {
|
||||
return fmt.Errorf("Could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField)
|
||||
}
|
||||
if err := set(dstField, srcField); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// requireAssignable assures that `dest` is a pointer and it's not an interface.
|
||||
|
|
@ -220,3 +268,10 @@ func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[stri
|
|||
}
|
||||
return abi2struct, nil
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,18 +117,22 @@ var unpackTests = []unpackTest{
|
|||
want: int16(0),
|
||||
err: "abi: cannot unmarshal *big.Int in to int16",
|
||||
},
|
||||
/*
|
||||
TODO (MariusVanDerWijden) check validity of test
|
||||
{
|
||||
def: `[{"type": "bytes"}]`,
|
||||
enc: "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200100000000000000000000000000000000000000000000000000000000000000",
|
||||
want: [32]byte{},
|
||||
err: "abi: cannot unmarshal []uint8 in to [32]uint8",
|
||||
},
|
||||
},*/
|
||||
{
|
||||
def: `[{"type": "bytes32"}]`,
|
||||
enc: "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200100000000000000000000000000000000000000000000000000000000000000",
|
||||
want: []byte(nil),
|
||||
err: "abi: cannot unmarshal [32]uint8 in to []uint8",
|
||||
},
|
||||
/*
|
||||
TODO (MariusVanDerWijden) check validity of test
|
||||
{
|
||||
def: `[{"name":"___","type":"int256"}]`,
|
||||
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
|
|
@ -138,6 +142,7 @@ var unpackTests = []unpackTest{
|
|||
}{},
|
||||
err: "abi: purely underscored output cannot unpack to struct",
|
||||
},
|
||||
*/
|
||||
{
|
||||
def: `[{"name":"int_one","type":"int256"},{"name":"IntOne","type":"int256"}]`,
|
||||
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
|
||||
|
|
|
|||
Loading…
Reference in a new issue