You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
2.1 KiB
65 lines
2.1 KiB
import rng from './rng.js'; |
|
import { unsafeStringify } from './stringify.js'; |
|
const _state = {}; |
|
function v7(options, buf, offset) { |
|
let bytes; |
|
if (options) { |
|
bytes = v7Bytes(options.random ?? options.rng?.() ?? rng(), options.msecs, options.seq, buf, offset); |
|
} |
|
else { |
|
const now = Date.now(); |
|
const rnds = rng(); |
|
updateV7State(_state, now, rnds); |
|
bytes = v7Bytes(rnds, _state.msecs, _state.seq, buf, offset); |
|
} |
|
return buf ?? unsafeStringify(bytes); |
|
} |
|
export function updateV7State(state, now, rnds) { |
|
state.msecs ??= -Infinity; |
|
state.seq ??= 0; |
|
if (now > state.msecs) { |
|
state.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; |
|
state.msecs = now; |
|
} |
|
else { |
|
state.seq = (state.seq + 1) | 0; |
|
if (state.seq === 0) { |
|
state.msecs++; |
|
} |
|
} |
|
return state; |
|
} |
|
function v7Bytes(rnds, msecs, seq, buf, offset = 0) { |
|
if (rnds.length < 16) { |
|
throw new Error('Random bytes length must be >= 16'); |
|
} |
|
if (!buf) { |
|
buf = new Uint8Array(16); |
|
offset = 0; |
|
} |
|
else { |
|
if (offset < 0 || offset + 16 > buf.length) { |
|
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`); |
|
} |
|
} |
|
msecs ??= Date.now(); |
|
seq ??= ((rnds[6] * 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9]; |
|
buf[offset++] = (msecs / 0x10000000000) & 0xff; |
|
buf[offset++] = (msecs / 0x100000000) & 0xff; |
|
buf[offset++] = (msecs / 0x1000000) & 0xff; |
|
buf[offset++] = (msecs / 0x10000) & 0xff; |
|
buf[offset++] = (msecs / 0x100) & 0xff; |
|
buf[offset++] = msecs & 0xff; |
|
buf[offset++] = 0x70 | ((seq >>> 28) & 0x0f); |
|
buf[offset++] = (seq >>> 20) & 0xff; |
|
buf[offset++] = 0x80 | ((seq >>> 14) & 0x3f); |
|
buf[offset++] = (seq >>> 6) & 0xff; |
|
buf[offset++] = ((seq << 2) & 0xff) | (rnds[10] & 0x03); |
|
buf[offset++] = rnds[11]; |
|
buf[offset++] = rnds[12]; |
|
buf[offset++] = rnds[13]; |
|
buf[offset++] = rnds[14]; |
|
buf[offset++] = rnds[15]; |
|
return buf; |
|
} |
|
export default v7;
|
|
|