package nomino import ( "crypto/rand" "strings" "github.com/deatil/go-encoding/base62" "github.com/google/uuid" ) // UUIDer is an interface for generating UUIDs. // It is recommended that you use either the UUIDv4 or UUIDv7 variables. type UUIDer interface { UUID() (uuid.UUID, error) } // UUIDFunc is a function that generates a UUID. type UUIDFunc func() (uuid.UUID, error) // UUID allows UUIDFunc to be used as a UUIDer. func (u UUIDFunc) UUID() (uuid.UUID, error) { return u() } var ( // UUIDv1. You probably don't want to use this. It is included for completeness sake. UUIDv1 = UUIDFunc(uuid.NewUUID) // UUIDv4 is the default. UUIDv4 = UUIDFunc(uuid.NewRandom) // UUIDv6 is primarily a replacement for UUIDv1. You probably should use 4 or 7. UUIDv6 = UUIDFunc(uuid.NewV6) // UUIDv7 should be used if you want it sortable by time. UUIDv7 = UUIDFunc(uuid.NewV7) ) // UUID generates a UUID. If nil.is passed as an argument, // a UUIDv4 is generated. func UUID(u UUIDer) Generator { if u == nil { u = UUIDv4 } return func(*Config) (string, error) { uu, err := u.UUID() if err != nil { return "", err } return uu.String(), nil } } type randConf struct { length int } // RandomOption is an option for the Random Generator. type RandomOption func(*randConf) // RandomLength controls the length of the string generated by Random. func RandomLength(length int) RandomOption { return func(c *randConf) { c.length = length } } func getRandomBytes(l int) []byte { key := make([]byte, l) _, _ = rand.Read(key) e := base62.StdEncoding.Encode(key) return e[:l] } func fillBuffer(buff *strings.Builder, length int) { for buff.Len() < length { buff.Write(getRandomBytes(length - buff.Len())) } } // Random generates a random string containing the characters [A-Za-z0-9]. // By default, it will be eight characters long. func Random(opts ...RandomOption) Generator { c := randConf{8} for _, opt := range opts { opt(&c) } return func(*Config) (string, error) { var buff strings.Builder buff.Grow(c.length) fillBuffer(&buff, c.length) return buff.String(), nil } }