refactor: rename options interface and move PRNG to generator

This commit is contained in:
Peter 2023-04-25 17:45:32 +02:00
parent 9bf6cb3539
commit 997460bbdc
No known key found for this signature in database
3 changed files with 57 additions and 47 deletions

8
api.go
View file

@ -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)
}

View file

@ -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

View file

@ -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
}