2023-04-25 13:56:11 +00:00
|
|
|
package pwgen
|
|
|
|
|
2023-04-25 15:45:32 +00:00
|
|
|
import (
|
|
|
|
"math/rand"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2023-04-25 13:56:11 +00:00
|
|
|
var (
|
|
|
|
_ Generator = (*DefaultGenerator)(nil)
|
2023-04-25 15:45:32 +00:00
|
|
|
Default = NewDefaultGenerator(nil)
|
|
|
|
lowerCase = alphabet('a', 'z')
|
|
|
|
upperCase = alphabet('A', 'Z')
|
|
|
|
letters = merge(lowerCase, upperCase)
|
|
|
|
digits = alphabet('0', '9')
|
2023-04-25 13:56:11 +00:00
|
|
|
)
|
|
|
|
|
2023-04-25 15:45:32 +00:00
|
|
|
func Generate(opts ...GenerationOption) (string, error) {
|
|
|
|
return Default.Generate(opts...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDefaultGenerator(prng Int32n) DefaultGenerator {
|
|
|
|
if prng == nil {
|
|
|
|
prng = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
|
}
|
|
|
|
|
|
|
|
return DefaultGenerator{
|
|
|
|
PRNG: prng,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-25 13:56:11 +00:00
|
|
|
type DefaultGenerator struct {
|
2023-04-25 15:45:32 +00:00
|
|
|
PRNG Int32n
|
2023-04-25 13:56:11 +00:00
|
|
|
}
|
|
|
|
|
2023-04-25 15:45:32 +00:00
|
|
|
func (d DefaultGenerator) Generate(opts ...GenerationOption) (string, error) {
|
2023-04-25 13:56:11 +00:00
|
|
|
compiledOptions := defaultOptions(opts...)
|
|
|
|
fullAlphabet := merge(lowerCase, upperCase, digits, []rune(compiledOptions.SpecialsAlphabet))
|
|
|
|
|
|
|
|
effectiveLength, err := compiledOptions.effectiveLength()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
generated := make([]rune, 0, effectiveLength)
|
|
|
|
|
|
|
|
for i := uint(0); i < compiledOptions.Lowercase; i++ {
|
2023-04-25 15:45:32 +00:00
|
|
|
generated = append(generated, runeFor(lowerCase, d.PRNG))
|
2023-04-25 13:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := uint(0); i < compiledOptions.Uppercase; i++ {
|
2023-04-25 15:45:32 +00:00
|
|
|
generated = append(generated, runeFor(upperCase, d.PRNG))
|
2023-04-25 13:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := uint(0); i < compiledOptions.Digits; i++ {
|
2023-04-25 15:45:32 +00:00
|
|
|
generated = append(generated, runeFor(digits, d.PRNG))
|
2023-04-25 13:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := uint(0); i < compiledOptions.Specials; i++ {
|
2023-04-25 15:45:32 +00:00
|
|
|
generated = append(generated, runeFor([]rune(compiledOptions.SpecialsAlphabet), d.PRNG))
|
2023-04-25 13:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := compiledOptions.Lowercase + compiledOptions.Uppercase; i < compiledOptions.Letters; i++ {
|
2023-04-25 15:45:32 +00:00
|
|
|
generated = append(generated, runeFor(letters, d.PRNG))
|
2023-04-25 13:56:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := uint(len(generated)); i < effectiveLength; i++ {
|
2023-04-25 15:45:32 +00:00
|
|
|
generated = append(generated, runeFor(fullAlphabet, d.PRNG))
|
2023-04-25 13:56:11 +00:00
|
|
|
}
|
|
|
|
|
2023-04-25 15:45:32 +00:00
|
|
|
return string(shuffle(generated, d.PRNG)), nil
|
2023-04-25 13:56:11 +00:00
|
|
|
}
|