~bigbes/core-go

ref: 21deda8caa1807ec3d00d29ba41a407e6a5866d5 core-go/model/cursor.go -rw-r--r-- 1.2 KiB
21deda8c — Drew DeVault valid: add OptionalBool 4 years ago
                                                                                
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
package model

import (
	"encoding/json"
	"fmt"
	"io"

	"git.sr.ht/~sircmpwn/core-go/crypto"
)

// TODO: Add field to prevent cursor reuse across unrelated resources
type Cursor struct {
	Count  int    `json:"count"`
	Next   string `json:"next"`
	Search string `json:"search"`
}

func (cur *Cursor) UnmarshalGQL(v interface{}) error {
	enc, ok := v.(string)
	if !ok {
		return fmt.Errorf("cursor must be strings")
	}
	plain := crypto.DecryptWithoutExpiration([]byte(enc))
	if plain == nil {
		return fmt.Errorf("Invalid cursor")
	}
	err := json.Unmarshal(plain, cur)
	if err != nil {
		// This is guaranteed to be a programming error
		panic(err)
	}
	return nil
}

func (cur Cursor) MarshalGQL(w io.Writer) {
	data, err := json.Marshal(cur)
	if err != nil {
		panic(err)
	}
	w.Write([]byte("\""))
	w.Write(crypto.Encrypt(data))
	w.Write([]byte("\""))
}

func derefOrInt(i *int, d int) int {
	if i != nil {
		return *i
	}
	return d
}

func NewCursor(filter *Filter) *Cursor {
	if filter != nil {
		count := derefOrInt(filter.Count, 25)
		if count <= 0 {
			count = 25
		}
		return &Cursor{
			Next:   "",
			Count:  count,
			Search: "", // TODO
		}
	}
	return &Cursor{
		Count:  25,
		Next:   "",
		Search: "",
	}
}