|
7 | 7 | }=primordials; |
8 | 8 |
|
9 | 9 | const{ AsyncWrap, Providers }=internalBinding('async_wrap'); |
10 | | -const{ kMaxLength }=require('buffer'); |
11 | | -const{randomBytes: _randomBytes}=internalBinding('crypto'); |
12 | 10 | const{ |
13 | | -ERR_INVALID_ARG_TYPE, |
14 | | -ERR_INVALID_CALLBACK, |
15 | | -ERR_OUT_OF_RANGE |
16 | | -}=require('internal/errors').codes; |
17 | | -const{ validateNumber }=require('internal/validators'); |
| 11 | + Buffer, |
| 12 | + kMaxLength, |
| 13 | +}=require('buffer'); |
| 14 | +const{ |
| 15 | +randomBytes: _randomBytes, |
| 16 | + secureBuffer, |
| 17 | +}=internalBinding('crypto'); |
| 18 | +const{ |
| 19 | +codes: { |
| 20 | +ERR_INVALID_ARG_TYPE, |
| 21 | +ERR_INVALID_CALLBACK, |
| 22 | +ERR_OUT_OF_RANGE, |
| 23 | +ERR_OPERATION_FAILED, |
| 24 | +} |
| 25 | +}=require('internal/errors'); |
| 26 | +const{ |
| 27 | + validateBoolean, |
| 28 | + validateNumber, |
| 29 | + validateObject, |
| 30 | +}=require('internal/validators'); |
18 | 31 | const{ isArrayBufferView }=require('internal/util/types'); |
19 | 32 | const{ FastBuffer }=require('internal/buffer'); |
20 | 33 |
|
@@ -203,9 +216,113 @@ function handleError(ex, buf){ |
203 | 216 | returnbuf; |
204 | 217 | } |
205 | 218 |
|
| 219 | +// Implements an RFC 4122 version 4 random UUID. |
| 220 | +// To improve performance, random data is generated in batches |
| 221 | +// large enough to cover kBatchSize UUID's at a time. The uuidData |
| 222 | +// and uuid buffers are reused. Each call to randomUUID() consumes |
| 223 | +// 16 bytes from the buffer. |
| 224 | + |
| 225 | +constkHexDigits=[ |
| 226 | +48,49,50,51,52,53,54,55, |
| 227 | +56,57,97,98,99,100,101,102 |
| 228 | +]; |
| 229 | + |
| 230 | +constkBatchSize=128; |
| 231 | +letuuidData; |
| 232 | +letuuidNotBuffered; |
| 233 | +letuuid; |
| 234 | +letuuidBatch=0; |
| 235 | + |
| 236 | +functiongetBufferedUUID(){ |
| 237 | +if(uuidData===undefined){ |
| 238 | +uuidData=secureBuffer(16*kBatchSize); |
| 239 | +if(uuidData===undefined) |
| 240 | +thrownewERR_OPERATION_FAILED('Out of memory'); |
| 241 | +} |
| 242 | + |
| 243 | +if(uuidBatch===0)randomFillSync(uuidData); |
| 244 | +uuidBatch=(uuidBatch+1)%kBatchSize; |
| 245 | +returnuuidData.slice(uuidBatch*16,(uuidBatch*16)+16); |
| 246 | +} |
| 247 | + |
| 248 | +functionrandomUUID(options){ |
| 249 | +if(options!==undefined) |
| 250 | +validateObject(options,'options'); |
| 251 | +const{ |
| 252 | + disableEntropyCache =false, |
| 253 | +}={ ...options}; |
| 254 | + |
| 255 | +validateBoolean(disableEntropyCache,'options.disableEntropyCache'); |
| 256 | + |
| 257 | +if(uuid===undefined){ |
| 258 | +uuid=Buffer.alloc(36,'-'); |
| 259 | +uuid[14]=52;// '4', identifies the UUID version |
| 260 | +} |
| 261 | + |
| 262 | +letuuidBuf; |
| 263 | +if(!disableEntropyCache){ |
| 264 | +uuidBuf=getBufferedUUID(); |
| 265 | +}else{ |
| 266 | +uuidBuf=uuidNotBuffered; |
| 267 | +if(uuidBuf===undefined) |
| 268 | +uuidBuf=uuidNotBuffered=secureBuffer(16); |
| 269 | +if(uuidBuf===undefined) |
| 270 | +thrownewERR_OPERATION_FAILED('Out of memory'); |
| 271 | +randomFillSync(uuidBuf); |
| 272 | +} |
| 273 | + |
| 274 | +// Variant byte: 10xxxxxx (variant 1) |
| 275 | +uuidBuf[8]=(uuidBuf[8]&0x3f)|0x80; |
| 276 | + |
| 277 | +// This function is structured the way it is for performance. |
| 278 | +// The uuid buffer stores the serialization of the random |
| 279 | +// bytes from uuidData. |
| 280 | +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
| 281 | +letn=0; |
| 282 | +uuid[0]=kHexDigits[uuidBuf[n]>>4]; |
| 283 | +uuid[1]=kHexDigits[uuidBuf[n++]&0xf]; |
| 284 | +uuid[2]=kHexDigits[uuidBuf[n]>>4]; |
| 285 | +uuid[3]=kHexDigits[uuidBuf[n++]&0xf]; |
| 286 | +uuid[4]=kHexDigits[uuidBuf[n]>>4]; |
| 287 | +uuid[5]=kHexDigits[uuidBuf[n++]&0xf]; |
| 288 | +uuid[6]=kHexDigits[uuidBuf[n]>>4]; |
| 289 | +uuid[7]=kHexDigits[uuidBuf[n++]&0xf]; |
| 290 | +// - |
| 291 | +uuid[9]=kHexDigits[uuidBuf[n]>>4]; |
| 292 | +uuid[10]=kHexDigits[uuidBuf[n++]&0xf]; |
| 293 | +uuid[11]=kHexDigits[uuidBuf[n]>>4]; |
| 294 | +uuid[12]=kHexDigits[uuidBuf[n++]&0xf]; |
| 295 | +// - |
| 296 | +// 4, uuid[14] is set already... |
| 297 | +uuid[15]=kHexDigits[uuidBuf[n++]&0xf]; |
| 298 | +uuid[16]=kHexDigits[uuidBuf[n]>>4]; |
| 299 | +uuid[17]=kHexDigits[uuidBuf[n++]&0xf]; |
| 300 | +// - |
| 301 | +uuid[19]=kHexDigits[uuidBuf[n]>>4]; |
| 302 | +uuid[20]=kHexDigits[uuidBuf[n++]&0xf]; |
| 303 | +uuid[21]=kHexDigits[uuidBuf[n]>>4]; |
| 304 | +uuid[22]=kHexDigits[uuidBuf[n++]&0xf]; |
| 305 | +// - |
| 306 | +uuid[24]=kHexDigits[uuidBuf[n]>>4]; |
| 307 | +uuid[25]=kHexDigits[uuidBuf[n++]&0xf]; |
| 308 | +uuid[26]=kHexDigits[uuidBuf[n]>>4]; |
| 309 | +uuid[27]=kHexDigits[uuidBuf[n++]&0xf]; |
| 310 | +uuid[28]=kHexDigits[uuidBuf[n]>>4]; |
| 311 | +uuid[29]=kHexDigits[uuidBuf[n++]&0xf]; |
| 312 | +uuid[30]=kHexDigits[uuidBuf[n]>>4]; |
| 313 | +uuid[31]=kHexDigits[uuidBuf[n++]&0xf]; |
| 314 | +uuid[32]=kHexDigits[uuidBuf[n]>>4]; |
| 315 | +uuid[33]=kHexDigits[uuidBuf[n++]&0xf]; |
| 316 | +uuid[34]=kHexDigits[uuidBuf[n]>>4]; |
| 317 | +uuid[35]=kHexDigits[uuidBuf[n]&0xf]; |
| 318 | + |
| 319 | +returnuuid.latin1Slice(0,36); |
| 320 | +} |
| 321 | + |
206 | 322 | module.exports={ |
207 | 323 | randomBytes, |
208 | 324 | randomFill, |
209 | 325 | randomFillSync, |
210 | | - randomInt |
| 326 | + randomInt, |
| 327 | + randomUUID, |
211 | 328 | }; |
0 commit comments