なるべく衝突しないIDを用意したい
時刻やMACアドレスなどの固有の値を使わず、なるべく衝突しない一意のIDを生成したい。それでは、UUIDを作りましょう。
バージョン4
乱数によるUUID。16進表記ではRRRRRRRR-RRRR-4RRR-rRRR-RRRRRRRRRRRRとなり、バリアント(10)とバージョン(0100)を除くすべてのビットを乱数(R:122ビット)で生成する。
UUID - Wikipedia
RFC4122 でも確認できます。
他ライブラリではどのように生成しているのか
Chrome Platform Analytics の実装 (Apache License v2.0)
identifier.js
/** @private {string} */
analytics.internal.Identifier.UUID_FMT_ =
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
/** @private {RegExp} */
analytics.internal.Identifier.UUID_MATCHER_ =
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
/**
* @return {string} A randomly generated UUID V4.
*/
analytics.internal.Identifier.generateUuid = function() {
var chars = analytics.internal.Identifier.UUID_FMT_.split('');
for (var i = 0, len = chars.length; i < len; i++) {
switch (chars[i]) {
case 'x':
chars[i] = goog.math.randomInt(16).toString(16);
break;
case 'y':
chars[i] = (goog.math.randomInt(4) + 8).toString(16);
break;
}
}
return chars.join('');
};
-
analytics.internal.Identifier.UUID_FMT_
を分解 - 分解した文字列(
chars
)を1文字ずつ取得して - パターンに合う文字を生成・書き換え
- 結合します
- パターンに合わない文字(
-
と4
)はそのまま出力されます。 - パターン「x」の場合は
0~9
またはa~f
のいずれか1文字が選択されます。 - パターン「y」の場合は
8
、9
、a
またはb
のいずれか1文字が選択されます。
なお、.UUID_MATCHER_
は、生成済みのUUIDがパターンと合致するかテストするための正規表現となります。
上記の実装では Google Closure Library が使われています。goog.math.randomInt(number)
をMath.floor(Math.random() * number)
に置き換える事ができます。
uuid-v4-switch.js
switch (chars[i]) {
case "x":
chars[i] = Math.floor(Math.random() * 16).toString(16);
break;
case "y":
chars[i] = (Math.floor(Math.random() * 4) + 8).toString(16);
break;
}
google/closure-library math.js
コードを書く
単体で生成できるようにしてみましょう。
uuid-v4.js
function generateUuid() {
// https://github.com/GoogleChrome/chrome-platform-analytics/blob/master/src/internal/identifier.js
// const FORMAT: string = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
let chars = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".split("");
for (let i = 0, len = chars.length; i < len; i++) {
switch (chars[i]) {
case "x":
chars[i] = Math.floor(Math.random() * 16).toString(16);
break;
case "y":
chars[i] = (Math.floor(Math.random() * 4) + 8).toString(16);
break;
}
}
return chars.join("");
}
確認する
JavaScript で UUID (Ver4) を作ることができました。