Add Random Generator

This commit is contained in:
Dan Jones 2025-03-15 15:36:43 -05:00
commit 1677a692d1
8 changed files with 142 additions and 53 deletions

60
gen_rand.go Normal file
View file

@ -0,0 +1,60 @@
package nomino
import (
"crypto/rand"
"strings"
"github.com/deatil/go-encoding/base62"
"github.com/google/uuid"
)
func uuidGen(*Config) (string, error) {
u, err := uuid.NewRandom()
if err != nil {
return "", err
}
return u.String(), nil
}
// UUID generates a UUIDv4.
func UUID() Generator {
return uuidGen
}
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
}
}

36
gen_rand_examples_test.go Normal file
View file

@ -0,0 +1,36 @@
package nomino_test
import (
"fmt"
"codeberg.org/danjones000/nomino"
)
func ExampleUUID() {
option := nomino.WithGenerator(nomino.UUID())
str, _ := nomino.Make(nomino.NewConfig(option))
fmt.Println(str)
str, _ = nomino.Make(nomino.NewConfig(option))
fmt.Println(str)
str, _ = nomino.Make(nomino.NewConfig(option))
fmt.Println(str)
}
func ExampleRandom() {
option := nomino.WithGenerator(nomino.Random())
str, _ := nomino.Make(nomino.NewConfig(option))
fmt.Println(str)
}
func ExampleRandomLength() {
option := nomino.WithGenerator(nomino.Random(
nomino.RandomLength(32),
))
str, _ := nomino.Make(nomino.NewConfig(option))
fmt.Println(str)
}

42
gen_rand_test.go Normal file
View file

@ -0,0 +1,42 @@
package nomino
import (
"errors"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
func TestUUID(t *testing.T) {
st, err := UUID()(nil)
assert.NoError(t, err)
_, parseErr := uuid.Parse(st)
assert.NoError(t, parseErr)
}
type badRead struct{}
func (badRead) Read([]byte) (int, error) {
return 0, errors.New("sorry")
}
func TestUUIDFail(t *testing.T) {
uuid.SetRand(badRead{})
defer uuid.SetRand(nil)
_, err := UUID()(nil)
assert.Equal(t, errors.New("sorry"), err)
}
func TestRand(t *testing.T) {
st, err := Random()(nil)
assert.NoError(t, err)
assert.Len(t, st, 8)
}
func TestRandLen(t *testing.T) {
st, err := Random(RandomLength(32))(nil)
assert.NoError(t, err)
assert.Len(t, st, 32)
}

View file

@ -1,10 +1,6 @@
package nomino
import (
"errors"
"github.com/google/uuid"
)
import "errors"
// Generator is a function that returns the "random" portion of the returned filename.
// Technically, it doesn't necessarily need to be random, and could be based on time, or a counter,
@ -43,16 +39,3 @@ func MultiGeneratorInOrder(gens ...Generator) Generator {
return st, err
}
}
func uuidGen(*Config) (string, error) {
u, err := uuid.NewRandom()
if err != nil {
return "", err
}
return u.String(), nil
}
// UUID generates a UUIDv4.
func UUID() Generator {
return uuidGen
}

View file

@ -50,16 +50,3 @@ func ExampleMultiGeneratorInOrder() {
// goodbye.txt
// hello.txt
}
func ExampleUUID() {
option := nomino.WithGenerator(nomino.UUID())
str, _ := nomino.Make(nomino.NewConfig(option))
fmt.Println(str)
str, _ = nomino.Make(nomino.NewConfig(option))
fmt.Println(str)
str, _ = nomino.Make(nomino.NewConfig(option))
fmt.Println(str)
}

View file

@ -4,7 +4,6 @@ import (
"errors"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
@ -61,24 +60,3 @@ func TestMultiGeneratorInOrderMissing(t *testing.T) {
assert.Zero(t, st)
assert.ErrorIs(t, err, ErrMissingGenerators)
}
func TestUUID(t *testing.T) {
st, err := UUID()(nil)
assert.NoError(t, err)
_, parseErr := uuid.Parse(st)
assert.NoError(t, parseErr)
}
type badRead struct{}
func (badRead) Read([]byte) (int, error) {
return 0, errors.New("sorry")
}
func TestUUIDFail(t *testing.T) {
uuid.SetRand(badRead{})
defer uuid.SetRand(nil)
_, err := UUID()(nil)
assert.Equal(t, errors.New("sorry"), err)
}

1
go.mod
View file

@ -3,6 +3,7 @@ module codeberg.org/danjones000/nomino
go 1.23.6
require (
github.com/deatil/go-encoding v1.0.3003
github.com/google/uuid v1.6.0
github.com/gosimple/slug v1.15.0
github.com/stretchr/testify v1.10.0

2
go.sum
View file

@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deatil/go-encoding v1.0.3003 h1:2b05UO+5JfVcXcOa8n/X3pm8aC6L6ET0mBZCb1kj3ck=
github.com/deatil/go-encoding v1.0.3003/go.mod h1:lTMMKsG0RRPGZzdW2EPVJCA7HQy4o1ZQKPf5CmVDy2k=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gosimple/slug v1.15.0 h1:wRZHsRrRcs6b0XnxMUBM6WK1U1Vg5B0R7VkIf1Xzobo=