github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/common/uuid/uuid.go (about) 1 package uuid // import "github.com/xmplusdev/xmcore/common/uuid" 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "crypto/sha1" 7 "encoding/hex" 8 9 "github.com/xmplusdev/xmcore/common" 10 "github.com/xmplusdev/xmcore/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 }