From 1677a692d16e825b90a650f2f8b45136996213d4 Mon Sep 17 00:00:00 2001 From: Dan Jones Date: Sat, 15 Mar 2025 15:36:43 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20Random=20Generator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gen_rand.go | 60 +++++++++++++++++++++++++++++++++++++ gen_rand_examples_test.go | 36 ++++++++++++++++++++++ gen_rand_test.go | 42 ++++++++++++++++++++++++++ generators.go | 19 +----------- generators_examples_test.go | 13 -------- generators_test.go | 22 -------------- go.mod | 1 + go.sum | 2 ++ 8 files changed, 142 insertions(+), 53 deletions(-) create mode 100644 gen_rand.go create mode 100644 gen_rand_examples_test.go create mode 100644 gen_rand_test.go diff --git a/gen_rand.go b/gen_rand.go new file mode 100644 index 0000000..8b4ce5a --- /dev/null +++ b/gen_rand.go @@ -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 + } +} diff --git a/gen_rand_examples_test.go b/gen_rand_examples_test.go new file mode 100644 index 0000000..45cb7fe --- /dev/null +++ b/gen_rand_examples_test.go @@ -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) +} diff --git a/gen_rand_test.go b/gen_rand_test.go new file mode 100644 index 0000000..832275b --- /dev/null +++ b/gen_rand_test.go @@ -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) +} diff --git a/generators.go b/generators.go index 25cd36e..94326dc 100644 --- a/generators.go +++ b/generators.go @@ -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 -} diff --git a/generators_examples_test.go b/generators_examples_test.go index c9d8710..a7f7a1c 100644 --- a/generators_examples_test.go +++ b/generators_examples_test.go @@ -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) -} diff --git a/generators_test.go b/generators_test.go index 7886ded..997d87c 100644 --- a/generators_test.go +++ b/generators_test.go @@ -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) -} diff --git a/go.mod b/go.mod index 6917d49..c733bcf 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 8638c59..209d634 100644 --- a/go.sum +++ b/go.sum @@ -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=