github.com/MontFerret/ferret@v0.18.0/pkg/stdlib/strings/random.go (about)

     1  package strings
     2  
     3  import (
     4  	"context"
     5  	"math/rand"
     6  	"time"
     7  
     8  	"github.com/MontFerret/ferret/pkg/runtime/core"
     9  	"github.com/MontFerret/ferret/pkg/runtime/values"
    10  	"github.com/MontFerret/ferret/pkg/runtime/values/types"
    11  )
    12  
    13  const (
    14  	letterBytes   = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    15  	letterIdxBits = 6                    // 6 bits to represent a letter index
    16  	letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
    17  	letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
    18  )
    19  
    20  // randSrc is a global variable because of this issue
    21  // https://github.com/golang/go/issues/8926
    22  var randSrc = rand.NewSource(time.Now().UnixNano())
    23  
    24  // RANDOM_TOKEN generates a pseudo-random token string with the specified length. The algorithm for token generation should be treated as opaque.
    25  // @param {Int} len - The desired string length for the token. It must be greater than 0 and at most 65536.
    26  // @return {String} - A generated token consisting of lowercase letters, uppercase letters and numbers.
    27  func RandomToken(_ context.Context, args ...core.Value) (core.Value, error) {
    28  	err := core.ValidateArgs(args, 1, 1)
    29  
    30  	if err != nil {
    31  		return values.EmptyString, err
    32  	}
    33  
    34  	err = core.ValidateType(args[0], types.Int)
    35  
    36  	if err != nil {
    37  		return values.EmptyString, err
    38  	}
    39  
    40  	size := args[0].(values.Int)
    41  	b := make([]byte, size)
    42  
    43  	for i, cache, remain := size-1, randSrc.Int63(), letterIdxMax; i >= 0; {
    44  		if remain == 0 {
    45  			cache, remain = randSrc.Int63(), letterIdxMax
    46  		}
    47  
    48  		if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
    49  			b[i] = letterBytes[idx]
    50  			i--
    51  		}
    52  
    53  		cache >>= letterIdxBits
    54  		remain--
    55  	}
    56  
    57  	return values.NewString(string(b)), nil
    58  }