diff options
Diffstat (limited to 'app/assets/javascripts/diffs/utils/uuids.js')
-rw-r--r-- | app/assets/javascripts/diffs/utils/uuids.js | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/app/assets/javascripts/diffs/utils/uuids.js b/app/assets/javascripts/diffs/utils/uuids.js new file mode 100644 index 00000000000..1a529c07ccc --- /dev/null +++ b/app/assets/javascripts/diffs/utils/uuids.js @@ -0,0 +1,79 @@ +/** + * @module uuids + */ + +/** + * A string or number representing a start state for a random generator + * @typedef {(Number|String)} Seed + */ +/** + * A UUIDv4 string in the format <code>Hex{8}-Hex{4}-4Hex{3}-[89ab]Hex{3}-Hex{12}</code> + * @typedef {String} UUIDv4 + */ + +// https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20 +/* eslint-disable import/prefer-default-export */ + +import MersenneTwister from 'mersenne-twister'; +import stringHash from 'string-hash'; +import { isString } from 'lodash'; +import { v4 } from 'uuid'; + +function getSeed(seeds) { + return seeds.reduce((seedling, seed, i) => { + let thisSeed = 0; + + if (Number.isInteger(seed)) { + thisSeed = seed; + } else if (isString(seed)) { + thisSeed = stringHash(seed); + } + + return seedling + (seeds.length - i) * thisSeed; + }, 0); +} + +function getPseudoRandomNumberGenerator(...seeds) { + let seedNumber; + + if (seeds.length) { + seedNumber = getSeed(seeds); + } else { + seedNumber = Math.floor(Math.random() * 10 ** 15); + } + + return new MersenneTwister(seedNumber); +} + +function randomValuesForUuid(prng) { + const randomValues = []; + + for (let i = 0; i <= 3; i += 1) { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + + view.setUint32(0, prng.random_int()); + + randomValues.push(view.getUint8(0), view.getUint8(1), view.getUint8(2), view.getUint8(3)); + } + + return randomValues; +} + +/** + * Get an array of UUIDv4s + * @param {Object} [options={}] + * @param {Seed[]} [options.seeds=[]] - A list of mixed strings or numbers to seed the UUIDv4 generator + * @param {Number} [options.count=1] - A total number of UUIDv4s to generate + * @returns {UUIDv4[]} An array of UUIDv4s + */ +export function uuids({ seeds = [], count = 1 } = {}) { + const rng = getPseudoRandomNumberGenerator(...seeds); + return ( + // Create an array the same size as the number of UUIDs requested + Array(count) + .fill(0) + // Replace each slot in the array with a UUID which needs 16 (pseudo)random values to generate + .map(() => v4({ random: randomValuesForUuid(rng) })) + ); +} |