Skip to content

Commit

Permalink
Merge branch 'main' into ts_port
Browse files Browse the repository at this point in the history
  • Loading branch information
broofa committed Jul 15, 2024
2 parents 574a6be + 1d532ca commit f8b253a
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 2 deletions.
50 changes: 49 additions & 1 deletion src/test/v7.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as assert from 'assert';
import test, { describe } from 'node:test';
import { Version7Options } from '../_types.js';
import v7 from '../v7.js';
import stringify from '../stringify.js';

/**
* fixture bit layout:
Expand Down Expand Up @@ -191,7 +193,7 @@ describe('v7', () => {
seq,
});

assert.strictEqual(uuid.substr(0, 25), '017f22e2-79b0-7fff-bfff-f');
assert.strictEqual(uuid.substr(0, 25), '017f22e2-79b0-7dff-bfff-f');
});

test('internal seq is reset upon timestamp change', () => {
Expand All @@ -206,4 +208,50 @@ describe('v7', () => {

assert.ok(uuid.indexOf('fff') !== 15);
});

test('flipping bits changes the result', () => {
// convert uint8array to BigInt (BE)
const asBigInt = (buf: Uint8Array) => buf.reduce((acc, v) => (acc << 8n) | BigInt(v), 0n);

// convert the given number of bits (LE) to number
const asNumber = (bits: number, data: bigint) => Number(BigInt.asUintN(bits, data));

// flip the nth bit (BE) in a BigInt
const flip = (data: bigint, n: number) => data ^ (1n << BigInt(127 - n));

// Extract v7 `options` from a (BigInt) UUID
const optionsFrom = (data: bigint): Version7Options => {
const ms = asNumber(48, data >> (128n - 48n));
const hi = asNumber(12, data >> (43n + 19n + 2n));
const lo = asNumber(19, data >> 43n);
const r = BigInt.asUintN(43, data);
return {
msecs: ms,
seq: (hi << 19) | lo,
random: Uint8Array.from([
...Array(10).fill(0),
...Array(6)
.fill(0)
.map((_, i) => asNumber(8, r >> (BigInt(i) * 8n)))
.reverse(),
]),
};
};
const buf = new Uint8Array(16);
const data = asBigInt(v7({}, buf));
const id = stringify(buf);
const reserved = [48, 49, 50, 51, 64, 65];
for (let i = 0; i < 128; ++i) {
if (reserved.includes(i)) {
continue; // skip bits used for version and variant
}
const flipped = flip(data, i);
assert.strictEqual(
asBigInt(v7(optionsFrom(flipped), buf)),
flipped,
`Unequal uuids at bit ${i}`
);
assert.notStrictEqual(stringify(buf), id);
}
});
});
2 changes: 1 addition & 1 deletion src/v7.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ function v7(options?: Version7Options, buf?: Uint8Array, offset?: number): UUIDT
b[i++] = _msecs & 0xff;

// [byte 6] - set 4 bits of version (7) with first 4 bits seq_hi
b[i++] = ((seqHigh >>> 4) & 0x0f) | 0x70;
b[i++] = ((seqHigh >>> 8) & 0x0f) | 0x70;

// [byte 7] remaining 8 bits of seq_hi
b[i++] = seqHigh & 0xff;
Expand Down
4 changes: 4 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// NOTE: Do not extend or alter this file. This file is only here to point
// VSCode to the correct config file. (There's no way of configuring the path
// VSCode uses for the tsconfig.json file)
{ "extends": "./tsconfig.esm.json" }

0 comments on commit f8b253a

Please sign in to comment.