mox/mox-/rand.go
Mechiel Lukkien 8550a5af45
don't expose functions on the prng that aren't mutex-protected
the current Intn calls in queue could be called concurrently, found by the race
detector with upcoming new tests.  best to just prevent any possible concurrent
access.
2024-03-07 10:05:35 +01:00

48 lines
937 B
Go

package mox
import (
cryptorand "crypto/rand"
"encoding/binary"
"fmt"
mathrand "math/rand"
"sync"
)
type rand struct {
rand *mathrand.Rand
sync.Mutex
}
// NewPseudoRand returns a new PRNG seeded with random bytes from crypto/rand. Its
// functions can be called concurrently.
func NewPseudoRand() *rand {
return &rand{rand: mathrand.New(mathrand.NewSource(CryptoRandInt()))}
}
func (r *rand) Float64() float64 {
r.Lock()
defer r.Unlock()
return r.rand.Float64()
}
func (r *rand) Intn(n int) int {
r.Lock()
defer r.Unlock()
return r.rand.Intn(n)
}
func (r *rand) Read(buf []byte) (int, error) {
r.Lock()
defer r.Unlock()
return r.rand.Read(buf)
}
// CryptoRandInt returns a cryptographically random number.
func CryptoRandInt() int64 {
buf := make([]byte, 8)
_, err := cryptorand.Read(buf)
if err != nil {
panic(fmt.Errorf("reading random bytes: %v", err))
}
return int64(binary.LittleEndian.Uint64(buf))
}