github.com/MontFerret/ferret@v0.18.0/pkg/runtime/collections/while.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 ( 11 WhileMode int 12 13 WhilePredicate func(ctx context.Context, scope *core.Scope) (bool, error) 14 15 WhileIterator struct { 16 mode WhileMode 17 predicate WhilePredicate 18 valVar string 19 pos int 20 } 21 ) 22 23 var ( 24 WhileModePost WhileMode 25 WhileModePre WhileMode = 1 26 ) 27 28 func NewWhileIterator( 29 mode WhileMode, 30 valVar string, 31 predicate WhilePredicate, 32 ) (Iterator, error) { 33 if valVar == "" { 34 return nil, core.Error(core.ErrMissedArgument, "value variable") 35 } 36 37 if predicate == nil { 38 return nil, core.Error(core.ErrMissedArgument, "predicate") 39 } 40 41 return &WhileIterator{mode, predicate, valVar, 0}, nil 42 } 43 44 func NewDefaultWhileIterator(mode WhileMode, predicate WhilePredicate) (Iterator, error) { 45 return NewWhileIterator(mode, DefaultValueVar, predicate) 46 } 47 48 func (iterator *WhileIterator) Next(ctx context.Context, scope *core.Scope) (*core.Scope, error) { 49 // if it's Post conditional execution, step in always 50 // Otherwise, it's not the first iteration 51 if iterator.mode == WhileModePost || iterator.pos > 0 { 52 doNext, err := iterator.predicate(ctx, scope) 53 54 if err != nil { 55 return nil, err 56 } 57 58 if !doNext { 59 return nil, core.ErrNoMoreData 60 } 61 } 62 63 counter := values.NewInt(iterator.pos) 64 iterator.pos++ 65 66 nextScope := scope.Fork() 67 68 if err := nextScope.SetVariable(iterator.valVar, counter); err != nil { 69 return nil, err 70 } 71 72 return nextScope, nil 73 }