github.com/MontFerret/ferret@v0.18.0/pkg/runtime/collections/map.go (about) 1 package collections 2 3 import ( 4 "context" 5 6 "github.com/MontFerret/ferret/pkg/runtime/core" 7 "github.com/MontFerret/ferret/pkg/runtime/values" 8 ) 9 10 type MapIterator struct { 11 valVar string 12 keyVar string 13 values map[string]core.Value 14 keys []string 15 pos int 16 } 17 18 func NewMapIterator( 19 valVar, 20 keyVar string, 21 values map[string]core.Value, 22 ) (Iterator, error) { 23 if valVar == "" { 24 return nil, core.Error(core.ErrMissedArgument, "value variable") 25 } 26 27 if values == nil { 28 return nil, core.Error(core.ErrMissedArgument, "result") 29 } 30 31 return &MapIterator{valVar, keyVar, values, nil, 0}, nil 32 } 33 34 func NewDefaultMapIterator(values map[string]core.Value) (Iterator, error) { 35 return NewMapIterator(DefaultValueVar, DefaultKeyVar, values) 36 } 37 38 func (iterator *MapIterator) Next(_ context.Context, scope *core.Scope) (*core.Scope, error) { 39 // lazy initialization 40 if iterator.keys == nil { 41 keys := make([]string, len(iterator.values)) 42 43 i := 0 44 for k := range iterator.values { 45 keys[i] = k 46 i++ 47 } 48 49 iterator.keys = keys 50 } 51 52 if len(iterator.keys) > iterator.pos { 53 key := iterator.keys[iterator.pos] 54 val := iterator.values[key] 55 56 iterator.pos++ 57 58 nextScope := scope.Fork() 59 60 if err := nextScope.SetVariable(iterator.valVar, val); err != nil { 61 return nil, err 62 } 63 64 if iterator.keyVar != "" { 65 if err := nextScope.SetVariable(iterator.keyVar, values.NewString(key)); err != nil { 66 return nil, err 67 } 68 } 69 70 return nextScope, nil 71 } 72 73 return nil, core.ErrNoMoreData 74 }