]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/satori/go.uuid/uuid.go
Initial transfer of provider code
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / satori / go.uuid / uuid.go
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).
25 package uuid
26
27 import (
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.
44 const (
45 VariantNCS = iota
46 VariantRFC4122
47 VariantMicrosoft
48 VariantFuture
49 )
50
51 // UUID DCE domains.
52 const (
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).
60 const epochStart = 122192928000000000
61
62 // Used in string method conversion
63 const dash byte = '-'
64
65 // UUID v1/v2 storage.
66 var (
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.
78 var (
79 urnPrefix = []byte("urn:uuid:")
80 byteGroups = []int{8, 4, 4, 4, 12}
81 )
82
83 func initClockSequence() {
84 buf := make([]byte, 2)
85 safeRandom(buf)
86 clockSequence = binary.BigEndian.Uint16(buf)
87 }
88
89 func 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
108 func initStorage() {
109 initClockSequence()
110 initHardwareAddr()
111 }
112
113 func 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.
122 func unixTimeFunc() uint64 {
123 return epochStart + uint64(time.Now().UnixNano()/100)
124 }
125
126 // UUID representation compliant with specification
127 // described in RFC 4122.
128 type 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
132 type 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.
139 var Nil = UUID{}
140
141 // Predefined namespace UUIDs.
142 var (
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.
150 func 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.
159 func 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.
168 func Equal(u1 UUID, u2 UUID) bool {
169 return bytes.Equal(u1[:], u2[:])
170 }
171
172 // Version returns algorithm version used to generate UUID.
173 func (u UUID) Version() uint {
174 return uint(u[6] >> 4)
175 }
176
177 // Variant returns UUID layout variant.
178 func (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.
191 func (u UUID) Bytes() []byte {
192 return u[:]
193 }
194
195 // Returns canonical string representation of UUID:
196 // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
197 func (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.
214 func (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.
219 func (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.
225 func (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"
235 func (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.
286 func (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.
293 func (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.
304 func (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.
311 func (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.
327 func (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.
336 func (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.
349 func 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.
356 func 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.
366 func 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.
373 func 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.
383 func 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.
401 func 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.
420 func 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.
446 func 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.
455 func 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.
465 func 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.
474 func 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 }