mirror of
https://github.com/sst/opencode.git
synced 2025-08-23 14:34:08 +00:00
96 lines
No EOL
1.9 KiB
Go
96 lines
No EOL
1.9 KiB
Go
package id
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
PrefixSession = "ses"
|
|
PrefixMessage = "msg"
|
|
PrefixUser = "usr"
|
|
PrefixPart = "prt"
|
|
)
|
|
|
|
const length = 26
|
|
|
|
var (
|
|
lastTimestamp int64
|
|
counter int64
|
|
mu sync.Mutex
|
|
)
|
|
|
|
type Prefix string
|
|
|
|
const (
|
|
Session Prefix = PrefixSession
|
|
Message Prefix = PrefixMessage
|
|
User Prefix = PrefixUser
|
|
Part Prefix = PrefixPart
|
|
)
|
|
|
|
func ValidatePrefix(id string, prefix Prefix) bool {
|
|
return strings.HasPrefix(id, string(prefix))
|
|
}
|
|
|
|
func Ascending(prefix Prefix, given ...string) string {
|
|
return generateID(prefix, false, given...)
|
|
}
|
|
|
|
func Descending(prefix Prefix, given ...string) string {
|
|
return generateID(prefix, true, given...)
|
|
}
|
|
|
|
func generateID(prefix Prefix, descending bool, given ...string) string {
|
|
if len(given) > 0 && given[0] != "" {
|
|
if !strings.HasPrefix(given[0], string(prefix)) {
|
|
panic(fmt.Sprintf("ID %s does not start with %s", given[0], string(prefix)))
|
|
}
|
|
return given[0]
|
|
}
|
|
|
|
return generateNewID(prefix, descending)
|
|
}
|
|
|
|
func randomBase62(length int) string {
|
|
const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
result := make([]byte, length)
|
|
bytes := make([]byte, length)
|
|
rand.Read(bytes)
|
|
|
|
for i := 0; i < length; i++ {
|
|
result[i] = chars[bytes[i]%62]
|
|
}
|
|
|
|
return string(result)
|
|
}
|
|
|
|
func generateNewID(prefix Prefix, descending bool) string {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
currentTimestamp := time.Now().UnixMilli()
|
|
|
|
if currentTimestamp != lastTimestamp {
|
|
lastTimestamp = currentTimestamp
|
|
counter = 0
|
|
}
|
|
counter++
|
|
|
|
now := uint64(currentTimestamp)*0x1000 + uint64(counter)
|
|
|
|
if descending {
|
|
now = ^now
|
|
}
|
|
|
|
timeBytes := make([]byte, 6)
|
|
for i := 0; i < 6; i++ {
|
|
timeBytes[i] = byte((now >> (40 - 8*i)) & 0xff)
|
|
}
|
|
|
|
return string(prefix) + "_" + hex.EncodeToString(timeBytes) + randomBase62(length-12)
|
|
} |