| 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; |