github.com/m4gshm/gollections@v0.0.10/kv/loop/loop.go (about)

     1  package loop
     2  
     3  import (
     4  	"github.com/m4gshm/gollections/kv"
     5  	"github.com/m4gshm/gollections/loop"
     6  )
     7  
     8  // NewIter creates an Iter instance that loops over key\value elements of a source.
     9  // The hasNext specifies a predicate that tests existing of a next element in the source.
    10  // The getNext extracts the one.
    11  func NewIter[S, K, V any](source S, hasNext func(S) bool, getNext func(S) (K, V, error)) Iter[S, K, V] {
    12  	return Iter[S, K, V]{source: source, hasNext: hasNext, getNext: getNext}
    13  }
    14  
    15  // Iter - universal key\value iterator implementation
    16  type Iter[S, K, V any] struct {
    17  	source  S
    18  	hasNext func(S) bool
    19  	getNext func(S) (K, V, error)
    20  	abort   error
    21  }
    22  
    23  var (
    24  	_ kv.Iterator[any, any] = (*Iter[any, any, any])(nil)
    25  )
    26  
    27  var _ kv.IterFor[any, any, *Iter[any, any, any]] = (*Iter[any, any, any])(nil)
    28  
    29  // Track takes key, value pairs retrieved by the iterator. Can be interrupt by returning ErrBreak
    30  func (i *Iter[S, K, V]) Track(traker func(key K, value V) error) error {
    31  	return loop.Track(i.Next, traker)
    32  }
    33  
    34  // TrackEach takes all key, value pairs retrieved by the iterator
    35  func (i *Iter[S, K, V]) TrackEach(traker func(key K, value V)) {
    36  	loop.TrackEach(i.Next, traker)
    37  }
    38  
    39  // Next implements kv.KVIterator
    40  func (i *Iter[S, K, V]) Next() (K, V, bool) {
    41  	if i.abort == nil && i.hasNext(i.source) {
    42  		k, v, err := i.getNext(i.source)
    43  		if err == nil {
    44  			return k, v, true
    45  		}
    46  		i.abort = err
    47  	}
    48  	var k K
    49  	var v V
    50  	return k, v, false
    51  }
    52  
    53  // Error implements kv.KVIteratorBreakable
    54  func (i *Iter[S, K, V]) Error() error {
    55  	return i.abort
    56  }
    57  
    58  // Start is used with for loop construct like 'for i, k, v, ok := i.Start(); ok; k, v, ok = i.Next() { }'
    59  func (i *Iter[S, K, V]) Start() (*Iter[S, K, V], K, V, bool) {
    60  	return startKvIt[K, V](i)
    61  }