diff --git a/config.go b/config.go index a7da5f5..c889a06 100644 --- a/config.go +++ b/config.go @@ -14,10 +14,18 @@ func NewConfig(options ...Option) Config { conf := Config{ extension: ".txt", separator: "_", - generator: uuidGen, + generator: UUID(nil), } for _, opt := range options { opt(&conf) } return conf } + +// AddOptions creates a new Config with options added. +func (c Config) AddOptions(options ...Option) Config { + for _, opt := range options { + opt(&c) + } + return c +} diff --git a/config_test.go b/config_test.go index adc35e6..f6ed21d 100644 --- a/config_test.go +++ b/config_test.go @@ -20,3 +20,12 @@ func TestNewConfWithOpts(t *testing.T) { assert.Equal(t, "", c.extension) assert.Equal(t, "foobar", c.prefix) } + +func TestConfAddOpts(t *testing.T) { + c := Config{original: "hi"} + c2 := c.AddOptions(WithOriginalSlug("Hello, my dear"), WithPrefix("yo")) + assert.Equal(t, "", c.prefix) + assert.Equal(t, "hi", c.original) + assert.Equal(t, "hello-my-dear", c2.original) + assert.Equal(t, "yo", c2.prefix) +} diff --git a/gen_rand.go b/gen_rand.go index 8b4ce5a..de71723 100644 --- a/gen_rand.go +++ b/gen_rand.go @@ -8,17 +8,44 @@ import ( "github.com/google/uuid" ) -func uuidGen(*Config) (string, error) { - u, err := uuid.NewRandom() - if err != nil { - return "", err - } - return u.String(), nil +// 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) } -// UUID generates a UUIDv4. -func UUID() Generator { - return uuidGen +// 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 { diff --git a/gen_rand_examples_test.go b/gen_rand_examples_test.go index 45cb7fe..29737fa 100644 --- a/gen_rand_examples_test.go +++ b/gen_rand_examples_test.go @@ -7,30 +7,34 @@ import ( ) func ExampleUUID() { - option := nomino.WithGenerator(nomino.UUID()) + gen := nomino.UUID(nil) - str, _ := nomino.Make(nomino.NewConfig(option)) + str, _ := gen.Make() fmt.Println(str) - str, _ = nomino.Make(nomino.NewConfig(option)) + str, _ = gen.Make() + fmt.Println(str) +} + +func ExampleUUID_v7() { + gen := nomino.UUID(nomino.UUIDv7) + + str, _ := gen.Make() fmt.Println(str) - str, _ = nomino.Make(nomino.NewConfig(option)) + str, _ = gen.Make() + fmt.Println(str) + + str, _ = gen.Make() fmt.Println(str) } func ExampleRandom() { - option := nomino.WithGenerator(nomino.Random()) - - str, _ := nomino.Make(nomino.NewConfig(option)) + str, _ := nomino.Random().Make() fmt.Println(str) } func ExampleRandomLength() { - option := nomino.WithGenerator(nomino.Random( - nomino.RandomLength(32), - )) - - str, _ := nomino.Make(nomino.NewConfig(option)) + str, _ := nomino.Random(nomino.RandomLength(32)).Make() fmt.Println(str) } diff --git a/gen_rand_test.go b/gen_rand_test.go index 832275b..51fc73f 100644 --- a/gen_rand_test.go +++ b/gen_rand_test.go @@ -9,7 +9,7 @@ import ( ) func TestUUID(t *testing.T) { - st, err := UUID()(nil) + st, err := UUID(nil)(nil) assert.NoError(t, err) _, parseErr := uuid.Parse(st) assert.NoError(t, parseErr) @@ -25,7 +25,7 @@ func TestUUIDFail(t *testing.T) { uuid.SetRand(badRead{}) defer uuid.SetRand(nil) - _, err := UUID()(nil) + _, err := UUID(nil)(nil) assert.Equal(t, errors.New("sorry"), err) } diff --git a/gen_ts_examples_test.go b/gen_ts_examples_test.go index 2f49392..26f8a91 100644 --- a/gen_ts_examples_test.go +++ b/gen_ts_examples_test.go @@ -9,8 +9,7 @@ import ( func ExampleTimestamp() { gen := nomino.Timestamp() - conf := nomino.NewConfig(nomino.WithGenerator(gen)) - s, _ := nomino.Make(conf) + s, _ := gen.Make() fmt.Println(s) } @@ -18,8 +17,7 @@ func ExampleTimestampTime() { tz, _ := time.LoadLocation("America/New_York") ts := time.Date(2009, time.January, 20, 12, 5, 0, 0, tz) gen := nomino.Timestamp(nomino.TimestampTime(ts)) - conf := nomino.NewConfig(nomino.WithGenerator(gen)) - s, _ := nomino.Make(conf) + s, _ := gen.Make() fmt.Println(s) // Output: 2009-01-20T12-05-00-0500.txt } @@ -28,8 +26,7 @@ func ExampleTimestampFormat() { tz, _ := time.LoadLocation("America/New_York") ts := time.Date(2009, time.January, 20, 12, 5, 0, 0, tz) gen := nomino.Timestamp(nomino.TimestampTime(ts), nomino.TimestampFormat("2006#01#02<>15|04|05-0700")) - conf := nomino.NewConfig(nomino.WithGenerator(gen)) - s, _ := nomino.Make(conf) + s, _ := gen.Make() fmt.Println(s) // Output: 2009#01#20<>12|05|00-0500.txt } @@ -38,8 +35,7 @@ func ExampleTimestampUTC() { tz, _ := time.LoadLocation("America/New_York") ts := time.Date(2009, time.January, 20, 12, 5, 0, 0, tz) gen := nomino.Timestamp(nomino.TimestampTime(ts), nomino.TimestampUTC()) - conf := nomino.NewConfig(nomino.WithGenerator(gen)) - s, _ := nomino.Make(conf) + s, _ := gen.Make() fmt.Println(s) // Output: 2009-01-20T17-05-00.txt } diff --git a/generators.go b/generators.go index c7ad4e8..e01ccc6 100644 --- a/generators.go +++ b/generators.go @@ -10,10 +10,15 @@ import ( // for example. type Generator func(conf *Config) (string, error) -// Make allows you to generate a new string directly from a generator. +// Make allows you to generate a new string directly from a Generator. func (g Generator) Make(opts ...Option) (string, error) { - opts = append(opts, WithGenerator(g)) - return Make(NewConfig(opts...)) + return g.MakeWithConfig(NewConfig(opts...)) +} + +// MakeWithConfig allows you to generate a new string directly from a Generator +// with a pre-existing Config. +func (g Generator) MakeWithConfig(c Config) (string, error) { + return Make(c.AddOptions(WithGenerator(g))) } // WithGenerator sets the specified generator