package pwgenerator import ( "crypto/rand" "math/big" "sort" "strings" ) /* GetCharset returns a CharSet from a set of characters. chars can be one of []rune, []byte, []string, or string. */ func GetCharset(chars interface{}) (charset CharSet, err error) { switch t := chars.(type) { case []rune: charset = CharSet(string(t)) case []byte: charset = CharSet(string(t)) case []string: s := strings.Join(t, "") charset = CharSet(s) case string: charset = CharSet(t) default: err = ErrBadType return } return } // sortDedupe sorts a slice of runes and deduplicates them. func sortDedupe(charset *CharSet) { var vals map[Char]bool = make(map[Char]bool) var sorted CharSet var idx int // This inherently dedupes. for _, i := range *charset { vals[i] = true } // This handles sorting. sorted = make(CharSet, len(vals)) // First we need a slice (again). for k := range vals { sorted[idx] = k idx++ } // And now we can sort... sort.Sort(&sorted) // And replace the original charset with the sorted, deduplicated one. *charset = sorted return } /* saferRandInt uses crypto/rand instead of math/rand to get a random number. While this is cryptographically safer, I guarantee it's a much bigger pain to do. */ func saferRandInt(max int) (randInt int, err error) { // Avoid a panic on max being 0 per rand.Int. if max == 0 { max = 1 } var max64 int64 = int64(max) var cryptoInt *big.Int = big.NewInt(max64) var randInt64 int64 if cryptoInt, err = rand.Int(rand.Reader, cryptoInt); err != nil { return } randInt64 = cryptoInt.Int64() randInt = int(randInt64) return }