| 74 | } |
| 75 | |
| 76 | function v7Bytes( |
| 77 | rnds: Uint8Array, |
| 78 | msecs?: number, |
| 79 | seq?: number, |
| 80 | buf?: Uint8Array, |
| 81 | offset = 0, |
| 82 | ) { |
| 83 | if (rnds.length < 16) { |
| 84 | throw new Error('Random bytes length must be >= 16'); |
| 85 | } |
| 86 | |
| 87 | if (!buf) { |
| 88 | buf = new Uint8Array(16); |
| 89 | offset = 0; |
| 90 | } else { |
| 91 | if (offset < 0 || offset + 16 > buf.length) { |
| 92 | throw new RangeError( |
| 93 | `UUID byte range ${offset}:${offset + 15} is out of buffer bounds`, |
| 94 | ); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // Defaults |
| 99 | msecs ??= Date.now(); |
| 100 | seq ??= ((rnds[6] * 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; |
| 101 | |
| 102 | // byte 0-5: timestamp (48 bits) |
| 103 | buf[offset++] = (msecs / 0x10000000000) & 0xff; |
| 104 | buf[offset++] = (msecs / 0x100000000) & 0xff; |
| 105 | buf[offset++] = (msecs / 0x1000000) & 0xff; |
| 106 | buf[offset++] = (msecs / 0x10000) & 0xff; |
| 107 | buf[offset++] = (msecs / 0x100) & 0xff; |
| 108 | buf[offset++] = msecs & 0xff; |
| 109 | |
| 110 | // byte 6: `version` (4 bits) | sequence bits 28-31 (4 bits) |
| 111 | buf[offset++] = 0x70 | ((seq >>> 28) & 0x0f); |
| 112 | |
| 113 | // byte 7: sequence bits 20-27 (8 bits) |
| 114 | buf[offset++] = (seq >>> 20) & 0xff; |
| 115 | |
| 116 | // byte 8: `variant` (2 bits) | sequence bits 14-19 (6 bits) |
| 117 | buf[offset++] = 0x80 | ((seq >>> 14) & 0x3f); |
| 118 | |
| 119 | // byte 9: sequence bits 6-13 (8 bits) |
| 120 | buf[offset++] = (seq >>> 6) & 0xff; |
| 121 | |
| 122 | // byte 10: sequence bits 0-5 (6 bits) | random (2 bits) |
| 123 | buf[offset++] = ((seq << 2) & 0xff) | (rnds[10] & 0x03); |
| 124 | |
| 125 | // bytes 11-15: random (40 bits) |
| 126 | buf[offset++] = rnds[11]; |
| 127 | buf[offset++] = rnds[12]; |
| 128 | buf[offset++] = rnds[13]; |
| 129 | buf[offset++] = rnds[14]; |
| 130 | buf[offset++] = rnds[15]; |
| 131 | |
| 132 | return buf; |
| 133 | } |