Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
kardolus
GitHub Repository: kardolus/chatgpt-cli
Path: blob/main/vendor/github.com/google/uuid/uuid.go
2875 views
1
// Copyright 2018 Google Inc. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
5
package uuid
6
7
import (
8
"bytes"
9
"crypto/rand"
10
"encoding/hex"
11
"errors"
12
"fmt"
13
"io"
14
"strings"
15
"sync"
16
)
17
18
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
19
// 4122.
20
type UUID [16]byte
21
22
// A Version represents a UUID's version.
23
type Version byte
24
25
// A Variant represents a UUID's variant.
26
type Variant byte
27
28
// Constants returned by Variant.
29
const (
30
Invalid = Variant(iota) // Invalid UUID
31
RFC4122 // The variant specified in RFC4122
32
Reserved // Reserved, NCS backward compatibility.
33
Microsoft // Reserved, Microsoft Corporation backward compatibility.
34
Future // Reserved for future definition.
35
)
36
37
const randPoolSize = 16 * 16
38
39
var (
40
rander = rand.Reader // random function
41
poolEnabled = false
42
poolMu sync.Mutex
43
poolPos = randPoolSize // protected with poolMu
44
pool [randPoolSize]byte // protected with poolMu
45
)
46
47
type invalidLengthError struct{ len int }
48
49
func (err invalidLengthError) Error() string {
50
return fmt.Sprintf("invalid UUID length: %d", err.len)
51
}
52
53
// IsInvalidLengthError is matcher function for custom error invalidLengthError
54
func IsInvalidLengthError(err error) bool {
55
_, ok := err.(invalidLengthError)
56
return ok
57
}
58
59
// Parse decodes s into a UUID or returns an error if it cannot be parsed. Both
60
// the standard UUID forms defined in RFC 4122
61
// (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
62
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are decoded. In addition,
63
// Parse accepts non-standard strings such as the raw hex encoding
64
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and 38 byte "Microsoft style" encodings,
65
// e.g. {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. Only the middle 36 bytes are
66
// examined in the latter case. Parse should not be used to validate strings as
67
// it parses non-standard encodings as indicated above.
68
func Parse(s string) (UUID, error) {
69
var uuid UUID
70
switch len(s) {
71
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
72
case 36:
73
74
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
75
case 36 + 9:
76
if !strings.EqualFold(s[:9], "urn:uuid:") {
77
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
78
}
79
s = s[9:]
80
81
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
82
case 36 + 2:
83
s = s[1:]
84
85
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
86
case 32:
87
var ok bool
88
for i := range uuid {
89
uuid[i], ok = xtob(s[i*2], s[i*2+1])
90
if !ok {
91
return uuid, errors.New("invalid UUID format")
92
}
93
}
94
return uuid, nil
95
default:
96
return uuid, invalidLengthError{len(s)}
97
}
98
// s is now at least 36 bytes long
99
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
100
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
101
return uuid, errors.New("invalid UUID format")
102
}
103
for i, x := range [16]int{
104
0, 2, 4, 6,
105
9, 11,
106
14, 16,
107
19, 21,
108
24, 26, 28, 30, 32, 34,
109
} {
110
v, ok := xtob(s[x], s[x+1])
111
if !ok {
112
return uuid, errors.New("invalid UUID format")
113
}
114
uuid[i] = v
115
}
116
return uuid, nil
117
}
118
119
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
120
func ParseBytes(b []byte) (UUID, error) {
121
var uuid UUID
122
switch len(b) {
123
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
124
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
125
if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) {
126
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
127
}
128
b = b[9:]
129
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
130
b = b[1:]
131
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
132
var ok bool
133
for i := 0; i < 32; i += 2 {
134
uuid[i/2], ok = xtob(b[i], b[i+1])
135
if !ok {
136
return uuid, errors.New("invalid UUID format")
137
}
138
}
139
return uuid, nil
140
default:
141
return uuid, invalidLengthError{len(b)}
142
}
143
// s is now at least 36 bytes long
144
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
145
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
146
return uuid, errors.New("invalid UUID format")
147
}
148
for i, x := range [16]int{
149
0, 2, 4, 6,
150
9, 11,
151
14, 16,
152
19, 21,
153
24, 26, 28, 30, 32, 34,
154
} {
155
v, ok := xtob(b[x], b[x+1])
156
if !ok {
157
return uuid, errors.New("invalid UUID format")
158
}
159
uuid[i] = v
160
}
161
return uuid, nil
162
}
163
164
// MustParse is like Parse but panics if the string cannot be parsed.
165
// It simplifies safe initialization of global variables holding compiled UUIDs.
166
func MustParse(s string) UUID {
167
uuid, err := Parse(s)
168
if err != nil {
169
panic(`uuid: Parse(` + s + `): ` + err.Error())
170
}
171
return uuid
172
}
173
174
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
175
// does not have a length of 16. The bytes are copied from the slice.
176
func FromBytes(b []byte) (uuid UUID, err error) {
177
err = uuid.UnmarshalBinary(b)
178
return uuid, err
179
}
180
181
// Must returns uuid if err is nil and panics otherwise.
182
func Must(uuid UUID, err error) UUID {
183
if err != nil {
184
panic(err)
185
}
186
return uuid
187
}
188
189
// Validate returns an error if s is not a properly formatted UUID in one of the following formats:
190
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
191
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
192
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
193
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
194
// It returns an error if the format is invalid, otherwise nil.
195
func Validate(s string) error {
196
switch len(s) {
197
// Standard UUID format
198
case 36:
199
200
// UUID with "urn:uuid:" prefix
201
case 36 + 9:
202
if !strings.EqualFold(s[:9], "urn:uuid:") {
203
return fmt.Errorf("invalid urn prefix: %q", s[:9])
204
}
205
s = s[9:]
206
207
// UUID enclosed in braces
208
case 36 + 2:
209
if s[0] != '{' || s[len(s)-1] != '}' {
210
return fmt.Errorf("invalid bracketed UUID format")
211
}
212
s = s[1 : len(s)-1]
213
214
// UUID without hyphens
215
case 32:
216
for i := 0; i < len(s); i += 2 {
217
_, ok := xtob(s[i], s[i+1])
218
if !ok {
219
return errors.New("invalid UUID format")
220
}
221
}
222
223
default:
224
return invalidLengthError{len(s)}
225
}
226
227
// Check for standard UUID format
228
if len(s) == 36 {
229
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
230
return errors.New("invalid UUID format")
231
}
232
for _, x := range []int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} {
233
if _, ok := xtob(s[x], s[x+1]); !ok {
234
return errors.New("invalid UUID format")
235
}
236
}
237
}
238
239
return nil
240
}
241
242
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
243
// , or "" if uuid is invalid.
244
func (uuid UUID) String() string {
245
var buf [36]byte
246
encodeHex(buf[:], uuid)
247
return string(buf[:])
248
}
249
250
// URN returns the RFC 2141 URN form of uuid,
251
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
252
func (uuid UUID) URN() string {
253
var buf [36 + 9]byte
254
copy(buf[:], "urn:uuid:")
255
encodeHex(buf[9:], uuid)
256
return string(buf[:])
257
}
258
259
func encodeHex(dst []byte, uuid UUID) {
260
hex.Encode(dst, uuid[:4])
261
dst[8] = '-'
262
hex.Encode(dst[9:13], uuid[4:6])
263
dst[13] = '-'
264
hex.Encode(dst[14:18], uuid[6:8])
265
dst[18] = '-'
266
hex.Encode(dst[19:23], uuid[8:10])
267
dst[23] = '-'
268
hex.Encode(dst[24:], uuid[10:])
269
}
270
271
// Variant returns the variant encoded in uuid.
272
func (uuid UUID) Variant() Variant {
273
switch {
274
case (uuid[8] & 0xc0) == 0x80:
275
return RFC4122
276
case (uuid[8] & 0xe0) == 0xc0:
277
return Microsoft
278
case (uuid[8] & 0xe0) == 0xe0:
279
return Future
280
default:
281
return Reserved
282
}
283
}
284
285
// Version returns the version of uuid.
286
func (uuid UUID) Version() Version {
287
return Version(uuid[6] >> 4)
288
}
289
290
func (v Version) String() string {
291
if v > 15 {
292
return fmt.Sprintf("BAD_VERSION_%d", v)
293
}
294
return fmt.Sprintf("VERSION_%d", v)
295
}
296
297
func (v Variant) String() string {
298
switch v {
299
case RFC4122:
300
return "RFC4122"
301
case Reserved:
302
return "Reserved"
303
case Microsoft:
304
return "Microsoft"
305
case Future:
306
return "Future"
307
case Invalid:
308
return "Invalid"
309
}
310
return fmt.Sprintf("BadVariant%d", int(v))
311
}
312
313
// SetRand sets the random number generator to r, which implements io.Reader.
314
// If r.Read returns an error when the package requests random data then
315
// a panic will be issued.
316
//
317
// Calling SetRand with nil sets the random number generator to the default
318
// generator.
319
func SetRand(r io.Reader) {
320
if r == nil {
321
rander = rand.Reader
322
return
323
}
324
rander = r
325
}
326
327
// EnableRandPool enables internal randomness pool used for Random
328
// (Version 4) UUID generation. The pool contains random bytes read from
329
// the random number generator on demand in batches. Enabling the pool
330
// may improve the UUID generation throughput significantly.
331
//
332
// Since the pool is stored on the Go heap, this feature may be a bad fit
333
// for security sensitive applications.
334
//
335
// Both EnableRandPool and DisableRandPool are not thread-safe and should
336
// only be called when there is no possibility that New or any other
337
// UUID Version 4 generation function will be called concurrently.
338
func EnableRandPool() {
339
poolEnabled = true
340
}
341
342
// DisableRandPool disables the randomness pool if it was previously
343
// enabled with EnableRandPool.
344
//
345
// Both EnableRandPool and DisableRandPool are not thread-safe and should
346
// only be called when there is no possibility that New or any other
347
// UUID Version 4 generation function will be called concurrently.
348
func DisableRandPool() {
349
poolEnabled = false
350
defer poolMu.Unlock()
351
poolMu.Lock()
352
poolPos = randPoolSize
353
}
354
355
// UUIDs is a slice of UUID types.
356
type UUIDs []UUID
357
358
// Strings returns a string slice containing the string form of each UUID in uuids.
359
func (uuids UUIDs) Strings() []string {
360
var uuidStrs = make([]string, len(uuids))
361
for i, uuid := range uuids {
362
uuidStrs[i] = uuid.String()
363
}
364
return uuidStrs
365
}
366
367