Skip to content

Instantly share code, notes, and snippets.

@davidglezz
Last active September 11, 2023 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidglezz/bf65ca5ba51c19f4266c342fa74533c5 to your computer and use it in GitHub Desktop.
Save davidglezz/bf65ca5ba51c19f4266c342fa74533c5 to your computer and use it in GitHub Desktop.
UUID pack/unpack
export function packUUID(uuid: string): string {
let v;
let bytes = '';
// Parse ########-....-....-....-............
bytes += String.fromCharCode((v = parseInt(uuid.slice(0, 8), 16)) >>> 24);
bytes += String.fromCharCode((v >>> 16) & 0xff);
bytes += String.fromCharCode((v >>> 8) & 0xff);
bytes += String.fromCharCode(v & 0xff);
// Parse ........-####-....-....-............
bytes += String.fromCharCode((v = parseInt(uuid.slice(9, 13), 16)) >>> 8);
bytes += String.fromCharCode(v & 0xff);
// Parse ........-....-####-....-............
bytes += String.fromCharCode((v = parseInt(uuid.slice(14, 18), 16)) >>> 8);
bytes += String.fromCharCode(v & 0xff);
// Parse ........-....-....-####-............
bytes += String.fromCharCode((v = parseInt(uuid.slice(19, 23), 16)) >>> 8);
bytes += String.fromCharCode(v & 0xff);
// Parse ........-....-....-....-############
// (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes)
bytes += String.fromCharCode(((v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000) & 0xff);
bytes += String.fromCharCode((v / 0x100000000) & 0xff);
bytes += String.fromCharCode((v >>> 24) & 0xff);
bytes += String.fromCharCode((v >>> 16) & 0xff);
bytes += String.fromCharCode((v >>> 8) & 0xff);
bytes += String.fromCharCode(v & 0xff);
return btoa(bytes)
.replaceAll('/', '_') // Replace / with _ (see RFC 4648, sec. 5)
.replaceAll('+', '-') // Replace + with - (see RFC 4648, sec. 5)
.substring(0, 22); // Drop '==' padding
}
export function unpackUUID(bytes: string): string {
const data = atob(bytes.replaceAll('_', '/').replaceAll('-', '+') + '==');
return (
(data.charCodeAt(0) + 0x100).toString(16).slice(1) +
(data.charCodeAt(1) + 0x100).toString(16).slice(1) +
(data.charCodeAt(2) + 0x100).toString(16).slice(1) +
(data.charCodeAt(3) + 0x100).toString(16).slice(1) +
'-' +
(data.charCodeAt(4) + 0x100).toString(16).slice(1) +
(data.charCodeAt(5) + 0x100).toString(16).slice(1) +
'-' +
(data.charCodeAt(6) + 0x100).toString(16).slice(1) +
(data.charCodeAt(7) + 0x100).toString(16).slice(1) +
'-' +
(data.charCodeAt(8) + 0x100).toString(16).slice(1) +
(data.charCodeAt(9) + 0x100).toString(16).slice(1) +
'-' +
(data.charCodeAt(10) + 0x100).toString(16).slice(1) +
(data.charCodeAt(11) + 0x100).toString(16).slice(1) +
(data.charCodeAt(12) + 0x100).toString(16).slice(1) +
(data.charCodeAt(13) + 0x100).toString(16).slice(1) +
(data.charCodeAt(14) + 0x100).toString(16).slice(1) +
(data.charCodeAt(15) + 0x100).toString(16).slice(1)
);
}
function test() {
for (let n = 0; n < 30000; n++) {
const uuid = crypto.randomUUID();
const compressed = packUUID(uuid);
const uncompresed = unpackUUID(compressed)
if (uuid !== uncompresed) {
console.log(uuid, compressed, uncompresed, uuid === uncompresed);
}
}
console.log('👌');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment