-
Notifications
You must be signed in to change notification settings - Fork 124
/
list_opt.go
102 lines (89 loc) · 2.29 KB
/
list_opt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package client
import (
"fmt"
"net/url"
"reflect"
)
const (
filterTagName = "qs"
DefaultPage = 1
DefaultPageSize = 50
PageField = "page"
PerPageField = "per_page"
)
type ListOptionsSerializer interface {
Serialize(values url.Values, tag string) error
}
var listOptionsSerializerType = reflect.TypeOf((*ListOptionsSerializer)(nil)).Elem()
type ListOptioner interface {
CurrentPage(page, perPage int)
ToQueryString() (url.Values, error)
}
// ListOptions is the shared common type for all other list option types
type ListOptions struct {
Page int `qs:"page"`
PerPage int `qs:"per_page"`
OrderBy string `qs:"order_by"`
LabelSel LabelSelector `qs:"label_selector"`
CreateAts TimestampFilter `qs:"created_ats"`
UpdatedAts TimestampFilter `qs:"updated_ats"`
}
// NewListOptions creates a default list options with page and page size set
func NewListOptions() *ListOptions {
return &ListOptions{
Page: DefaultPage,
PerPage: DefaultPageSize,
}
}
func (lo *ListOptions) CurrentPage(page, perPage int) {
lo.Page = page
lo.PerPage = perPage
}
func (lo ListOptions) Serialize(values url.Values, _ string) error {
return serializeField(values, reflect.ValueOf(lo))
}
func (lo *ListOptions) ToQueryString(subOptionsPtr any) (url.Values, error) {
if subOptionsPtr != nil {
values := url.Values{}
err := serializeField(values, reflect.ValueOf(subOptionsPtr))
return values, err
}
return nil, nil
}
func serializeField(values url.Values, val reflect.Value) error {
if val.Kind() == reflect.Ptr {
if val.IsNil() {
return nil
}
val = val.Elem()
}
if val.Kind() != reflect.Struct {
return nil
}
valTypes := val.Type()
for i := 0; i < valTypes.NumField(); i++ {
fieldType := valTypes.Field(i)
rawTag := fieldType.Tag.Get(filterTagName)
if (rawTag != "" && rawTag != "-") || fieldType.Type.Implements(listOptionsSerializerType) {
sv := val.Field(i)
if sv.Kind() == reflect.Ptr {
if sv.IsNil() {
continue
}
sv = sv.Elem()
}
if sv.IsZero() {
continue
}
svi := sv.Interface()
if filter, ok := svi.(ListOptionsSerializer); ok {
if err := filter.Serialize(values, rawTag); err != nil {
return err
}
} else {
values.Add(rawTag, fmt.Sprintf("%v", svi))
}
}
}
return nil
}