mirror of
https://github.com/rjNemo/go-wiki
synced 2026-06-06 02:36:40 +00:00
133 lines
3 KiB
Go
133 lines
3 KiB
Go
package stripe
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/stripe/stripe-go/form"
|
|
)
|
|
|
|
//
|
|
// Public types
|
|
//
|
|
|
|
// Iter provides a convenient interface
|
|
// for iterating over the elements
|
|
// returned from paginated list API calls.
|
|
// Successive calls to the Next method
|
|
// will step through each item in the list,
|
|
// fetching pages of items as needed.
|
|
// Iterators are not thread-safe, so they should not be consumed
|
|
// across multiple goroutines.
|
|
type Iter struct {
|
|
cur interface{}
|
|
err error
|
|
formValues *form.Values
|
|
listParams ListParams
|
|
meta ListMeta
|
|
query Query
|
|
values []interface{}
|
|
}
|
|
|
|
// Current returns the most recent item
|
|
// visited by a call to Next.
|
|
func (it *Iter) Current() interface{} {
|
|
return it.cur
|
|
}
|
|
|
|
// Err returns the error, if any,
|
|
// that caused the Iter to stop.
|
|
// It must be inspected
|
|
// after Next returns false.
|
|
func (it *Iter) Err() error {
|
|
return it.err
|
|
}
|
|
|
|
// Meta returns the list metadata.
|
|
func (it *Iter) Meta() *ListMeta {
|
|
return &it.meta
|
|
}
|
|
|
|
// Next advances the Iter to the next item in the list,
|
|
// which will then be available
|
|
// through the Current method.
|
|
// It returns false when the iterator stops
|
|
// at the end of the list.
|
|
func (it *Iter) Next() bool {
|
|
if len(it.values) == 0 && it.meta.HasMore && !it.listParams.Single {
|
|
// determine if we're moving forward or backwards in paging
|
|
if it.listParams.EndingBefore != nil {
|
|
it.listParams.EndingBefore = String(listItemID(it.cur))
|
|
it.formValues.Set(EndingBefore, *it.listParams.EndingBefore)
|
|
} else {
|
|
it.listParams.StartingAfter = String(listItemID(it.cur))
|
|
it.formValues.Set(StartingAfter, *it.listParams.StartingAfter)
|
|
}
|
|
it.getPage()
|
|
}
|
|
if len(it.values) == 0 {
|
|
return false
|
|
}
|
|
it.cur = it.values[0]
|
|
it.values = it.values[1:]
|
|
return true
|
|
}
|
|
|
|
func (it *Iter) getPage() {
|
|
it.values, it.meta, it.err = it.query(it.listParams.GetParams(), it.formValues)
|
|
|
|
if it.listParams.EndingBefore != nil {
|
|
// We are moving backward,
|
|
// but items arrive in forward order.
|
|
reverse(it.values)
|
|
}
|
|
}
|
|
|
|
// Query is the function used to get a page listing.
|
|
type Query func(*Params, *form.Values) ([]interface{}, ListMeta, error)
|
|
|
|
//
|
|
// Public functions
|
|
//
|
|
|
|
// GetIter returns a new Iter for a given query and its options.
|
|
func GetIter(container ListParamsContainer, query Query) *Iter {
|
|
var listParams *ListParams
|
|
formValues := &form.Values{}
|
|
|
|
if container != nil {
|
|
reflectValue := reflect.ValueOf(container)
|
|
|
|
// See the comment on Call in stripe.go.
|
|
if reflectValue.Kind() == reflect.Ptr && !reflectValue.IsNil() {
|
|
listParams = container.GetListParams()
|
|
form.AppendTo(formValues, container)
|
|
}
|
|
}
|
|
|
|
if listParams == nil {
|
|
listParams = &ListParams{}
|
|
}
|
|
iter := &Iter{
|
|
formValues: formValues,
|
|
listParams: *listParams,
|
|
query: query,
|
|
}
|
|
|
|
iter.getPage()
|
|
|
|
return iter
|
|
}
|
|
|
|
//
|
|
// Private functions
|
|
//
|
|
|
|
func listItemID(x interface{}) string {
|
|
return reflect.ValueOf(x).Elem().FieldByName("ID").String()
|
|
}
|
|
|
|
func reverse(a []interface{}) {
|
|
for i := 0; i < len(a)/2; i++ {
|
|
a[i], a[len(a)-i-1] = a[len(a)-i-1], a[i]
|
|
}
|
|
}
|