amuz.es/src/infra/goutils@v0.1.3/misc/uuid.go (about) 1 package misc 2 3 import ( 4 "bytes" 5 "database/sql/driver" 6 "encoding/hex" 7 "errors" 8 "github.com/NebulousLabs/fastrand" 9 "fmt" 10 ) 11 12 type UUID [16]byte 13 14 func (u UUID) Marshal() ([]byte, error) { 15 return u[:], nil 16 } 17 18 func (u UUID) MarshalTo(buf []byte) (n int, err error) { 19 if len(u) == 0 { 20 return 0, nil 21 } 22 copy(buf, u[:]) 23 return len(u), nil 24 } 25 func (u *UUID) Unmarshal(buf []byte) error { 26 if len(buf) != 16 { 27 return fmt.Errorf("invalid UUID (got %d bytes)", len(buf)) 28 } 29 copy(u[:], buf) 30 return nil 31 } 32 33 func (u UUID) Compare(other UUID) int { 34 return bytes.Compare(u[:], other[:]) 35 } 36 37 func (u UUID) Equal(other UUID) bool { 38 return u.Compare(other) == 0 39 } 40 func (u *UUID) UnmarshalJSON(from []byte) error { 41 quote := []byte("\"") 42 quoteSize := len(quote) 43 44 if len(from) < quoteSize*2 { 45 return errors.New("invalid quote notation") 46 } 47 48 if !bytes.HasPrefix(from, quote) || !bytes.HasSuffix(from, quote) { 49 return errors.New("invalid quote notation") 50 } else if err := u.Unmarshal(from[quoteSize:len(from)-quoteSize]); err != nil { 51 return err 52 } 53 return nil 54 } 55 56 func (u UUID) MarshalJSON() ([]byte, error) { 57 var buffer bytes.Buffer 58 buffer.WriteRune('"') 59 buffer.WriteString(hex.EncodeToString(u[:])) 60 buffer.WriteRune('"') 61 return buffer.Bytes(), nil 62 } 63 64 func (u *UUID) Size() int { 65 if u == nil { 66 return 0 67 } 68 if len(*u) == 0 { 69 return 0 70 } 71 return 16 72 } 73 74 func NewUUID() (u UUID) { 75 newObj := UUID{} 76 newObj.Random() 77 return newObj 78 } 79 80 func (u *UUID) UUIDFromHexString(buf []byte) (error) { 81 hexBuf := make([]byte, hex.DecodedLen(len(buf))) 82 if _, err := hex.Decode(hexBuf, buf); err != nil { 83 return err 84 } else if err := u.Unmarshal(hexBuf); err != nil { 85 return err 86 } 87 return nil 88 } 89 90 func (u UUID) ToHexString() (string) { 91 return hex.EncodeToString(u[:]) 92 } 93 94 // Scan implements the Scanner interface. 95 func (u *UUID) Scan(src interface{}) error { 96 if src == nil { 97 return nil 98 } 99 100 b, ok := src.([]byte) 101 if !ok { 102 return errors.New("Scan source was not []bytes") 103 } 104 105 u.UUIDFromHexString(b) 106 return nil 107 } 108 109 // Value implements the driver Valuer interface. 110 func (u UUID) Value() (driver.Value, error) { 111 return u.ToHexString(), nil 112 } 113 114 func (u UUID) Random() { 115 fastrand.Read(u[:]) 116 u[6] = (u[6] & 0x0f) | 0x40 // Version 4 117 u[8] = (u[8] & 0x3f) | 0x80 // Variant is 10 118 }