This commit is contained in:
Jakob Borg 2017-06-12 23:22:29 +00:00 committed by GitHub
commit 489ce69695
3 changed files with 53 additions and 3 deletions

View file

@ -304,12 +304,21 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
// struct will match named return values to the struct's field
// names
case reflect.Struct:
idx := 0
for i := 0; i < len(method.Outputs); i++ {
marshalledValue, err := toGoType(i, method.Outputs[i], output)
marshalledValue, err := toGoType(idx, method.Outputs[i], output)
if err != nil {
return err
}
reflectValue := reflect.ValueOf(marshalledValue)
kind := reflectValue.Type().Kind()
if (kind == reflect.Array || kind == reflect.Slice) &&
reflectValue.Type().Elem().Kind() != reflect.Uint8 {
// This is a slice of something other than bytes.
idx += reflectValue.Len()
} else {
idx++
}
for j := 0; j < typ.NumField(); j++ {
field := typ.Field(j)

View file

@ -1002,7 +1002,8 @@ func TestUnmarshal(t *testing.T) {
{ "name" : "intArraySingle", "constant" : false, "outputs": [ { "type": "uint256[3]" } ] },
{ "name" : "addressSliceSingle", "constant" : false, "outputs": [ { "type": "address[]" } ] },
{ "name" : "addressSliceDouble", "constant" : false, "outputs": [ { "name": "a", "type": "address[]" }, { "name": "b", "type": "address[]" } ] },
{ "name" : "mixedBytes", "constant" : true, "outputs": [ { "name": "a", "type": "bytes" }, { "name": "b", "type": "bytes32" } ] }]`
{ "name" : "mixedBytes", "constant" : true, "outputs": [ { "name": "a", "type": "bytes" }, { "name": "b", "type": "bytes32" } ] },
{ "name" : "arraysStruct", "constant" : true, "outputs": [ { "name": "a", "type": "bytes4[2]" }, { "name": "b", "type": "bytes20[2]" } ] }]`
abi, err := JSON(strings.NewReader(definition))
if err != nil {
@ -1238,4 +1239,37 @@ func TestUnmarshal(t *testing.T) {
if err == nil {
t.Fatal("expected error:", err)
}
// marshal arrays of arrays
buff.Reset()
buff.Write(common.Hex2Bytes("0000000100000000000000000000000000000000000000000000000000000000")) // a[0]
buff.Write(common.Hex2Bytes("0000000200000000000000000000000000000000000000000000000000000000")) // a[1]
buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000003000000000000000000000000")) // b[0]
buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000004000000000000000000000000")) // b[1]
var arraysStruct struct {
A [2][4]byte
B [2][20]byte
}
err = abi.Unpack(&arraysStruct, "arraysStruct", buff.Bytes())
if err != nil {
t.Fatal("didn't expect error:", err)
}
exp4 := [4]byte{0, 0, 0, 1}
if arraysStruct.A[0] != exp4 {
t.Errorf("expected %x, got %x", exp4, arraysStruct.A[0])
}
exp4 = [4]byte{0, 0, 0, 2}
if arraysStruct.A[1] != exp4 {
t.Errorf("expected %x, got %x", exp4, arraysStruct.A[1])
}
exp20 := [20]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}
if arraysStruct.B[0] != exp20 {
t.Errorf("expected %x, got %x", exp20, arraysStruct.B[0])
}
exp20 = [20]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}
if arraysStruct.B[1] != exp20 {
t.Errorf("expected %x, got %x", exp20, arraysStruct.B[1])
}
}

View file

@ -81,7 +81,14 @@ func set(dst, src reflect.Value, output Argument) error {
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)
switch dstType.Elem().Kind() {
case reflect.Array:
for i := 0; i < dst.Len(); i++ {
reflect.Copy(dst.Index(i), src.Index(i))
}
default:
reflect.Copy(dst, src)
}
case dstType.Kind() == reflect.Interface:
dst.Set(src)
case dstType.Kind() == reflect.Ptr: