package cursortoken import ( "encoding/base32" "encoding/json" "gogs.mikescher.com/BlackForestBytes/goext/exerr" "strconv" "strings" "time" ) type CursorToken interface { Token() string IsEnd() bool } 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 } 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 } else { return nil, exerr.New(exerr.TypeCursorTokenDecode, "could not decode token, missing/unknown prefix").Str("token", tok).Build() } }