mirror of
https://github.com/wneessen/apg-go.git
synced 2024-11-22 13:50:49 +01:00
#53 Refactor mode handling and bitmask functions
The naming and handling of mode bitmasks have been refactored for improved code readability and maintainability. The term "Mode" was replaced with "ModeMask" for clarity and all associated functions were renamed accordingly (e.g., "SetMode" to "MaskSetMode"). These changes provide better insight into the function of the code and increase understandability for future development efforts. The command-line utility now also supports specifying modes via the "-M" flag.
This commit is contained in:
parent
ac97b94ec9
commit
b31219046a
4 changed files with 88 additions and 21 deletions
|
@ -4,6 +4,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/wneessen/apg-go"
|
"github.com/wneessen/apg-go"
|
||||||
|
@ -13,12 +14,20 @@ func main() {
|
||||||
c := apg.NewConfig()
|
c := apg.NewConfig()
|
||||||
|
|
||||||
// Configure and parse the CLI flags
|
// Configure and parse the CLI flags
|
||||||
|
var ms string
|
||||||
flag.Int64Var(&c.MinLength, "m", c.MinLength, "")
|
flag.Int64Var(&c.MinLength, "m", c.MinLength, "")
|
||||||
flag.Int64Var(&c.MaxLength, "x", c.MaxLength, "")
|
flag.Int64Var(&c.MaxLength, "x", c.MaxLength, "")
|
||||||
|
flag.StringVar(&ms, "M", "", "")
|
||||||
flag.Int64Var(&c.NumberPass, "n", c.NumberPass, "")
|
flag.Int64Var(&c.NumberPass, "n", c.NumberPass, "")
|
||||||
flag.Usage = usage
|
flag.Usage = usage
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
if ms != "" {
|
||||||
|
c.Modes = apg.ModesFromFlags(ms)
|
||||||
|
}
|
||||||
|
for _, m := range []apg.Mode{apg.ModeHumanReadable, apg.ModeLowerCase, apg.ModeNumber, apg.ModeSpecial, apg.ModeUpperCase} {
|
||||||
|
fmt.Printf("%s: %t\n", m, apg.MaskHasMode(c.Modes, m))
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
g := apg.New(c)
|
g := apg.New(c)
|
||||||
rb, err := g.RandomBytes(c.MinLength)
|
rb, err := g.RandomBytes(c.MinLength)
|
||||||
|
|
|
@ -18,6 +18,8 @@ type Config struct {
|
||||||
MaxLength int64
|
MaxLength int64
|
||||||
// MinLength sets the minimum length for a generated password
|
// MinLength sets the minimum length for a generated password
|
||||||
MinLength int64
|
MinLength int64
|
||||||
|
// Modes holds the different character modes for the Random algorithm
|
||||||
|
Modes ModeMask
|
||||||
// NumberPass sets the number of passwords that are generated
|
// NumberPass sets the number of passwords that are generated
|
||||||
// and returned by the generator
|
// and returned by the generator
|
||||||
NumberPass int64
|
NumberPass int64
|
||||||
|
|
72
mode.go
72
mode.go
|
@ -1,8 +1,13 @@
|
||||||
package apg
|
package apg
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
// Mode represents a mode of characters
|
// Mode represents a mode of characters
|
||||||
type Mode uint8
|
type Mode uint8
|
||||||
|
|
||||||
|
// ModeMask represents a bitmask of character modes
|
||||||
|
type ModeMask uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ModeNumber sets the bitmask to include numbers in the generated passwords
|
// ModeNumber sets the bitmask to include numbers in the generated passwords
|
||||||
ModeNumber = 1 << iota
|
ModeNumber = 1 << iota
|
||||||
|
@ -38,14 +43,65 @@ const (
|
||||||
CharRangeSpecialHuman = `#%*+-:;=`
|
CharRangeSpecialHuman = `#%*+-:;=`
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetMode sets a specific Mode to a given Mode bitmask
|
// MaskSetMode sets a specific Mode to a given Mode bitmask
|
||||||
func SetMode(b, m Mode) Mode { return b | m }
|
func MaskSetMode(ma ModeMask, mo Mode) ModeMask { return ModeMask(uint8(ma) | uint8(mo)) }
|
||||||
|
|
||||||
// ClearMode clears a specific Mode from a given Mode bitmask
|
// MaskClearMode clears a specific Mode from a given Mode bitmask
|
||||||
func ClearMode(b, m Mode) Mode { return b &^ m }
|
func MaskClearMode(ma ModeMask, mo Mode) ModeMask { return ModeMask(uint8(ma) &^ uint8(mo)) }
|
||||||
|
|
||||||
// ToggleMode toggles a specific Mode in a given Mode bitmask
|
// MaskToggleMode toggles a specific Mode in a given Mode bitmask
|
||||||
func ToggleMode(b, m Mode) Mode { return b ^ m }
|
func MaskToggleMode(ma ModeMask, mo Mode) ModeMask { return ModeMask(uint8(ma) ^ uint8(mo)) }
|
||||||
|
|
||||||
// HasMode returns true if a given Mode bitmask holds a specific Mode
|
// MaskHasMode returns true if a given Mode bitmask holds a specific Mode
|
||||||
func HasMode(b, m Mode) bool { return b&m != 0 }
|
func MaskHasMode(ma ModeMask, mo Mode) bool { return uint8(ma)&uint8(mo) != 0 }
|
||||||
|
|
||||||
|
func ModesFromFlags(ms string) ModeMask {
|
||||||
|
var mm ModeMask
|
||||||
|
for _, m := range strings.Split(ms, "") {
|
||||||
|
switch m {
|
||||||
|
case "C":
|
||||||
|
mm = MaskSetMode(mm, ModeLowerCase|ModeNumber|ModeSpecial|ModeUpperCase)
|
||||||
|
case "h":
|
||||||
|
mm = MaskClearMode(mm, ModeHumanReadable)
|
||||||
|
case "H":
|
||||||
|
mm = MaskSetMode(mm, ModeHumanReadable)
|
||||||
|
case "l":
|
||||||
|
mm = MaskClearMode(mm, ModeLowerCase)
|
||||||
|
case "L":
|
||||||
|
mm = MaskSetMode(mm, ModeLowerCase)
|
||||||
|
case "n":
|
||||||
|
mm = MaskClearMode(mm, ModeNumber)
|
||||||
|
case "N":
|
||||||
|
mm = MaskSetMode(mm, ModeNumber)
|
||||||
|
case "s":
|
||||||
|
mm = MaskClearMode(mm, ModeSpecial)
|
||||||
|
case "S":
|
||||||
|
mm = MaskSetMode(mm, ModeSpecial)
|
||||||
|
case "u":
|
||||||
|
mm = MaskClearMode(mm, ModeUpperCase)
|
||||||
|
case "U":
|
||||||
|
mm = MaskSetMode(mm, ModeUpperCase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mm
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// String satisfies the fmt.Stringer interface for the Mode type
|
||||||
|
func (m Mode) String() string {
|
||||||
|
switch m {
|
||||||
|
case ModeHumanReadable:
|
||||||
|
return "Human-readable"
|
||||||
|
case ModeLowerCase:
|
||||||
|
return "Lower-case"
|
||||||
|
case ModeNumber:
|
||||||
|
return "Number"
|
||||||
|
case ModeSpecial:
|
||||||
|
return "Special"
|
||||||
|
case ModeUpperCase:
|
||||||
|
return "Upper-case"
|
||||||
|
default:
|
||||||
|
return "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
26
mode_test.go
26
mode_test.go
|
@ -18,22 +18,22 @@ func TestSetClearHasToggleMode(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range tt {
|
for _, tc := range tt {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
var m Mode
|
var m ModeMask
|
||||||
m = SetMode(m, tc.mode)
|
m = MaskSetMode(m, tc.mode)
|
||||||
if !HasMode(m, tc.mode) {
|
if !MaskHasMode(m, tc.mode) {
|
||||||
t.Errorf("SetMode() failed, mode not found in bitmask")
|
t.Errorf("MaskSetMode() failed, mode not found in bitmask")
|
||||||
}
|
}
|
||||||
m = ToggleMode(m, tc.mode)
|
m = MaskToggleMode(m, tc.mode)
|
||||||
if HasMode(m, tc.mode) {
|
if MaskHasMode(m, tc.mode) {
|
||||||
t.Errorf("ToggleMode() failed, mode found in bitmask")
|
t.Errorf("MaskToggleMode() failed, mode found in bitmask")
|
||||||
}
|
}
|
||||||
m = ToggleMode(m, tc.mode)
|
m = MaskToggleMode(m, tc.mode)
|
||||||
if !HasMode(m, tc.mode) {
|
if !MaskHasMode(m, tc.mode) {
|
||||||
t.Errorf("ToggleMode() failed, mode not found in bitmask")
|
t.Errorf("MaskToggleMode() failed, mode not found in bitmask")
|
||||||
}
|
}
|
||||||
m = ClearMode(m, tc.mode)
|
m = MaskClearMode(m, tc.mode)
|
||||||
if HasMode(m, tc.mode) {
|
if MaskHasMode(m, tc.mode) {
|
||||||
t.Errorf("ClearMode() failed, mode found in bitmask")
|
t.Errorf("MaskClearMode() failed, mode found in bitmask")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue