ires 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,121 @@
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
23
+
24
+ import (
25
+ "testing"
26
+ )
27
+
28
+ func BenchmarkFromBytes(b *testing.B) {
29
+ bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
30
+ for i := 0; i < b.N; i++ {
31
+ FromBytes(bytes)
32
+ }
33
+ }
34
+
35
+ func BenchmarkFromString(b *testing.B) {
36
+ s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
37
+ for i := 0; i < b.N; i++ {
38
+ FromString(s)
39
+ }
40
+ }
41
+
42
+ func BenchmarkFromStringUrn(b *testing.B) {
43
+ s := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
44
+ for i := 0; i < b.N; i++ {
45
+ FromString(s)
46
+ }
47
+ }
48
+
49
+ func BenchmarkFromStringWithBrackets(b *testing.B) {
50
+ s := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}"
51
+ for i := 0; i < b.N; i++ {
52
+ FromString(s)
53
+ }
54
+ }
55
+
56
+ func BenchmarkNewV1(b *testing.B) {
57
+ for i := 0; i < b.N; i++ {
58
+ NewV1()
59
+ }
60
+ }
61
+
62
+ func BenchmarkNewV2(b *testing.B) {
63
+ for i := 0; i < b.N; i++ {
64
+ NewV2(DomainPerson)
65
+ }
66
+ }
67
+
68
+ func BenchmarkNewV3(b *testing.B) {
69
+ for i := 0; i < b.N; i++ {
70
+ NewV3(NamespaceDNS, "www.example.com")
71
+ }
72
+ }
73
+
74
+ func BenchmarkNewV4(b *testing.B) {
75
+ for i := 0; i < b.N; i++ {
76
+ NewV4()
77
+ }
78
+ }
79
+
80
+ func BenchmarkNewV5(b *testing.B) {
81
+ for i := 0; i < b.N; i++ {
82
+ NewV5(NamespaceDNS, "www.example.com")
83
+ }
84
+ }
85
+
86
+ func BenchmarkMarshalBinary(b *testing.B) {
87
+ u := NewV4()
88
+ for i := 0; i < b.N; i++ {
89
+ u.MarshalBinary()
90
+ }
91
+ }
92
+
93
+ func BenchmarkMarshalText(b *testing.B) {
94
+ u := NewV4()
95
+ for i := 0; i < b.N; i++ {
96
+ u.MarshalText()
97
+ }
98
+ }
99
+
100
+ func BenchmarkUnmarshalBinary(b *testing.B) {
101
+ bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
102
+ u := UUID{}
103
+ for i := 0; i < b.N; i++ {
104
+ u.UnmarshalBinary(bytes)
105
+ }
106
+ }
107
+
108
+ func BenchmarkUnmarshalText(b *testing.B) {
109
+ bytes := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
110
+ u := UUID{}
111
+ for i := 0; i < b.N; i++ {
112
+ u.UnmarshalText(bytes)
113
+ }
114
+ }
115
+
116
+ func BenchmarkMarshalToString(b *testing.B) {
117
+ u := NewV4()
118
+ for i := 0; i < b.N; i++ {
119
+ u.String()
120
+ }
121
+ }
@@ -0,0 +1,488 @@
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 && t[0] == '-' {
255
+ t = t[1:]
256
+ } else if i > 0 && t[0] != '-' {
257
+ err = fmt.Errorf("uuid: invalid string format")
258
+ return
259
+ }
260
+
261
+ if i == 2 {
262
+ if !bytes.Contains([]byte("012345"), []byte{t[0]}) {
263
+ err = fmt.Errorf("uuid: invalid version number: %s", t[0])
264
+ return
265
+ }
266
+ }
267
+
268
+ if len(t) < byteGroup {
269
+ err = fmt.Errorf("uuid: UUID string too short: %s", text)
270
+ return
271
+ }
272
+
273
+ if i == 4 && len(t) > byteGroup &&
274
+ ((braced && t[byteGroup] != '}') || len(t[byteGroup:]) > 1 || !braced) {
275
+ err = fmt.Errorf("uuid: UUID string too long: %s", t)
276
+ return
277
+ }
278
+
279
+ _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup])
280
+
281
+ if err != nil {
282
+ return
283
+ }
284
+
285
+ t = t[byteGroup:]
286
+ b = b[byteGroup/2:]
287
+ }
288
+
289
+ return
290
+ }
291
+
292
+ // MarshalBinary implements the encoding.BinaryMarshaler interface.
293
+ func (u UUID) MarshalBinary() (data []byte, err error) {
294
+ data = u.Bytes()
295
+ return
296
+ }
297
+
298
+ // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
299
+ // It will return error if the slice isn't 16 bytes long.
300
+ func (u *UUID) UnmarshalBinary(data []byte) (err error) {
301
+ if len(data) != 16 {
302
+ err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
303
+ return
304
+ }
305
+ copy(u[:], data)
306
+
307
+ return
308
+ }
309
+
310
+ // Value implements the driver.Valuer interface.
311
+ func (u UUID) Value() (driver.Value, error) {
312
+ return u.String(), nil
313
+ }
314
+
315
+ // Scan implements the sql.Scanner interface.
316
+ // A 16-byte slice is handled by UnmarshalBinary, while
317
+ // a longer byte slice or a string is handled by UnmarshalText.
318
+ func (u *UUID) Scan(src interface{}) error {
319
+ switch src := src.(type) {
320
+ case []byte:
321
+ if len(src) == 16 {
322
+ return u.UnmarshalBinary(src)
323
+ }
324
+ return u.UnmarshalText(src)
325
+
326
+ case string:
327
+ return u.UnmarshalText([]byte(src))
328
+ }
329
+
330
+ return fmt.Errorf("uuid: cannot convert %T to UUID", src)
331
+ }
332
+
333
+ // Value implements the driver.Valuer interface.
334
+ func (u NullUUID) Value() (driver.Value, error) {
335
+ if !u.Valid {
336
+ return nil, nil
337
+ }
338
+ // Delegate to UUID Value function
339
+ return u.UUID.Value()
340
+ }
341
+
342
+ // Scan implements the sql.Scanner interface.
343
+ func (u *NullUUID) Scan(src interface{}) error {
344
+ if src == nil {
345
+ u.UUID, u.Valid = Nil, false
346
+ return nil
347
+ }
348
+
349
+ // Delegate to UUID Scan function
350
+ u.Valid = true
351
+ return u.UUID.Scan(src)
352
+ }
353
+
354
+ // FromBytes returns UUID converted from raw byte slice input.
355
+ // It will return error if the slice isn't 16 bytes long.
356
+ func FromBytes(input []byte) (u UUID, err error) {
357
+ err = u.UnmarshalBinary(input)
358
+ return
359
+ }
360
+
361
+ // FromBytesOrNil returns UUID converted from raw byte slice input.
362
+ // Same behavior as FromBytes, but returns a Nil UUID on error.
363
+ func FromBytesOrNil(input []byte) UUID {
364
+ uuid, err := FromBytes(input)
365
+ if err != nil {
366
+ return Nil
367
+ }
368
+ return uuid
369
+ }
370
+
371
+ // FromString returns UUID parsed from string input.
372
+ // Input is expected in a form accepted by UnmarshalText.
373
+ func FromString(input string) (u UUID, err error) {
374
+ err = u.UnmarshalText([]byte(input))
375
+ return
376
+ }
377
+
378
+ // FromStringOrNil returns UUID parsed from string input.
379
+ // Same behavior as FromString, but returns a Nil UUID on error.
380
+ func FromStringOrNil(input string) UUID {
381
+ uuid, err := FromString(input)
382
+ if err != nil {
383
+ return Nil
384
+ }
385
+ return uuid
386
+ }
387
+
388
+ // Returns UUID v1/v2 storage state.
389
+ // Returns epoch timestamp, clock sequence, and hardware address.
390
+ func getStorage() (uint64, uint16, []byte) {
391
+ storageOnce.Do(initStorage)
392
+
393
+ storageMutex.Lock()
394
+ defer storageMutex.Unlock()
395
+
396
+ timeNow := epochFunc()
397
+ // Clock changed backwards since last UUID generation.
398
+ // Should increase clock sequence.
399
+ if timeNow <= lastTime {
400
+ clockSequence++
401
+ }
402
+ lastTime = timeNow
403
+
404
+ return timeNow, clockSequence, hardwareAddr[:]
405
+ }
406
+
407
+ // NewV1 returns UUID based on current timestamp and MAC address.
408
+ func NewV1() UUID {
409
+ u := UUID{}
410
+
411
+ timeNow, clockSeq, hardwareAddr := getStorage()
412
+
413
+ binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
414
+ binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
415
+ binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
416
+ binary.BigEndian.PutUint16(u[8:], clockSeq)
417
+
418
+ copy(u[10:], hardwareAddr)
419
+
420
+ u.SetVersion(1)
421
+ u.SetVariant()
422
+
423
+ return u
424
+ }
425
+
426
+ // NewV2 returns DCE Security UUID based on POSIX UID/GID.
427
+ func NewV2(domain byte) UUID {
428
+ u := UUID{}
429
+
430
+ timeNow, clockSeq, hardwareAddr := getStorage()
431
+
432
+ switch domain {
433
+ case DomainPerson:
434
+ binary.BigEndian.PutUint32(u[0:], posixUID)
435
+ case DomainGroup:
436
+ binary.BigEndian.PutUint32(u[0:], posixGID)
437
+ }
438
+
439
+ binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
440
+ binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
441
+ binary.BigEndian.PutUint16(u[8:], clockSeq)
442
+ u[9] = domain
443
+
444
+ copy(u[10:], hardwareAddr)
445
+
446
+ u.SetVersion(2)
447
+ u.SetVariant()
448
+
449
+ return u
450
+ }
451
+
452
+ // NewV3 returns UUID based on MD5 hash of namespace UUID and name.
453
+ func NewV3(ns UUID, name string) UUID {
454
+ u := newFromHash(md5.New(), ns, name)
455
+ u.SetVersion(3)
456
+ u.SetVariant()
457
+
458
+ return u
459
+ }
460
+
461
+ // NewV4 returns random generated UUID.
462
+ func NewV4() UUID {
463
+ u := UUID{}
464
+ safeRandom(u[:])
465
+ u.SetVersion(4)
466
+ u.SetVariant()
467
+
468
+ return u
469
+ }
470
+
471
+ // NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
472
+ func NewV5(ns UUID, name string) UUID {
473
+ u := newFromHash(sha1.New(), ns, name)
474
+ u.SetVersion(5)
475
+ u.SetVariant()
476
+
477
+ return u
478
+ }
479
+
480
+ // Returns UUID based on hashing of namespace UUID and name.
481
+ func newFromHash(h hash.Hash, ns UUID, name string) UUID {
482
+ u := UUID{}
483
+ h.Write(ns[:])
484
+ h.Write([]byte(name))
485
+ copy(u[:], h.Sum(nil))
486
+
487
+ return u
488
+ }