39 lines
1.0 KiB
Go
39 lines
1.0 KiB
Go
package shorturl
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"fmt"
|
||
"math/big"
|
||
"regexp"
|
||
)
|
||
|
||
// CodeLength is the length of generated short codes. 10 base36 characters
|
||
// give 36^10 ≈ 3.6 × 10^15 combinations.
|
||
const CodeLength = 10
|
||
|
||
// codeAlphabet is the base36 alphabet (lowercase letters + digits).
|
||
const codeAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||
|
||
var codeAlphabetBig = big.NewInt(int64(len(codeAlphabet)))
|
||
|
||
// RandomCode returns a cryptographically random base36 code of CodeLength chars.
|
||
func RandomCode() (string, error) {
|
||
buf := make([]byte, CodeLength)
|
||
for i := range buf {
|
||
n, err := rand.Int(rand.Reader, codeAlphabetBig)
|
||
if err != nil {
|
||
return "", fmt.Errorf("random code: %w", err)
|
||
}
|
||
buf[i] = codeAlphabet[n.Int64()]
|
||
}
|
||
return string(buf), nil
|
||
}
|
||
|
||
var validCodeRe = regexp.MustCompile(`^[a-z0-9]{4,16}$`)
|
||
|
||
// ValidCode returns true if s could plausibly be a short code we issued.
|
||
// Lenient on length (4-16) to allow future tuning without breaking old links.
|
||
func ValidCode(s string) bool {
|
||
return validCodeRe.MatchString(s)
|
||
}
|