-
Notifications
You must be signed in to change notification settings - Fork 0
/
rand.go
80 lines (66 loc) · 2.05 KB
/
rand.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package entity
import (
"hash/maphash"
"math/rand"
"unicode"
)
// Default set, matches "[a-zA-Z0-9_.-]"
const (
_lettersAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
_lettersAlphaNum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
_letterIdxBits = 6 // 6 bits to represent a letter index
_letterIdxMask = 1<<_letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
_letterIdxMax = 63 / _letterIdxBits // # of letter indices fitting in 63 bits
)
var (
_lettersASCII string
mapHashSrc = rand.New(rand.NewSource(int64(new(maphash.Hash).Sum64())))
TemplateFnsMap = map[string]any{
"random": func() any { return RandomFn{} },
}
)
func init() {
var (
lower = int32(Space[0])
upper = int32(Tilda[0])
)
chars := make([]rune, 0, int(upper)-int(lower))
for r := lower; r <= upper; r++ {
if unicode.IsGraphic(r) {
chars = append(chars, r)
}
}
_lettersASCII = string(chars)
}
// RandomFn has to generate random string value
type RandomFn struct{}
// Alpha Generates a random alphabetical (A-Z, a-z) string of a desired length.
func (RandomFn) Alpha(n int) string {
return randomString(n, _lettersAlpha)
}
// AlphaNum Generates a random alphanumeric (0-9, A-Z, a-z) string of a desired length.
func (RandomFn) AlphaNum(n int) string {
return randomString(n, _lettersAlphaNum)
}
// ASCII Generates a random string of a desired length, containing the set of printable characters from the 7-bit ASCII set.
// This includes space (’ ‘), but no other whitespace character
func (RandomFn) ASCII(n int) string {
return randomString(n, _lettersASCII)
}
func randomString(n int, set string) string {
src := mapHashSrc
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
for i, cache, remain := n-1, src.Int63(), _letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), _letterIdxMax
}
if idx := int(cache & _letterIdxMask); idx < len(set) {
b[i] = set[idx]
i--
}
cache >>= _letterIdxBits
remain--
}
return string(b)
}