2023-06-06 21:18:40 +02:00
|
|
|
package cursortoken
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base32"
|
|
|
|
"encoding/json"
|
2024-07-23 14:21:03 +02:00
|
|
|
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
2024-10-25 09:45:42 +02:00
|
|
|
"strconv"
|
2023-06-06 21:18:40 +02:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2024-10-25 09:45:42 +02:00
|
|
|
type CursorToken interface {
|
|
|
|
Token() string
|
2024-10-27 02:21:35 +02:00
|
|
|
IsEnd() bool
|
2024-10-25 09:45:42 +02:00
|
|
|
}
|
|
|
|
|
2023-06-06 21:18:40 +02:00
|
|
|
type Mode string
|
|
|
|
|
|
|
|
const (
|
|
|
|
CTMStart Mode = "START"
|
|
|
|
CTMNormal Mode = "NORMAL"
|
|
|
|
CTMEnd Mode = "END"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Extra struct {
|
|
|
|
Timestamp *time.Time
|
|
|
|
Id *string
|
|
|
|
Page *int
|
|
|
|
PageSize *int
|
|
|
|
}
|
|
|
|
|
|
|
|
func Decode(tok string) (CursorToken, error) {
|
|
|
|
if tok == "" {
|
|
|
|
return Start(), nil
|
|
|
|
}
|
|
|
|
if strings.ToLower(tok) == "@start" {
|
|
|
|
return Start(), nil
|
|
|
|
}
|
|
|
|
if strings.ToLower(tok) == "@end" {
|
|
|
|
return End(), nil
|
|
|
|
}
|
2024-10-25 09:45:42 +02:00
|
|
|
if strings.ToLower(tok) == "$end" {
|
|
|
|
return PageEnd(), nil
|
|
|
|
}
|
|
|
|
if strings.HasPrefix(tok, "$") && len(tok) > 1 {
|
|
|
|
n, err := strconv.ParseInt(tok[1:], 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return nil, exerr.Wrap(err, "failed to deserialize token").Str("token", tok).WithType(exerr.TypeCursorTokenDecode).Build()
|
|
|
|
}
|
|
|
|
return Page(int(n)), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if strings.HasPrefix(tok, "tok_") {
|
|
|
|
|
|
|
|
body, err := base32.StdEncoding.DecodeString(tok[len("tok_"):])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var tokenDeserialize cursorTokenKeySortSerialize
|
|
|
|
err = json.Unmarshal(body, &tokenDeserialize)
|
|
|
|
if err != nil {
|
|
|
|
return nil, exerr.Wrap(err, "failed to deserialize token").Str("token", tok).WithType(exerr.TypeCursorTokenDecode).Build()
|
|
|
|
}
|
|
|
|
|
|
|
|
token := CTKeySort{Mode: CTMNormal}
|
|
|
|
|
|
|
|
if tokenDeserialize.ValuePrimary != nil {
|
|
|
|
token.ValuePrimary = *tokenDeserialize.ValuePrimary
|
|
|
|
}
|
|
|
|
if tokenDeserialize.ValueSecondary != nil {
|
|
|
|
token.ValueSecondary = *tokenDeserialize.ValueSecondary
|
|
|
|
}
|
|
|
|
if tokenDeserialize.Direction != nil {
|
|
|
|
token.Direction = *tokenDeserialize.Direction
|
|
|
|
}
|
|
|
|
if tokenDeserialize.DirectionSecondary != nil {
|
|
|
|
token.DirectionSecondary = *tokenDeserialize.DirectionSecondary
|
|
|
|
}
|
|
|
|
if tokenDeserialize.PageSize != nil {
|
|
|
|
token.PageSize = *tokenDeserialize.PageSize
|
|
|
|
}
|
|
|
|
|
|
|
|
token.Extra.Timestamp = tokenDeserialize.ExtraTimestamp
|
|
|
|
token.Extra.Id = tokenDeserialize.ExtraId
|
|
|
|
token.Extra.Page = tokenDeserialize.ExtraPage
|
|
|
|
token.Extra.PageSize = tokenDeserialize.ExtraPageSize
|
|
|
|
|
|
|
|
return token, nil
|
2023-06-06 21:18:40 +02:00
|
|
|
|
|
|
|
} else {
|
2024-10-25 09:45:42 +02:00
|
|
|
return nil, exerr.New(exerr.TypeCursorTokenDecode, "could not decode token, missing/unknown prefix").Str("token", tok).Build()
|
2023-06-06 21:18:40 +02:00
|
|
|
}
|
|
|
|
}
|