vm: implement Map item serialization
This commit is contained in:
parent
cd690803cf
commit
e1d019e087
2 changed files with 39 additions and 5 deletions
|
@ -21,14 +21,20 @@ const (
|
||||||
|
|
||||||
func serializeItem(item StackItem) ([]byte, error) {
|
func serializeItem(item StackItem) ([]byte, error) {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
serializeItemTo(item, w.BinWriter)
|
serializeItemTo(item, w.BinWriter, make(map[StackItem]bool))
|
||||||
if w.Err != nil {
|
if w.Err != nil {
|
||||||
return nil, w.Err
|
return nil, w.Err
|
||||||
}
|
}
|
||||||
return w.Bytes(), nil
|
return w.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func serializeItemTo(item StackItem, w *io.BinWriter) {
|
func serializeItemTo(item StackItem, w *io.BinWriter, seen map[StackItem]bool) {
|
||||||
|
if seen[item] {
|
||||||
|
w.Err = errors.New("recursive structures are not supported")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
seen[item] = true
|
||||||
|
|
||||||
switch t := item.(type) {
|
switch t := item.(type) {
|
||||||
case *ByteArrayItem:
|
case *ByteArrayItem:
|
||||||
w.WriteLE(byte(byteArrayT))
|
w.WriteLE(byte(byteArrayT))
|
||||||
|
@ -46,7 +52,12 @@ func serializeItemTo(item StackItem, w *io.BinWriter) {
|
||||||
case *StructItem:
|
case *StructItem:
|
||||||
w.Err = errors.New("not implemented")
|
w.Err = errors.New("not implemented")
|
||||||
case *MapItem:
|
case *MapItem:
|
||||||
w.Err = errors.New("not implemented")
|
w.WriteLE(byte(mapT))
|
||||||
|
w.WriteVarUint(uint64(len(t.value)))
|
||||||
|
for k, v := range t.value {
|
||||||
|
serializeItemTo(v, w, seen)
|
||||||
|
serializeItemTo(makeStackItem(k), w, seen)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +98,17 @@ func deserializeItemFrom(r *io.BinReader) StackItem {
|
||||||
r.Err = errors.New("not implemented")
|
r.Err = errors.New("not implemented")
|
||||||
return nil
|
return nil
|
||||||
case mapT:
|
case mapT:
|
||||||
r.Err = errors.New("not implemented")
|
size := int(r.ReadVarUint())
|
||||||
return nil
|
m := NewMapItem()
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
value := deserializeItemFrom(r)
|
||||||
|
key := deserializeItemFrom(r)
|
||||||
|
if r.Err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
m.Add(key, value)
|
||||||
|
}
|
||||||
|
return m
|
||||||
default:
|
default:
|
||||||
r.Err = errors.New("unknown type")
|
r.Err = errors.New("unknown type")
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -256,6 +256,20 @@ func TestSerializeInteger(t *testing.T) {
|
||||||
require.Equal(t, value, vm.estack.Top().BigInt().Int64())
|
require.Equal(t, value, vm.estack.Top().BigInt().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSerializeMap(t *testing.T) {
|
||||||
|
vm := load(getSerializeProg())
|
||||||
|
item := NewMapItem()
|
||||||
|
item.Add(makeStackItem(true), makeStackItem([]byte{1, 2, 3}))
|
||||||
|
item.Add(makeStackItem([]byte{0}), makeStackItem(false))
|
||||||
|
|
||||||
|
vm.estack.Push(&Element{value: item})
|
||||||
|
|
||||||
|
testSerialize(t, vm)
|
||||||
|
|
||||||
|
require.IsType(t, (*MapItem)(nil), vm.estack.Top().value)
|
||||||
|
require.Equal(t, item.value, vm.estack.Top().value.(*MapItem).value)
|
||||||
|
}
|
||||||
|
|
||||||
func callNTimes(n uint16) []byte {
|
func callNTimes(n uint16) []byte {
|
||||||
return makeProgram(
|
return makeProgram(
|
||||||
PUSHBYTES2, Instruction(n), Instruction(n>>8), // little-endian
|
PUSHBYTES2, Instruction(n), Instruction(n>>8), // little-endian
|
||||||
|
|
Loading…
Reference in a new issue