package iterator import ( "git.marketally.com/tutus-one/tutus-chain/pkg/core/interop" "git.marketally.com/tutus-one/tutus-chain/pkg/vm/stackitem" ) type iterator interface { Next() bool Value() stackitem.Item } // Next advances the iterator, pushes true on success and false otherwise. func Next(ic *interop.Context) error { iop := ic.VM.Estack().Pop().Interop() arr := iop.Value().(iterator) ic.VM.Estack().PushItem(stackitem.Bool(arr.Next())) return nil } // Value returns current iterator value and depends on iterator type: // For slices the result is just value. // For maps the result is key-value pair packed in a struct. func Value(ic *interop.Context) error { iop := ic.VM.Estack().Pop().Interop() arr := iop.Value().(iterator) ic.VM.Estack().PushItem(arr.Value()) return nil } // IsIterator returns whether stackitem implements iterator interface. func IsIterator(item stackitem.Item) bool { _, ok := item.Value().(iterator) return ok } // ValuesTruncated returns an array of up to `maxNum` iterator values. The second // return parameter denotes whether iterator is truncated, i.e. has more values. // The third return parameter is the next value in the iterator. If the iterator // doesn't have more values, then third return parameter is nil. The iterator can // be reused for subsequent traversal, but `curr` will not be automatically // included in subsequent calls to Values or ValuesTruncated. func ValuesTruncated(item stackitem.Item, maxNum int) ([]stackitem.Item, bool, stackitem.Item) { arr, ok := item.Value().(iterator) if !ok { return nil, false, nil } result := Values(item, maxNum) if arr.Next() { curr := arr.Value() return result, true, curr } return result, false, nil } // Values returns an array of up to `maxNum` iterator values. The provided // iterator can safely be reused to retrieve the rest of its values in the // subsequent calls to Values and to ValuesTruncated. func Values(item stackitem.Item, maxNum int) []stackitem.Item { var result []stackitem.Item arr := item.Value().(iterator) for maxNum > 0 && arr.Next() { result = append(result, arr.Value()) maxNum-- } return result }