Skip to content

Commit

Permalink
core: adjust System.Enumerator.Create interop
Browse files Browse the repository at this point in the history
Part of #1201.

It should be able to create enumerator from primitive byte-array-like
stack items too.
  • Loading branch information
AnnaShaleva committed Jul 23, 2020
1 parent d6342ab commit 459ac34
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 10 deletions.
2 changes: 1 addition & 1 deletion pkg/core/interop/enumerator/interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ func Concat(_ *interop.Context, v *vm.VM) error {
return vm.EnumeratorConcat(v)
}

// Create creates an enumerator from an array-like stack item.
// Create creates an enumerator from an array-like or bytearray-like stack item.
func Create(_ *interop.Context, v *vm.VM) error {
return vm.EnumeratorCreate(v)
}
Expand Down
10 changes: 5 additions & 5 deletions pkg/interop/enumerator/enumerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ package enumerator
// or structures that have values with no explicit keys.
type Enumerator struct{}

// Create creates a new enumerator from the given items (slice or structure).
// New enumerator points at index -1 of its items, so the user of it has to
// advance it first with Next. This function uses `System.Enumerator.Create`
// syscall.
func Create(items []interface{}) Enumerator {
// Create creates a new enumerator from the given items (slice, structure, byte
// array and integer or boolean converted to byte array). New enumerator points
// at index -1 of its items, so the user of it has to advance it first with Next.
// This function uses `System.Enumerator.Create` syscall.
func Create(items interface{}) Enumerator {
return Enumerator{}
}

Expand Down
21 changes: 17 additions & 4 deletions pkg/vm/interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,25 @@ func init() {

// EnumeratorCreate handles syscall System.Enumerator.Create.
func EnumeratorCreate(v *VM) error {
data := v.Estack().Pop().Array()
v.Estack().Push(&Element{
value: stackitem.NewInterop(&arrayWrapper{
var interop interface{}
switch t := v.Estack().Pop().value.(type) {
case *stackitem.Array, *stackitem.Struct:
interop = &arrayWrapper{
index: -1,
value: t.Value().([]stackitem.Item),
}
default:
data, err := t.TryBytes()
if err != nil {
return fmt.Errorf("can not create enumerator from type %s: %v", t.Type(), err)
}
interop = &byteArrayWrapper{
index: -1,
value: data,
}),
}
}
v.Estack().Push(&Element{
value: stackitem.NewInterop(interop),
})

return nil
Expand Down
24 changes: 24 additions & 0 deletions pkg/vm/interop_iterators.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package vm

import (
"math/big"

"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)

Expand All @@ -15,6 +17,11 @@ type (
value []stackitem.Item
}

byteArrayWrapper struct {
index int
value []byte
}

concatEnum struct {
current enumerator
second enumerator
Expand Down Expand Up @@ -63,6 +70,23 @@ func (a *arrayWrapper) Key() stackitem.Item {
return stackitem.Make(a.index)
}

func (a *byteArrayWrapper) Next() bool {
if next := a.index + 1; next < len(a.value) {
a.index = next
return true
}

return false
}

func (a *byteArrayWrapper) Value() stackitem.Item {
return stackitem.NewBigInteger(big.NewInt(int64(a.value[a.index])))
}

func (a *byteArrayWrapper) Key() stackitem.Item {
return stackitem.Make(a.index)
}

func (c *concatEnum) Next() bool {
if c.current.Next() {
return true
Expand Down

0 comments on commit 459ac34

Please sign in to comment.