diff options
Diffstat (limited to 'vendor/github.com/satori/go.uuid/generator.go')
-rw-r--r-- | vendor/github.com/satori/go.uuid/generator.go | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/vendor/github.com/satori/go.uuid/generator.go b/vendor/github.com/satori/go.uuid/generator.go new file mode 100644 index 0000000..3f2f1da --- /dev/null +++ b/vendor/github.com/satori/go.uuid/generator.go | |||
@@ -0,0 +1,239 @@ | |||
1 | // Copyright (C) 2013-2018 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 | "crypto/md5" | ||
26 | "crypto/rand" | ||
27 | "crypto/sha1" | ||
28 | "encoding/binary" | ||
29 | "hash" | ||
30 | "net" | ||
31 | "os" | ||
32 | "sync" | ||
33 | "time" | ||
34 | ) | ||
35 | |||
36 | // Difference in 100-nanosecond intervals between | ||
37 | // UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). | ||
38 | const epochStart = 122192928000000000 | ||
39 | |||
40 | var ( | ||
41 | global = newDefaultGenerator() | ||
42 | |||
43 | epochFunc = unixTimeFunc | ||
44 | posixUID = uint32(os.Getuid()) | ||
45 | posixGID = uint32(os.Getgid()) | ||
46 | ) | ||
47 | |||
48 | // NewV1 returns UUID based on current timestamp and MAC address. | ||
49 | func NewV1() UUID { | ||
50 | return global.NewV1() | ||
51 | } | ||
52 | |||
53 | // NewV2 returns DCE Security UUID based on POSIX UID/GID. | ||
54 | func NewV2(domain byte) UUID { | ||
55 | return global.NewV2(domain) | ||
56 | } | ||
57 | |||
58 | // NewV3 returns UUID based on MD5 hash of namespace UUID and name. | ||
59 | func NewV3(ns UUID, name string) UUID { | ||
60 | return global.NewV3(ns, name) | ||
61 | } | ||
62 | |||
63 | // NewV4 returns random generated UUID. | ||
64 | func NewV4() UUID { | ||
65 | return global.NewV4() | ||
66 | } | ||
67 | |||
68 | // NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. | ||
69 | func NewV5(ns UUID, name string) UUID { | ||
70 | return global.NewV5(ns, name) | ||
71 | } | ||
72 | |||
73 | // Generator provides interface for generating UUIDs. | ||
74 | type Generator interface { | ||
75 | NewV1() UUID | ||
76 | NewV2(domain byte) UUID | ||
77 | NewV3(ns UUID, name string) UUID | ||
78 | NewV4() UUID | ||
79 | NewV5(ns UUID, name string) UUID | ||
80 | } | ||
81 | |||
82 | // Default generator implementation. | ||
83 | type generator struct { | ||
84 | storageOnce sync.Once | ||
85 | storageMutex sync.Mutex | ||
86 | |||
87 | lastTime uint64 | ||
88 | clockSequence uint16 | ||
89 | hardwareAddr [6]byte | ||
90 | } | ||
91 | |||
92 | func newDefaultGenerator() Generator { | ||
93 | return &generator{} | ||
94 | } | ||
95 | |||
96 | // NewV1 returns UUID based on current timestamp and MAC address. | ||
97 | func (g *generator) NewV1() UUID { | ||
98 | u := UUID{} | ||
99 | |||
100 | timeNow, clockSeq, hardwareAddr := g.getStorage() | ||
101 | |||
102 | binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) | ||
103 | binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) | ||
104 | binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) | ||
105 | binary.BigEndian.PutUint16(u[8:], clockSeq) | ||
106 | |||
107 | copy(u[10:], hardwareAddr) | ||
108 | |||
109 | u.SetVersion(V1) | ||
110 | u.SetVariant(VariantRFC4122) | ||
111 | |||
112 | return u | ||
113 | } | ||
114 | |||
115 | // NewV2 returns DCE Security UUID based on POSIX UID/GID. | ||
116 | func (g *generator) NewV2(domain byte) UUID { | ||
117 | u := UUID{} | ||
118 | |||
119 | timeNow, clockSeq, hardwareAddr := g.getStorage() | ||
120 | |||
121 | switch domain { | ||
122 | case DomainPerson: | ||
123 | binary.BigEndian.PutUint32(u[0:], posixUID) | ||
124 | case DomainGroup: | ||
125 | binary.BigEndian.PutUint32(u[0:], posixGID) | ||
126 | } | ||
127 | |||
128 | binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) | ||
129 | binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) | ||
130 | binary.BigEndian.PutUint16(u[8:], clockSeq) | ||
131 | u[9] = domain | ||
132 | |||
133 | copy(u[10:], hardwareAddr) | ||
134 | |||
135 | u.SetVersion(V2) | ||
136 | u.SetVariant(VariantRFC4122) | ||
137 | |||
138 | return u | ||
139 | } | ||
140 | |||
141 | // NewV3 returns UUID based on MD5 hash of namespace UUID and name. | ||
142 | func (g *generator) NewV3(ns UUID, name string) UUID { | ||
143 | u := newFromHash(md5.New(), ns, name) | ||
144 | u.SetVersion(V3) | ||
145 | u.SetVariant(VariantRFC4122) | ||
146 | |||
147 | return u | ||
148 | } | ||
149 | |||
150 | // NewV4 returns random generated UUID. | ||
151 | func (g *generator) NewV4() UUID { | ||
152 | u := UUID{} | ||
153 | g.safeRandom(u[:]) | ||
154 | u.SetVersion(V4) | ||
155 | u.SetVariant(VariantRFC4122) | ||
156 | |||
157 | return u | ||
158 | } | ||
159 | |||
160 | // NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. | ||
161 | func (g *generator) NewV5(ns UUID, name string) UUID { | ||
162 | u := newFromHash(sha1.New(), ns, name) | ||
163 | u.SetVersion(V5) | ||
164 | u.SetVariant(VariantRFC4122) | ||
165 | |||
166 | return u | ||
167 | } | ||
168 | |||
169 | func (g *generator) initStorage() { | ||
170 | g.initClockSequence() | ||
171 | g.initHardwareAddr() | ||
172 | } | ||
173 | |||
174 | func (g *generator) initClockSequence() { | ||
175 | buf := make([]byte, 2) | ||
176 | g.safeRandom(buf) | ||
177 | g.clockSequence = binary.BigEndian.Uint16(buf) | ||
178 | } | ||
179 | |||
180 | func (g *generator) initHardwareAddr() { | ||
181 | interfaces, err := net.Interfaces() | ||
182 | if err == nil { | ||
183 | for _, iface := range interfaces { | ||
184 | if len(iface.HardwareAddr) >= 6 { | ||
185 | copy(g.hardwareAddr[:], iface.HardwareAddr) | ||
186 | return | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
191 | // Initialize hardwareAddr randomly in case | ||
192 | // of real network interfaces absence | ||
193 | g.safeRandom(g.hardwareAddr[:]) | ||
194 | |||
195 | // Set multicast bit as recommended in RFC 4122 | ||
196 | g.hardwareAddr[0] |= 0x01 | ||
197 | } | ||
198 | |||
199 | func (g *generator) safeRandom(dest []byte) { | ||
200 | if _, err := rand.Read(dest); err != nil { | ||
201 | panic(err) | ||
202 | } | ||
203 | } | ||
204 | |||
205 | // Returns UUID v1/v2 storage state. | ||
206 | // Returns epoch timestamp, clock sequence, and hardware address. | ||
207 | func (g *generator) getStorage() (uint64, uint16, []byte) { | ||
208 | g.storageOnce.Do(g.initStorage) | ||
209 | |||
210 | g.storageMutex.Lock() | ||
211 | defer g.storageMutex.Unlock() | ||
212 | |||
213 | timeNow := epochFunc() | ||
214 | // Clock changed backwards since last UUID generation. | ||
215 | // Should increase clock sequence. | ||
216 | if timeNow <= g.lastTime { | ||
217 | g.clockSequence++ | ||
218 | } | ||
219 | g.lastTime = timeNow | ||
220 | |||
221 | return timeNow, g.clockSequence, g.hardwareAddr[:] | ||
222 | } | ||
223 | |||
224 | // Returns difference in 100-nanosecond intervals between | ||
225 | // UUID epoch (October 15, 1582) and current time. | ||
226 | // This is default epoch calculation function. | ||
227 | func unixTimeFunc() uint64 { | ||
228 | return epochStart + uint64(time.Now().UnixNano()/100) | ||
229 | } | ||
230 | |||
231 | // Returns UUID based on hashing of namespace UUID and name. | ||
232 | func newFromHash(h hash.Hash, ns UUID, name string) UUID { | ||
233 | u := UUID{} | ||
234 | h.Write(ns[:]) | ||
235 | h.Write([]byte(name)) | ||
236 | copy(u[:], h.Sum(nil)) | ||
237 | |||
238 | return u | ||
239 | } | ||