Spaces:
Sleeping
Sleeping
| import rng from './rng.js'; | |
| import { unsafeStringify } from './stringify.js'; | |
| const _state = {}; | |
| function v1(options, buf, offset) { | |
| let bytes; | |
| const isV6 = options?._v6 ?? false; | |
| if (options) { | |
| const optionsKeys = Object.keys(options); | |
| if (optionsKeys.length === 1 && optionsKeys[0] === '_v6') { | |
| options = undefined; | |
| } | |
| } | |
| if (options) { | |
| bytes = v1Bytes(options.random ?? options.rng?.() ?? rng(), options.msecs, options.nsecs, options.clockseq, options.node, buf, offset); | |
| } | |
| else { | |
| const now = Date.now(); | |
| const rnds = rng(); | |
| updateV1State(_state, now, rnds); | |
| bytes = v1Bytes(rnds, _state.msecs, _state.nsecs, isV6 ? undefined : _state.clockseq, isV6 ? undefined : _state.node, buf, offset); | |
| } | |
| return buf ?? unsafeStringify(bytes); | |
| } | |
| export function updateV1State(state, now, rnds) { | |
| state.msecs ??= -Infinity; | |
| state.nsecs ??= 0; | |
| if (now === state.msecs) { | |
| state.nsecs++; | |
| if (state.nsecs >= 10000) { | |
| state.node = undefined; | |
| state.nsecs = 0; | |
| } | |
| } | |
| else if (now > state.msecs) { | |
| state.nsecs = 0; | |
| } | |
| else if (now < state.msecs) { | |
| state.node = undefined; | |
| } | |
| if (!state.node) { | |
| state.node = rnds.slice(10, 16); | |
| state.node[0] |= 0x01; | |
| state.clockseq = ((rnds[8] << 8) | rnds[9]) & 0x3fff; | |
| } | |
| state.msecs = now; | |
| return state; | |
| } | |
| function v1Bytes(rnds, msecs, nsecs, clockseq, node, 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(); | |
| nsecs ??= 0; | |
| clockseq ??= ((rnds[8] << 8) | rnds[9]) & 0x3fff; | |
| node ??= rnds.slice(10, 16); | |
| msecs += 12219292800000; | |
| const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; | |
| buf[offset++] = (tl >>> 24) & 0xff; | |
| buf[offset++] = (tl >>> 16) & 0xff; | |
| buf[offset++] = (tl >>> 8) & 0xff; | |
| buf[offset++] = tl & 0xff; | |
| const tmh = ((msecs / 0x100000000) * 10000) & 0xfffffff; | |
| buf[offset++] = (tmh >>> 8) & 0xff; | |
| buf[offset++] = tmh & 0xff; | |
| buf[offset++] = ((tmh >>> 24) & 0xf) | 0x10; | |
| buf[offset++] = (tmh >>> 16) & 0xff; | |
| buf[offset++] = (clockseq >>> 8) | 0x80; | |
| buf[offset++] = clockseq & 0xff; | |
| for (let n = 0; n < 6; ++n) { | |
| buf[offset++] = node[n]; | |
| } | |
| return buf; | |
| } | |
| export default v1; | |