This commit is contained in:
antanst
2025-10-09 17:43:23 +03:00
parent 2ead66f012
commit 3a5835fc42
54 changed files with 5881 additions and 120 deletions

5
vendor/git.antanst.com/antanst/uid/README.md generated vendored Normal file
View File

@@ -0,0 +1,5 @@
# UID
This project generates a reasonably secure and convenient UID.
Borrows code from https://github.com/matoous/go-nanoid

68
vendor/git.antanst.com/antanst/uid/uid.go generated vendored Normal file
View File

@@ -0,0 +1,68 @@
package uid
import (
"crypto/rand"
"errors"
"math"
)
// UID is a high level function that returns a reasonably secure UID.
// Only alphanumeric characters except 'o','O' and 'l'
func UID() string {
id, err := Generate("abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ0123456789", 20)
if err != nil {
panic(err)
}
return id
}
// Generate is a low-level function to change alphabet and ID size.
// Taken from go-nanoid project
func Generate(alphabet string, size int) (string, error) {
chars := []rune(alphabet)
if len(alphabet) == 0 || len(alphabet) > 255 {
return "", errors.New("alphabet must not be empty and contain no more than 255 chars")
}
if size <= 0 {
return "", errors.New("size must be positive integer")
}
mask := getMask(len(chars))
// estimate how many random bytes we will need for the ID, we might actually need more but this is tradeoff
// between average case and worst case
ceilArg := 1.6 * float64(mask*size) / float64(len(alphabet))
step := int(math.Ceil(ceilArg))
id := make([]rune, size)
bytes := make([]byte, step)
for j := 0; ; {
_, err := rand.Read(bytes)
if err != nil {
return "", err
}
for i := 0; i < step; i++ {
currByte := bytes[i] & byte(mask)
if currByte < byte(len(chars)) {
id[j] = chars[currByte]
j++
if j == size {
return string(id[:size]), nil
}
}
}
}
}
// getMask generates bit mask used to obtain bits from the random bytes that are used to get index of random character
// from the alphabet. Example: if the alphabet has 6 = (110)_2 characters it is sufficient to use mask 7 = (111)_2
// Taken from go-nanoid project
func getMask(alphabetSize int) int {
for i := 1; i <= 8; i++ {
mask := (2 << uint(i)) - 1
if mask >= alphabetSize-1 {
return mask
}
}
return 0
}