pagination.go

  1// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
  2
  3package pagination
  4
  5import (
  6	"net/http"
  7	"reflect"
  8
  9	"github.com/openai/openai-go/internal/apijson"
 10	"github.com/openai/openai-go/internal/requestconfig"
 11	"github.com/openai/openai-go/option"
 12	"github.com/openai/openai-go/packages/param"
 13	"github.com/openai/openai-go/packages/resp"
 14)
 15
 16// aliased to make [param.APIUnion] private when embedding
 17type paramUnion = param.APIUnion
 18
 19// aliased to make [param.APIObject] private when embedding
 20type paramObj = param.APIObject
 21
 22type Page[T any] struct {
 23	Data   []T    `json:"data"`
 24	Object string `json:"object,required"`
 25	// Metadata for the response, check the presence of optional fields with the
 26	// [resp.Field.IsPresent] method.
 27	JSON struct {
 28		Data        resp.Field
 29		Object      resp.Field
 30		ExtraFields map[string]resp.Field
 31		raw         string
 32	} `json:"-"`
 33	cfg *requestconfig.RequestConfig
 34	res *http.Response
 35}
 36
 37// Returns the unmodified JSON received from the API
 38func (r Page[T]) RawJSON() string { return r.JSON.raw }
 39func (r *Page[T]) UnmarshalJSON(data []byte) error {
 40	return apijson.UnmarshalRoot(data, r)
 41}
 42
 43// GetNextPage returns the next page as defined by this pagination style. When
 44// there is no next page, this function will return a 'nil' for the page value, but
 45// will not return an error
 46func (r *Page[T]) GetNextPage() (res *Page[T], err error) {
 47	// This page represents a response that isn't actually paginated at the API level
 48	// so there will never be a next page.
 49	cfg := (*requestconfig.RequestConfig)(nil)
 50	if cfg == nil {
 51		return nil, nil
 52	}
 53	var raw *http.Response
 54	cfg.ResponseInto = &raw
 55	cfg.ResponseBodyInto = &res
 56	err = cfg.Execute()
 57	if err != nil {
 58		return nil, err
 59	}
 60	res.SetPageConfig(cfg, raw)
 61	return res, nil
 62}
 63
 64func (r *Page[T]) SetPageConfig(cfg *requestconfig.RequestConfig, res *http.Response) {
 65	if r == nil {
 66		r = &Page[T]{}
 67	}
 68	r.cfg = cfg
 69	r.res = res
 70}
 71
 72type PageAutoPager[T any] struct {
 73	page *Page[T]
 74	cur  T
 75	idx  int
 76	run  int
 77	err  error
 78	paramObj
 79}
 80
 81func NewPageAutoPager[T any](page *Page[T], err error) *PageAutoPager[T] {
 82	return &PageAutoPager[T]{
 83		page: page,
 84		err:  err,
 85	}
 86}
 87
 88func (r *PageAutoPager[T]) Next() bool {
 89	if r.page == nil || len(r.page.Data) == 0 {
 90		return false
 91	}
 92	if r.idx >= len(r.page.Data) {
 93		r.idx = 0
 94		r.page, r.err = r.page.GetNextPage()
 95		if r.err != nil || r.page == nil || len(r.page.Data) == 0 {
 96			return false
 97		}
 98	}
 99	r.cur = r.page.Data[r.idx]
100	r.run += 1
101	r.idx += 1
102	return true
103}
104
105func (r *PageAutoPager[T]) Current() T {
106	return r.cur
107}
108
109func (r *PageAutoPager[T]) Err() error {
110	return r.err
111}
112
113func (r *PageAutoPager[T]) Index() int {
114	return r.run
115}
116
117type CursorPage[T any] struct {
118	Data    []T  `json:"data"`
119	HasMore bool `json:"has_more"`
120	// Metadata for the response, check the presence of optional fields with the
121	// [resp.Field.IsPresent] method.
122	JSON struct {
123		Data        resp.Field
124		HasMore     resp.Field
125		ExtraFields map[string]resp.Field
126		raw         string
127	} `json:"-"`
128	cfg *requestconfig.RequestConfig
129	res *http.Response
130}
131
132// Returns the unmodified JSON received from the API
133func (r CursorPage[T]) RawJSON() string { return r.JSON.raw }
134func (r *CursorPage[T]) UnmarshalJSON(data []byte) error {
135	return apijson.UnmarshalRoot(data, r)
136}
137
138// GetNextPage returns the next page as defined by this pagination style. When
139// there is no next page, this function will return a 'nil' for the page value, but
140// will not return an error
141func (r *CursorPage[T]) GetNextPage() (res *CursorPage[T], err error) {
142	if r.JSON.HasMore.IsPresent() && r.HasMore == false {
143		return nil, nil
144	}
145	items := r.Data
146	if items == nil || len(items) == 0 {
147		return nil, nil
148	}
149	cfg := r.cfg.Clone(r.cfg.Context)
150	value := reflect.ValueOf(items[len(items)-1])
151	field := value.FieldByName("ID")
152	cfg.Apply(option.WithQuery("after", field.Interface().(string)))
153	var raw *http.Response
154	cfg.ResponseInto = &raw
155	cfg.ResponseBodyInto = &res
156	err = cfg.Execute()
157	if err != nil {
158		return nil, err
159	}
160	res.SetPageConfig(cfg, raw)
161	return res, nil
162}
163
164func (r *CursorPage[T]) SetPageConfig(cfg *requestconfig.RequestConfig, res *http.Response) {
165	if r == nil {
166		r = &CursorPage[T]{}
167	}
168	r.cfg = cfg
169	r.res = res
170}
171
172type CursorPageAutoPager[T any] struct {
173	page *CursorPage[T]
174	cur  T
175	idx  int
176	run  int
177	err  error
178	paramObj
179}
180
181func NewCursorPageAutoPager[T any](page *CursorPage[T], err error) *CursorPageAutoPager[T] {
182	return &CursorPageAutoPager[T]{
183		page: page,
184		err:  err,
185	}
186}
187
188func (r *CursorPageAutoPager[T]) Next() bool {
189	if r.page == nil || len(r.page.Data) == 0 {
190		return false
191	}
192	if r.idx >= len(r.page.Data) {
193		r.idx = 0
194		r.page, r.err = r.page.GetNextPage()
195		if r.err != nil || r.page == nil || len(r.page.Data) == 0 {
196			return false
197		}
198	}
199	r.cur = r.page.Data[r.idx]
200	r.run += 1
201	r.idx += 1
202	return true
203}
204
205func (r *CursorPageAutoPager[T]) Current() T {
206	return r.cur
207}
208
209func (r *CursorPageAutoPager[T]) Err() error {
210	return r.err
211}
212
213func (r *CursorPageAutoPager[T]) Index() int {
214	return r.run
215}