github.com/xraypb/xray-core@v1.6.6/common/uuid/uuid.go (about)

     1  package uuid // import "github.com/xraypb/xray-core/common/uuid"
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"crypto/sha1"
     7  	"encoding/hex"
     8  
     9  	"github.com/xraypb/xray-core/common"
    10  	"github.com/xraypb/xray-core/common/errors"
    11  )
    12  
    13  var byteGroups = []int{8, 4, 4, 4, 12}
    14  
    15  type UUID [16]byte
    16  
    17  // String returns the string representation of this UUID.
    18  func (u *UUID) String() string {
    19  	bytes := u.Bytes()
    20  	result := hex.EncodeToString(bytes[0 : byteGroups[0]/2])
    21  	start := byteGroups[0] / 2
    22  	for i := 1; i < len(byteGroups); i++ {
    23  		nBytes := byteGroups[i] / 2
    24  		result += "-"
    25  		result += hex.EncodeToString(bytes[start : start+nBytes])
    26  		start += nBytes
    27  	}
    28  	return result
    29  }
    30  
    31  // Bytes returns the bytes representation of this UUID.
    32  func (u *UUID) Bytes() []byte {
    33  	return u[:]
    34  }
    35  
    36  // Equals returns true if this UUID equals another UUID by value.
    37  func (u *UUID) Equals(another *UUID) bool {
    38  	if u == nil && another == nil {
    39  		return true
    40  	}
    41  	if u == nil || another == nil {
    42  		return false
    43  	}
    44  	return bytes.Equal(u.Bytes(), another.Bytes())
    45  }
    46  
    47  // New creates a UUID with random value.
    48  func New() UUID {
    49  	var uuid UUID
    50  	common.Must2(rand.Read(uuid.Bytes()))
    51  	uuid[6] = (uuid[6] & 0x0f) | (4 << 4)
    52  	uuid[8] = (uuid[8]&(0xff>>2) | (0x02 << 6))
    53  	return uuid
    54  }
    55  
    56  // ParseBytes converts a UUID in byte form to object.
    57  func ParseBytes(b []byte) (UUID, error) {
    58  	var uuid UUID
    59  	if len(b) != 16 {
    60  		return uuid, errors.New("invalid UUID: ", b)
    61  	}
    62  	copy(uuid[:], b)
    63  	return uuid, nil
    64  }
    65  
    66  // ParseString converts a UUID in string form to object.
    67  func ParseString(str string) (UUID, error) {
    68  	var uuid UUID
    69  
    70  	text := []byte(str)
    71  	if l := len(text); l < 32 || l > 36 {
    72  		if l == 0 || l > 30 {
    73  			return uuid, errors.New("invalid UUID: ", str)
    74  		}
    75  		h := sha1.New()
    76  		h.Write(uuid[:])
    77  		h.Write(text)
    78  		u := h.Sum(nil)[:16]
    79  		u[6] = (u[6] & 0x0f) | (5 << 4)
    80  		u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
    81  		copy(uuid[:], u)
    82  		return uuid, nil
    83  	}
    84  
    85  	b := uuid.Bytes()
    86  
    87  	for _, byteGroup := range byteGroups {
    88  		if text[0] == '-' {
    89  			text = text[1:]
    90  		}
    91  
    92  		if _, err := hex.Decode(b[:byteGroup/2], text[:byteGroup]); err != nil {
    93  			return uuid, err
    94  		}
    95  
    96  		text = text[byteGroup:]
    97  		b = b[byteGroup/2:]
    98  	}
    99  
   100  	return uuid, nil
   101  }