78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
//go:build go1.18
|
|
// +build go1.18
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
)
|
|
|
|
// PagingHandler contains the required data for constructing a Pager.
|
|
type PagingHandler[T any] struct {
|
|
// More returns a boolean indicating if there are more pages to fetch.
|
|
// It uses the provided page to make the determination.
|
|
More func(T) bool
|
|
|
|
// Fetcher fetches the first and subsequent pages.
|
|
Fetcher func(context.Context, *T) (T, error)
|
|
}
|
|
|
|
// Pager provides operations for iterating over paged responses.
|
|
type Pager[T any] struct {
|
|
current *T
|
|
handler PagingHandler[T]
|
|
firstPage bool
|
|
}
|
|
|
|
// NewPager creates an instance of Pager using the specified PagingHandler.
|
|
// Pass a non-nil T for firstPage if the first page has already been retrieved.
|
|
func NewPager[T any](handler PagingHandler[T]) *Pager[T] {
|
|
return &Pager[T]{
|
|
handler: handler,
|
|
firstPage: true,
|
|
}
|
|
}
|
|
|
|
// More returns true if there are more pages to retrieve.
|
|
func (p *Pager[T]) More() bool {
|
|
if p.current != nil {
|
|
return p.handler.More(*p.current)
|
|
}
|
|
return true
|
|
}
|
|
|
|
// NextPage advances the pager to the next page.
|
|
func (p *Pager[T]) NextPage(ctx context.Context) (T, error) {
|
|
var resp T
|
|
var err error
|
|
if p.current != nil {
|
|
if p.firstPage {
|
|
// we get here if it's an LRO-pager, we already have the first page
|
|
p.firstPage = false
|
|
return *p.current, nil
|
|
} else if !p.handler.More(*p.current) {
|
|
return *new(T), errors.New("no more pages")
|
|
}
|
|
resp, err = p.handler.Fetcher(ctx, p.current)
|
|
} else {
|
|
// non-LRO case, first page
|
|
p.firstPage = false
|
|
resp, err = p.handler.Fetcher(ctx, nil)
|
|
}
|
|
if err != nil {
|
|
return *new(T), err
|
|
}
|
|
p.current = &resp
|
|
return *p.current, nil
|
|
}
|
|
|
|
// UnmarshalJSON implements the json.Unmarshaler interface for Pager[T].
|
|
func (p *Pager[T]) UnmarshalJSON(data []byte) error {
|
|
return json.Unmarshal(data, &p.current)
|
|
}
|