Playing with QUID string keys
François-Emmanuel CORTES

François-Emmanuel CORTES @hefeust

About: lately web dev at Université de Bretagne Occidentale -during yezr 2022) interests: aero and sea drones, chess playing, sailing Physics Math and IT studies

Location:
Brest, Britany, Fraznce
Joined:
Sep 15, 2022

Playing with QUID string keys

Publish Date: Jun 4
0 0

Playing with QUID string keys

I call those QUID string keys for "Quasi-Unique IDentifiers" : these randomized string keymaps are not ~100% guaranteed (cryptographocally speaking) to be unique during runtime, but the program can use them easily and safely to identify a bunch of data items, acommodating with possible collisions between consecutive computed values of the keys.

Context

Let's have a very big collections of blocks stored data inside a JS/TS Map:

type Block = { /* user data */ }

const blocks: Map <string, Block> = new Map ()

blocks.set ('abcd', { x: 1 })
blocks.set ('ef12', { y: 2 })
blocks.set ('3456', { z: 3 })        
blocks.set ('7890', { w: 4 })        

// oops we erased some useful data !
blocks.set ('abcd', { bad: '#ERROR!' })
Enter fullscreen mode Exit fullscreen mode

We want enough keys to avoid collision and data loss; both we also want to keep human-readability for keys.

UUIDs ? No, just QUIDs !

Of course you probably think to a node library UUID-like to produce keys in the form: XXXX-XXXX-4YXX-XXXX-XXXXXXXXXXX ?If so you can watch

(see tutos #random #generator #etc...)

But do you really need for your todolists, a lightweb game a such level of uniqness and unpredictility in yout keys ?

If not, just try the QUID approach !

Let's figure out N-digits hexadecimal strings, such as "900dcafe": "bada55e5" or "c0cac01a".

LENGTH  available values
2 256
4 65536 (= 256 * 256)
8 ~ 4.2 * Math.pow (10, 9)
16 ... isn't it enough ??
Enter fullscreen mode Exit fullscreen mode




Computing

Since access to Map is algorithmically time-constant O(1) complexity, let's compute new keys against user map keys.

// "phantom" property...
export type QUID = string & { __quid: void }

export const nextQUID = (exists: (qtest: QUID) => boolean): QUID => {
let counter: number = 0
let qtest: QUID

do {
    const str = [0, 1, 2, 3].map ((_) =&gt; {
        return Math.floor (256 * Math.random ())
            .toString (16)
            .padStart (2, '0')

    }).reduce ((acc, str) =&gt; acc += str, '')

    qtest = fromString (str)    

    if (counter &gt; 1000) {
        throw new Error ('#QUID_LOOP!')
    }

    counter++
} while (exists (qtest))

return qtest
Enter fullscreen mode Exit fullscreen mode

}

Enter fullscreen mode Exit fullscreen mode




Storage impacts

Performance considerations

Since Map.has is O(1) time complexity and 8-kzngth hexa-string could address 4.2 * Math.pow (10, 9), collision risks are limited, same for loops in nextQUID function.

So can be efficient.

Happy coding !

Comments 0 total

    Add comment