github.com/wfusion/gofusion@v1.1.14/common/utils/random.go (about)

     1  package utils
     2  
     3  import (
     4  	cryptoRand "crypto/rand"
     5  	"encoding/ascii85"
     6  	"encoding/base64"
     7  	"encoding/hex"
     8  	"math/rand"
     9  	"reflect"
    10  	"strconv"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/google/uuid"
    15  	"github.com/lithammer/shortuuid/v4"
    16  	"github.com/oklog/ulid/v2"
    17  
    18  	"github.com/wfusion/gofusion/common/constant"
    19  	"github.com/wfusion/gofusion/common/utils/inspect"
    20  )
    21  
    22  func UUID() string {
    23  	return uuid.New().String()
    24  }
    25  
    26  // UUID_
    27  //nolint: revive // uuid without hyphen function issue
    28  func UUID_() string {
    29  	return strings.Replace(uuid.New().String(), constant.Hyphen, "", -1)
    30  }
    31  
    32  // ShortUUID returns a new short UUID with base57
    33  func ShortUUID() string {
    34  	return shortuuid.New()
    35  }
    36  
    37  // ULID returns a new ULID.
    38  func ULID() string {
    39  	return ulid.MustNew(ulid.Now(), cryptoRand.Reader).String()
    40  }
    41  
    42  func UUID20() string {
    43  	id := uuid.New()
    44  	t := make([]byte, ascii85.MaxEncodedLen(len(id)))
    45  	n := ascii85.Encode(t, id[:])
    46  	return string(t[:n])
    47  }
    48  
    49  func UUID22() string {
    50  	id := uuid.New()
    51  	return base64.RawURLEncoding.EncodeToString(id[:])
    52  }
    53  
    54  const (
    55  	randomChars       = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    56  	randomCharsLength = len(randomChars)
    57  )
    58  
    59  func CryptoRandom(b []byte) (n int, err error) {
    60  	return cryptoRand.Read(b)
    61  }
    62  
    63  func CryptoRandomBytes(size int) ([]byte, error) {
    64  	b := make([]byte, size)
    65  	if _, err := cryptoRand.Read(b); err != nil {
    66  		return nil, err
    67  	}
    68  	return b, nil
    69  }
    70  
    71  func CryptoRandomLetterAndNumber(n int) (string, error) {
    72  	b, err := CryptoRandomBytes(n)
    73  	if err != nil {
    74  		return "", err
    75  	}
    76  
    77  	random := make([]byte, 0, n)
    78  	for i := 0; i < n; i++ {
    79  		random = append(random, randomChars[b[i]%uint8(randomCharsLength)])
    80  	}
    81  	return string(random), nil
    82  }
    83  
    84  func RandomLetterAndNumber(n int) string {
    85  	random := make([]byte, 0, n)
    86  	rand.Seed(time.Now().UnixNano())
    87  	for i := 0; i < n; i++ {
    88  		random = append(random, randomChars[rand.Intn(randomCharsLength)])
    89  	}
    90  
    91  	return string(random)
    92  }
    93  
    94  func Random(b []byte, seed int64) (n int, err error) {
    95  	if seed == 0 {
    96  		rand.Seed(time.Now().UnixNano())
    97  	} else {
    98  		rand.Seed(seed)
    99  	}
   100  	return rand.Read(b)
   101  }
   102  
   103  func RandomNumbers(n int) string {
   104  	rand.Seed(time.Now().UnixNano())
   105  	ret := ""
   106  	for i := 0; i < n; i++ {
   107  		ret += strconv.Itoa(rand.Intn(10))
   108  	}
   109  	return ret
   110  }
   111  
   112  func CryptoRandomNumbers(n int) (string, error) {
   113  	b, err := CryptoRandomBytes(n)
   114  	if err != nil {
   115  		return "", err
   116  	}
   117  
   118  	random := make([]byte, 0, n)
   119  	for i := 0; i < n; i++ {
   120  		random = append(random, randomChars[b[i]%uint8(10)])
   121  	}
   122  	return string(random), nil
   123  }
   124  
   125  func NginxID() string {
   126  	upper := func(c byte) byte {
   127  		val := c
   128  		if val >= 97 && val <= 122 {
   129  			return val - 32
   130  		}
   131  		return c
   132  	}
   133  	int2byte := func(bs []byte, val int) {
   134  		size := 10
   135  		l := len(bs) - 1
   136  		for idx := l; idx >= 0; idx-- {
   137  			bs[idx] = byte(uint(val%size) + uint('0'))
   138  			val = val / size
   139  		}
   140  	}
   141  
   142  	ret := [33]byte{}
   143  	t := time.Now()
   144  	year, month, day := t.Date()
   145  	hour, minute, second := t.Clock()
   146  	int2byte(ret[:4], year)
   147  	int2byte(ret[4:6], int(month))
   148  	int2byte(ret[6:8], day)
   149  	int2byte(ret[8:10], hour)
   150  	int2byte(ret[10:12], minute)
   151  	int2byte(ret[12:14], second)
   152  	copy(ret[14:26], LocalIP.Bytes())
   153  	ms := t.UnixNano() / 1e6 % 1000
   154  	int2byte(ret[26:29], int(ms))
   155  	u32 := rand.Uint32()
   156  	u32 >>= 16
   157  	src := []byte{byte(u32 & 0xff), byte((u32 >> 8) & 0xff)}
   158  	hex.Encode(ret[29:33], src)
   159  	for idx := 29; idx < 33; idx++ {
   160  		ret[idx] = upper(ret[idx])
   161  	}
   162  	return string(ret[:])
   163  }
   164  
   165  func NewSafeRand(seed int64) *rand.Rand {
   166  	return rand.New(newBuiltinLockedSource(seed))
   167  }
   168  
   169  func newBuiltinLockedSource(seed int64) rand.Source64 {
   170  	t := inspect.TypeOf("math/rand.lockedSource")
   171  	source := reflect.New(t).Interface()
   172  
   173  	var err error
   174  	IfAny(
   175  		// go1.16 - go1.19
   176  		func() bool {
   177  			_, err = Catch(func() { inspect.SetField(source, "src", rand.NewSource(seed)) })
   178  			return err == nil
   179  		},
   180  		// go1.20 - go1.21, source is renamed and set seed when calling rather than constructing stage
   181  		func() bool {
   182  			_, err = Catch(func() { inspect.SetField(source, "s", rand.NewSource(seed)) })
   183  			return err == nil
   184  		},
   185  	)
   186  	if err != nil {
   187  		panic(err)
   188  	}
   189  
   190  	return source.(rand.Source64)
   191  }
   192  
   193  func init() {
   194  	rand.Seed(time.Now().Unix())
   195  
   196  	// assert if rand.lockedSource struct is not changed
   197  	newBuiltinLockedSource(1).Int63()
   198  }