1 // Copyright (C) 2013-2015 by Maxim Bublis <b@codemonkey.ru>
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // Package uuid provides implementation of Universally Unique Identifier (UUID).
23 // Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
24 // version 2 (as specified in DCE 1.1).
43 // UUID layout variants.
58 // Difference in 100-nanosecond intervals between
59 // UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
60 const epochStart = 122192928000000000
62 // Used in string method conversion
65 // UUID v1/v2 storage.
67 storageMutex sync.Mutex
69 epochFunc = unixTimeFunc
73 posixUID = uint32(os.Getuid())
74 posixGID = uint32(os.Getgid())
77 // String parse helpers.
79 urnPrefix = []byte("urn:uuid:")
80 byteGroups = []int{8, 4, 4, 4, 12}
83 func initClockSequence() {
84 buf := make([]byte, 2)
86 clockSequence = binary.BigEndian.Uint16(buf)
89 func initHardwareAddr() {
90 interfaces, err := net.Interfaces()
92 for _, iface := range interfaces {
93 if len(iface.HardwareAddr) >= 6 {
94 copy(hardwareAddr[:], iface.HardwareAddr)
100 // Initialize hardwareAddr randomly in case
101 // of real network interfaces absence
102 safeRandom(hardwareAddr[:])
104 // Set multicast bit as recommended in RFC 4122
105 hardwareAddr[0] |= 0x01
113 func safeRandom(dest []byte) {
114 if _, err := rand.Read(dest); err != nil {
119 // Returns difference in 100-nanosecond intervals between
120 // UUID epoch (October 15, 1582) and current time.
121 // This is default epoch calculation function.
122 func unixTimeFunc() uint64 {
123 return epochStart + uint64(time.Now().UnixNano()/100)
126 // UUID representation compliant with specification
127 // described in RFC 4122.
130 // NullUUID can be used with the standard sql package to represent a
131 // UUID value that can be NULL in the database
132 type NullUUID struct {
137 // The nil UUID is special form of UUID that is specified to have all
138 // 128 bits set to zero.
141 // Predefined namespace UUIDs.
143 NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
144 NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
145 NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
146 NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
149 // And returns result of binary AND of two UUIDs.
150 func And(u1 UUID, u2 UUID) UUID {
152 for i := 0; i < 16; i++ {
158 // Or returns result of binary OR of two UUIDs.
159 func Or(u1 UUID, u2 UUID) UUID {
161 for i := 0; i < 16; i++ {
167 // Equal returns true if u1 and u2 equals, otherwise returns false.
168 func Equal(u1 UUID, u2 UUID) bool {
169 return bytes.Equal(u1[:], u2[:])
172 // Version returns algorithm version used to generate UUID.
173 func (u UUID) Version() uint {
174 return uint(u[6] >> 4)
177 // Variant returns UUID layout variant.
178 func (u UUID) Variant() uint {
180 case (u[8] & 0x80) == 0x00:
182 case (u[8]&0xc0)|0x80 == 0x80:
183 return VariantRFC4122
184 case (u[8]&0xe0)|0xc0 == 0xc0:
185 return VariantMicrosoft
190 // Bytes returns bytes slice representation of UUID.
191 func (u UUID) Bytes() []byte {
195 // Returns canonical string representation of UUID:
196 // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
197 func (u UUID) String() string {
198 buf := make([]byte, 36)
200 hex.Encode(buf[0:8], u[0:4])
202 hex.Encode(buf[9:13], u[4:6])
204 hex.Encode(buf[14:18], u[6:8])
206 hex.Encode(buf[19:23], u[8:10])
208 hex.Encode(buf[24:], u[10:])
213 // SetVersion sets version bits.
214 func (u *UUID) SetVersion(v byte) {
215 u[6] = (u[6] & 0x0f) | (v << 4)
218 // SetVariant sets variant bits as described in RFC 4122.
219 func (u *UUID) SetVariant() {
220 u[8] = (u[8] & 0xbf) | 0x80
223 // MarshalText implements the encoding.TextMarshaler interface.
224 // The encoding is the same as returned by String.
225 func (u UUID) MarshalText() (text []byte, err error) {
226 text = []byte(u.String())
230 // UnmarshalText implements the encoding.TextUnmarshaler interface.
231 // Following formats are supported:
232 // "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
233 // "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
234 // "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
235 func (u *UUID) UnmarshalText(text []byte) (err error) {
237 err = fmt.Errorf("uuid: UUID string too short: %s", text)
244 if bytes.Equal(t[:9], urnPrefix) {
246 } else if t[0] == '{' {
253 for i, byteGroup := range byteGroups {
256 err = fmt.Errorf("uuid: invalid string format")
262 if len(t) < byteGroup {
263 err = fmt.Errorf("uuid: UUID string too short: %s", text)
267 if i == 4 && len(t) > byteGroup &&
268 ((braced && t[byteGroup] != '}') || len(t[byteGroup:]) > 1 || !braced) {
269 err = fmt.Errorf("uuid: UUID string too long: %s", text)
273 _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup])
285 // MarshalBinary implements the encoding.BinaryMarshaler interface.
286 func (u UUID) MarshalBinary() (data []byte, err error) {
291 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
292 // It will return error if the slice isn't 16 bytes long.
293 func (u *UUID) UnmarshalBinary(data []byte) (err error) {
295 err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
303 // Value implements the driver.Valuer interface.
304 func (u UUID) Value() (driver.Value, error) {
305 return u.String(), nil
308 // Scan implements the sql.Scanner interface.
309 // A 16-byte slice is handled by UnmarshalBinary, while
310 // a longer byte slice or a string is handled by UnmarshalText.
311 func (u *UUID) Scan(src interface{}) error {
312 switch src := src.(type) {
315 return u.UnmarshalBinary(src)
317 return u.UnmarshalText(src)
320 return u.UnmarshalText([]byte(src))
323 return fmt.Errorf("uuid: cannot convert %T to UUID", src)
326 // Value implements the driver.Valuer interface.
327 func (u NullUUID) Value() (driver.Value, error) {
331 // Delegate to UUID Value function
332 return u.UUID.Value()
335 // Scan implements the sql.Scanner interface.
336 func (u *NullUUID) Scan(src interface{}) error {
338 u.UUID, u.Valid = Nil, false
342 // Delegate to UUID Scan function
344 return u.UUID.Scan(src)
347 // FromBytes returns UUID converted from raw byte slice input.
348 // It will return error if the slice isn't 16 bytes long.
349 func FromBytes(input []byte) (u UUID, err error) {
350 err = u.UnmarshalBinary(input)
354 // FromBytesOrNil returns UUID converted from raw byte slice input.
355 // Same behavior as FromBytes, but returns a Nil UUID on error.
356 func FromBytesOrNil(input []byte) UUID {
357 uuid, err := FromBytes(input)
364 // FromString returns UUID parsed from string input.
365 // Input is expected in a form accepted by UnmarshalText.
366 func FromString(input string) (u UUID, err error) {
367 err = u.UnmarshalText([]byte(input))
371 // FromStringOrNil returns UUID parsed from string input.
372 // Same behavior as FromString, but returns a Nil UUID on error.
373 func FromStringOrNil(input string) UUID {
374 uuid, err := FromString(input)
381 // Returns UUID v1/v2 storage state.
382 // Returns epoch timestamp, clock sequence, and hardware address.
383 func getStorage() (uint64, uint16, []byte) {
384 storageOnce.Do(initStorage)
387 defer storageMutex.Unlock()
389 timeNow := epochFunc()
390 // Clock changed backwards since last UUID generation.
391 // Should increase clock sequence.
392 if timeNow <= lastTime {
397 return timeNow, clockSequence, hardwareAddr[:]
400 // NewV1 returns UUID based on current timestamp and MAC address.
404 timeNow, clockSeq, hardwareAddr := getStorage()
406 binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
407 binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
408 binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
409 binary.BigEndian.PutUint16(u[8:], clockSeq)
411 copy(u[10:], hardwareAddr)
419 // NewV2 returns DCE Security UUID based on POSIX UID/GID.
420 func NewV2(domain byte) UUID {
423 timeNow, clockSeq, hardwareAddr := getStorage()
427 binary.BigEndian.PutUint32(u[0:], posixUID)
429 binary.BigEndian.PutUint32(u[0:], posixGID)
432 binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
433 binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
434 binary.BigEndian.PutUint16(u[8:], clockSeq)
437 copy(u[10:], hardwareAddr)
445 // NewV3 returns UUID based on MD5 hash of namespace UUID and name.
446 func NewV3(ns UUID, name string) UUID {
447 u := newFromHash(md5.New(), ns, name)
454 // NewV4 returns random generated UUID.
464 // NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
465 func NewV5(ns UUID, name string) UUID {
466 u := newFromHash(sha1.New(), ns, name)
473 // Returns UUID based on hashing of namespace UUID and name.
474 func newFromHash(h hash.Hash, ns UUID, name string) UUID {
477 h.Write([]byte(name))
478 copy(u[:], h.Sum(nil))