const MszRandomInt = function(min, max) {
    let ret = 0;
    const range = max - min;

    const bitsNeeded = Math.ceil(Math.log2(range));
    if(bitsNeeded > 53)
        return -1;

    const bytesNeeded = Math.ceil(bitsNeeded / 8),
        mask = Math.pow(2, bitsNeeded) - 1;

    const bytes = new Uint8Array(bytesNeeded);
    crypto.getRandomValues(bytes);

    let p = (bytesNeeded - 1) * 8;
    for(let i = 0; i < bytesNeeded; ++i) {
        ret += bytes[i] * Math.pow(2, p);
        p -= 8;
    }

    ret &= mask;

    if(ret >= range)
        return MszRandomInt(min, max);

    return min + ret;
};

const MszUniqueStr = (function() {
    const chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789';

    return function(length) {
        let str = '';
        for(let i = 0; i < length; ++i)
            str += chars[MszRandomInt(0, chars.length)];
        return str;
    };
})();
