From 997460bbdc2917cfbfcddec9d7eb3d55f56f0f95 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Tue, 25 Apr 2023 17:45:32 +0200 Subject: [PATCH] refactor: rename options interface and move PRNG to generator --- api.go | 8 ++++++-- options.go | 48 +++++++++++++++++------------------------------- pwgen.go | 48 ++++++++++++++++++++++++++++++++++-------------- 3 files changed, 57 insertions(+), 47 deletions(-) diff --git a/api.go b/api.go index ee9056c..1fc2506 100644 --- a/api.go +++ b/api.go @@ -1,9 +1,13 @@ package pwgen -type GeneratorOption interface { +type Int32n interface { + Int31n(n int32) int32 +} + +type GenerationOption interface { ApplyToOptions(options *options) } type Generator interface { - Generate(opts ...GeneratorOption) (string, error) + Generate(opts ...GenerationOption) (string, error) } diff --git a/options.go b/options.go index 38abfd1..3889732 100644 --- a/options.go +++ b/options.go @@ -2,8 +2,6 @@ package pwgen import ( "errors" - "math/rand" - "time" ) const ( @@ -13,50 +11,50 @@ const ( var ErrLengthOverflow = errors.New("length overflow") -type generatorOptionFunc func(options *options) +type generationOptionFunc func(options *options) -func (f generatorOptionFunc) ApplyToOptions(options *options) { +func (f generationOptionFunc) ApplyToOptions(options *options) { f(options) } -func WithLength(length uint) GeneratorOption { - return generatorOptionFunc(func(options *options) { +func WithLength(length uint) GenerationOption { + return generationOptionFunc(func(options *options) { options.Length = length }) } -func WithLetters(letters uint) GeneratorOption { - return generatorOptionFunc(func(options *options) { +func WithLetters(letters uint) GenerationOption { + return generationOptionFunc(func(options *options) { options.Letters = letters }) } -func WithUppercase(uppercase uint) GeneratorOption { - return generatorOptionFunc(func(options *options) { +func WithUppercase(uppercase uint) GenerationOption { + return generationOptionFunc(func(options *options) { options.Uppercase = uppercase }) } -func WithLowercase(lowercase uint) GeneratorOption { - return generatorOptionFunc(func(options *options) { +func WithLowercase(lowercase uint) GenerationOption { + return generationOptionFunc(func(options *options) { options.Lowercase = lowercase }) } -func WithDigits(digits uint) GeneratorOption { - return generatorOptionFunc(func(options *options) { +func WithDigits(digits uint) GenerationOption { + return generationOptionFunc(func(options *options) { options.Digits = digits }) } -func WithSpecials(specials uint) GeneratorOption { - return generatorOptionFunc(func(options *options) { +func WithSpecials(specials uint) GenerationOption { + return generationOptionFunc(func(options *options) { options.Specials = specials }) } -func WithSpecialsAlphabet(specialsAlphabet string) GeneratorOption { - return generatorOptionFunc(func(options *options) { +func WithSpecialsAlphabet(specialsAlphabet string) GenerationOption { + return generationOptionFunc(func(options *options) { if specialsAlphabet == "" { specialsAlphabet = DefaultSpecialsAlphabet } @@ -64,15 +62,8 @@ func WithSpecialsAlphabet(specialsAlphabet string) GeneratorOption { }) } -func WithPRNG(prng Int32n) GeneratorOption { - return generatorOptionFunc(func(options *options) { - options.PRNG = prng - }) -} - -func defaultOptions(opts ...GeneratorOption) *options { +func defaultOptions(opts ...GenerationOption) *options { o := &options{ - PRNG: rand.New(rand.NewSource(time.Now().Unix())), Length: DefaultLength, Letters: 0, Digits: 3, @@ -89,12 +80,7 @@ func defaultOptions(opts ...GeneratorOption) *options { return o } -type Int32n interface { - Int31n(n int32) int32 -} - type options struct { - PRNG Int32n Length uint Letters uint Digits uint diff --git a/pwgen.go b/pwgen.go index 9f7b42f..a7321c0 100644 --- a/pwgen.go +++ b/pwgen.go @@ -1,18 +1,38 @@ package pwgen +import ( + "math/rand" + "time" +) + var ( _ Generator = (*DefaultGenerator)(nil) - Default DefaultGenerator - lowerCase = alphabet('a', 'z') - upperCase = alphabet('A', 'Z') - letters = merge(lowerCase, upperCase) - digits = alphabet('0', '9') + Default = NewDefaultGenerator(nil) + lowerCase = alphabet('a', 'z') + upperCase = alphabet('A', 'Z') + letters = merge(lowerCase, upperCase) + digits = alphabet('0', '9') ) -type DefaultGenerator struct { +func Generate(opts ...GenerationOption) (string, error) { + return Default.Generate(opts...) } -func (d DefaultGenerator) Generate(opts ...GeneratorOption) (string, error) { +func NewDefaultGenerator(prng Int32n) DefaultGenerator { + if prng == nil { + prng = rand.New(rand.NewSource(time.Now().UnixNano())) + } + + return DefaultGenerator{ + PRNG: prng, + } +} + +type DefaultGenerator struct { + PRNG Int32n +} + +func (d DefaultGenerator) Generate(opts ...GenerationOption) (string, error) { compiledOptions := defaultOptions(opts...) fullAlphabet := merge(lowerCase, upperCase, digits, []rune(compiledOptions.SpecialsAlphabet)) @@ -24,28 +44,28 @@ func (d DefaultGenerator) Generate(opts ...GeneratorOption) (string, error) { generated := make([]rune, 0, effectiveLength) for i := uint(0); i < compiledOptions.Lowercase; i++ { - generated = append(generated, runeFor(lowerCase, compiledOptions.PRNG)) + generated = append(generated, runeFor(lowerCase, d.PRNG)) } for i := uint(0); i < compiledOptions.Uppercase; i++ { - generated = append(generated, runeFor(upperCase, compiledOptions.PRNG)) + generated = append(generated, runeFor(upperCase, d.PRNG)) } for i := uint(0); i < compiledOptions.Digits; i++ { - generated = append(generated, runeFor(digits, compiledOptions.PRNG)) + generated = append(generated, runeFor(digits, d.PRNG)) } for i := uint(0); i < compiledOptions.Specials; i++ { - generated = append(generated, runeFor([]rune(compiledOptions.SpecialsAlphabet), compiledOptions.PRNG)) + generated = append(generated, runeFor([]rune(compiledOptions.SpecialsAlphabet), d.PRNG)) } for i := compiledOptions.Lowercase + compiledOptions.Uppercase; i < compiledOptions.Letters; i++ { - generated = append(generated, runeFor(letters, compiledOptions.PRNG)) + generated = append(generated, runeFor(letters, d.PRNG)) } for i := uint(len(generated)); i < effectiveLength; i++ { - generated = append(generated, runeFor(fullAlphabet, compiledOptions.PRNG)) + generated = append(generated, runeFor(fullAlphabet, d.PRNG)) } - return string(shuffle(generated, compiledOptions.PRNG)), nil + return string(shuffle(generated, d.PRNG)), nil }