From 40e0f1c42964f20b350b0d8364f1d961d6514429 Mon Sep 17 00:00:00 2001 From: Michael Primeaux Date: Sat, 7 Dec 2024 15:30:36 -0600 Subject: [PATCH] debt: Minor refactoring to improve code readability and maintainability. (#39) --- CHANGELOG/CHANGELOG-1.x.md | 15 +++++++++++- README.md | 3 +++ config.go | 14 ++++++------ config_test.go | 2 +- go.mod | 4 ++-- go.sum | 8 +++---- nanoid.go | 47 +++++++++++++++++++------------------- nanoid_benchmark_test.go | 6 ++--- nanoid_test.go | 14 ++++++------ vendor/modules.txt | 4 ++-- 10 files changed, 67 insertions(+), 50 deletions(-) diff --git a/CHANGELOG/CHANGELOG-1.x.md b/CHANGELOG/CHANGELOG-1.x.md index 9f9fd8b..8cc420a 100644 --- a/CHANGELOG/CHANGELOG-1.x.md +++ b/CHANGELOG/CHANGELOG-1.x.md @@ -17,6 +17,18 @@ Date format: `YYYY-MM-DD` ### Fixed ### Security +--- +## [1.21.0] - 2024-12-07 + +### Added +### Changed +- **debt**: Minor refactoring to improve code readability and maintainability. + +### Deprecated +### Removed +### Fixed +### Security + --- ## [1.20.1] - 2024-11-24 @@ -488,7 +500,8 @@ Date format: `YYYY-MM-DD` ### Fixed ### Security -[Unreleased]: https://github.com/sixafter/nanoid/compare/v1.20.1...HEAD +[Unreleased]: https://github.com/sixafter/nanoid/compare/v1.21.0...HEAD +[1.21.0]: https://github.com/sixafter/nanoid/compare/v1.20.1...v1.21.0 [1.20.1]: https://github.com/sixafter/nanoid/compare/v1.20.0...v1.20.1 [1.20.0]: https://github.com/sixafter/nanoid/compare/v1.19.0...v1.20.0 [1.19.0]: https://github.com/sixafter/nanoid/compare/v1.18.1...v1.19.0 diff --git a/README.md b/README.md index f49cfd6..226ebcd 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ package main import ( "fmt" + "github.com/sixafter/nanoid" ) @@ -92,6 +93,7 @@ package main import ( "fmt" + "github.com/sixafter/nanoid" ) @@ -120,6 +122,7 @@ package main import ( "fmt" "io" + "github.com/sixafter/nanoid" ) diff --git a/config.go b/config.go index 333985f..9e0a63b 100644 --- a/config.go +++ b/config.go @@ -13,7 +13,7 @@ import ( "unicode/utf8" ) -// ConfigOptions holds the configurable options for the Generator. +// ConfigOptions holds the configurable options for the Interface. // It is used with the Function Options pattern. type ConfigOptions struct { // RandReader is the source of randomness used for generating IDs. @@ -134,12 +134,12 @@ type Configuration interface { Config() Config } -// Option defines a function type for configuring the Generator. +// Option defines a function type for configuring the Interface. // It allows for flexible and extensible configuration by applying -// various settings to the ConfigOptions during Generator initialization. +// various settings to the ConfigOptions during Interface initialization. type Option func(*ConfigOptions) -// WithAlphabet sets a custom alphabet for the Generator. +// WithAlphabet sets a custom alphabet for the Interface. // The provided alphabet string defines the set of characters that will be // used to generate Nano IDs. This allows users to customize the character set // according to their specific requirements, such as using only alphanumeric @@ -160,8 +160,8 @@ func WithAlphabet(alphabet string) Option { } } -// WithRandReader sets a custom random reader for the Generator. -// By default, the Generator uses a cryptographically secure random number +// WithRandReader sets a custom random reader for the Interface. +// By default, the Interface uses a cryptographically secure random number // generator (e.g., crypto/rand.Reader). However, in some cases, users might // want to provide their own source of randomness, such as for testing purposes // or to integrate with a different entropy source. @@ -184,7 +184,7 @@ func WithRandReader(reader io.Reader) Option { } // WithLengthHint sets the hint of the intended length of the IDs to be generated. -// Providing a length hint allows the Generator to optimize internal configurations, +// Providing a length hint allows the Interface to optimize internal configurations, // such as buffer sizes and scaling factors, based on the expected ID length. This // can enhance performance and efficiency, especially when generating a large number // of IDs with similar lengths. diff --git a/config_test.go b/config_test.go index 9a3ae79..fc3e98a 100644 --- a/config_test.go +++ b/config_test.go @@ -23,7 +23,7 @@ func TestGetConfig(t *testing.T) { // Assert that generator implements Configuration interface config, ok := gen.(Configuration) - is.True(ok, "Generator should implement Configuration interface") + is.True(ok, "Interface should implement Configuration interface") runtimeConfig := config.Config() diff --git a/go.mod b/go.mod index e6c5175..9d4b617 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,13 @@ go 1.23 require ( github.com/stretchr/testify v1.10.0 - golang.org/x/crypto v0.29.0 + golang.org/x/crypto v0.30.0 golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.27.0 // indirect + golang.org/x/sys v0.28.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 57582bf..5dd800e 100644 --- a/go.sum +++ b/go.sum @@ -4,12 +4,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/nanoid.go b/nanoid.go index 96e83d8..ca0b663 100644 --- a/nanoid.go +++ b/nanoid.go @@ -14,11 +14,11 @@ import ( ) var ( - // DefaultGenerator is a global, shared instance of a Nano ID generator. It is safe for concurrent use. - DefaultGenerator Generator + // Generator is a global, shared instance of a Nano ID generator. It is safe for concurrent use. + Generator Interface - // DefaultRandReader is the default random number generator used for generating IDs. - DefaultRandReader = prng.Reader + // RandReader is the default random number generator used for generating IDs. + RandReader = prng.Reader ) const ( @@ -60,16 +60,17 @@ const ( func init() { var err error - DefaultGenerator, err = NewGenerator() + Generator, err = NewGenerator() if err != nil { - panic(fmt.Sprintf("failed to initialize DefaultGenerator: %v", err)) + panic(fmt.Sprintf("failed to initialize Generator: %v", err)) } } -// Generator defines the interface for generating Nano IDs. +// Interface defines the contract for generating Nano IDs. +// // Implementations of this interface provide methods to create new IDs // and to read random data, supporting both ID generation and direct random byte access. -type Generator interface { +type Interface interface { // New generates and returns a new Nano ID as a string with the specified length. // The 'length' parameter determines the number of characters in the generated ID. // Returns an error if the ID generation fails due to issues like insufficient randomness. @@ -85,7 +86,7 @@ type Generator interface { // Read fills the provided byte slice 'p' with random data, reading up to len(p) bytes. // Returns the number of bytes read and any error encountered during the read operation. // - // Implements the io.Reader interface, allowing the Generator to be used wherever an io.Reader is accepted. + // Implements the io.Reader interface, allowing the Interface to be used wherever an io.Reader is accepted. // This can be useful for directly obtaining random bytes or integrating with other components that consume random data. // // Usage: @@ -95,7 +96,7 @@ type Generator interface { // // handle error // } // fmt.Printf("Read %d random bytes\n", n) - Read(p []byte) (n int, err error) + Read(b []byte) (n int, err error) } type generator struct { @@ -132,7 +133,7 @@ func New() (ID, error) { // } // fmt.Println("Generated ID:", id) func NewWithLength(length int) (ID, error) { - return DefaultGenerator.New(length) + return Generator.New(length) } // Must generates a new Nano ID using the default length specified by `DefaultLength`. @@ -201,22 +202,22 @@ func MustWithLength(length int) ID { // nothing happened; in particular it does not indicate EOF. // // Implementations must not retain p. -func Read(p []byte) (n int, err error) { - return DefaultGenerator.Read(p) +func Read(b []byte) (n int, err error) { + return Generator.Read(b) } -// NewGenerator creates a new Generator with buffer pooling enabled. -// It accepts variadic Option parameters to configure the Generator's behavior. +// NewGenerator creates a new Interface with buffer pooling enabled. +// It accepts variadic Option parameters to configure the Interface's behavior. // The function initializes the configuration with default values, applies any provided options, // validates the configuration, constructs the runtime configuration, initializes buffer pools, -// and returns a configured Generator or an error if the configuration is invalid. +// and returns a configured Interface or an error if the configuration is invalid. // // Parameters: -// - options ...Option: A variadic list of Option functions to customize the Generator's configuration. +// - options ...Option: A variadic list of Option functions to customize the Interface's configuration. // // Returns: -// - Generator: An instance of the Generator interface configured with the specified options. -// - error: An error object if the Generator could not be created due to invalid configuration. +// - Interface: An instance of the Interface interface configured with the specified options. +// - error: An error object if the Interface could not be created due to invalid configuration. // // Error Conditions: // - ErrInvalidLength: Returned if the provided LengthHint is less than 1. @@ -224,13 +225,13 @@ func Read(p []byte) (n int, err error) { // - ErrInvalidAlphabet: Returned if the alphabet is invalid or contains invalid UTF-8 characters. // - ErrNonUTF8Alphabet: Returned if the alphabet contains non-UTF-8 characters. // - ErrDuplicateCharacters: Returned if the alphabet contains duplicate characters. -func NewGenerator(options ...Option) (Generator, error) { +func NewGenerator(options ...Option) (Interface, error) { // Initialize ConfigOptions with default values. // These defaults include the default alphabet, the default random reader, // and the default length hint for ID generation. configOpts := &ConfigOptions{ Alphabet: DefaultAlphabet, - RandReader: DefaultRandReader, + RandReader: RandReader, LengthHint: DefaultLength, } @@ -286,7 +287,7 @@ func NewGenerator(options ...Option) (Generator, error) { } } - // Return the configured Generator instance. + // Return the configured Interface instance. // The generator holds references to the runtime configuration and buffer pools, // facilitating efficient and thread-safe ID generation. return &generator{ @@ -313,7 +314,7 @@ func NewGenerator(options ...Option) (Generator, error) { // // Usage Example: // -// id, err := DefaultGenerator.New(21) +// id, err := Generator.New(21) // if err != nil { // // handle error // } diff --git a/nanoid_benchmark_test.go b/nanoid_benchmark_test.go index 13f303c..ea6481f 100644 --- a/nanoid_benchmark_test.go +++ b/nanoid_benchmark_test.go @@ -150,7 +150,7 @@ func BenchmarkGenerator_Read_DefaultLength(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - _, err := DefaultGenerator.Read(buffer) + _, err := Generator.Read(buffer) if err != nil { b.Fatalf("Read returned an unexpected error: %v", err) } @@ -187,7 +187,7 @@ func BenchmarkGenerator_Read_ZeroLengthBuffer(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - _, err := DefaultGenerator.Read(buffer) + _, err := Generator.Read(buffer) if err != nil { b.Fatalf("Read returned an unexpected error: %v", err) } @@ -211,7 +211,7 @@ func BenchmarkGenerator_Read_Concurrent(b *testing.B) { defer wg.Done() buffer := make([]byte, bufferSize) for j := 0; j < b.N/concurrency; j++ { - _, err := DefaultGenerator.Read(buffer) + _, err := Generator.Read(buffer) if err != nil { b.Errorf("Read returned an unexpected error: %v", err) return diff --git a/nanoid_test.go b/nanoid_test.go index ad58ba2..27ad535 100644 --- a/nanoid_test.go +++ b/nanoid_test.go @@ -129,7 +129,7 @@ func TestGenerateWithDuplicateAlphabet(t *testing.T) { WithAlphabet(alphabet), ) is.Error(err, "NewGenerator() should return an error with duplicate characters in the alphabet") - is.Nil(gen, "Generator should be nil when initialization fails") + is.Nil(gen, "Interface should be nil when initialization fails") is.Equal(ErrDuplicateCharacters, err, "Expected ErrDuplicateCharacters") } @@ -164,11 +164,11 @@ func TestNewGeneratorWithInvalidAlphabet(t *testing.T) { switch true { case l < MinAlphabetLength: is.Error(err, "NewGenerator() should return an error with an invalid alphabet length") - is.Nil(gen, "Generator should be nil when initialization fails") + is.Nil(gen, "Interface should be nil when initialization fails") is.Equal(ErrAlphabetTooShort, err, "Expected ErrAlphabetTooShort") case l > MaxAlphabetLength: is.Error(err, "NewGenerator() should return an error with an invalid alphabet length") - is.Nil(gen, "Generator should be nil when initialization fails") + is.Nil(gen, "Interface should be nil when initialization fails") is.Equal(ErrAlphabetTooLong, err, "Expected ErrAlphabetTooLong") default: is.NoError(err, "NewGenerator() should not return an error when initialization succeeds") @@ -191,7 +191,7 @@ func TestInvalidUTF8Alphabet(t *testing.T) { ) is.Error(err, "NewGenerator() should return an error with an invalid alphabet") - is.Nil(gen, "Generator should be nil when initialization fails") + is.Nil(gen, "Interface should be nil when initialization fails") is.Equal(ErrNonUTF8Alphabet, err, "Expected ErrNonUTF8Alphabet") } @@ -662,7 +662,7 @@ func TestNewWithZeroLengthHintAndMaxAlphabet(t *testing.T) { WithLengthHint(lengthHint), ) is.Error(err, "NewGenerator() should return an error with LengthHint=0 and maximum alphabet size") - is.Nil(gen, "Generator should be nil when LengthHint is zero") + is.Nil(gen, "Interface should be nil when LengthHint is zero") } // TestGenerateWithCustomRandReaderReturningNoBytes tests generator behavior when the custom reader returns no bytes. @@ -974,8 +974,8 @@ func TestGenerator_Read_Concurrent(t *testing.T) { t.Parallel() is := assert.New(t) - gen, ok := DefaultGenerator.(*generator) - is.True(ok, "DefaultGenerator should be of type *generator") + gen, ok := Generator.(*generator) + is.True(ok, "Generator should be of type *generator") numGoroutines := 10 readsPerGoroutine := 100 diff --git a/vendor/modules.txt b/vendor/modules.txt index fa9e181..967c02a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -10,14 +10,14 @@ github.com/pmezard/go-difflib/difflib ## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/assert/yaml -# golang.org/x/crypto v0.29.0 +# golang.org/x/crypto v0.30.0 ## explicit; go 1.20 golang.org/x/crypto/chacha20 golang.org/x/crypto/internal/alias # golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f ## explicit; go 1.22.0 golang.org/x/exp/constraints -# golang.org/x/sys v0.27.0 +# golang.org/x/sys v0.28.0 ## explicit; go 1.18 golang.org/x/sys/cpu # gopkg.in/yaml.v3 v3.0.1