v1.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import rng from './rng.js';
  2. import { unsafeStringify } from './stringify.js';
  3. const _state = {};
  4. function v1(options, buf, offset) {
  5. let bytes;
  6. const isV6 = options?._v6 ?? false;
  7. if (options) {
  8. const optionsKeys = Object.keys(options);
  9. if (optionsKeys.length === 1 && optionsKeys[0] === '_v6') {
  10. options = undefined;
  11. }
  12. }
  13. if (options) {
  14. bytes = v1Bytes(options.random ?? options.rng?.() ?? rng(), options.msecs, options.nsecs, options.clockseq, options.node, buf, offset);
  15. }
  16. else {
  17. const now = Date.now();
  18. const rnds = rng();
  19. updateV1State(_state, now, rnds);
  20. bytes = v1Bytes(rnds, _state.msecs, _state.nsecs, isV6 ? undefined : _state.clockseq, isV6 ? undefined : _state.node, buf, offset);
  21. }
  22. return buf ?? unsafeStringify(bytes);
  23. }
  24. export function updateV1State(state, now, rnds) {
  25. state.msecs ??= -Infinity;
  26. state.nsecs ??= 0;
  27. if (now === state.msecs) {
  28. state.nsecs++;
  29. if (state.nsecs >= 10000) {
  30. state.node = undefined;
  31. state.nsecs = 0;
  32. }
  33. }
  34. else if (now > state.msecs) {
  35. state.nsecs = 0;
  36. }
  37. else if (now < state.msecs) {
  38. state.node = undefined;
  39. }
  40. if (!state.node) {
  41. state.node = rnds.slice(10, 16);
  42. state.node[0] |= 0x01;
  43. state.clockseq = ((rnds[8] << 8) | rnds[9]) & 0x3fff;
  44. }
  45. state.msecs = now;
  46. return state;
  47. }
  48. function v1Bytes(rnds, msecs, nsecs, clockseq, node, buf, offset = 0) {
  49. if (rnds.length < 16) {
  50. throw new Error('Random bytes length must be >= 16');
  51. }
  52. if (!buf) {
  53. buf = new Uint8Array(16);
  54. offset = 0;
  55. }
  56. else {
  57. if (offset < 0 || offset + 16 > buf.length) {
  58. throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
  59. }
  60. }
  61. msecs ??= Date.now();
  62. nsecs ??= 0;
  63. clockseq ??= ((rnds[8] << 8) | rnds[9]) & 0x3fff;
  64. node ??= rnds.slice(10, 16);
  65. msecs += 12219292800000;
  66. const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
  67. buf[offset++] = (tl >>> 24) & 0xff;
  68. buf[offset++] = (tl >>> 16) & 0xff;
  69. buf[offset++] = (tl >>> 8) & 0xff;
  70. buf[offset++] = tl & 0xff;
  71. const tmh = ((msecs / 0x100000000) * 10000) & 0xfffffff;
  72. buf[offset++] = (tmh >>> 8) & 0xff;
  73. buf[offset++] = tmh & 0xff;
  74. buf[offset++] = ((tmh >>> 24) & 0xf) | 0x10;
  75. buf[offset++] = (tmh >>> 16) & 0xff;
  76. buf[offset++] = (clockseq >>> 8) | 0x80;
  77. buf[offset++] = clockseq & 0xff;
  78. for (let n = 0; n < 6; ++n) {
  79. buf[offset++] = node[n];
  80. }
  81. return buf;
  82. }
  83. export default v1;