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 }