github.com/yaling888/clash@v1.53.0/transport/ssr/tools/random.go (about)

     1  package tools
     2  
     3  import (
     4  	"encoding/binary"
     5  
     6  	"github.com/yaling888/clash/common/pool"
     7  )
     8  
     9  // XorShift128Plus - a pseudorandom number generator
    10  type XorShift128Plus struct {
    11  	s [2]uint64
    12  }
    13  
    14  func (r *XorShift128Plus) Next() uint64 {
    15  	x := r.s[0]
    16  	y := r.s[1]
    17  	r.s[0] = y
    18  	x ^= x << 23
    19  	x ^= y ^ (x >> 17) ^ (y >> 26)
    20  	r.s[1] = x
    21  	return x + y
    22  }
    23  
    24  func (r *XorShift128Plus) InitFromBin(bin []byte) {
    25  	var full []byte
    26  	if len(bin) < 16 {
    27  		bufP := pool.GetBufferWriter()
    28  		defer pool.PutBufferWriter(bufP)
    29  
    30  		*bufP = append(*bufP, bin...)
    31  		for len(*bufP) < 16 {
    32  			*bufP = append(*bufP, 0)
    33  		}
    34  		full = *bufP
    35  	} else {
    36  		full = bin
    37  	}
    38  	r.s[0] = binary.LittleEndian.Uint64(full[:8])
    39  	r.s[1] = binary.LittleEndian.Uint64(full[8:16])
    40  }
    41  
    42  func (r *XorShift128Plus) InitFromBinAndLength(bin []byte, length int) {
    43  	var full []byte
    44  	if len(bin) < 16 {
    45  		bufP := pool.GetBufferWriter()
    46  		defer pool.PutBufferWriter(bufP)
    47  
    48  		*bufP = append(*bufP, bin...)
    49  		for len(*bufP) < 16 {
    50  			*bufP = append(*bufP, 0)
    51  		}
    52  		full = *bufP
    53  	} else {
    54  		full = bin
    55  	}
    56  	binary.LittleEndian.PutUint16(full, uint16(length))
    57  	r.s[0] = binary.LittleEndian.Uint64(full[:8])
    58  	r.s[1] = binary.LittleEndian.Uint64(full[8:16])
    59  	for i := 0; i < 4; i++ {
    60  		r.Next()
    61  	}
    62  }