github.com/grafana/pyroscope@v1.18.0/pkg/iter/iter.go (about)

     1  package iter
     2  
     3  import (
     4  	"context"
     5  	"sort"
     6  	"sync"
     7  
     8  	"github.com/samber/lo"
     9  	"golang.org/x/exp/constraints"
    10  )
    11  
    12  type Iterator[A any] interface {
    13  	// Next advances the iterator and returns true if another value was found.
    14  	Next() bool
    15  
    16  	// At returns the value at the current iterator position.
    17  	At() A
    18  
    19  	// Err returns the last error of the iterator.
    20  	Err() error
    21  
    22  	Close() error
    23  }
    24  
    25  type SeekIterator[A any, B any] interface {
    26  	Iterator[A]
    27  
    28  	// Like Next but skips over results until reading >= the given location
    29  	Seek(pos B) bool
    30  }
    31  
    32  type errIterator[A any] struct {
    33  	err error
    34  }
    35  
    36  func NewErrIterator[A any](err error) Iterator[A] {
    37  	return &errIterator[A]{
    38  		err: err,
    39  	}
    40  }
    41  
    42  func (i *errIterator[A]) Err() error {
    43  	return i.err
    44  }
    45  
    46  func (*errIterator[A]) At() (a A) {
    47  	return a
    48  }
    49  
    50  func (*errIterator[A]) Next() bool {
    51  	return false
    52  }
    53  
    54  func (*errIterator[A]) Close() error {
    55  	return nil
    56  }
    57  
    58  type errSeekIterator[A any, B any] struct {
    59  	Iterator[A]
    60  }
    61  
    62  func NewErrSeekIterator[A any, B any](err error) SeekIterator[A, B] {
    63  	return &errSeekIterator[A, B]{
    64  		Iterator: NewErrIterator[A](err),
    65  	}
    66  }
    67  
    68  func (*errSeekIterator[A, B]) Seek(_ B) bool {
    69  	return false
    70  }
    71  
    72  type sliceIterator[A any] struct {
    73  	list []A
    74  	cur  A
    75  }
    76  
    77  func NewSliceIterator[A any](s []A) Iterator[A] {
    78  	return &sliceIterator[A]{
    79  		list: s,
    80  	}
    81  }
    82  
    83  func (i *sliceIterator[A]) Err() error {
    84  	return nil
    85  }
    86  
    87  func (i *sliceIterator[A]) Next() bool {
    88  	if len(i.list) > 0 {
    89  		i.cur = i.list[0]
    90  		i.list = i.list[1:]
    91  		return true
    92  	}
    93  	var a A
    94  	i.cur = a
    95  	return false
    96  }
    97  
    98  func NewSliceSeekIterator[A constraints.Ordered](s []A) SeekIterator[A, A] {
    99  	return &sliceSeekIterator[A]{
   100  		sliceIterator: &sliceIterator[A]{
   101  			list: s,
   102  		},
   103  	}
   104  }
   105  
   106  type slicePositionIterator[T constraints.Integer, M any] struct {
   107  	i Iterator[T]
   108  	s []M
   109  }
   110  
   111  func NewSliceIndexIterator[T constraints.Integer, M any](s []M, i Iterator[T]) Iterator[M] {
   112  	return slicePositionIterator[T, M]{s: s, i: i}
   113  }
   114  
   115  func (i slicePositionIterator[T, M]) Next() bool   { return i.i.Next() }
   116  func (i slicePositionIterator[T, M]) At() M        { return i.s[i.i.At()] }
   117  func (i slicePositionIterator[T, M]) Err() error   { return i.i.Err() }
   118  func (i slicePositionIterator[T, M]) Close() error { return i.i.Close() }
   119  
   120  type sliceSeekIterator[A constraints.Ordered] struct {
   121  	*sliceIterator[A]
   122  }
   123  
   124  func (i *sliceSeekIterator[A]) Seek(x A) bool {
   125  	// If the current value satisfies, then return.
   126  	if i.cur >= x {
   127  		return true
   128  	}
   129  	if len(i.list) == 0 {
   130  		return false
   131  	}
   132  
   133  	// Do binary search between current position and end.
   134  	pos := sort.Search(len(i.list), func(pos int) bool {
   135  		return i.list[pos] >= x
   136  	})
   137  	if pos < len(i.list) {
   138  		i.cur = i.list[pos]
   139  		i.list = i.list[pos+1:]
   140  		return true
   141  	}
   142  	i.list = nil
   143  	return false
   144  }
   145  
   146  func (i *sliceIterator[A]) At() A {
   147  	return i.cur
   148  }
   149  
   150  func (i *sliceIterator[A]) Close() error {
   151  	return nil
   152  }
   153  
   154  func Slice[T any](it Iterator[T]) ([]T, error) {
   155  	if s, ok := it.(*sliceIterator[T]); ok {
   156  		return s.list, nil
   157  	}
   158  	var result []T
   159  	defer it.Close()
   160  	for it.Next() {
   161  		result = append(result, it.At())
   162  	}
   163  	return result, it.Err()
   164  }
   165  
   166  func MustSlice[T any](it Iterator[T]) []T {
   167  	s, err := Slice(it)
   168  	if err != nil {
   169  		panic(err)
   170  	}
   171  	return s
   172  }
   173  
   174  // CloneN returns N copy of the iterator.
   175  // The returned iterators are independent of the original iterator.
   176  // The original might be exhausted and should be discarded.
   177  func CloneN[T any](it Iterator[T], n int) ([]Iterator[T], error) {
   178  	if sl, ok := it.(*sliceIterator[T]); ok {
   179  		return lo.Times(n, func(_ int) Iterator[T] { return NewSliceIterator(sl.list) }), nil
   180  	}
   181  	slice, err := Slice(it)
   182  	if err != nil {
   183  		return nil, err
   184  	}
   185  	return lo.Times(n, func(_ int) Iterator[T] { return NewSliceIterator(slice) }), nil
   186  }
   187  
   188  type unionIterator[T any] struct {
   189  	iters []Iterator[T]
   190  }
   191  
   192  func NewUnionIterator[T any](iters ...Iterator[T]) Iterator[T] {
   193  	return &unionIterator[T]{
   194  		iters: iters,
   195  	}
   196  }
   197  
   198  func (u *unionIterator[T]) Next() bool {
   199  	idx := 0
   200  	for idx < len(u.iters) {
   201  		it := u.iters[idx]
   202  
   203  		if it.Next() {
   204  			return true
   205  		}
   206  		if it.Err() != nil {
   207  			return false
   208  		}
   209  
   210  		u.iters = u.iters[1:]
   211  	}
   212  	return false
   213  }
   214  
   215  func (it *unionIterator[T]) At() T {
   216  	return it.iters[0].At()
   217  }
   218  
   219  func (it *unionIterator[T]) Err() error {
   220  	return it.iters[0].Err()
   221  }
   222  
   223  func (it *unionIterator[T]) Close() error {
   224  	for _, it := range it.iters {
   225  		if err := it.Close(); err != nil {
   226  			return err
   227  		}
   228  	}
   229  	return nil
   230  }
   231  
   232  type emptyIterator[T any] struct{}
   233  
   234  func NewEmptyIterator[T any]() Iterator[T] {
   235  	return &emptyIterator[T]{}
   236  }
   237  
   238  func (it *emptyIterator[T]) Next() bool {
   239  	return false
   240  }
   241  
   242  func (it *emptyIterator[T]) At() T {
   243  	var t T
   244  	return t
   245  }
   246  
   247  func (it *emptyIterator[T]) Err() error {
   248  	return nil
   249  }
   250  
   251  func (it *emptyIterator[T]) Close() error {
   252  	return nil
   253  }
   254  
   255  type BufferedIterator[T any] struct {
   256  	Iterator[T]
   257  	buff chan T
   258  	at   T
   259  
   260  	ctx    context.Context
   261  	cancel context.CancelFunc
   262  	wg     sync.WaitGroup
   263  }
   264  
   265  // NewBufferedIterator returns an iterator that reads asynchronously from the given iterator and buffers up to size elements.
   266  func NewBufferedIterator[T any](it Iterator[T], size int) Iterator[T] {
   267  	ctx, cancel := context.WithCancel(context.Background())
   268  	buffered := &BufferedIterator[T]{
   269  		Iterator: it,
   270  		buff:     make(chan T, size),
   271  		ctx:      ctx,
   272  		cancel:   cancel,
   273  	}
   274  
   275  	buffered.wg.Add(1)
   276  	go buffered.fill()
   277  	return buffered
   278  }
   279  
   280  func (it *BufferedIterator[T]) fill() {
   281  	defer it.wg.Done()
   282  	defer close(it.buff)
   283  
   284  	for it.Iterator.Next() {
   285  		select {
   286  		case <-it.ctx.Done():
   287  			return
   288  		case it.buff <- it.Iterator.At():
   289  			continue
   290  		}
   291  	}
   292  }
   293  
   294  func (it *BufferedIterator[T]) Next() bool {
   295  	at, ok := <-it.buff
   296  	if ok {
   297  		it.at = at
   298  	}
   299  	return ok
   300  }
   301  
   302  func (it *BufferedIterator[T]) Err() error {
   303  	return it.Iterator.Err()
   304  }
   305  
   306  func (it *BufferedIterator[T]) At() T {
   307  	return it.at
   308  }
   309  
   310  func (it *BufferedIterator[T]) Close() error {
   311  	err := it.Iterator.Close()
   312  	it.cancel()
   313  	it.wg.Wait()
   314  	return err
   315  }