mirror of https://github.com/docker/docs.git
				
				
				
			
		
			
				
	
	
		
			72 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			72 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Go
		
	
	
	
package random
 | 
						|
 | 
						|
import (
 | 
						|
	cryptorand "crypto/rand"
 | 
						|
	"io"
 | 
						|
	"math"
 | 
						|
	"math/big"
 | 
						|
	"math/rand"
 | 
						|
	"sync"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
// Rand is a global *rand.Rand instance, which initialized with NewSource() source.
 | 
						|
var Rand = rand.New(NewSource())
 | 
						|
 | 
						|
// Reader is a global, shared instance of a pseudorandom bytes generator.
 | 
						|
// It doesn't consume entropy.
 | 
						|
var Reader io.Reader = &reader{rnd: Rand}
 | 
						|
 | 
						|
// copypaste from standard math/rand
 | 
						|
type lockedSource struct {
 | 
						|
	lk  sync.Mutex
 | 
						|
	src rand.Source
 | 
						|
}
 | 
						|
 | 
						|
func (r *lockedSource) Int63() (n int64) {
 | 
						|
	r.lk.Lock()
 | 
						|
	n = r.src.Int63()
 | 
						|
	r.lk.Unlock()
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func (r *lockedSource) Seed(seed int64) {
 | 
						|
	r.lk.Lock()
 | 
						|
	r.src.Seed(seed)
 | 
						|
	r.lk.Unlock()
 | 
						|
}
 | 
						|
 | 
						|
// NewSource returns math/rand.Source safe for concurrent use and initialized
 | 
						|
// with current unix-nano timestamp
 | 
						|
func NewSource() rand.Source {
 | 
						|
	var seed int64
 | 
						|
	if cryptoseed, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64)); err != nil {
 | 
						|
		// This should not happen, but worst-case fallback to time-based seed.
 | 
						|
		seed = time.Now().UnixNano()
 | 
						|
	} else {
 | 
						|
		seed = cryptoseed.Int64()
 | 
						|
	}
 | 
						|
	return &lockedSource{
 | 
						|
		src: rand.NewSource(seed),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type reader struct {
 | 
						|
	rnd *rand.Rand
 | 
						|
}
 | 
						|
 | 
						|
func (r *reader) Read(b []byte) (int, error) {
 | 
						|
	i := 0
 | 
						|
	for {
 | 
						|
		val := r.rnd.Int63()
 | 
						|
		for val > 0 {
 | 
						|
			b[i] = byte(val)
 | 
						|
			i++
 | 
						|
			if i == len(b) {
 | 
						|
				return i, nil
 | 
						|
			}
 | 
						|
			val >>= 8
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |