aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/satori/go.uuid/uuid.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/satori/go.uuid/uuid.go')
-rw-r--r--vendor/github.com/satori/go.uuid/uuid.go481
1 files changed, 481 insertions, 0 deletions
diff --git a/vendor/github.com/satori/go.uuid/uuid.go b/vendor/github.com/satori/go.uuid/uuid.go
new file mode 100644
index 0000000..295f3fc
--- /dev/null
+++ b/vendor/github.com/satori/go.uuid/uuid.go
@@ -0,0 +1,481 @@
1// Copyright (C) 2013-2015 by Maxim Bublis <b@codemonkey.ru>
2//
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:
10//
11// The above copyright notice and this permission notice shall be
12// included in all copies or substantial portions of the Software.
13//
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.
21
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).
25package uuid
26
27import (
28 "bytes"
29 "crypto/md5"
30 "crypto/rand"
31 "crypto/sha1"
32 "database/sql/driver"
33 "encoding/binary"
34 "encoding/hex"
35 "fmt"
36 "hash"
37 "net"
38 "os"
39 "sync"
40 "time"
41)
42
43// UUID layout variants.
44const (
45 VariantNCS = iota
46 VariantRFC4122
47 VariantMicrosoft
48 VariantFuture
49)
50
51// UUID DCE domains.
52const (
53 DomainPerson = iota
54 DomainGroup
55 DomainOrg
56)
57
58// Difference in 100-nanosecond intervals between
59// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
60const epochStart = 122192928000000000
61
62// Used in string method conversion
63const dash byte = '-'
64
65// UUID v1/v2 storage.
66var (
67 storageMutex sync.Mutex
68 storageOnce sync.Once
69 epochFunc = unixTimeFunc
70 clockSequence uint16
71 lastTime uint64
72 hardwareAddr [6]byte
73 posixUID = uint32(os.Getuid())
74 posixGID = uint32(os.Getgid())
75)
76
77// String parse helpers.
78var (
79 urnPrefix = []byte("urn:uuid:")
80 byteGroups = []int{8, 4, 4, 4, 12}
81)
82
83func initClockSequence() {
84 buf := make([]byte, 2)
85 safeRandom(buf)
86 clockSequence = binary.BigEndian.Uint16(buf)
87}
88
89func initHardwareAddr() {
90 interfaces, err := net.Interfaces()
91 if err == nil {
92 for _, iface := range interfaces {
93 if len(iface.HardwareAddr) >= 6 {
94 copy(hardwareAddr[:], iface.HardwareAddr)
95 return
96 }
97 }
98 }
99
100 // Initialize hardwareAddr randomly in case
101 // of real network interfaces absence
102 safeRandom(hardwareAddr[:])
103
104 // Set multicast bit as recommended in RFC 4122
105 hardwareAddr[0] |= 0x01
106}
107
108func initStorage() {
109 initClockSequence()
110 initHardwareAddr()
111}
112
113func safeRandom(dest []byte) {
114 if _, err := rand.Read(dest); err != nil {
115 panic(err)
116 }
117}
118
119// Returns difference in 100-nanosecond intervals between
120// UUID epoch (October 15, 1582) and current time.
121// This is default epoch calculation function.
122func unixTimeFunc() uint64 {
123 return epochStart + uint64(time.Now().UnixNano()/100)
124}
125
126// UUID representation compliant with specification
127// described in RFC 4122.
128type UUID [16]byte
129
130// NullUUID can be used with the standard sql package to represent a
131// UUID value that can be NULL in the database
132type NullUUID struct {
133 UUID UUID
134 Valid bool
135}
136
137// The nil UUID is special form of UUID that is specified to have all
138// 128 bits set to zero.
139var Nil = UUID{}
140
141// Predefined namespace UUIDs.
142var (
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")
147)
148
149// And returns result of binary AND of two UUIDs.
150func And(u1 UUID, u2 UUID) UUID {
151 u := UUID{}
152 for i := 0; i < 16; i++ {
153 u[i] = u1[i] & u2[i]
154 }
155 return u
156}
157
158// Or returns result of binary OR of two UUIDs.
159func Or(u1 UUID, u2 UUID) UUID {
160 u := UUID{}
161 for i := 0; i < 16; i++ {
162 u[i] = u1[i] | u2[i]
163 }
164 return u
165}
166
167// Equal returns true if u1 and u2 equals, otherwise returns false.
168func Equal(u1 UUID, u2 UUID) bool {
169 return bytes.Equal(u1[:], u2[:])
170}
171
172// Version returns algorithm version used to generate UUID.
173func (u UUID) Version() uint {
174 return uint(u[6] >> 4)
175}
176
177// Variant returns UUID layout variant.
178func (u UUID) Variant() uint {
179 switch {
180 case (u[8] & 0x80) == 0x00:
181 return VariantNCS
182 case (u[8]&0xc0)|0x80 == 0x80:
183 return VariantRFC4122
184 case (u[8]&0xe0)|0xc0 == 0xc0:
185 return VariantMicrosoft
186 }
187 return VariantFuture
188}
189
190// Bytes returns bytes slice representation of UUID.
191func (u UUID) Bytes() []byte {
192 return u[:]
193}
194
195// Returns canonical string representation of UUID:
196// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
197func (u UUID) String() string {
198 buf := make([]byte, 36)
199
200 hex.Encode(buf[0:8], u[0:4])
201 buf[8] = dash
202 hex.Encode(buf[9:13], u[4:6])
203 buf[13] = dash
204 hex.Encode(buf[14:18], u[6:8])
205 buf[18] = dash
206 hex.Encode(buf[19:23], u[8:10])
207 buf[23] = dash
208 hex.Encode(buf[24:], u[10:])
209
210 return string(buf)
211}
212
213// SetVersion sets version bits.
214func (u *UUID) SetVersion(v byte) {
215 u[6] = (u[6] & 0x0f) | (v << 4)
216}
217
218// SetVariant sets variant bits as described in RFC 4122.
219func (u *UUID) SetVariant() {
220 u[8] = (u[8] & 0xbf) | 0x80
221}
222
223// MarshalText implements the encoding.TextMarshaler interface.
224// The encoding is the same as returned by String.
225func (u UUID) MarshalText() (text []byte, err error) {
226 text = []byte(u.String())
227 return
228}
229
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"
235func (u *UUID) UnmarshalText(text []byte) (err error) {
236 if len(text) < 32 {
237 err = fmt.Errorf("uuid: UUID string too short: %s", text)
238 return
239 }
240
241 t := text[:]
242 braced := false
243
244 if bytes.Equal(t[:9], urnPrefix) {
245 t = t[9:]
246 } else if t[0] == '{' {
247 braced = true
248 t = t[1:]
249 }
250
251 b := u[:]
252
253 for i, byteGroup := range byteGroups {
254 if i > 0 {
255 if t[0] != '-' {
256 err = fmt.Errorf("uuid: invalid string format")
257 return
258 }
259 t = t[1:]
260 }
261
262 if len(t) < byteGroup {
263 err = fmt.Errorf("uuid: UUID string too short: %s", text)
264 return
265 }
266
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)
270 return
271 }
272
273 _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup])
274 if err != nil {
275 return
276 }
277
278 t = t[byteGroup:]
279 b = b[byteGroup/2:]
280 }
281
282 return
283}
284
285// MarshalBinary implements the encoding.BinaryMarshaler interface.
286func (u UUID) MarshalBinary() (data []byte, err error) {
287 data = u.Bytes()
288 return
289}
290
291// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
292// It will return error if the slice isn't 16 bytes long.
293func (u *UUID) UnmarshalBinary(data []byte) (err error) {
294 if len(data) != 16 {
295 err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
296 return
297 }
298 copy(u[:], data)
299
300 return
301}
302
303// Value implements the driver.Valuer interface.
304func (u UUID) Value() (driver.Value, error) {
305 return u.String(), nil
306}
307
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.
311func (u *UUID) Scan(src interface{}) error {
312 switch src := src.(type) {
313 case []byte:
314 if len(src) == 16 {
315 return u.UnmarshalBinary(src)
316 }
317 return u.UnmarshalText(src)
318
319 case string:
320 return u.UnmarshalText([]byte(src))
321 }
322
323 return fmt.Errorf("uuid: cannot convert %T to UUID", src)
324}
325
326// Value implements the driver.Valuer interface.
327func (u NullUUID) Value() (driver.Value, error) {
328 if !u.Valid {
329 return nil, nil
330 }
331 // Delegate to UUID Value function
332 return u.UUID.Value()
333}
334
335// Scan implements the sql.Scanner interface.
336func (u *NullUUID) Scan(src interface{}) error {
337 if src == nil {
338 u.UUID, u.Valid = Nil, false
339 return nil
340 }
341
342 // Delegate to UUID Scan function
343 u.Valid = true
344 return u.UUID.Scan(src)
345}
346
347// FromBytes returns UUID converted from raw byte slice input.
348// It will return error if the slice isn't 16 bytes long.
349func FromBytes(input []byte) (u UUID, err error) {
350 err = u.UnmarshalBinary(input)
351 return
352}
353
354// FromBytesOrNil returns UUID converted from raw byte slice input.
355// Same behavior as FromBytes, but returns a Nil UUID on error.
356func FromBytesOrNil(input []byte) UUID {
357 uuid, err := FromBytes(input)
358 if err != nil {
359 return Nil
360 }
361 return uuid
362}
363
364// FromString returns UUID parsed from string input.
365// Input is expected in a form accepted by UnmarshalText.
366func FromString(input string) (u UUID, err error) {
367 err = u.UnmarshalText([]byte(input))
368 return
369}
370
371// FromStringOrNil returns UUID parsed from string input.
372// Same behavior as FromString, but returns a Nil UUID on error.
373func FromStringOrNil(input string) UUID {
374 uuid, err := FromString(input)
375 if err != nil {
376 return Nil
377 }
378 return uuid
379}
380
381// Returns UUID v1/v2 storage state.
382// Returns epoch timestamp, clock sequence, and hardware address.
383func getStorage() (uint64, uint16, []byte) {
384 storageOnce.Do(initStorage)
385
386 storageMutex.Lock()
387 defer storageMutex.Unlock()
388
389 timeNow := epochFunc()
390 // Clock changed backwards since last UUID generation.
391 // Should increase clock sequence.
392 if timeNow <= lastTime {
393 clockSequence++
394 }
395 lastTime = timeNow
396
397 return timeNow, clockSequence, hardwareAddr[:]
398}
399
400// NewV1 returns UUID based on current timestamp and MAC address.
401func NewV1() UUID {
402 u := UUID{}
403
404 timeNow, clockSeq, hardwareAddr := getStorage()
405
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)
410
411 copy(u[10:], hardwareAddr)
412
413 u.SetVersion(1)
414 u.SetVariant()
415
416 return u
417}
418
419// NewV2 returns DCE Security UUID based on POSIX UID/GID.
420func NewV2(domain byte) UUID {
421 u := UUID{}
422
423 timeNow, clockSeq, hardwareAddr := getStorage()
424
425 switch domain {
426 case DomainPerson:
427 binary.BigEndian.PutUint32(u[0:], posixUID)
428 case DomainGroup:
429 binary.BigEndian.PutUint32(u[0:], posixGID)
430 }
431
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)
435 u[9] = domain
436
437 copy(u[10:], hardwareAddr)
438
439 u.SetVersion(2)
440 u.SetVariant()
441
442 return u
443}
444
445// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
446func NewV3(ns UUID, name string) UUID {
447 u := newFromHash(md5.New(), ns, name)
448 u.SetVersion(3)
449 u.SetVariant()
450
451 return u
452}
453
454// NewV4 returns random generated UUID.
455func NewV4() UUID {
456 u := UUID{}
457 safeRandom(u[:])
458 u.SetVersion(4)
459 u.SetVariant()
460
461 return u
462}
463
464// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
465func NewV5(ns UUID, name string) UUID {
466 u := newFromHash(sha1.New(), ns, name)
467 u.SetVersion(5)
468 u.SetVariant()
469
470 return u
471}
472
473// Returns UUID based on hashing of namespace UUID and name.
474func newFromHash(h hash.Hash, ns UUID, name string) UUID {
475 u := UUID{}
476 h.Write(ns[:])
477 h.Write([]byte(name))
478 copy(u[:], h.Sum(nil))
479
480 return u
481}