nomino/gen_rand.go

87 lines
2 KiB
Go

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]
}
// 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)
for buff.Len() < c.length {
buff.Write(getRandomBytes(c.length - buff.Len()))
}
return buff.String(), nil
}
}