github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/x/stringsx/util.go (about)

     1  package stringsx
     2  
     3  import (
     4  	"math/rand"
     5  	"time"
     6  )
     7  
     8  var (
     9  	visibleChars    []byte
    10  	visibleCharsLen int
    11  
    12  	src = rand.NewSource(time.Now().UnixNano())
    13  )
    14  
    15  var GenRandomVisibleString = GenRandomVisibleStringV2
    16  
    17  const (
    18  	letterIdxBits = 7                    // 7 bits to represent a letter index
    19  	letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
    20  	letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
    21  )
    22  
    23  func init() {
    24  	visibleCharsLen = 95 // all visible chars [32,126] 95=1011111b
    25  	visibleChars = make([]byte, visibleCharsLen)
    26  	for i := byte(0); int(i) < visibleCharsLen; i++ {
    27  		visibleChars[i] = i + 32
    28  	}
    29  }
    30  
    31  func GenRandomVisibleStringV1(length int, excluded ...byte) string {
    32  	if length == 0 {
    33  		return ""
    34  	}
    35  	result := make([]byte, 0, length)
    36  	rand.Seed(time.Now().UnixNano() + int64(rand.Intn(100)))
    37  	for i := 0; i < length; {
    38  	SKIP:
    39  		idx := rand.Intn(visibleCharsLen)
    40  		c := visibleChars[idx]
    41  		if len(excluded) > 0 {
    42  			for _, v := range excluded {
    43  				if v == c {
    44  					goto SKIP
    45  				}
    46  			}
    47  		}
    48  		result = append(result, c)
    49  		i++
    50  	}
    51  	return string(result)
    52  }
    53  
    54  func GenRandomVisibleStringV2(n int, excluded ...byte) string {
    55  	if n == 0 {
    56  		return ""
    57  	}
    58  	b := make([]byte, n)
    59  	// A src.Int63() generates 63 random bits, enough for letterIdxMax characters
    60  	for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
    61  		if remain == 0 {
    62  			cache, remain = src.Int63(), letterIdxMax
    63  		}
    64  		if idx := int(cache & letterIdxMask); idx < len(visibleChars) {
    65  			c := visibleChars[idx]
    66  			if len(excluded) > 0 {
    67  				for _, v := range excluded {
    68  					if v == c {
    69  						goto SKIP
    70  					}
    71  				}
    72  			}
    73  			b[i] = c
    74  			i--
    75  		}
    76  	SKIP:
    77  		cache >>= letterIdxBits
    78  		remain--
    79  	}
    80  	return string(b)
    81  }