Copyright 2016 Google LLC. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Package iterator provides support for standard Google API iterators. See https://github.com/GoogleCloudPlatform/gcloud-golang/wiki/Iterator-Guidelines.
package iterator

import (
	
	
	
)
Done is returned by an iterator's Next method when the iteration is complete; when there are no more items to return.
var Done = errors.New("no more items in iterator")
We don't support mixed calls to Next and NextPage because they play with the paging state in incompatible ways.
var errMixed = errors.New("iterator: Next and NextPage called on same iterator")
PageInfo contains information about an iterator's paging state.
Token is the token used to retrieve the next page of items from the API. You may set Token immediately after creating an iterator to begin iteration at a particular point. If Token is the empty string, the iterator will begin with the first eligible item. The result of setting Token after the first call to Next is undefined. After the underlying API method is called to retrieve a page of items, Token is set to the next-page token in the response.
MaxSize is the maximum number of items returned by a call to the API. Set MaxSize as a hint to optimize the buffering behavior of the iterator. If zero, the page size is determined by the underlying service. Use Pager to retrieve a page of a specific, exact size.
The error state of the iterator. Manipulated by PageInfo.next and Pager. This is a latch: it starts as nil, and once set should never change.
If true, no more calls to fetch should be made. Set to true when fetch returns an empty page token. The iterator is Done when this is true AND the buffer is empty.
Function that fetches a page from the underlying service. It should pass the pageSize and pageToken arguments to the service, fill the buffer with the results from the call, and return the next-page token returned by the service. The function must not remove any existing items from the buffer. If the underlying RPC takes an int32 page size, pageSize should be silently truncated.
	fetch func(pageSize int, pageToken string) (nextPageToken string, err error)
Function that returns the number of currently buffered items.
	bufLen func() int
Function that returns the buffer, after setting the buffer variable to nil.
	takeBuf func() interface{}
Set to true on first call to PageInfo.next or Pager.NextPage. Used to check for calls to both Next and NextPage with the same iterator.
NewPageInfo exposes internals for iterator implementations. It is not a stable interface.
newPageInfo creates and returns a PageInfo and a next func. If an iterator can support paging, its iterator-creating method should call this. Each time the iterator's Next is called, it should call the returned next fn to determine whether a next item exists, and if so it should pop an item from the buffer. The fetch, bufLen and takeBuf arguments provide access to the iterator's internal slice of buffered items. They behave as described in PageInfo, above. The return value is the PageInfo.next method bound to the returned PageInfo value. (Returning it avoids exporting PageInfo.next.) Note: the returned PageInfo and next fn do not remove items from the buffer. It is up to the iterator using these to remove items from the buffer: typically by performing a pop in its Next. If items are not removed from the buffer, memory may grow unbounded.
func ( func(int, string) (string, error),  func() int,  func() interface{}) ( *PageInfo,  func() error) {
	 = &PageInfo{
		fetch:   ,
		bufLen:  ,
		takeBuf: ,
	}
	return , .next
}
Remaining returns the number of items available before the iterator makes another API call.
func ( *PageInfo) () int { return .bufLen() }
next provides support for an iterator's Next function. An iterator's Next should return the error returned by next if non-nil; else it can assume there is at least one item in its buffer, and it should return that item and remove it from the buffer.
func ( *PageInfo) () error {
	.nextCalled = true
TODO(jba): fix so users can retry on transient errors? Probably not worth it.
		return .err
	}
	if .nextPageCalled {
		.err = errMixed
		return .err
Loop until we get some items or reach the end.
	for .bufLen() == 0 && !.atEnd {
		if  := .fill(.MaxSize);  != nil {
			.err = 
			return .err
		}
		if .Token == "" {
			.atEnd = true
		}
Either the buffer is non-empty or pi.atEnd is true (or both).
The buffer is empty and pi.atEnd is true, i.e. the service has no more items.
		.err = Done
	}
	return .err
}
Call the service to fill the buffer, using size and pi.Token. Set pi.Token to the next-page token returned by the call. If fill returns a non-nil error, the buffer will be empty.
func ( *PageInfo) ( int) error {
	,  := .fetch(, .Token)
	if  != nil {
		.takeBuf() // clear the buffer
		return 
	}
	.Token = 
	return nil
}
Pageable is implemented by iterators that support paging.
PageInfo returns paging information associated with the iterator.
	PageInfo() *PageInfo
}
Pager supports retrieving iterator items a page at a time.
type Pager struct {
	pageInfo *PageInfo
	pageSize int
}
NewPager returns a pager that uses iter. Calls to its NextPage method will obtain exactly pageSize items, unless fewer remain. The pageToken argument indicates where to start the iteration. Pass the empty string to start at the beginning, or pass a token retrieved from a call to Pager.NextPage. If you use an iterator with a Pager, you must not call Next on the iterator.
func ( Pageable,  int,  string) *Pager {
	 := &Pager{
		pageInfo: .PageInfo(),
		pageSize: ,
	}
	.pageInfo.Token = 
	if  <= 0 {
		.pageInfo.err = errors.New("iterator: page size must be positive")
	}
	return 
}
NextPage retrieves a sequence of items from the iterator and appends them to slicep, which must be a pointer to a slice of the iterator's item type. Exactly p.pageSize items will be appended, unless fewer remain. The first return value is the page token to use for the next page of items. If empty, there are no more pages. Aside from checking for the end of the iteration, the returned page token is only needed if the iteration is to be resumed a later time, in another context (possibly another process). The second return value is non-nil if an error occurred. It will never be the special iterator sentinel value Done. To recognize the end of the iteration, compare nextPageToken to the empty string. It is possible for NextPage to return a single zero-length page along with an empty page token when there are no more items in the iteration.
func ( *Pager) ( interface{}) ( string,  error) {
	.pageInfo.nextPageCalled = true
	if .pageInfo.err != nil {
		return "", .pageInfo.err
	}
	if .pageInfo.nextCalled {
		.pageInfo.err = errMixed
		return "", .pageInfo.err
	}
	if .pageInfo.bufLen() > 0 {
		return "", errors.New("must call NextPage with an empty buffer")
The buffer must be empty here, so takeBuf is a no-op. We call it just to get the buffer's type.
	 := reflect.PtrTo(reflect.ValueOf(.pageInfo.takeBuf()).Type())
	if  == nil {
		return "", errors.New("nil passed to Pager.NextPage")
	}
	 := reflect.ValueOf()
	if .Type() !=  {
		return "", fmt.Errorf("slicep should be of type %s, got %T", , )
	}
	for .pageInfo.bufLen() < .pageSize {
		if  := .pageInfo.fill(.pageSize - .pageInfo.bufLen());  != nil {
			.pageInfo.err = 
			return "", .pageInfo.err
		}
		if .pageInfo.Token == "" {
			break
		}
	}
	 := .Elem()
	.Set(reflect.AppendSlice(, reflect.ValueOf(.pageInfo.takeBuf())))
	return .pageInfo.Token, nil