Various improvements.
This commit is contained in:
@@ -8,7 +8,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
MaxIndex = block
|
||||
MaxIndex = block
|
||||
MaxRandomAttempts = 1024
|
||||
|
||||
letters = 26
|
||||
numbers = 900 // 100–999
|
||||
@@ -23,9 +24,16 @@ var (
|
||||
ErrNumberOutOfRange = errors.New("number out of range")
|
||||
ErrInvalidChecksum = errors.New("invalid checksum")
|
||||
ErrIndexOutOfRange = errors.New("index out of range")
|
||||
ErrRandomGenerationFailed = errors.New("random code generation failed")
|
||||
ErrRandomSourceFailed = errors.New("random source failed")
|
||||
ErrNoAvailableIndex = errors.New("no available index found")
|
||||
)
|
||||
|
||||
type RandomCodeOptions struct {
|
||||
MaxAttempts int
|
||||
IsInUse func(uint32) bool
|
||||
RandomIndex func(max uint32) (uint32, error)
|
||||
}
|
||||
|
||||
func Encode(code string) (uint32, error) {
|
||||
// Expected format: L1L2L3-NNN-L4C => length 10, positions: 0,1,2,4,5,6,8,9
|
||||
if len(code) != 10 || code[3] != '-' || code[7] != '-' {
|
||||
@@ -103,15 +111,34 @@ func Decode(idx uint32) (string, error) {
|
||||
}
|
||||
|
||||
func RandomCode(isInUse ...func(uint32) bool) (string, uint32, error) {
|
||||
var inUse func(uint32) bool
|
||||
options := RandomCodeOptions{}
|
||||
if len(isInUse) > 0 {
|
||||
inUse = isInUse[0]
|
||||
options.IsInUse = isInUse[0]
|
||||
}
|
||||
|
||||
for attempts := 0; attempts < 1024; attempts++ {
|
||||
idx, err := randomUint32n(MaxIndex)
|
||||
return RandomCodeWithOptions(options)
|
||||
}
|
||||
|
||||
func RandomCodeWithOptions(options RandomCodeOptions) (string, uint32, error) {
|
||||
maxAttempts := options.MaxAttempts
|
||||
if maxAttempts <= 0 {
|
||||
maxAttempts = MaxRandomAttempts
|
||||
}
|
||||
|
||||
inUse := options.IsInUse
|
||||
randomIndex := options.RandomIndex
|
||||
if randomIndex == nil {
|
||||
randomIndex = randomUint32n
|
||||
}
|
||||
|
||||
for attempts := 0; attempts < maxAttempts; attempts++ {
|
||||
idx, err := randomIndex(MaxIndex)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
return "", 0, fmt.Errorf("%w: %v", ErrRandomSourceFailed, err)
|
||||
}
|
||||
|
||||
if idx >= MaxIndex {
|
||||
return "", 0, fmt.Errorf("%w: index out of range", ErrRandomSourceFailed)
|
||||
}
|
||||
|
||||
if inUse != nil && inUse(idx) {
|
||||
@@ -129,7 +156,7 @@ func RandomCode(isInUse ...func(uint32) bool) (string, uint32, error) {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
return "", 0, ErrRandomGenerationFailed
|
||||
return "", 0, ErrNoAvailableIndex
|
||||
}
|
||||
|
||||
func checksumLetter(idx uint32) byte {
|
||||
|
||||
Reference in New Issue
Block a user