pkg/iter/iter.go (67 lines of code) (raw):

// Licensed to Apache Software Foundation (ASF) under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Apache Software Foundation (ASF) licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // Package iter implement a generic Iterator. package iter // An Iterator is a stream of items of some type. type Iterator[T any] interface { // Next checks whether if the iteration has more elements and // returns the next one if exists. Next() (T, bool) } // FromSlice creates a new iterator which returns all items from the slice starting at index 0 until // all items are consumed. func FromSlice[T any](slice []T) Iterator[T] { return &sliceIterator[T]{slice: slice} } type sliceIterator[T any] struct { slice []T } func (iter *sliceIterator[T]) Next() (T, bool) { if len(iter.slice) == 0 { var zero T return zero, false } item := iter.slice[0] iter.slice = iter.slice[1:] return item, true } // Map returns a new iterator which applies a function to all items from the input iterator which // are subsequently returned. // // The mapping function should not mutate the state outside its scope. func Map[T any, O any](from Iterator[T], mapFunc func(T) O) Iterator[O] { return &mapIterator[T, O]{from: from, mapFunc: mapFunc} } type mapIterator[T any, O any] struct { from Iterator[T] mapFunc func(T) O } func (iter *mapIterator[T, O]) Next() (O, bool) { item, ok := iter.from.Next() if !ok { var zero O return zero, false } mapped := iter.mapFunc(item) return mapped, true } // Flatten applies a function to all items of the specified iterator, returning an iterator for each // item. The resulting iterators are then concatenated into a single iterator. func Flatten[T any](from Iterator[Iterator[T]]) Iterator[T] { return &flattenIterator[T]{from: from} } type flattenIterator[T any] struct { from Iterator[Iterator[T]] head Iterator[T] } func (iter *flattenIterator[T]) Next() (T, bool) { for { if iter.head == nil { item, ok := iter.from.Next() if !ok { var zero T return zero, false } iter.head = item } item, ok := iter.head.Next() if ok { return item, true } iter.head = nil } } // Empty returns an iterator that never returns anything. func Empty[T any]() Iterator[T] { return emptyIterator[T]{} } type emptyIterator[T any] struct{} func (emptyIterator[T]) Next() (T, bool) { var zero T return zero, false }