You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
40 lines
824 B
40 lines
824 B
package generate
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
mrand "math/rand"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ID generates an ID using crypto-random, falling back to math random when that fails
|
|
// to avoid disrupting operation because of a faulty RNG. Database implementations does
|
|
// not need to use this if some other scheme improves storage.
|
|
func ID(prefix string, length int) string {
|
|
var data [32]byte
|
|
|
|
result := strings.Builder{}
|
|
result.Grow(length + 32)
|
|
result.WriteString(prefix)
|
|
|
|
pos := 0
|
|
for result.Len() < length {
|
|
if pos == 0 {
|
|
randRead(data[:])
|
|
}
|
|
|
|
result.WriteString(strconv.FormatUint(binary.BigEndian.Uint64(data[pos:pos+8]), 36))
|
|
|
|
pos = (pos + 8) % 32
|
|
}
|
|
|
|
return result.String()[:length]
|
|
}
|
|
|
|
func randRead(data []byte) {
|
|
n, err := rand.Read(data)
|
|
if err != nil {
|
|
mrand.Read(data[n:])
|
|
}
|
|
}
|