2024-10-25 09:45:42 +02:00
|
|
|
package cursortoken
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base32"
|
|
|
|
"encoding/json"
|
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type CTKeySort struct {
|
|
|
|
Mode Mode
|
|
|
|
ValuePrimary string
|
|
|
|
ValueSecondary string
|
|
|
|
Direction SortDirection
|
|
|
|
DirectionSecondary SortDirection
|
|
|
|
PageSize int
|
|
|
|
Extra Extra
|
|
|
|
}
|
|
|
|
|
|
|
|
type cursorTokenKeySortSerialize struct {
|
|
|
|
ValuePrimary *string `json:"v1,omitempty"`
|
|
|
|
ValueSecondary *string `json:"v2,omitempty"`
|
|
|
|
Direction *SortDirection `json:"dir,omitempty"`
|
|
|
|
DirectionSecondary *SortDirection `json:"dir2,omitempty"`
|
|
|
|
PageSize *int `json:"size,omitempty"`
|
|
|
|
|
|
|
|
ExtraTimestamp *time.Time `json:"ts,omitempty"`
|
|
|
|
ExtraId *string `json:"id,omitempty"`
|
|
|
|
ExtraPage *int `json:"pg,omitempty"`
|
|
|
|
ExtraPageSize *int `json:"sz,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewKeySortToken(valuePrimary string, valueSecondary string, direction SortDirection, directionSecondary SortDirection, pageSize int, extra Extra) CursorToken {
|
|
|
|
return CTKeySort{
|
|
|
|
Mode: CTMNormal,
|
|
|
|
ValuePrimary: valuePrimary,
|
|
|
|
ValueSecondary: valueSecondary,
|
|
|
|
Direction: direction,
|
|
|
|
DirectionSecondary: directionSecondary,
|
|
|
|
PageSize: pageSize,
|
|
|
|
Extra: extra,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Start() CursorToken {
|
|
|
|
return CTKeySort{
|
|
|
|
Mode: CTMStart,
|
|
|
|
ValuePrimary: "",
|
|
|
|
ValueSecondary: "",
|
|
|
|
Direction: "",
|
|
|
|
DirectionSecondary: "",
|
|
|
|
PageSize: 0,
|
|
|
|
Extra: Extra{},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func End() CursorToken {
|
|
|
|
return CTKeySort{
|
|
|
|
Mode: CTMEnd,
|
|
|
|
ValuePrimary: "",
|
|
|
|
ValueSecondary: "",
|
|
|
|
Direction: "",
|
|
|
|
DirectionSecondary: "",
|
|
|
|
PageSize: 0,
|
|
|
|
Extra: Extra{},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CTKeySort) Token() string {
|
|
|
|
|
|
|
|
if c.Mode == CTMStart {
|
|
|
|
return "@start"
|
|
|
|
}
|
|
|
|
if c.Mode == CTMEnd {
|
|
|
|
return "@end"
|
|
|
|
}
|
|
|
|
|
|
|
|
// We kinda manually implement omitempty for the CursorToken here
|
|
|
|
// because omitempty does not work for time.Time and otherwise we would always
|
|
|
|
// get weird time values when decoding a token that initially didn't have an Timestamp set
|
|
|
|
// For this usecase we treat Unix=0 as an empty timestamp
|
|
|
|
|
|
|
|
sertok := cursorTokenKeySortSerialize{}
|
|
|
|
|
|
|
|
if c.ValuePrimary != "" {
|
|
|
|
sertok.ValuePrimary = &c.ValuePrimary
|
|
|
|
}
|
|
|
|
if c.ValueSecondary != "" {
|
|
|
|
sertok.ValueSecondary = &c.ValueSecondary
|
|
|
|
}
|
|
|
|
if c.Direction != "" {
|
|
|
|
sertok.Direction = &c.Direction
|
|
|
|
}
|
|
|
|
if c.DirectionSecondary != "" {
|
|
|
|
sertok.DirectionSecondary = &c.DirectionSecondary
|
|
|
|
}
|
|
|
|
if c.PageSize != 0 {
|
|
|
|
sertok.PageSize = &c.PageSize
|
|
|
|
}
|
|
|
|
|
|
|
|
sertok.ExtraTimestamp = c.Extra.Timestamp
|
|
|
|
sertok.ExtraId = c.Extra.Id
|
|
|
|
sertok.ExtraPage = c.Extra.Page
|
|
|
|
sertok.ExtraPageSize = c.Extra.PageSize
|
|
|
|
|
|
|
|
body, err := json.Marshal(sertok)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return "tok_" + base32.StdEncoding.EncodeToString(body)
|
|
|
|
}
|
|
|
|
|
2024-10-27 02:21:35 +02:00
|
|
|
func (c CTKeySort) IsEnd() bool {
|
|
|
|
return c.Mode == CTMEnd
|
|
|
|
}
|
|
|
|
|
2024-10-25 09:45:42 +02:00
|
|
|
func (c CTKeySort) valuePrimaryObjectId() (primitive.ObjectID, bool) {
|
|
|
|
if oid, err := primitive.ObjectIDFromHex(c.ValuePrimary); err == nil {
|
|
|
|
return oid, true
|
|
|
|
} else {
|
|
|
|
return primitive.ObjectID{}, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CTKeySort) valueSecondaryObjectId() (primitive.ObjectID, bool) {
|
|
|
|
if oid, err := primitive.ObjectIDFromHex(c.ValueSecondary); err == nil {
|
|
|
|
return oid, true
|
|
|
|
} else {
|
|
|
|
return primitive.ObjectID{}, false
|
|
|
|
}
|
|
|
|
}
|