github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/cmn/cos/rand.go (about)

     1  // Package cos provides common low-level types and utilities for all aistore projects
     2  /*
     3   * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package cos
     6  
     7  import (
     8  	cryptorand "crypto/rand"
     9  	"encoding/binary"
    10  	"math/rand"
    11  
    12  	"github.com/NVIDIA/aistore/cmn/debug"
    13  	"github.com/NVIDIA/aistore/cmn/mono"
    14  )
    15  
    16  const (
    17  	LetterRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    18  	LenRunes    = len(LetterRunes)
    19  
    20  	letterIdxBits = 6                    // 6 bits to represent a letter index
    21  	letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
    22  	letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
    23  )
    24  
    25  ///////////
    26  // crand //
    27  ///////////
    28  
    29  type crand struct{}
    30  
    31  var crnd rand.Source = &crand{}
    32  
    33  func (*crand) Int63() int64 {
    34  	var buf [8]byte
    35  	// crypto/rand uses syscalls or reads from /dev/random (or /dev/urandom) to get random bytes.
    36  	// See https://golang.org/pkg/crypto/rand/#pkg-variables for more.
    37  	_, err := cryptorand.Read(buf[:])
    38  	debug.AssertNoErr(err)
    39  	return int64(binary.LittleEndian.Uint64(buf[:]))
    40  }
    41  
    42  func (*crand) Seed(int64) {}
    43  
    44  func CryptoRandS(n int) string { return RandStringWithSrc(crnd, n) }
    45  
    46  //
    47  // misc. rand utils
    48  //
    49  
    50  func RandStringWithSrc(src rand.Source, n int) string {
    51  	b := make([]byte, n)
    52  	// src.Int63() generates 63 random bits, enough for letterIdxMax characters
    53  	for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
    54  		if remain == 0 {
    55  			cache, remain = src.Int63(), letterIdxMax
    56  		}
    57  		if idx := int(cache & letterIdxMask); idx < LenRunes {
    58  			b[i] = LetterRunes[idx]
    59  			i--
    60  		}
    61  		cache >>= letterIdxBits
    62  		remain--
    63  	}
    64  	return string(b)
    65  }
    66  
    67  func NowRand() *rand.Rand {
    68  	return rand.New(rand.NewSource(mono.NanoTime()))
    69  }