first commit
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
mathRand "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.
|
||||
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 {
|
||||
mathRand.Read(data[n:])
|
||||
}
|
||||
}
|
||||
|
||||
// InternalErrorID generates a long string
|
||||
func InternalErrorID() string {
|
||||
return ID("ISE", 32)
|
||||
}
|
||||
|
||||
// TagID generates a location ID. len=8
|
||||
func TagID(longName string) string {
|
||||
return friendlyID('T', longName, 8)
|
||||
}
|
||||
|
||||
// CharacterID generates a character ID. len=8
|
||||
func CharacterID(longName string) string {
|
||||
return friendlyID('C', longName, 8)
|
||||
}
|
||||
|
||||
func friendlyID(prefix byte, name string, length int) string {
|
||||
b := strings.Builder{}
|
||||
b.Grow(4)
|
||||
b.WriteByte(prefix)
|
||||
for _, ch := range strings.ToLower(name) {
|
||||
if ch >= 'a' && ch <= 'z' {
|
||||
b.WriteRune(ch)
|
||||
|
||||
if b.Len() > 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ID(b.String(), length)
|
||||
}
|
||||
|
||||
// StoryID generates a story ID: len=8
|
||||
func StoryID() string {
|
||||
return ID("S", 12)
|
||||
}
|
||||
|
||||
// PostID generates a post ID. len=12
|
||||
func PostID() string {
|
||||
return ID("P", 16)
|
||||
}
|
||||
|
||||
// AnnotationID generates an annotation.sql ID. len=12
|
||||
func AnnotationID() string {
|
||||
return ID("A", 16)
|
||||
}
|
||||
Reference in New Issue
Block a user