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
|
package pwgen
|
||||||
|
|
||||||
type GeneratorOption interface {
|
type Int32n interface {
|
||||||
|
Int31n(n int32) int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenerationOption interface {
|
||||||
ApplyToOptions(options *options)
|
ApplyToOptions(options *options)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Generator interface {
|
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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -13,50 +11,50 @@ const (
|
||||||
|
|
||||||
var ErrLengthOverflow = errors.New("length overflow")
|
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)
|
f(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithLength(length uint) GeneratorOption {
|
func WithLength(length uint) GenerationOption {
|
||||||
return generatorOptionFunc(func(options *options) {
|
return generationOptionFunc(func(options *options) {
|
||||||
options.Length = length
|
options.Length = length
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithLetters(letters uint) GeneratorOption {
|
func WithLetters(letters uint) GenerationOption {
|
||||||
return generatorOptionFunc(func(options *options) {
|
return generationOptionFunc(func(options *options) {
|
||||||
options.Letters = letters
|
options.Letters = letters
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithUppercase(uppercase uint) GeneratorOption {
|
func WithUppercase(uppercase uint) GenerationOption {
|
||||||
return generatorOptionFunc(func(options *options) {
|
return generationOptionFunc(func(options *options) {
|
||||||
options.Uppercase = uppercase
|
options.Uppercase = uppercase
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithLowercase(lowercase uint) GeneratorOption {
|
func WithLowercase(lowercase uint) GenerationOption {
|
||||||
return generatorOptionFunc(func(options *options) {
|
return generationOptionFunc(func(options *options) {
|
||||||
options.Lowercase = lowercase
|
options.Lowercase = lowercase
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithDigits(digits uint) GeneratorOption {
|
func WithDigits(digits uint) GenerationOption {
|
||||||
return generatorOptionFunc(func(options *options) {
|
return generationOptionFunc(func(options *options) {
|
||||||
options.Digits = digits
|
options.Digits = digits
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithSpecials(specials uint) GeneratorOption {
|
func WithSpecials(specials uint) GenerationOption {
|
||||||
return generatorOptionFunc(func(options *options) {
|
return generationOptionFunc(func(options *options) {
|
||||||
options.Specials = specials
|
options.Specials = specials
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithSpecialsAlphabet(specialsAlphabet string) GeneratorOption {
|
func WithSpecialsAlphabet(specialsAlphabet string) GenerationOption {
|
||||||
return generatorOptionFunc(func(options *options) {
|
return generationOptionFunc(func(options *options) {
|
||||||
if specialsAlphabet == "" {
|
if specialsAlphabet == "" {
|
||||||
specialsAlphabet = DefaultSpecialsAlphabet
|
specialsAlphabet = DefaultSpecialsAlphabet
|
||||||
}
|
}
|
||||||
|
@ -64,15 +62,8 @@ func WithSpecialsAlphabet(specialsAlphabet string) GeneratorOption {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithPRNG(prng Int32n) GeneratorOption {
|
func defaultOptions(opts ...GenerationOption) *options {
|
||||||
return generatorOptionFunc(func(options *options) {
|
|
||||||
options.PRNG = prng
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultOptions(opts ...GeneratorOption) *options {
|
|
||||||
o := &options{
|
o := &options{
|
||||||
PRNG: rand.New(rand.NewSource(time.Now().Unix())),
|
|
||||||
Length: DefaultLength,
|
Length: DefaultLength,
|
||||||
Letters: 0,
|
Letters: 0,
|
||||||
Digits: 3,
|
Digits: 3,
|
||||||
|
@ -89,12 +80,7 @@ func defaultOptions(opts ...GeneratorOption) *options {
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
type Int32n interface {
|
|
||||||
Int31n(n int32) int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type options struct {
|
type options struct {
|
||||||
PRNG Int32n
|
|
||||||
Length uint
|
Length uint
|
||||||
Letters uint
|
Letters uint
|
||||||
Digits uint
|
Digits uint
|
||||||
|
|
40
pwgen.go
40
pwgen.go
|
@ -1,18 +1,38 @@
|
||||||
package pwgen
|
package pwgen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ Generator = (*DefaultGenerator)(nil)
|
_ Generator = (*DefaultGenerator)(nil)
|
||||||
Default DefaultGenerator
|
Default = NewDefaultGenerator(nil)
|
||||||
lowerCase = alphabet('a', 'z')
|
lowerCase = alphabet('a', 'z')
|
||||||
upperCase = alphabet('A', 'Z')
|
upperCase = alphabet('A', 'Z')
|
||||||
letters = merge(lowerCase, upperCase)
|
letters = merge(lowerCase, upperCase)
|
||||||
digits = alphabet('0', '9')
|
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...)
|
compiledOptions := defaultOptions(opts...)
|
||||||
fullAlphabet := merge(lowerCase, upperCase, digits, []rune(compiledOptions.SpecialsAlphabet))
|
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)
|
generated := make([]rune, 0, effectiveLength)
|
||||||
|
|
||||||
for i := uint(0); i < compiledOptions.Lowercase; i++ {
|
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++ {
|
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++ {
|
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++ {
|
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++ {
|
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++ {
|
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