neo-go/pkg/vm/interop_iterators.go
Roman Khimov 2d0ad30fcf vm: rework Map with internal slice representation
Which makes iterating over map stable which is important for serialization and
and even fixes occasional test failures. We use the same ordering here as
NEO 3.0 uses, but it should also be fine for NEO 2.0 because it has no
defined order.
2020-04-01 19:33:53 +03:00

123 lines
1.7 KiB
Go

package vm
type (
enumerator interface {
Next() bool
Value() StackItem
}
arrayWrapper struct {
index int
value []StackItem
}
concatEnum struct {
current enumerator
second enumerator
}
)
type (
iterator interface {
enumerator
Key() StackItem
}
mapWrapper struct {
index int
m []MapElement
}
concatIter struct {
current iterator
second iterator
}
keysWrapper struct {
iter iterator
}
valuesWrapper struct {
iter iterator
}
)
func (a *arrayWrapper) Next() bool {
if next := a.index + 1; next < len(a.value) {
a.index = next
return true
}
return false
}
func (a *arrayWrapper) Value() StackItem {
return a.value[a.index]
}
func (a *arrayWrapper) Key() StackItem {
return makeStackItem(a.index)
}
func (c *concatEnum) Next() bool {
if c.current.Next() {
return true
}
c.current = c.second
return c.current.Next()
}
func (c *concatEnum) Value() StackItem {
return c.current.Value()
}
func (i *concatIter) Next() bool {
if i.current.Next() {
return true
}
i.current = i.second
return i.second.Next()
}
func (i *concatIter) Value() StackItem {
return i.current.Value()
}
func (i *concatIter) Key() StackItem {
return i.current.Key()
}
func (m *mapWrapper) Next() bool {
if next := m.index + 1; next < len(m.m) {
m.index = next
return true
}
return false
}
func (m *mapWrapper) Value() StackItem {
return m.m[m.index].Value
}
func (m *mapWrapper) Key() StackItem {
return m.m[m.index].Key
}
func (e *keysWrapper) Next() bool {
return e.iter.Next()
}
func (e *keysWrapper) Value() StackItem {
return e.iter.Key()
}
func (e *valuesWrapper) Next() bool {
return e.iter.Next()
}
func (e *valuesWrapper) Value() StackItem {
return e.iter.Value()
}