Last active
September 11, 2023 13:59
-
-
Save davidglezz/bf65ca5ba51c19f4266c342fa74533c5 to your computer and use it in GitHub Desktop.
UUID pack/unpack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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