vm: implement Array and Struct item serialization

This commit is contained in:
Evgenii Stratonikov 2019-11-05 12:25:15 +03:00
parent e1d019e087
commit 59f9c2bddc
2 changed files with 68 additions and 10 deletions

View file

@ -47,10 +47,19 @@ func serializeItemTo(item StackItem, w *io.BinWriter, seen map[StackItem]bool) {
w.WriteBytes(t.Bytes())
case *InteropItem:
w.Err = errors.New("not supported")
case *ArrayItem:
w.Err = errors.New("not implemented")
case *StructItem:
w.Err = errors.New("not implemented")
case *ArrayItem, *StructItem:
_, isArray := t.(*ArrayItem)
if isArray {
w.WriteLE(byte(arrayT))
} else {
w.WriteLE(byte(structT))
}
arr := t.Value().([]StackItem)
w.WriteVarUint(uint64(len(arr)))
for i := range arr {
serializeItemTo(arr[i], w, seen)
}
case *MapItem:
w.WriteLE(byte(mapT))
w.WriteVarUint(uint64(len(t.value)))
@ -91,12 +100,17 @@ func deserializeItemFrom(r *io.BinReader) StackItem {
return &BigIntegerItem{
value: num,
}
case arrayT:
r.Err = errors.New("not implemented")
return nil
case structT:
r.Err = errors.New("not implemented")
return nil
case arrayT, structT:
size := int(r.ReadVarUint())
arr := make([]StackItem, size)
for i := 0; i < size; i++ {
arr[i] = deserializeItemFrom(r)
}
if stackItemType(t) == arrayT {
return &ArrayItem{value: arr}
}
return &StructItem{value: arr}
case mapT:
size := int(r.ReadVarUint())
m := NewMapItem()

View file

@ -256,6 +256,50 @@ func TestSerializeInteger(t *testing.T) {
require.Equal(t, value, vm.estack.Top().BigInt().Int64())
}
func TestSerializeArray(t *testing.T) {
vm := load(getSerializeProg())
item := NewArrayItem([]StackItem{
makeStackItem(true),
makeStackItem(123),
NewMapItem(),
})
vm.estack.Push(&Element{value: item})
testSerialize(t, vm)
require.IsType(t, (*ArrayItem)(nil), vm.estack.Top().value)
require.Equal(t, item.value, vm.estack.Top().Array())
}
func TestSerializeArrayBad(t *testing.T) {
vm := load(getSerializeProg())
item := NewArrayItem(makeArrayOfFalses(2))
item.value[1] = item
vm.estack.Push(&Element{value: item})
err := vm.Step()
require.Error(t, err)
require.True(t, vm.HasFailed())
}
func TestSerializeStruct(t *testing.T) {
vm := load(getSerializeProg())
item := NewStructItem([]StackItem{
makeStackItem(true),
makeStackItem(123),
NewMapItem(),
})
vm.estack.Push(&Element{value: item})
testSerialize(t, vm)
require.IsType(t, (*StructItem)(nil), vm.estack.Top().value)
require.Equal(t, item.value, vm.estack.Top().Array())
}
func TestSerializeMap(t *testing.T) {
vm := load(getSerializeProg())
item := NewMapItem()