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 }