Improve paging cursor enc/dec
This commit is contained in:
parent
9a21226163
commit
8cee9740ae
@ -35,6 +35,10 @@ type (
|
||||
desc []bool
|
||||
Reverse bool
|
||||
}
|
||||
|
||||
pagingCursorValue struct {
|
||||
v interface{}
|
||||
}
|
||||
)
|
||||
|
||||
func NewPaging(limit uint, cursor string) (p Paging, err error) {
|
||||
@ -68,6 +72,7 @@ func (p *PagingCursor) Values() []interface{} {
|
||||
return p.values
|
||||
}
|
||||
|
||||
// Stirng to implement Stringer and to get human-readable representation of the cursor
|
||||
func (p *PagingCursor) String() string {
|
||||
var o = "<"
|
||||
|
||||
@ -84,6 +89,7 @@ func (p *PagingCursor) String() string {
|
||||
return o + ">"
|
||||
}
|
||||
|
||||
// MarshalJSON serializes cursor struct as JSON and encodes it as base64 + adds quotes to be treated as JSON string
|
||||
func (p *PagingCursor) MarshalJSON() ([]byte, error) {
|
||||
buf, err := json.Marshal(struct {
|
||||
K []string
|
||||
@ -117,7 +123,7 @@ func (p *PagingCursor) UnmarshalJSON(in []byte) error {
|
||||
var (
|
||||
aux struct {
|
||||
K []string
|
||||
V []interface{}
|
||||
V []pagingCursorValue
|
||||
D []bool
|
||||
R bool
|
||||
}
|
||||
@ -128,10 +134,15 @@ func (p *PagingCursor) UnmarshalJSON(in []byte) error {
|
||||
}
|
||||
|
||||
p.keys = aux.K
|
||||
p.values = aux.V
|
||||
p.desc = aux.D
|
||||
p.Reverse = aux.R
|
||||
|
||||
// json.Unmarshal treats uint64 in values ([]interface{}) as float64 and we don't like that.
|
||||
p.values = make([]interface{}, len(aux.V))
|
||||
for i, v := range aux.V {
|
||||
p.values[i] = v.v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -166,3 +177,23 @@ func parseCursor(in string) (p *PagingCursor, err error) {
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Making sure uint64 other int* values are properly unmarshaled
|
||||
func (v *pagingCursorValue) UnmarshalJSON(in []byte) (err error) {
|
||||
var (
|
||||
u uint64
|
||||
i int64
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(in, &u); err == nil {
|
||||
v.v = u
|
||||
return
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(in, &i); err == nil {
|
||||
v.v = i
|
||||
return
|
||||
}
|
||||
|
||||
return json.Unmarshal(in, &v.v)
|
||||
}
|
||||
|
||||
64
pkg/filter/pagination_test.go
Normal file
64
pkg/filter/pagination_test.go
Normal file
@ -0,0 +1,64 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_cursorEncDec(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
|
||||
id = uint64(201244712307261628)
|
||||
|
||||
enc string
|
||||
cur = &PagingCursor{}
|
||||
dec = &PagingCursor{}
|
||||
)
|
||||
|
||||
{
|
||||
cur.Set("uint64", id, true)
|
||||
cur.Set("string", "foo", true)
|
||||
req.Len(cur.values, 2)
|
||||
req.Equal(id, cur.values[0])
|
||||
req.Equal(fmt.Sprintf("<uint64: %d, string: foo, forward>", id), cur.String())
|
||||
}
|
||||
|
||||
{
|
||||
enc = cur.Encode()
|
||||
req.NotEmpty(enc)
|
||||
}
|
||||
{
|
||||
req.NoError(dec.Decode(enc[1 : len(enc)-1]))
|
||||
req.Len(dec.values, 2)
|
||||
req.Equal(id, dec.values[0])
|
||||
req.Equal("foo", dec.values[1])
|
||||
req.Equal(fmt.Sprintf("<uint64: %d, string: foo, forward>", id), cur.String())
|
||||
}
|
||||
}
|
||||
|
||||
func Test_cursorValueUnmarshal(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
pcv = &pagingCursorValue{}
|
||||
)
|
||||
|
||||
req.NoError(pcv.UnmarshalJSON([]byte("201244712307261628")))
|
||||
req.Equal(pcv.v, uint64(201244712307261628))
|
||||
|
||||
req.NoError(pcv.UnmarshalJSON([]byte("42")))
|
||||
req.Equal(pcv.v, uint64(42))
|
||||
|
||||
req.NoError(pcv.UnmarshalJSON([]byte("-42")))
|
||||
req.Equal(pcv.v, int64(-42))
|
||||
|
||||
req.NoError(pcv.UnmarshalJSON([]byte("true")))
|
||||
req.Equal(pcv.v, true)
|
||||
|
||||
req.NoError(pcv.UnmarshalJSON([]byte("42.42")))
|
||||
req.Equal(pcv.v, 42.42)
|
||||
|
||||
req.NoError(pcv.UnmarshalJSON([]byte(`"foo"`)))
|
||||
req.Equal(pcv.v, "foo")
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user