forked from einride/aip-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pagetoken.go
68 lines (62 loc) · 1.97 KB
/
pagetoken.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
package pagination
import (
"fmt"
)
// PageToken is a page token that uses an offset to delineate which page to fetch.
type PageToken struct {
// Offset of the page.
Offset int64
// RequestChecksum is the checksum of the request that generated the page token.
RequestChecksum uint32
}
// pageTokenChecksumMask is a random bitmask applied to offset-based page token checksums.
//
// Change the bitmask to force checksum failures when changing the page token implementation.
const pageTokenChecksumMask uint32 = 0x9acb0442
// ParsePageToken parses an offset-based page token from the provided Request.
//
// If the request does not have a page token, a page token with offset 0 will be returned.
func ParsePageToken(request Request) (_ PageToken, err error) {
defer func() {
if err != nil {
err = fmt.Errorf("parse offset page token: %w", err)
}
}()
requestChecksum, err := calculateRequestChecksum(request)
if err != nil {
return PageToken{}, err
}
requestChecksum ^= pageTokenChecksumMask // apply checksum mask for PageToken
if request.GetPageToken() == "" {
offset := int64(0)
if s, ok := request.(skipRequest); ok {
offset += int64(s.GetSkip())
}
return PageToken{
Offset: offset,
RequestChecksum: requestChecksum,
}, nil
}
var pageToken PageToken
if err := DecodePageTokenStruct(request.GetPageToken(), &pageToken); err != nil {
return PageToken{}, err
}
if pageToken.RequestChecksum != requestChecksum {
return PageToken{}, fmt.Errorf(
"checksum mismatch (got 0x%x but expected 0x%x)", pageToken.RequestChecksum, requestChecksum,
)
}
if s, ok := request.(skipRequest); ok {
pageToken.Offset += int64(s.GetSkip())
}
return pageToken, nil
}
// Next returns the next page token for the provided Request.
func (p PageToken) Next(request Request) PageToken {
p.Offset += int64(request.GetPageSize())
return p
}
// String returns a string representation of the page token.
func (p PageToken) String() string {
return EncodePageTokenStruct(&p)
}