package profile import ( "crypto/rand" "fmt" ) // ProfileId is a 64-bit profile identifier with a compact base62 string form, // the same scheme the cart and order use so ids are consistent across services. type ProfileId uint64 const base62Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" var base62Rev [256]byte func init() { for i := range base62Rev { base62Rev[i] = 0xFF } for i := 0; i < len(base62Alphabet); i++ { base62Rev[base62Alphabet[i]] = byte(i) } } // String returns the canonical base62 encoding. func (id ProfileId) String() string { return encodeBase62(uint64(id)) } // NewProfileId generates a cryptographically random non-zero id. func NewProfileId() (ProfileId, error) { var b [8]byte if _, err := rand.Read(b[:]); err != nil { return 0, fmt.Errorf("NewProfileId: %w", err) } u := uint64(b[0])<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 | uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7]) if u == 0 { return NewProfileId() } return ProfileId(u), nil } // ParseProfileId parses a base62 string into a ProfileId. func ParseProfileId(s string) (ProfileId, bool) { if len(s) == 0 || len(s) > 11 { return 0, false } var v uint64 for i := 0; i < len(s); i++ { d := base62Rev[s[i]] if d == 0xFF { return 0, false } v = v*62 + uint64(d) } return ProfileId(v), true } func encodeBase62(u uint64) string { if u == 0 { return "0" } var buf [11]byte i := len(buf) for u > 0 { i-- buf[i] = base62Alphabet[u%62] u /= 62 } return string(buf[i:]) }