github.com/MontFerret/ferret@v0.18.0/pkg/runtime/collections/unique.go (about)

     1  package collections
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/MontFerret/ferret/pkg/runtime/core"
     7  )
     8  
     9  type (
    10  	UniqueIterator struct {
    11  		values  Iterator
    12  		hashes  map[uint64]bool
    13  		hashKey string
    14  	}
    15  )
    16  
    17  func NewUniqueIterator(values Iterator, hashKey string) (*UniqueIterator, error) {
    18  	if values == nil {
    19  		return nil, core.Error(core.ErrMissedArgument, "source")
    20  	}
    21  
    22  	return &UniqueIterator{
    23  		values:  values,
    24  		hashes:  make(map[uint64]bool),
    25  		hashKey: hashKey,
    26  	}, nil
    27  }
    28  
    29  func (iterator *UniqueIterator) Next(ctx context.Context, scope *core.Scope) (*core.Scope, error) {
    30  	for {
    31  		nextScope, err := iterator.values.Next(ctx, scope.Fork())
    32  
    33  		if err != nil {
    34  			return nil, err
    35  		}
    36  
    37  		v, err := nextScope.GetVariable(iterator.hashKey)
    38  
    39  		if err != nil {
    40  			return nil, err
    41  		}
    42  
    43  		h := v.Hash()
    44  
    45  		_, exists := iterator.hashes[h]
    46  
    47  		if exists {
    48  			continue
    49  		}
    50  
    51  		iterator.hashes[h] = true
    52  
    53  		return nextScope, nil
    54  	}
    55  }