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 }