130 lines
2.6 KiB
Go
130 lines
2.6 KiB
Go
package randomvalues
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"math/big"
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
|
|
"fiskerinc.com/modules/utils/mt19937"
|
|
)
|
|
|
|
type Generator struct {
|
|
characters string
|
|
counter int32
|
|
maxUniform int32
|
|
onceUniform sync.Once
|
|
uniform *mt19937.UniformIntDistribution
|
|
mt *mt19937.MT19937
|
|
}
|
|
|
|
func NewGenerator(allowedchars string) Generator {
|
|
if len(allowedchars) == 0 {
|
|
allowedchars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
}
|
|
instance := Generator{
|
|
characters: allowedchars,
|
|
maxUniform: 255,
|
|
}
|
|
val, _ := instance.GetUInt32()
|
|
instance.counter = int32(val)
|
|
|
|
return instance
|
|
}
|
|
|
|
func (g *Generator) GetBytes(length int) ([]byte, error) {
|
|
result := make([]byte, length)
|
|
_, err := rand.Read(result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (g *Generator) GetString(length int) (string, error) {
|
|
result := make([]byte, length)
|
|
for i := 0; i < length; i++ {
|
|
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(g.characters))))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
result[i] = g.characters[num.Int64()]
|
|
}
|
|
|
|
return string(result), nil
|
|
}
|
|
|
|
func (g *Generator) GetUInt64() (uint64, error) {
|
|
buf := make([]byte, 8)
|
|
_, err := rand.Read(buf)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return binary.LittleEndian.Uint64(buf), nil
|
|
}
|
|
|
|
func (g *Generator) GetUInt32() (uint32, error) {
|
|
buf := make([]byte, 4)
|
|
_, err := rand.Read(buf)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return binary.LittleEndian.Uint32(buf), nil
|
|
}
|
|
|
|
func (g *Generator) GetInt(max int) int {
|
|
result, _ := rand.Int(rand.Reader, big.NewInt(int64(max)))
|
|
return int(result.Int64())
|
|
}
|
|
|
|
func (g *Generator) GetHex() (string, error) {
|
|
value, err := g.GetUInt64()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return fmt.Sprintf("%016s", strconv.FormatUint(value, 16)), nil
|
|
}
|
|
|
|
func (g *Generator) getUniformIntDistribution() *mt19937.UniformIntDistribution {
|
|
g.onceUniform.Do(func() {
|
|
if g.uniform != nil {
|
|
return
|
|
}
|
|
g.mt = mt19937.New()
|
|
g.uniform = mt19937.DistInt64(g.mt, 0, 255)
|
|
})
|
|
|
|
return g.uniform
|
|
}
|
|
|
|
func (g *Generator) GetUnformDistInt() int {
|
|
dist := g.getUniformIntDistribution()
|
|
return int(dist.Int64())
|
|
}
|
|
|
|
func (g *Generator) GetUniformDistHex() (string, error) {
|
|
now := time.Now().UnixNano()
|
|
result := uint64(now) << 32
|
|
d := g.GetUnformDistInt() & 0xFF
|
|
result |= uint64(d << 24)
|
|
d = g.GetUnformDistInt() & 0xFF
|
|
result |= uint64(d << 16)
|
|
c := g.counter & 0xFFFF
|
|
result |= uint64(c)
|
|
g.counter++
|
|
|
|
return fmt.Sprintf("%016s", strconv.FormatUint(result, 16)), nil
|
|
}
|
|
|
|
func (g *Generator) Close() {
|
|
g.counter = 0
|
|
g.characters = ""
|
|
g.mt = nil
|
|
g.uniform = nil
|
|
}
|