vm: implement Array and Struct item serialization
This commit is contained in:
parent
e1d019e087
commit
59f9c2bddc
2 changed files with 68 additions and 10 deletions
|
@ -47,10 +47,19 @@ func serializeItemTo(item StackItem, w *io.BinWriter, seen map[StackItem]bool) {
|
||||||
w.WriteBytes(t.Bytes())
|
w.WriteBytes(t.Bytes())
|
||||||
case *InteropItem:
|
case *InteropItem:
|
||||||
w.Err = errors.New("not supported")
|
w.Err = errors.New("not supported")
|
||||||
case *ArrayItem:
|
case *ArrayItem, *StructItem:
|
||||||
w.Err = errors.New("not implemented")
|
_, isArray := t.(*ArrayItem)
|
||||||
case *StructItem:
|
if isArray {
|
||||||
w.Err = errors.New("not implemented")
|
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:
|
case *MapItem:
|
||||||
w.WriteLE(byte(mapT))
|
w.WriteLE(byte(mapT))
|
||||||
w.WriteVarUint(uint64(len(t.value)))
|
w.WriteVarUint(uint64(len(t.value)))
|
||||||
|
@ -91,12 +100,17 @@ func deserializeItemFrom(r *io.BinReader) StackItem {
|
||||||
return &BigIntegerItem{
|
return &BigIntegerItem{
|
||||||
value: num,
|
value: num,
|
||||||
}
|
}
|
||||||
case arrayT:
|
case arrayT, structT:
|
||||||
r.Err = errors.New("not implemented")
|
size := int(r.ReadVarUint())
|
||||||
return nil
|
arr := make([]StackItem, size)
|
||||||
case structT:
|
for i := 0; i < size; i++ {
|
||||||
r.Err = errors.New("not implemented")
|
arr[i] = deserializeItemFrom(r)
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
if stackItemType(t) == arrayT {
|
||||||
|
return &ArrayItem{value: arr}
|
||||||
|
}
|
||||||
|
return &StructItem{value: arr}
|
||||||
case mapT:
|
case mapT:
|
||||||
size := int(r.ReadVarUint())
|
size := int(r.ReadVarUint())
|
||||||
m := NewMapItem()
|
m := NewMapItem()
|
||||||
|
|
|
@ -256,6 +256,50 @@ func TestSerializeInteger(t *testing.T) {
|
||||||
require.Equal(t, value, vm.estack.Top().BigInt().Int64())
|
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) {
|
func TestSerializeMap(t *testing.T) {
|
||||||
vm := load(getSerializeProg())
|
vm := load(getSerializeProg())
|
||||||
item := NewMapItem()
|
item := NewMapItem()
|
||||||
|
|
Loading…
Reference in a new issue