-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrandom.go
80 lines (66 loc) · 1.46 KB
/
random.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
/*
* Copyright (c) 2024 Mikhail Knyazhev <markus621@yandex.com>. All rights reserved.
* Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file.
*/
package random
import (
crand "crypto/rand"
"math/rand"
"sync"
"time"
)
var (
digest = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-+=~*@#$%&?!<>")
pool = sync.Pool{New: func() any {
return createRand()
}}
)
func createRand() *rand.Rand {
return rand.New(rand.NewSource(time.Now().UnixNano()))
}
func BytesOf(n int, src []byte) []byte {
rnd, ok := pool.Get().(*rand.Rand)
if !ok {
rnd = createRand()
}
defer pool.Put(rnd)
tmp := make([]byte, len(src))
copy(tmp, src)
rnd.Shuffle(len(tmp), func(i, j int) {
tmp[i], tmp[j] = tmp[j], tmp[i]
})
b := make([]byte, n)
for i := range b {
b[i] = tmp[rnd.Intn(len(tmp))]
}
return b
}
func StringOf(n int, src string) string {
return string(BytesOf(n, []byte(src)))
}
func Bytes(n int) []byte {
return BytesOf(n, digest)
}
func String(n int) string {
return string(Bytes(n))
}
func Shuffle[T any](v []T) []T {
rnd, ok := pool.Get().(*rand.Rand)
if !ok {
rnd = createRand()
}
defer pool.Put(rnd)
rnd.Shuffle(len(v), func(i, j int) { v[i], v[j] = v[j], v[i] })
return v
}
func CryptoBytes(n int) ([]byte, error) {
b := make([]byte, n)
var err error
for i := 0; i < 10; i++ {
if _, err = crand.Read(b); err != nil {
continue
}
return b, nil
}
return nil, err
}