core: adjust System.Enumerator.Create interop
Part of #1201. It should be able to create enumerator from primitive byte-array-like stack items too.
This commit is contained in:
parent
d6342ab68c
commit
459ac34839
4 changed files with 47 additions and 10 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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{}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
|
@ -15,6 +17,11 @@ type (
|
|||
value []stackitem.Item
|
||||
}
|
||||
|
||||
byteArrayWrapper struct {
|
||||
index int
|
||||
value []byte
|
||||
}
|
||||
|
||||
concatEnum struct {
|
||||
current enumerator
|
||||
second enumerator
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue