2021-01-12 10:39:31 +00:00
|
|
|
package storage
|
|
|
|
|
|
|
|
import "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
|
|
|
|
|
|
// Storage iterator options.
|
|
|
|
const (
|
|
|
|
FindDefault = 0
|
|
|
|
FindKeysOnly = 1 << 0
|
|
|
|
FindRemovePrefix = 1 << 1
|
|
|
|
FindValuesOnly = 1 << 2
|
2021-01-12 12:09:05 +00:00
|
|
|
FindDeserialize = 1 << 3
|
2021-01-12 12:32:27 +00:00
|
|
|
FindPick0 = 1 << 4
|
|
|
|
FindPick1 = 1 << 5
|
2021-01-12 10:39:31 +00:00
|
|
|
|
2021-01-12 12:09:05 +00:00
|
|
|
FindAll = FindDefault | FindKeysOnly | FindRemovePrefix | FindValuesOnly |
|
2021-01-12 12:32:27 +00:00
|
|
|
FindDeserialize | FindPick0 | FindPick1
|
2021-01-12 10:39:31 +00:00
|
|
|
)
|
|
|
|
|
2021-01-15 18:06:35 +00:00
|
|
|
// Iterator is an iterator state representation.
|
2021-01-12 10:39:31 +00:00
|
|
|
type Iterator struct {
|
2021-04-29 14:29:21 +00:00
|
|
|
m []stackitem.MapElement
|
|
|
|
opts int64
|
|
|
|
index int
|
|
|
|
prefixSize int
|
2021-01-12 10:39:31 +00:00
|
|
|
}
|
|
|
|
|
2021-01-15 18:06:35 +00:00
|
|
|
// NewIterator creates a new Iterator with given options for a given map.
|
2021-04-29 14:29:21 +00:00
|
|
|
func NewIterator(m *stackitem.Map, prefix int, opts int64) *Iterator {
|
2021-01-12 10:39:31 +00:00
|
|
|
return &Iterator{
|
2021-04-29 14:29:21 +00:00
|
|
|
m: m.Value().([]stackitem.MapElement),
|
|
|
|
opts: opts,
|
|
|
|
index: -1,
|
|
|
|
prefixSize: prefix,
|
2021-01-12 10:39:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-15 18:06:35 +00:00
|
|
|
// Next advances the iterator and returns true if Value can be called at the
|
|
|
|
// current position.
|
2021-01-12 10:39:31 +00:00
|
|
|
func (s *Iterator) Next() bool {
|
|
|
|
if s.index < len(s.m) {
|
2021-01-15 18:06:35 +00:00
|
|
|
s.index++
|
2021-01-12 10:39:31 +00:00
|
|
|
}
|
|
|
|
return s.index < len(s.m)
|
|
|
|
}
|
|
|
|
|
2021-01-15 18:06:35 +00:00
|
|
|
// Value returns current iterators value (exact type depends on options this
|
|
|
|
// iterator was created with).
|
2021-01-12 10:39:31 +00:00
|
|
|
func (s *Iterator) Value() stackitem.Item {
|
|
|
|
key := s.m[s.index].Key.Value().([]byte)
|
|
|
|
if s.opts&FindRemovePrefix != 0 {
|
2021-04-29 14:29:21 +00:00
|
|
|
key = key[s.prefixSize:]
|
2021-01-12 10:39:31 +00:00
|
|
|
}
|
|
|
|
if s.opts&FindKeysOnly != 0 {
|
|
|
|
return stackitem.NewByteArray(key)
|
|
|
|
}
|
2021-01-12 12:09:05 +00:00
|
|
|
value := s.m[s.index].Value
|
|
|
|
if s.opts&FindDeserialize != 0 {
|
|
|
|
bs := s.m[s.index].Value.Value().([]byte)
|
|
|
|
var err error
|
|
|
|
value, err = stackitem.DeserializeItem(bs)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
2021-01-12 12:32:27 +00:00
|
|
|
if s.opts&FindPick0 != 0 {
|
|
|
|
value = value.Value().([]stackitem.Item)[0]
|
|
|
|
} else if s.opts&FindPick1 != 0 {
|
|
|
|
value = value.Value().([]stackitem.Item)[1]
|
|
|
|
}
|
2021-01-12 10:39:31 +00:00
|
|
|
if s.opts&FindValuesOnly != 0 {
|
2021-01-12 12:09:05 +00:00
|
|
|
return value
|
2021-01-12 10:39:31 +00:00
|
|
|
}
|
|
|
|
return stackitem.NewStruct([]stackitem.Item{
|
|
|
|
stackitem.NewByteArray(key),
|
2021-01-12 12:09:05 +00:00
|
|
|
value,
|
2021-01-12 10:39:31 +00:00
|
|
|
})
|
|
|
|
}
|