github.com/polygon-io/client-go@v1.16.4/rest/iter/iter.go (about)

     1  package iter
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/polygon-io/client-go/rest/encoder"
     7  )
     8  
     9  // ListResponse defines an interface that list API responses must implement.
    10  type ListResponse interface {
    11  	// NextPage returns a URL for retrieving the next page of list results.
    12  	NextPage() string
    13  }
    14  
    15  // Query defines a closure that domain specific iterators must implement. The implementation should
    16  // include a call to the API and should return the API response with a separate slice of the results.
    17  type Query[T any] func(string) (ListResponse, []T, error)
    18  
    19  // Iter defines an iterator type that list methods should return. The contained type should typically
    20  // be a model that's returned in the results of a list method response.
    21  type Iter[T any] struct {
    22  	ctx   context.Context
    23  	query Query[T]
    24  
    25  	page    ListResponse
    26  	item    T
    27  	results []T
    28  
    29  	err error
    30  }
    31  
    32  // NewIter returns a new initialized iterator. This method automatically makes the first query to populate
    33  // the results. List methods should use this helper method when building domain specific iterators.
    34  func NewIter[T any](ctx context.Context, path string, params any, query Query[T]) *Iter[T] {
    35  	it := Iter[T]{
    36  		ctx:   ctx,
    37  		query: query,
    38  	}
    39  
    40  	uri, err := encoder.New().EncodeParams(path, params)
    41  	if err != nil {
    42  		it.err = err
    43  		return &it
    44  	}
    45  
    46  	it.page, it.results, it.err = it.query(uri)
    47  	return &it
    48  }
    49  
    50  // Next moves the iterator to the next result.
    51  func (it *Iter[T]) Next() bool {
    52  	if it.err != nil {
    53  		return false
    54  	}
    55  
    56  	if len(it.results) == 0 && it.page.NextPage() != "" {
    57  		it.page, it.results, it.err = it.query(it.page.NextPage())
    58  	}
    59  
    60  	if it.err != nil || len(it.results) == 0 {
    61  		return false
    62  	}
    63  
    64  	it.err = it.ctx.Err()
    65  	if it.err != nil {
    66  		return false
    67  	}
    68  
    69  	it.item = it.results[0]
    70  	it.results = it.results[1:]
    71  	return true
    72  }
    73  
    74  // Item returns the result that the iterator is currently pointing to.
    75  func (it *Iter[T]) Item() T {
    76  	return it.item
    77  }
    78  
    79  // Err returns any errors that occur during iteration.
    80  func (it *Iter[T]) Err() error {
    81  	return it.err
    82  }