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  }