Andrey Pavlov | 9b47f32 | 2020-04-05 22:31:40 +0300 | [diff] [blame] | 1 | /*
|
| 2 | * UUID-js: A js library to generate and parse UUIDs, TimeUUIDs and generate
|
| 3 | * TimeUUID based on dates for range selections.
|
| 4 | * @see http://www.ietf.org/rfc/rfc4122.txt
|
| 5 | **/
|
| 6 |
|
| 7 | function UUIDjs() {
|
| 8 | };
|
| 9 |
|
| 10 | UUIDjs.maxFromBits = function(bits) {
|
| 11 | return Math.pow(2, bits);
|
| 12 | };
|
| 13 |
|
| 14 | UUIDjs.limitUI04 = UUIDjs.maxFromBits(4);
|
| 15 | UUIDjs.limitUI06 = UUIDjs.maxFromBits(6);
|
| 16 | UUIDjs.limitUI08 = UUIDjs.maxFromBits(8);
|
| 17 | UUIDjs.limitUI12 = UUIDjs.maxFromBits(12);
|
| 18 | UUIDjs.limitUI14 = UUIDjs.maxFromBits(14);
|
| 19 | UUIDjs.limitUI16 = UUIDjs.maxFromBits(16);
|
| 20 | UUIDjs.limitUI32 = UUIDjs.maxFromBits(32);
|
| 21 | UUIDjs.limitUI40 = UUIDjs.maxFromBits(40);
|
| 22 | UUIDjs.limitUI48 = UUIDjs.maxFromBits(48);
|
| 23 |
|
| 24 | UUIDjs.randomUI04 = function() {
|
| 25 | return Math.round(Math.random() * UUIDjs.limitUI04);
|
| 26 | };
|
| 27 | UUIDjs.randomUI06 = function() {
|
| 28 | return Math.round(Math.random() * UUIDjs.limitUI06);
|
| 29 | };
|
| 30 | UUIDjs.randomUI08 = function() {
|
| 31 | return Math.round(Math.random() * UUIDjs.limitUI08);
|
| 32 | };
|
| 33 | UUIDjs.randomUI12 = function() {
|
| 34 | return Math.round(Math.random() * UUIDjs.limitUI12);
|
| 35 | };
|
| 36 | UUIDjs.randomUI14 = function() {
|
| 37 | return Math.round(Math.random() * UUIDjs.limitUI14);
|
| 38 | };
|
| 39 | UUIDjs.randomUI16 = function() {
|
| 40 | return Math.round(Math.random() * UUIDjs.limitUI16);
|
| 41 | };
|
| 42 | UUIDjs.randomUI32 = function() {
|
| 43 | return Math.round(Math.random() * UUIDjs.limitUI32);
|
| 44 | };
|
| 45 | UUIDjs.randomUI40 = function() {
|
| 46 | return (0 | Math.random() * (1 << 30)) + (0 | Math.random() * (1 << 40 - 30)) * (1 << 30);
|
| 47 | };
|
| 48 | UUIDjs.randomUI48 = function() {
|
| 49 | return (0 | Math.random() * (1 << 30)) + (0 | Math.random() * (1 << 48 - 30)) * (1 << 30);
|
| 50 | };
|
| 51 |
|
| 52 | UUIDjs.paddedString = function(string, length, z) {
|
| 53 | string = String(string);
|
| 54 | z = (!z) ? '0' : z;
|
| 55 | var i = length - string.length;
|
| 56 | for (; i > 0; i >>>= 1, z += z) {
|
| 57 | if (i & 1) {
|
| 58 | string = z + string;
|
| 59 | }
|
| 60 | }
|
| 61 | return string;
|
| 62 | };
|
| 63 |
|
| 64 | UUIDjs.prototype.fromParts = function(timeLow, timeMid, timeHiAndVersion, clockSeqHiAndReserved, clockSeqLow, node) {
|
| 65 | this.version = (timeHiAndVersion >> 12) & 0xF;
|
| 66 | this.hex = UUIDjs.paddedString(timeLow.toString(16), 8)
|
| 67 | + '-'
|
| 68 | + UUIDjs.paddedString(timeMid.toString(16), 4)
|
| 69 | + '-'
|
| 70 | + UUIDjs.paddedString(timeHiAndVersion.toString(16), 4)
|
| 71 | + '-'
|
| 72 | + UUIDjs.paddedString(clockSeqHiAndReserved.toString(16), 2)
|
| 73 | + UUIDjs.paddedString(clockSeqLow.toString(16), 2)
|
| 74 | + '-'
|
| 75 | + UUIDjs.paddedString(node.toString(16), 12);
|
| 76 | return this;
|
| 77 | };
|
| 78 |
|
| 79 | UUIDjs.prototype.toString = function() {
|
| 80 | return this.hex;
|
| 81 | };
|
| 82 | UUIDjs.prototype.toURN = function() {
|
| 83 | return 'urn:uuid:' + this.hex;
|
| 84 | };
|
| 85 |
|
| 86 | UUIDjs.prototype.toBytes = function() {
|
| 87 | var parts = this.hex.split('-');
|
| 88 | var ints = [];
|
| 89 | var intPos = 0;
|
| 90 | for (var i = 0; i < parts.length; i++) {
|
| 91 | for (var j = 0; j < parts[i].length; j+=2) {
|
| 92 | ints[intPos++] = parseInt(parts[i].substr(j, 2), 16);
|
| 93 | }
|
| 94 | }
|
| 95 | return ints;
|
| 96 | };
|
| 97 |
|
| 98 | UUIDjs.prototype.equals = function(uuid) {
|
| 99 | if (!(uuid instanceof UUID)) {
|
| 100 | return false;
|
| 101 | }
|
| 102 | if (this.hex !== uuid.hex) {
|
| 103 | return false;
|
| 104 | }
|
| 105 | return true;
|
| 106 | };
|
| 107 |
|
| 108 | UUIDjs.getTimeFieldValues = function(time) {
|
| 109 | var ts = time - Date.UTC(1582, 9, 15);
|
| 110 | var hm = ((ts / 0x100000000) * 10000) & 0xFFFFFFF;
|
| 111 | return { low: ((ts & 0xFFFFFFF) * 10000) % 0x100000000,
|
| 112 | mid: hm & 0xFFFF, hi: hm >>> 16, timestamp: ts };
|
| 113 | };
|
| 114 |
|
| 115 | UUIDjs._create4 = function() {
|
| 116 | return new UUIDjs().fromParts(
|
| 117 | UUIDjs.randomUI32(),
|
| 118 | UUIDjs.randomUI16(),
|
| 119 | 0x4000 | UUIDjs.randomUI12(),
|
| 120 | 0x80 | UUIDjs.randomUI06(),
|
| 121 | UUIDjs.randomUI08(),
|
| 122 | UUIDjs.randomUI48()
|
| 123 | );
|
| 124 | };
|
| 125 |
|
| 126 | UUIDjs._create1 = function() {
|
| 127 | var now = new Date().getTime();
|
| 128 | var sequence = UUIDjs.randomUI14();
|
| 129 | var node = (UUIDjs.randomUI08() | 1) * 0x10000000000 + UUIDjs.randomUI40();
|
| 130 | var tick = UUIDjs.randomUI04();
|
| 131 | var timestamp = 0;
|
| 132 | var timestampRatio = 1/4;
|
| 133 |
|
| 134 | if (now != timestamp) {
|
| 135 | if (now < timestamp) {
|
| 136 | sequence++;
|
| 137 | }
|
| 138 | timestamp = now;
|
| 139 | tick = UUIDjs.randomUI04();
|
| 140 | } else if (Math.random() < timestampRatio && tick < 9984) {
|
| 141 | tick += 1 + UUIDjs.randomUI04();
|
| 142 | } else {
|
| 143 | sequence++;
|
| 144 | }
|
| 145 |
|
| 146 | var tf = UUIDjs.getTimeFieldValues(timestamp);
|
| 147 | var tl = tf.low + tick;
|
| 148 | var thav = (tf.hi & 0xFFF) | 0x1000;
|
| 149 |
|
| 150 | sequence &= 0x3FFF;
|
| 151 | var cshar = (sequence >>> 8) | 0x80;
|
| 152 | var csl = sequence & 0xFF;
|
| 153 |
|
| 154 | return new UUIDjs().fromParts(tl, tf.mid, thav, cshar, csl, node);
|
| 155 | };
|
| 156 |
|
| 157 | UUIDjs.create = function(version) {
|
| 158 | version = version || 4;
|
| 159 | return this['_create' + version]();
|
| 160 | };
|
| 161 |
|
| 162 | UUIDjs.fromTime = function(time, last) {
|
| 163 | last = (!last) ? false : last;
|
| 164 | var tf = UUIDjs.getTimeFieldValues(time);
|
| 165 | var tl = tf.low;
|
| 166 | var thav = (tf.hi & 0xFFF) | 0x1000; // set version '0001'
|
| 167 | if (last === false) {
|
| 168 | return new UUIDjs().fromParts(tl, tf.mid, thav, 0, 0, 0);
|
| 169 | } else {
|
| 170 | return new UUIDjs().fromParts(tl, tf.mid, thav, 0x80 | UUIDjs.limitUI06, UUIDjs.limitUI08 - 1, UUIDjs.limitUI48 - 1);
|
| 171 | }
|
| 172 | };
|
| 173 |
|
| 174 | UUIDjs.firstFromTime = function(time) {
|
| 175 | return UUIDjs.fromTime(time, false);
|
| 176 | };
|
| 177 | UUIDjs.lastFromTime = function(time) {
|
| 178 | return UUIDjs.fromTime(time, true);
|
| 179 | };
|
| 180 |
|
| 181 | UUIDjs.fromURN = function(strId) {
|
| 182 | var r, p = /^(?:urn:uuid:|\{)?([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{2})([0-9a-f]{2})-([0-9a-f]{12})(?:\})?$/i;
|
| 183 | if ((r = p.exec(strId))) {
|
| 184 | return new UUIDjs().fromParts(parseInt(r[1], 16), parseInt(r[2], 16),
|
| 185 | parseInt(r[3], 16), parseInt(r[4], 16),
|
| 186 | parseInt(r[5], 16), parseInt(r[6], 16));
|
| 187 | }
|
| 188 | return null;
|
| 189 | };
|
| 190 |
|
| 191 | UUIDjs.fromBytes = function(ints) {
|
| 192 | if (ints.length < 5) {
|
| 193 | return null;
|
| 194 | }
|
| 195 | var str = '';
|
| 196 | var pos = 0;
|
| 197 | var parts = [4, 2, 2, 2, 6];
|
| 198 | for (var i = 0; i < parts.length; i++) {
|
| 199 | for (var j = 0; j < parts[i]; j++) {
|
| 200 | var octet = ints[pos++].toString(16);
|
| 201 | if (octet.length == 1) {
|
| 202 | octet = '0' + octet;
|
| 203 | }
|
| 204 | str += octet;
|
| 205 | }
|
| 206 | if (parts[i] !== 6) {
|
| 207 | str += '-';
|
| 208 | }
|
| 209 | }
|
| 210 | return UUIDjs.fromURN(str);
|
| 211 | };
|
| 212 |
|
| 213 | UUIDjs.fromBinary = function(binary) {
|
| 214 | var ints = [];
|
| 215 | for (var i = 0; i < binary.length; i++) {
|
| 216 | ints[i] = binary.charCodeAt(i);
|
| 217 | if (ints[i] > 255 || ints[i] < 0) {
|
| 218 | throw new Error('Unexpected byte in binary data.');
|
| 219 | }
|
| 220 | }
|
| 221 | return UUIDjs.fromBytes(ints);
|
| 222 | };
|
| 223 |
|
| 224 | // Aliases to support legacy code. Do not use these when writing new code as
|
| 225 | // they may be removed in future versions!
|
| 226 | UUIDjs.new = function() {
|
| 227 | return this.create(4);
|
| 228 | };
|
| 229 | UUIDjs.newTS = function() {
|
| 230 | return this.create(1);
|
| 231 | };
|
| 232 |
|
| 233 | //module.exports = UUIDjs;
|