forked from thecodeteam/libstorage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
types_uuid.go
114 lines (100 loc) · 2.79 KB
/
types_uuid.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package types
import (
"crypto/rand"
"encoding/hex"
"fmt"
"regexp"
"github.com/akutz/goof"
)
// UUID is a UUID.
//
// This was totally stolen from
// https://github.com/nu7hatch/gouuid/blob/master/uuid.go, and all credit goes
// to that author. It was included like this in order to reduce external
// dependencies.
type UUID [16]byte
const (
reservedNCS byte = 0x80
reservedRFC4122 byte = 0x40
reservedMicrosoft byte = 0x20
reservedFuture byte = 0x00
// pattern used to parse hex string representation of the UUID.
hexPattern = `^(urn\:uuid\:)?\{?([a-z0-9]{8})-([a-z0-9]{4})-` +
`([1-5][a-z0-9]{3})-([a-z0-9]{4})-([a-z0-9]{12})\}?$`
)
var (
hexRX = regexp.MustCompile(hexPattern)
)
// String returns unparsed version of the generated UUID sequence.
func (u *UUID) String() string {
return fmt.Sprintf("%x-%x-%x-%x-%x",
u[0:4], u[4:6], u[6:8], u[8:10], u[10:])
}
// MarshalText marshals the UUID to a string.
func (u *UUID) MarshalText() ([]byte, error) {
return []byte(u.String()), nil
}
// UnmarshalText unmarshals the UUID from a hex string to a UUID instance.
// This function accepts UUID string in following formats:
//
// uuid.ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
// uuid.ParseHex("{6ba7b814-9dad-11d1-80b4-00c04fd430c8}")
// uuid.ParseHex("urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8")
func (u *UUID) UnmarshalText(text []byte) error {
md := hexRX.FindSubmatch(text)
if len(md) == 0 {
return goof.New("invalid uuid string")
}
hash := []byte{}
for x := 2; x < 7; x++ {
hash = append(hash, md[x]...)
}
if _, err := hex.Decode(u[:], hash); err != nil {
return err
}
return nil
}
// NewUUID returns a new UUID.
func NewUUID() (*UUID, error) {
u := &UUID{}
if _, err := rand.Read(u[:]); err != nil {
return nil, err
}
u.setVariant(reservedRFC4122)
u.setVersion(4)
return u, nil
}
// MustNewUUID is like NewUUID but panics if it encounters an error when
// creating a new UUID.
func MustNewUUID() *UUID {
uuid, err := NewUUID()
if err != nil {
panic(err)
}
return uuid
}
// ParseUUID is a helper function on top of UnmarshalText.
func ParseUUID(s string) (*UUID, error) {
u := &UUID{}
if err := u.UnmarshalText([]byte(s)); err != nil {
return nil, err
}
return u, nil
}
// setVariant sets the two most significant bits (bits 6 and 7) of the
// clock_seq_hi_and_reserved to zero and one, respectively.
func (u *UUID) setVariant(v byte) {
switch v {
case reservedNCS:
u[8] = (u[8] | reservedNCS) & 0xBF
case reservedRFC4122:
u[8] = (u[8] | reservedRFC4122) & 0x7F
case reservedMicrosoft:
u[8] = (u[8] | reservedMicrosoft) & 0x3F
}
}
// setVersion sets the four most significant bits (bits 12 through 15) of the
// time_hi_and_version field to the 4-bit version number.
func (u *UUID) setVersion(v byte) {
u[6] = (u[6] & 0xF) | (v << 4)
}