Mercurial > pub > ImplabJs
comparison src/implab/Uuid.js @ 34:27e8e9e38e07 default tip
Слияние
author | nickolay |
---|---|
date | Wed, 05 Jun 2019 20:44:15 +0300 |
parents | 8af8e840dd49 1dc2fd263b90 |
children |
comparison
equal
deleted
inserted
replaced
33:8af8e840dd49 | 34:27e8e9e38e07 |
---|---|
1 // uuid.js | |
2 // | |
3 // Copyright (c) 2010-2012 Robert Kieffer | |
4 // MIT License - http://opensource.org/licenses/mit-license.php | |
5 define([], function () { | |
6 'use strict'; | |
7 | |
8 var _window = 'undefined' !== typeof window ? window : null; | |
9 | |
10 // Unique ID creation requires a high quality random # generator. We | |
11 // feature | |
12 // detect to determine the best RNG source, normalizing to a function | |
13 // that | |
14 // returns 128-bits of randomness, since that's what's usually required | |
15 var _rng, _mathRNG, _nodeRNG, _whatwgRNG, _previousRoot; | |
16 | |
17 function setupBrowser() { | |
18 // Allow for MSIE11 msCrypto | |
19 var _crypto = _window.crypto || _window.msCrypto; | |
20 | |
21 if (!_rng && _crypto && _crypto.getRandomValues) { | |
22 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto | |
23 // | |
24 // Moderately fast, high quality | |
25 try { | |
26 var _rnds8 = new Uint8Array(16); | |
27 _whatwgRNG = _rng = function whatwgRNG() { | |
28 _crypto.getRandomValues(_rnds8); | |
29 return _rnds8; | |
30 }; | |
31 _rng(); | |
32 } catch (e) { /**/ } | |
33 } | |
34 | |
35 if (!_rng) { | |
36 // Math.random()-based (RNG) | |
37 // | |
38 // If all else fails, use Math.random(). It's fast, but is of | |
39 // unspecified | |
40 // quality. | |
41 var _rnds = new Array(16); | |
42 _mathRNG = _rng = function () { | |
43 for (var i = 0, r; i < 16; i++) { | |
44 if ((i & 0x03) === 0) { | |
45 r = Math.random() * 0x100000000; | |
46 } | |
47 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; | |
48 } | |
49 | |
50 return _rnds; | |
51 }; | |
52 if ('undefined' !== typeof console && console.warn) { | |
53 console | |
54 .warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()"); | |
55 } | |
56 } | |
57 } | |
58 | |
59 function setupNode() { | |
60 // Node.js crypto-based RNG - | |
61 // http://nodejs.org/docs/v0.6.2/api/crypto.html | |
62 // | |
63 // Moderately fast, high quality | |
64 if ('function' === typeof require) { | |
65 try { | |
66 var _rb = require('crypto').randomBytes; | |
67 _nodeRNG = _rng = _rb && function () { | |
68 return _rb(16); | |
69 }; | |
70 _rng(); | |
71 } catch (e) { /**/ } | |
72 } | |
73 } | |
74 | |
75 if (_window) { | |
76 setupBrowser(); | |
77 } else { | |
78 setupNode(); | |
79 } | |
80 | |
81 // Buffer class to use | |
82 var BufferClass = ('function' === typeof Buffer) ? Buffer : Array; | |
83 | |
84 // Maps for number <-> hex string conversion | |
85 var _byteToHex = []; | |
86 var _hexToByte = {}; | |
87 for (var i = 0; i < 256; i++) { | |
88 _byteToHex[i] = (i + 0x100).toString(16).substr(1); | |
89 _hexToByte[_byteToHex[i]] = i; | |
90 } | |
91 | |
92 // **`parse()` - Parse a UUID into it's component bytes** | |
93 function parse(s, buf, offset) { | |
94 var i = (buf && offset) || 0, | |
95 ii = 0; | |
96 | |
97 buf = buf || []; | |
98 s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) { | |
99 if (ii < 16) { // Don't overflow! | |
100 buf[i + ii++] = _hexToByte[oct]; | |
101 } | |
102 }); | |
103 | |
104 // Zero out remaining bytes if string was short | |
105 while (ii < 16) { | |
106 buf[i + ii++] = 0; | |
107 } | |
108 | |
109 return buf; | |
110 } | |
111 | |
112 // **`unparse()` - Convert UUID byte array (ala parse()) into a string** | |
113 function unparse(buf, offset) { | |
114 var i = offset || 0, | |
115 bth = _byteToHex; | |
116 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + | |
117 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + | |
118 bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + | |
119 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + | |
120 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]]; | |
121 } | |
122 | |
123 // **`v1()` - Generate time-based UUID** | |
124 // | |
125 // Inspired by https://github.com/LiosK/UUID.js | |
126 // and http://docs.python.org/library/uuid.html | |
127 | |
128 // random #'s we need to init node and clockseq | |
129 var _seedBytes = _rng(); | |
130 | |
131 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = | |
132 // 1) | |
133 var _nodeId = [ | |
134 _seedBytes[0] | 0x01, | |
135 _seedBytes[1], | |
136 _seedBytes[2], | |
137 _seedBytes[3], | |
138 _seedBytes[4], | |
139 _seedBytes[5] | |
140 ]; | |
141 | |
142 // Per 4.2.2, randomize (14 bit) clockseq | |
143 var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; | |
144 | |
145 // Previous uuid creation time | |
146 var _lastMSecs = 0, | |
147 _lastNSecs = 0; | |
148 | |
149 // See https://github.com/broofa/node-uuid for API details | |
150 function v1(options, buf, offset) { | |
151 var i = buf && offset || 0; | |
152 var b = buf || []; | |
153 | |
154 options = options || {}; | |
155 | |
156 var clockseq = (options.clockseq != null) ? options.clockseq : _clockseq; | |
157 | |
158 // UUID timestamps are 100 nano-second units since the Gregorian | |
159 // epoch, | |
160 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so | |
161 // time is handled internally as 'msecs' (integer milliseconds) and | |
162 // 'nsecs' | |
163 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 | |
164 // 00:00. | |
165 var msecs = (options.msecs != null) ? options.msecs : new Date() | |
166 .getTime(); | |
167 | |
168 // Per 4.2.1.2, use count of uuid's generated during the current | |
169 // clock | |
170 // cycle to simulate higher resolution clock | |
171 var nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1; | |
172 | |
173 // Time since last uuid creation (in msecs) | |
174 var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000; | |
175 | |
176 // Per 4.2.1.2, Bump clockseq on clock regression | |
177 if (dt < 0 && options.clockseq == null) { | |
178 clockseq = clockseq + 1 & 0x3fff; | |
179 } | |
180 | |
181 // Reset nsecs if clock regresses (new clockseq) or we've moved onto | |
182 // a new | |
183 // time interval | |
184 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { | |
185 nsecs = 0; | |
186 } | |
187 | |
188 // Per 4.2.1.2 Throw error if too many uuids are requested | |
189 if (nsecs >= 10000) { | |
190 throw new Error( | |
191 'uuid.v1(): Can\'t create more than 10M uuids/sec'); | |
192 } | |
193 | |
194 _lastMSecs = msecs; | |
195 _lastNSecs = nsecs; | |
196 _clockseq = clockseq; | |
197 | |
198 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch | |
199 msecs += 12219292800000; | |
200 | |
201 // `time_low` | |
202 var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; | |
203 b[i++] = tl >>> 24 & 0xff; | |
204 b[i++] = tl >>> 16 & 0xff; | |
205 b[i++] = tl >>> 8 & 0xff; | |
206 b[i++] = tl & 0xff; | |
207 | |
208 // `time_mid` | |
209 var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; | |
210 b[i++] = tmh >>> 8 & 0xff; | |
211 b[i++] = tmh & 0xff; | |
212 | |
213 // `time_high_and_version` | |
214 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version | |
215 b[i++] = tmh >>> 16 & 0xff; | |
216 | |
217 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) | |
218 b[i++] = clockseq >>> 8 | 0x80; | |
219 | |
220 // `clock_seq_low` | |
221 b[i++] = clockseq & 0xff; | |
222 | |
223 // `node` | |
224 var node = options.node || _nodeId; | |
225 for (var n = 0; n < 6; n++) { | |
226 b[i + n] = node[n]; | |
227 } | |
228 | |
229 return buf ? buf : unparse(b); | |
230 } | |
231 | |
232 // **`v4()` - Generate random UUID** | |
233 | |
234 // See https://github.com/broofa/node-uuid for API details | |
235 function v4(options, buf, offset) { | |
236 // Deprecated - 'format' argument, as supported in v1.2 | |
237 var i = buf && offset || 0; | |
238 | |
239 if (typeof (options) === 'string') { | |
240 buf = (options === 'binary') ? new BufferClass(16) : null; | |
241 options = null; | |
242 } | |
243 options = options || {}; | |
244 | |
245 var rnds = options.random || (options.rng || _rng)(); | |
246 | |
247 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` | |
248 rnds[6] = (rnds[6] & 0x0f) | 0x40; | |
249 rnds[8] = (rnds[8] & 0x3f) | 0x80; | |
250 | |
251 // Copy bytes to buffer, if provided | |
252 if (buf) { | |
253 for (var ii = 0; ii < 16; ii++) { | |
254 buf[i + ii] = rnds[ii]; | |
255 } | |
256 } | |
257 | |
258 return buf || unparse(rnds); | |
259 } | |
260 | |
261 // Export public API | |
262 var uuid = function () { | |
263 return new String(v4()); | |
264 }; | |
265 uuid.v1 = v1; | |
266 uuid.v4 = v4; | |
267 uuid.create = v4; | |
268 uuid.empty = "00000000-0000-0000-0000-000000000000"; | |
269 uuid.parse = parse; | |
270 uuid.unparse = unparse; | |
271 uuid.BufferClass = BufferClass; | |
272 uuid._rng = _rng; | |
273 uuid._mathRNG = _mathRNG; | |
274 uuid._nodeRNG = _nodeRNG; | |
275 uuid._whatwgRNG = _whatwgRNG; | |
276 | |
277 return uuid; | |
278 }); |