Skip to content

Commit

Permalink
refactor sequencer into sub-package
Browse files Browse the repository at this point in the history
  • Loading branch information
jedib0t committed Apr 20, 2024
1 parent 40cf7bc commit c0235a2
Show file tree
Hide file tree
Showing 17 changed files with 190 additions and 164 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
default: test

bench:
go test -bench=. -benchmem ./passphrase ./password
go test -bench=. -benchmem ./passphrase ./password ./password/sequencer

cyclo:
gocyclo -over 13 ./*/*.go
Expand Down
55 changes: 31 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Passphrase & Password generation library for GoLang.

## Passphrases
```golang
generator, err := passphrase.NewGenerator(
g, err := passphrase.NewGenerator(
passphrase.WithCapitalizedWords(true),
passphrase.WithDictionary(dictionaries.English()),
passphrase.WithNumWords(3),
Expand All @@ -21,7 +21,7 @@ Passphrase & Password generation library for GoLang.
panic(err.Error())
}
for idx := 1; idx <= 10; idx++ {
fmt.Printf("Passphrase #%3d: %#v\n", idx, generator.Generate())
fmt.Printf("Passphrase #%3d: %#v\n", idx, g.Generate())
}
```
<details>
Expand All @@ -42,8 +42,8 @@ Passphrase # 10: "Mirks6-Woofer-Lase"

## Passwords
```golang
generator, err := password.NewGenerator(
password.WithCharset(password.AllChars.WithoutAmbiguity().WithoutDuplicates()),
g, err := password.NewGenerator(
password.WithCharset(charset.AllChars.WithoutAmbiguity().WithoutDuplicates()),
password.WithLength(12),
password.WithMinLowerCase(5),
password.WithMinUpperCase(2),
Expand All @@ -53,7 +53,7 @@ Passphrase # 10: "Mirks6-Woofer-Lase"
panic(err.Error())
}
for idx := 1; idx <= 10; idx++ {
fmt.Printf("Password #%3d: %#v\n", idx, generator.Generate())
fmt.Printf("Password #%3d: %#v\n", idx, g.Generate())
}
```
<details>
Expand All @@ -75,20 +75,20 @@ Password # 10: "kmQVb&fPqexj"
### Sequential Passwords

```golang
sequencer, err := password.NewSequencer(
password.WithCharset(password.AllChars.WithoutAmbiguity()),
password.WithLength(8),
s, err := sequencer.New(
sequencer.WithCharset(charset.AllChars.WithoutAmbiguity()),
sequencer.WithLength(8),
)
if err != nil {
panic(err.Error())
}
for idx := 1; idx <= 10; idx++ {
fmt.Printf("Password #%3d: %#v\n", idx, sequencer.Get())
fmt.Printf("Password #%3d: %#v\n", idx, s.Get())

if !sequencer.HasNext() {
if !s.HasNext() {
break
}
sequencer.Next()
s.Next()
}
```
<details>
Expand All @@ -109,9 +109,9 @@ Password # 10: "AAAAAAAK"

#### Streamed (for async processing)
```golang
sequencer, err := password.NewSequencer(
password.WithCharset(password.Charset("AB")),
password.WithLength(4),
s, err := sequencer.New(
sequencer.WithCharset(charset.Charset("AB")),
sequencer.WithLength(4),
)
if err != nil {
panic(err.Error())
Expand All @@ -122,7 +122,7 @@ Password # 10: "AAAAAAAK"

chPasswords := make(chan string, 1)
go func() {
err := sequencer.Stream(ctx, chPasswords)
err := s.Stream(ctx, chPasswords)
if err != nil {
panic(err.Error())
}
Expand Down Expand Up @@ -170,20 +170,27 @@ goos: linux
goarch: amd64
pkg: github.com/jedib0t/go-passwords/passphrase
cpu: AMD Ryzen 9 5900X 12-Core Processor
BenchmarkGenerator_Generate-12 2862954 393.5 ns/op 167 B/op 8 allocs/op
BenchmarkGenerator_Generate-12 3015926 392.7 ns/op 167 B/op 8 allocs/op
PASS
ok github.com/jedib0t/go-passwords/passphrase 1.567s
ok github.com/jedib0t/go-passwords/passphrase 1.603s
goos: linux
goarch: amd64
pkg: github.com/jedib0t/go-passwords/password
cpu: AMD Ryzen 9 5900X 12-Core Processor
BenchmarkGenerator_Generate-12 6413606 185.3 ns/op 40 B/op 2 allocs/op
BenchmarkSequencer_GotoN-12 4353010 272.5 ns/op 32 B/op 3 allocs/op
BenchmarkSequencer_Next-12 13955396 84.61 ns/op 16 B/op 1 allocs/op
BenchmarkSequencer_NextN-12 6473270 183.9 ns/op 32 B/op 3 allocs/op
BenchmarkSequencer_Prev-12 13106161 87.22 ns/op 16 B/op 1 allocs/op
BenchmarkSequencer_PrevN-12 3967755 288.8 ns/op 32 B/op 3 allocs/op
BenchmarkGenerator_Generate-12 6263398 187.5 ns/op 40 B/op 2 allocs/op
PASS
ok github.com/jedib0t/go-passwords/password 8.192s
ok github.com/jedib0t/go-passwords/password 1.375s
goos: linux
goarch: amd64
pkg: github.com/jedib0t/go-passwords/password/sequencer
cpu: AMD Ryzen 9 5900X 12-Core Processor
BenchmarkSequencer_GotoN-12 4355002 274.6 ns/op 32 B/op 3 allocs/op
BenchmarkSequencer_Next-12 13614666 88.99 ns/op 16 B/op 1 allocs/op
BenchmarkSequencer_NextN-12 6216072 187.2 ns/op 32 B/op 3 allocs/op
BenchmarkSequencer_Prev-12 13569340 87.69 ns/op 16 B/op 1 allocs/op
BenchmarkSequencer_PrevN-12 4230654 277.9 ns/op 32 B/op 3 allocs/op
PASS
ok github.com/jedib0t/go-passwords/password/sequencer 6.888s
```
2 changes: 1 addition & 1 deletion password/charset.go → charset/charset.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package password
package charset

import (
"math/rand"
Expand Down
2 changes: 1 addition & 1 deletion password/charset_test.go → charset/charset_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package password
package charset

import (
"math/rand"
Expand Down
32 changes: 17 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"fmt"
"time"

"github.com/jedib0t/go-passwords/charset"
"github.com/jedib0t/go-passwords/passphrase"
"github.com/jedib0t/go-passwords/passphrase/dictionaries"
"github.com/jedib0t/go-passwords/password"
"github.com/jedib0t/go-passwords/password/sequencer"
)

func main() {
Expand All @@ -29,7 +31,7 @@ func main() {
}

func passphraseGenerator() {
generator, err := passphrase.NewGenerator(
g, err := passphrase.NewGenerator(
passphrase.WithCapitalizedWords(true),
passphrase.WithDictionary(dictionaries.English()),
passphrase.WithNumWords(3),
Expand All @@ -41,13 +43,13 @@ func passphraseGenerator() {
panic(err.Error())
}
for idx := 1; idx <= 10; idx++ {
fmt.Printf("Passphrase #%3d: %#v\n", idx, generator.Generate())
fmt.Printf("Passphrase #%3d: %#v\n", idx, g.Generate())
}
}

func passwordGenerator() {
generator, err := password.NewGenerator(
password.WithCharset(password.AllChars.WithoutAmbiguity().WithoutDuplicates()),
g, err := password.NewGenerator(
password.WithCharset(charset.AllChars.WithoutAmbiguity().WithoutDuplicates()),
password.WithLength(12),
password.WithMinLowerCase(5),
password.WithMinUpperCase(2),
Expand All @@ -57,32 +59,32 @@ func passwordGenerator() {
panic(err.Error())
}
for idx := 1; idx <= 10; idx++ {
fmt.Printf("Password #%3d: %#v\n", idx, generator.Generate())
fmt.Printf("Password #%3d: %#v\n", idx, g.Generate())
}
}

func passwordSequencer() {
sequencer, err := password.NewSequencer(
password.WithCharset(password.AllChars.WithoutAmbiguity()),
password.WithLength(8),
s, err := sequencer.New(
sequencer.WithCharset(charset.AllChars.WithoutAmbiguity()),
sequencer.WithLength(8),
)
if err != nil {
panic(err.Error())
}
for idx := 1; idx <= 10; idx++ {
fmt.Printf("Password #%3d: %#v\n", idx, sequencer.Get())
fmt.Printf("Password #%3d: %#v\n", idx, s.Get())

if !sequencer.HasNext() {
if !s.HasNext() {
break
}
sequencer.Next()
s.Next()
}
}

func passwordSequencerStreaming() {
sequencer, err := password.NewSequencer(
password.WithCharset(password.Charset("AB")),
password.WithLength(4),
s, err := sequencer.New(
sequencer.WithCharset(charset.Charset("AB")),
sequencer.WithLength(4),
)
if err != nil {
panic(err.Error())
Expand All @@ -93,7 +95,7 @@ func passwordSequencerStreaming() {

chPasswords := make(chan string, 1)
go func() {
err := sequencer.Stream(ctx, chPasswords)
err := s.Stream(ctx, chPasswords)
if err != nil {
panic(err.Error())
}
Expand Down
46 changes: 14 additions & 32 deletions passphrase/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package passphrase
import "github.com/jedib0t/go-passwords/passphrase/dictionaries"

// Rule controls how the Generator/Sequencer generates passwords.
type Rule func(a any)
type Rule func(g *generator)

var (
basicRules = []Rule{
Expand All @@ -18,59 +18,41 @@ var (

// WithCapitalizedWords ensures the words are Capitalized.
func WithCapitalizedWords(enabled bool) Rule {
return func(a any) {
switch v := a.(type) {
case *generator:
v.capitalize = enabled
}
return func(g *generator) {
g.capitalize = enabled
}
}

func WithDictionary(words []string) Rule {
return func(a any) {
switch v := a.(type) {
case *generator:
v.dictionary = words
}
return func(g *generator) {
g.dictionary = words
}
}

// WithNumber injects a random number after one of the words in the passphrase.
func WithNumber(enabled bool) Rule {
return func(a any) {
switch v := a.(type) {
case *generator:
v.withNumber = enabled
}
return func(g *generator) {
g.withNumber = enabled
}
}

// WithNumWords sets the number of words in the passphrase.
func WithNumWords(n int) Rule {
return func(a any) {
switch v := a.(type) {
case *generator:
v.numWords = n
}
return func(g *generator) {
g.numWords = n
}
}

// WithSeparator sets up the delimiter to separate words.
func WithSeparator(s string) Rule {
return func(a any) {
switch v := a.(type) {
case *generator:
v.separator = s
}
return func(g *generator) {
g.separator = s
}
}

func WithWordLength(min, max int) Rule {
return func(a any) {
switch v := a.(type) {
case *generator:
v.wordLenMin = min
v.wordLenMax = max
}
return func(g *generator) {
g.wordLenMin = min
g.wordLenMax = max
}
}
4 changes: 3 additions & 1 deletion password/default_generator.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package password

import "github.com/jedib0t/go-passwords/charset"

var (
defaultGenerator, _ = NewGenerator(
WithCharset(AllChars.WithoutAmbiguity()),
WithCharset(charset.AllChars.WithoutAmbiguity()),
WithLength(12),
WithMinLowerCase(3),
WithMinUpperCase(1),
Expand Down
8 changes: 6 additions & 2 deletions password/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"sync"
"time"
"unicode"

"github.com/jedib0t/go-passwords/charset"
)

var (
Expand Down Expand Up @@ -45,8 +47,8 @@ func NewGenerator(rules ...Rule) (Generator, error) {
// split the charsets
g.charsetCaseLower = filterRunes(g.charset, unicode.IsLower)
g.charsetCaseUpper = filterRunes(g.charset, unicode.IsUpper)
g.charsetNonSymbols = filterRunes(g.charset, func(r rune) bool { return !Symbols.Contains(r) })
g.charsetSymbols = filterRunes(g.charset, Symbols.Contains)
g.charsetNonSymbols = filterRunes(g.charset, func(r rune) bool { return !charset.Symbols.Contains(r) })
g.charsetSymbols = filterRunes(g.charset, charset.Symbols.Contains)

// create a storage pool with enough objects to support enough parallelism
g.pool = &sync.Pool{
Expand Down Expand Up @@ -111,6 +113,8 @@ func (g *generator) numSymbolsToGenerate() int {
return 0
}

func (g *generator) ruleEnforcer() {}

func (g *generator) sanitize() (Generator, error) {
// validate the inputs
if len(g.charset) == 0 {
Expand Down
Loading

0 comments on commit c0235a2

Please sign in to comment.