finalize session management
This commit is contained in:
parent
8c134774ee
commit
50f4cb91f6
|
@ -139,33 +139,26 @@ func (s *Session) SizePlain() (size int) {
|
||||||
// ID
|
// ID
|
||||||
size += bstd.SizeString(s.ID)
|
size += bstd.SizeString(s.ID)
|
||||||
|
|
||||||
// Data (map of string to any)
|
// Data map
|
||||||
// For simplicity, we store data as binary-encoded strings
|
size += bstd.SizeMap(s.Data, bstd.SizeString, func(v any) int {
|
||||||
// This is a simplification, in a real-world scenario you would handle
|
return sizeAny(v)
|
||||||
// different types differently
|
})
|
||||||
dataAsStrings := make(map[string]string)
|
|
||||||
for k, v := range s.Data {
|
|
||||||
dataAsStrings[k] = toString(v)
|
|
||||||
}
|
|
||||||
size += bstd.SizeMap(dataAsStrings, bstd.SizeString, bstd.SizeString)
|
|
||||||
|
|
||||||
// Time fields
|
// Time fields stored as int64 Unix timestamps
|
||||||
size += bstd.SizeInt64() * 4 // Store Unix timestamps for all time fields
|
size += bstd.SizeInt64() * 4
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalPlain serializes the session to binary
|
// MarshalPlain serializes the session to binary
|
||||||
func (s *Session) MarshalPlain(n int, b []byte) (int, error) {
|
func (s *Session) MarshalPlain(n int, b []byte) int {
|
||||||
// ID
|
// ID
|
||||||
n = bstd.MarshalString(n, b, s.ID)
|
n = bstd.MarshalString(n, b, s.ID)
|
||||||
|
|
||||||
// Data
|
// Data map
|
||||||
dataAsStrings := make(map[string]string)
|
n = bstd.MarshalMap(n, b, s.Data, bstd.MarshalString, func(n int, b []byte, v any) int {
|
||||||
for k, v := range s.Data {
|
return marshalAny(n, b, v)
|
||||||
dataAsStrings[k] = toString(v)
|
})
|
||||||
}
|
|
||||||
n = bstd.MarshalMap(n, b, dataAsStrings, bstd.MarshalString, bstd.MarshalString)
|
|
||||||
|
|
||||||
// Time fields as Unix timestamps
|
// Time fields as Unix timestamps
|
||||||
n = bstd.MarshalInt64(n, b, s.CreatedAt.Unix())
|
n = bstd.MarshalInt64(n, b, s.CreatedAt.Unix())
|
||||||
|
@ -173,7 +166,7 @@ func (s *Session) MarshalPlain(n int, b []byte) (int, error) {
|
||||||
n = bstd.MarshalInt64(n, b, s.LastUsed.Unix())
|
n = bstd.MarshalInt64(n, b, s.LastUsed.Unix())
|
||||||
n = bstd.MarshalInt64(n, b, s.Expiry.Unix())
|
n = bstd.MarshalInt64(n, b, s.Expiry.Unix())
|
||||||
|
|
||||||
return n, nil
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalPlain deserializes the session from binary
|
// UnmarshalPlain deserializes the session from binary
|
||||||
|
@ -186,44 +179,35 @@ func (s *Session) UnmarshalPlain(n int, b []byte) (int, error) {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data
|
// Data map
|
||||||
var dataAsStrings map[string]string
|
n, s.Data, err = bstd.UnmarshalMap[string, any](n, b, bstd.UnmarshalString, func(n int, b []byte) (int, any, error) {
|
||||||
n, dataAsStrings, err = bstd.UnmarshalMap[string, string](n, b, bstd.UnmarshalString, bstd.UnmarshalString)
|
return unmarshalAny(n, b)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert string data back to original types
|
// Time fields as Unix timestamps
|
||||||
s.Data = make(map[string]any, len(dataAsStrings))
|
|
||||||
for k, v := range dataAsStrings {
|
|
||||||
s.Data[k] = fromString(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time fields
|
|
||||||
var timestamp int64
|
var timestamp int64
|
||||||
|
|
||||||
// CreatedAt
|
|
||||||
n, timestamp, err = bstd.UnmarshalInt64(n, b)
|
n, timestamp, err = bstd.UnmarshalInt64(n, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
s.CreatedAt = time.Unix(timestamp, 0)
|
s.CreatedAt = time.Unix(timestamp, 0)
|
||||||
|
|
||||||
// UpdatedAt
|
|
||||||
n, timestamp, err = bstd.UnmarshalInt64(n, b)
|
n, timestamp, err = bstd.UnmarshalInt64(n, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
s.UpdatedAt = time.Unix(timestamp, 0)
|
s.UpdatedAt = time.Unix(timestamp, 0)
|
||||||
|
|
||||||
// LastUsed
|
|
||||||
n, timestamp, err = bstd.UnmarshalInt64(n, b)
|
n, timestamp, err = bstd.UnmarshalInt64(n, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
s.LastUsed = time.Unix(timestamp, 0)
|
s.LastUsed = time.Unix(timestamp, 0)
|
||||||
|
|
||||||
// Expiry
|
|
||||||
n, timestamp, err = bstd.UnmarshalInt64(n, b)
|
n, timestamp, err = bstd.UnmarshalInt64(n, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
|
@ -238,8 +222,7 @@ func (s *Session) Marshal() ([]byte, error) {
|
||||||
size := s.SizePlain()
|
size := s.SizePlain()
|
||||||
|
|
||||||
data, err := bufPool.Marshal(size, func(b []byte) (n int) {
|
data, err := bufPool.Marshal(size, func(b []byte) (n int) {
|
||||||
n, _ = s.MarshalPlain(0, b)
|
return s.MarshalPlain(0, b)
|
||||||
return n
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -260,52 +243,108 @@ func Unmarshal(data []byte) (*Session, error) {
|
||||||
return session, nil
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions to convert between any and string
|
// Type identifiers for any values
|
||||||
// In a production environment, you would use a more robust serialization method for the map values
|
const (
|
||||||
func toString(v any) string {
|
typeNull byte = 0
|
||||||
|
typeString byte = 1
|
||||||
|
typeInt byte = 2
|
||||||
|
typeFloat byte = 3
|
||||||
|
typeBool byte = 4
|
||||||
|
typeBytes byte = 5
|
||||||
|
)
|
||||||
|
|
||||||
|
// sizeAny calculates the size needed for any value
|
||||||
|
func sizeAny(v any) int {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return ""
|
return 1 // Just the type byte
|
||||||
}
|
}
|
||||||
switch t := v.(type) {
|
|
||||||
|
// 1 byte for type + size of the value
|
||||||
|
switch val := v.(type) {
|
||||||
case string:
|
case string:
|
||||||
return t
|
return 1 + bstd.SizeString(val)
|
||||||
case []byte:
|
|
||||||
return string(t)
|
|
||||||
case int:
|
case int:
|
||||||
return "i:" + string(rune(t))
|
return 1 + bstd.SizeInt64()
|
||||||
|
case int64:
|
||||||
|
return 1 + bstd.SizeInt64()
|
||||||
|
case float64:
|
||||||
|
return 1 + bstd.SizeFloat64()
|
||||||
case bool:
|
case bool:
|
||||||
if t {
|
return 1 + bstd.SizeBool()
|
||||||
return "b:t"
|
case []byte:
|
||||||
}
|
return 1 + bstd.SizeBytes(val)
|
||||||
return "b:f"
|
|
||||||
default:
|
default:
|
||||||
return "u:" // unknown type
|
// Convert unhandled types to string
|
||||||
|
return 1 + bstd.SizeString("unknown")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromString(s string) any {
|
// marshalAny serializes any value
|
||||||
if s == "" {
|
func marshalAny(n int, b []byte, v any) int {
|
||||||
return nil
|
if v == nil {
|
||||||
}
|
b[n] = typeNull
|
||||||
if len(s) < 2 {
|
return n + 1
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix := s[:2]
|
switch val := v.(type) {
|
||||||
switch prefix {
|
case string:
|
||||||
case "i:":
|
b[n] = typeString
|
||||||
if len(s) > 2 {
|
return bstd.MarshalString(n+1, b, val)
|
||||||
return int(rune(s[2]))
|
case int:
|
||||||
}
|
b[n] = typeInt
|
||||||
return 0
|
return bstd.MarshalInt64(n+1, b, int64(val))
|
||||||
case "b:":
|
case int64:
|
||||||
if len(s) > 2 && s[2] == 't' {
|
b[n] = typeInt
|
||||||
return true
|
return bstd.MarshalInt64(n+1, b, val)
|
||||||
}
|
case float64:
|
||||||
return false
|
b[n] = typeFloat
|
||||||
case "u:":
|
return bstd.MarshalFloat64(n+1, b, val)
|
||||||
return nil
|
case bool:
|
||||||
|
b[n] = typeBool
|
||||||
|
return bstd.MarshalBool(n+1, b, val)
|
||||||
|
case []byte:
|
||||||
|
b[n] = typeBytes
|
||||||
|
return bstd.MarshalBytes(n+1, b, val)
|
||||||
default:
|
default:
|
||||||
return s
|
// Convert unhandled types to string
|
||||||
|
b[n] = typeString
|
||||||
|
return bstd.MarshalString(n+1, b, "unknown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unmarshalAny deserializes any value
|
||||||
|
func unmarshalAny(n int, b []byte) (int, any, error) {
|
||||||
|
if len(b) <= n {
|
||||||
|
return n, nil, benc.ErrBufTooSmall
|
||||||
|
}
|
||||||
|
|
||||||
|
typeId := b[n]
|
||||||
|
n++
|
||||||
|
|
||||||
|
switch typeId {
|
||||||
|
case typeNull:
|
||||||
|
return n, nil, nil
|
||||||
|
case typeString:
|
||||||
|
return bstd.UnmarshalString(n, b)
|
||||||
|
case typeInt:
|
||||||
|
var val int64
|
||||||
|
var err error
|
||||||
|
n, val, err = bstd.UnmarshalInt64(n, b)
|
||||||
|
return n, val, err
|
||||||
|
case typeFloat:
|
||||||
|
var val float64
|
||||||
|
var err error
|
||||||
|
n, val, err = bstd.UnmarshalFloat64(n, b)
|
||||||
|
return n, val, err
|
||||||
|
case typeBool:
|
||||||
|
var val bool
|
||||||
|
var err error
|
||||||
|
n, val, err = bstd.UnmarshalBool(n, b)
|
||||||
|
return n, val, err
|
||||||
|
case typeBytes:
|
||||||
|
return bstd.UnmarshalBytesCopied(n, b)
|
||||||
|
default:
|
||||||
|
// Unknown type, return nil
|
||||||
|
return n, nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user