github.com/Files-com/files-sdk-go/v3@v3.1.81/iter.go (about) 1 package files_sdk 2 3 import ( 4 "github.com/Files-com/files-sdk-go/v3/lib" 5 ) 6 7 type ListParams struct { 8 Page int64 `json:"page,omitempty" url:"page,omitempty" required:"false"` 9 PerPage int64 `json:"per_page,omitempty" url:"per_page,omitempty" required:"false"` 10 Cursor string `json:"cursor,omitempty" url:"cursor,omitempty" required:"false"` 11 MaxPages int64 `json:"-" url:"-"` 12 } 13 14 // ListParamsContainer is a general interface for which all list parameter 15 // structs should comply. They achieve this by embedding a ListParams struct 16 // and inheriting its implementation of this interface. 17 type ListParamsContainer interface { 18 GetListParams() *ListParams 19 } 20 21 // GetListParams returns a ListParams struct (itself). It exists because any 22 // structs that embed ListParams will inherit it, and thus implement the 23 // ListParamsContainer interface. 24 func (p *ListParams) GetListParams() *ListParams { 25 return p 26 } 27 28 type OnPageError func(error) (*[]interface{}, error) 29 type Query func(params lib.Values, opts ...RequestResponseOption) (*[]interface{}, string, error) 30 31 type IterI interface { 32 Next() bool 33 Current() interface{} 34 Err() error 35 } 36 37 var _ IterI = (*Iter)(nil) 38 39 type TypedIterI[T any] interface { 40 Next() bool 41 Current() interface{} 42 Resource() T 43 Err() error 44 } 45 46 type IterPagingI interface { 47 IterI 48 EOFPage() bool 49 } 50 51 var _ IterPagingI = (*Iter)(nil) 52 53 type ResourceIterator interface { 54 Iterate(interface{}, ...RequestResponseOption) (IterI, error) 55 } 56 57 type ReloadIterator interface { 58 Reload(opts ...RequestResponseOption) IterI 59 } 60 61 var _ ReloadIterator = (*Iter)(nil) 62 63 type ResourceLoader interface { 64 LoadResource(interface{}, ...RequestResponseOption) (interface{}, error) 65 } 66 67 type Identifier interface { 68 Identifier() interface{} 69 } 70 71 type Iterable interface { 72 Iterable() bool 73 } 74 75 type Iter struct { 76 Query 77 ListParams ListParamsContainer 78 Params []interface{} 79 CurrentIndex int 80 Values *[]interface{} 81 Cursor string 82 Error error 83 OnPageError 84 requestResponseOptions []RequestResponseOption 85 } 86 87 // Err returns the error, if any, 88 // that caused the Iter to stop. 89 // It must be inspected 90 // after Next returns false. 91 func (i *Iter) Err() error { 92 return i.Error 93 } 94 95 func (i *Iter) Current() interface{} { 96 return (*i.Values)[i.CurrentIndex] 97 } 98 99 func (i *Iter) GetParams() *ListParams { 100 return i.ListParams.GetListParams() 101 } 102 103 func (i *Iter) ExportParams() (lib.ExportValues, error) { 104 p := lib.Params{Params: i.GetParams()} 105 paramValues, err := p.ToValues() 106 if err != nil { 107 return lib.ExportValues{}, err 108 } 109 listParamValues, err := lib.Params{Params: i.ListParams}.ToValues() 110 111 if err != nil { 112 return lib.ExportValues{}, err 113 } 114 115 for key, value := range paramValues { 116 listParamValues.Set(key, value[0]) 117 } 118 119 if i.GetCursor() != "" { 120 listParamValues.Del("page") 121 } 122 123 return lib.ExportValues{Values: listParamValues}, nil 124 } 125 126 func (i *Iter) GetPage() bool { 127 if i.GetParams().MaxPages != 0 && i.GetParams().Page == i.GetParams().MaxPages { 128 return false 129 } 130 131 i.CurrentIndex = 0 132 133 i.GetParams().Page += 1 134 if i.GetParams().Page == 2 && i.Cursor == "" { 135 return false 136 } 137 params, _ := i.ExportParams() 138 i.Values, i.Cursor, i.Error = i.Query(params, i.requestResponseOptions...) 139 i.SetCursor(i.Cursor) 140 if i.Error != nil && i.OnPageError != nil { 141 i.Values, i.Error = i.OnPageError(i.Error) 142 } 143 return i.Error == nil && len(*i.Values) != 0 144 } 145 146 func (i *Iter) EOFPage() bool { 147 return len(*i.Values) == i.CurrentIndex+1 148 } 149 150 func (i *Iter) Paging() bool { 151 return true 152 } 153 154 func (i *Iter) GetCursor() string { 155 return i.GetParams().Cursor 156 } 157 158 func (i *Iter) SetCursor(cursor string) { 159 i.GetParams().Cursor = cursor 160 i.Cursor = cursor 161 } 162 163 // Next iterates the results in i.Current() or i.`ResourceName`(). 164 // It returns true until there are no results remaining. 165 // To adjust the number of results set ListParams.PerPage. 166 // To have it auto-paginate set ListParams.MaxPages, default is 1. 167 // 168 // To iterate over all results use the following pattern. 169 // 170 // for i.Next() { 171 // i.Current() 172 // } 173 func (i *Iter) Next() bool { 174 if i.Values == nil { 175 return i.GetPage() && len(*i.Values) > 0 176 } else if len(*i.Values) > i.CurrentIndex+1 { 177 i.CurrentIndex += 1 178 return true 179 } 180 181 if i.EOFPage() { 182 return i.GetPage() 183 } 184 185 return false 186 } 187 188 func (i *Iter) NextPage() bool { 189 return i.Cursor != "" 190 } 191 192 // Reload ignores any id passed in and creates a new reset Iter 193 func (i *Iter) Reload(opts ...RequestResponseOption) IterI { 194 newIter := *i 195 newIter.ListParams = &ListParams{} 196 newIter.requestResponseOptions = opts 197 return &newIter 198 }