| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- 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)
- }
|