refactor: rename options interface and move PRNG to generator
This commit is contained in:
parent
9bf6cb3539
commit
997460bbdc
3 changed files with 57 additions and 47 deletions
8
api.go
8
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)
|
||||
}
|
||||
|
|
48
options.go
48
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
|
||||
|
|
40
pwgen.go
40
pwgen.go
|
@ -1,18 +1,38 @@
|
|||
package pwgen
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
_ Generator = (*DefaultGenerator)(nil)
|
||||
Default DefaultGenerator
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue