103 lines
2.3 KiB
Go
103 lines
2.3 KiB
Go
package miter
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
)
|
|
|
|
// Empty returns the empty Iterator, i.e. one which will immediately produce
|
|
// ErrEnd.
|
|
func Empty[T any]() Iterator[T] { return Error[T](ErrEnd) }
|
|
|
|
// ForEach calls fn with each item read off the iterator, returning nil once
|
|
// ErrEnd is returned from the Iterator or function. If the Iterator or function
|
|
// return any other error then that is returned instead.
|
|
func ForEach[T any](
|
|
ctx context.Context, i Iterator[T], fn func(T) error,
|
|
) error {
|
|
for {
|
|
v, err := i.Next(ctx)
|
|
if errors.Is(err, ErrEnd) {
|
|
return nil
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := fn(v); errors.Is(err, ErrEnd) {
|
|
return nil
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
// Map will read items from the given Iterator, pass them through the given
|
|
// mapping function, and produce the mapped items from the returned Iterator.
|
|
//
|
|
// If the mapping function returns an error then that is returned from returned
|
|
// Iterator, and no more calls should be made to it.
|
|
func Map[T1, T2 any](i Iterator[T1], fn func(T1) (T2, error)) Iterator[T2] {
|
|
return FromFunc(func(ctx context.Context) (T2, error) {
|
|
v, err := i.Next(ctx)
|
|
if err != nil {
|
|
var zero T2
|
|
return zero, err
|
|
}
|
|
|
|
return fn(v)
|
|
})
|
|
}
|
|
|
|
// Concat concats all the given Iterators together into a single larger one.
|
|
// Each Iterator will be consumed until ErrEnd in turn. Any other errors from
|
|
// the inner Iterators will be returned as-is from the outer one.
|
|
func Concat[T any](iters ...Iterator[T]) Iterator[T] {
|
|
var (
|
|
i int
|
|
zero T
|
|
)
|
|
|
|
return FromFunc(func(ctx context.Context) (T, error) {
|
|
for {
|
|
if i >= len(iters) {
|
|
return zero, ErrEnd
|
|
}
|
|
|
|
v, err := iters[i].Next(ctx)
|
|
if errors.Is(err, ErrEnd) {
|
|
i++
|
|
continue
|
|
}
|
|
|
|
return v, err
|
|
}
|
|
})
|
|
}
|
|
|
|
// Filter returns an Iterator which will produce all items from the given
|
|
// Iterator for which the function returns true. If the function returns any
|
|
// error then that error is returned as-is.
|
|
func Filter[T any](
|
|
i Iterator[T], fn func(context.Context, T) (bool, error),
|
|
) Iterator[T] {
|
|
var zero T
|
|
|
|
return FromFunc(func(ctx context.Context) (T, error) {
|
|
for {
|
|
v, err := i.Next(ctx)
|
|
if err != nil {
|
|
return zero, err
|
|
}
|
|
|
|
keep, err := fn(ctx, v)
|
|
if err != nil {
|
|
return zero, err
|
|
}
|
|
|
|
if keep {
|
|
return v, nil
|
|
}
|
|
}
|
|
})
|
|
}
|