🐙
Javascript で UUID (v4) を生成する
UUIDにはいくつかの変種やバージョンがありますが、その中でもRFC 4122の中で定義されているバージョン4は単純に乱数で生成するという非常にシンプルな仕組みになっています。
自前で作るのも簡単なので、実際にJavascriptでも書いてみました。
実際に作ってみる
その1
class UUID {
static #uuidIte = ( function* () {
const HEXOCTETS = Object.freeze( [ ...Array( 0x100 ) ].map( ( e, i ) => i.toString( 0x10 ).padStart( 2, "0" ).toUpperCase() ) );
const VARSION = 0x40;
const VARIANT = 0x80;
for (;;) {
const bytes = crypto.getRandomValues( new Uint8Array( 16 ) );
yield "" +
HEXOCTETS[ bytes[ 0 ] ] +
HEXOCTETS[ bytes[ 1 ] ] +
HEXOCTETS[ bytes[ 2 ] ] +
HEXOCTETS[ bytes[ 3 ] ] + "-" +
HEXOCTETS[ bytes[ 4 ] ] +
HEXOCTETS[ bytes[ 5 ] ] + "-" +
HEXOCTETS[ bytes[ 6 ] & 0x0f | VARSION ] +
HEXOCTETS[ bytes[ 7 ] ] + "-" +
HEXOCTETS[ bytes[ 8 ] & 0x3f | VARIANT ] +
HEXOCTETS[ bytes[ 9 ] ] + "-" +
HEXOCTETS[ bytes[ 10 ] ] +
HEXOCTETS[ bytes[ 11 ] ] +
HEXOCTETS[ bytes[ 12 ] ] +
HEXOCTETS[ bytes[ 13 ] ] +
HEXOCTETS[ bytes[ 14 ] ] +
HEXOCTETS[ bytes[ 15 ] ];
}
} )();
static randomUUID() {
return this.#uuidIte.next().value;
}
}
console.log( UUID.randomUUID() ); //e.g. 16E3908E-96DF-468E-B148-90A11814615F
ついでに、Node.jsでは組み込みにcrypto
がないようなので、Math.random()
を使った実装も載せます。
その2(crypto未使用)
class UUID {
static #uuidIte = ( function* () {
const HEXOCTETS = Object.freeze( [ ...Array( 0x100 ) ].map( ( e, i ) => i.toString( 0x10 ).padStart( 2, "0" ).toUpperCase() ) );
const VARSION = 0x40;
const VARIANT = 0x80;
const bytes = new Uint8Array( 16 );
const rand = new Uint32Array( bytes.buffer );
for (;;) {
for ( let i = 0; i < rand.length; i++ ) {
rand[ i ] = Math.random() * 0x100000000 >>> 0;
}
yield "" +
HEXOCTETS[ bytes[ 0 ] ] +
HEXOCTETS[ bytes[ 1 ] ] +
HEXOCTETS[ bytes[ 2 ] ] +
HEXOCTETS[ bytes[ 3 ] ] + "-" +
HEXOCTETS[ bytes[ 4 ] ] +
HEXOCTETS[ bytes[ 5 ] ] + "-" +
HEXOCTETS[ bytes[ 6 ] & 0x0f | VARSION ] +
HEXOCTETS[ bytes[ 7 ] ] + "-" +
HEXOCTETS[ bytes[ 8 ] & 0x3f | VARIANT ] +
HEXOCTETS[ bytes[ 9 ] ] + "-" +
HEXOCTETS[ bytes[ 10 ] ] +
HEXOCTETS[ bytes[ 11 ] ] +
HEXOCTETS[ bytes[ 12 ] ] +
HEXOCTETS[ bytes[ 13 ] ] +
HEXOCTETS[ bytes[ 14 ] ] +
HEXOCTETS[ bytes[ 15 ] ];
}
} )();
static randomUUID() {
return this.#uuidIte.next().value;
}
}
console.log( UUID.randomUUID() ); //e.g. 16E3908E-96DF-468E-B148-90A11814615F
以上!
分散型でかなり高速に生成できるのに一意な値として使えるのは不思議な感じがします。
Discussion