UNPKG

tedious

Version:

A TDS driver, for connecting to MS SQLServer databases.

738 lines (595 loc) 74.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _metadataParser = require("./metadata-parser"); var _dataType = require("./data-type"); var _iconvLite = _interopRequireDefault(require("iconv-lite")); var _sprintfJs = require("sprintf-js"); var _guidParser = require("./guid-parser"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const NULL = (1 << 16) - 1; const MAX = (1 << 16) - 1; const THREE_AND_A_THIRD = 3 + 1 / 3; const MONEY_DIVISOR = 10000; const PLP_NULL = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]); const UNKNOWN_PLP_LEN = Buffer.from([0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]); const DEFAULT_ENCODING = 'utf8'; function readTinyInt(parser, callback) { parser.readUInt8(callback); } function readSmallInt(parser, callback) { parser.readInt16LE(callback); } function readInt(parser, callback) { parser.readInt32LE(callback); } function readBigInt(parser, callback) { parser.readBigInt64LE(value => { callback(value.toString()); }); } function readReal(parser, callback) { parser.readFloatLE(callback); } function readFloat(parser, callback) { parser.readDoubleLE(callback); } function readSmallMoney(parser, callback) { parser.readInt32LE(value => { callback(value / MONEY_DIVISOR); }); } function readMoney(parser, callback) { parser.readInt32LE(high => { parser.readUInt32LE(low => { callback((low + 0x100000000 * high) / MONEY_DIVISOR); }); }); } function readBit(parser, callback) { parser.readUInt8(value => { callback(!!value); }); } function valueParse(parser, metadata, options, callback) { const type = metadata.type; switch (type.name) { case 'Null': return callback(null); case 'TinyInt': return readTinyInt(parser, callback); case 'SmallInt': return readSmallInt(parser, callback); case 'Int': return readInt(parser, callback); case 'BigInt': return readBigInt(parser, callback); case 'IntN': return parser.readUInt8(dataLength => { switch (dataLength) { case 0: return callback(null); case 1: return readTinyInt(parser, callback); case 2: return readSmallInt(parser, callback); case 4: return readInt(parser, callback); case 8: return readBigInt(parser, callback); default: throw new Error('Unsupported dataLength ' + dataLength + ' for IntN'); } }); case 'Real': return readReal(parser, callback); case 'Float': return readFloat(parser, callback); case 'FloatN': return parser.readUInt8(dataLength => { switch (dataLength) { case 0: return callback(null); case 4: return readReal(parser, callback); case 8: return readFloat(parser, callback); default: throw new Error('Unsupported dataLength ' + dataLength + ' for FloatN'); } }); case 'SmallMoney': return readSmallMoney(parser, callback); case 'Money': return readMoney(parser, callback); case 'MoneyN': return parser.readUInt8(dataLength => { switch (dataLength) { case 0: return callback(null); case 4: return readSmallMoney(parser, callback); case 8: return readMoney(parser, callback); default: throw new Error('Unsupported dataLength ' + dataLength + ' for MoneyN'); } }); case 'Bit': return readBit(parser, callback); case 'BitN': return parser.readUInt8(dataLength => { switch (dataLength) { case 0: return callback(null); case 1: return readBit(parser, callback); default: throw new Error('Unsupported dataLength ' + dataLength + ' for BitN'); } }); case 'VarChar': case 'Char': const codepage = metadata.collation.codepage; if (metadata.dataLength === MAX) { return readMaxChars(parser, codepage, callback); } else { return parser.readUInt16LE(dataLength => { if (dataLength === NULL) { return callback(null); } readChars(parser, dataLength, codepage, callback); }); } case 'NVarChar': case 'NChar': if (metadata.dataLength === MAX) { return readMaxNChars(parser, callback); } else { return parser.readUInt16LE(dataLength => { if (dataLength === NULL) { return callback(null); } readNChars(parser, dataLength, callback); }); } case 'VarBinary': case 'Binary': if (metadata.dataLength === MAX) { return readMaxBinary(parser, callback); } else { return parser.readUInt16LE(dataLength => { if (dataLength === NULL) { return callback(null); } readBinary(parser, dataLength, callback); }); } case 'Text': return parser.readUInt8(textPointerLength => { if (textPointerLength === 0) { return callback(null); } parser.readBuffer(textPointerLength, _textPointer => { parser.readBuffer(8, _timestamp => { parser.readUInt32LE(dataLength => { readChars(parser, dataLength, metadata.collation.codepage, callback); }); }); }); }); case 'NText': return parser.readUInt8(textPointerLength => { if (textPointerLength === 0) { return callback(null); } parser.readBuffer(textPointerLength, _textPointer => { parser.readBuffer(8, _timestamp => { parser.readUInt32LE(dataLength => { readNChars(parser, dataLength, callback); }); }); }); }); case 'Image': return parser.readUInt8(textPointerLength => { if (textPointerLength === 0) { return callback(null); } parser.readBuffer(textPointerLength, _textPointer => { parser.readBuffer(8, _timestamp => { parser.readUInt32LE(dataLength => { readBinary(parser, dataLength, callback); }); }); }); }); case 'Xml': return readMaxNChars(parser, callback); case 'SmallDateTime': return readSmallDateTime(parser, options.useUTC, callback); case 'DateTime': return readDateTime(parser, options.useUTC, callback); case 'DateTimeN': return parser.readUInt8(dataLength => { switch (dataLength) { case 0: return callback(null); case 4: return readSmallDateTime(parser, options.useUTC, callback); case 8: return readDateTime(parser, options.useUTC, callback); default: throw new Error('Unsupported dataLength ' + dataLength + ' for DateTimeN'); } }); case 'Time': return parser.readUInt8(dataLength => { if (dataLength === 0) { return callback(null); } else { return readTime(parser, dataLength, metadata.scale, options.useUTC, callback); } }); case 'Date': return parser.readUInt8(dataLength => { if (dataLength === 0) { return callback(null); } else { return readDate(parser, options.useUTC, callback); } }); case 'DateTime2': return parser.readUInt8(dataLength => { if (dataLength === 0) { return callback(null); } else { return readDateTime2(parser, dataLength, metadata.scale, options.useUTC, callback); } }); case 'DateTimeOffset': return parser.readUInt8(dataLength => { if (dataLength === 0) { return callback(null); } else { return readDateTimeOffset(parser, dataLength, metadata.scale, callback); } }); case 'NumericN': case 'DecimalN': return parser.readUInt8(dataLength => { if (dataLength === 0) { return callback(null); } else { return readNumeric(parser, dataLength, metadata.precision, metadata.scale, callback); } }); case 'UniqueIdentifier': return parser.readUInt8(dataLength => { switch (dataLength) { case 0: return callback(null); case 0x10: return readUniqueIdentifier(parser, options, callback); default: throw new Error((0, _sprintfJs.sprintf)('Unsupported guid size %d', dataLength - 1)); } }); case 'UDT': return readMaxBinary(parser, callback); case 'Variant': return parser.readUInt32LE(dataLength => { if (dataLength === 0) { return callback(null); } readVariant(parser, options, dataLength, callback); }); default: throw new Error((0, _sprintfJs.sprintf)('Unrecognised type %s', type.name)); } } function readUniqueIdentifier(parser, options, callback) { parser.readBuffer(0x10, data => { callback(options.lowerCaseGuids ? (0, _guidParser.bufferToLowerCaseGuid)(data) : (0, _guidParser.bufferToUpperCaseGuid)(data)); }); } function readNumeric(parser, dataLength, _precision, scale, callback) { parser.readUInt8(sign => { sign = sign === 1 ? 1 : -1; let readValue; if (dataLength === 5) { readValue = parser.readUInt32LE; } else if (dataLength === 9) { readValue = parser.readUNumeric64LE; } else if (dataLength === 13) { readValue = parser.readUNumeric96LE; } else if (dataLength === 17) { readValue = parser.readUNumeric128LE; } else { throw new Error((0, _sprintfJs.sprintf)('Unsupported numeric dataLength %d', dataLength)); } readValue.call(parser, value => { callback(value * sign / Math.pow(10, scale)); }); }); } function readVariant(parser, options, dataLength, callback) { return parser.readUInt8(baseType => { const type = _dataType.TYPE[baseType]; return parser.readUInt8(propBytes => { dataLength = dataLength - propBytes - 2; switch (type.name) { case 'UniqueIdentifier': return readUniqueIdentifier(parser, options, callback); case 'Bit': return readBit(parser, callback); case 'TinyInt': return readTinyInt(parser, callback); case 'SmallInt': return readSmallInt(parser, callback); case 'Int': return readInt(parser, callback); case 'BigInt': return readBigInt(parser, callback); case 'SmallDateTime': return readSmallDateTime(parser, options.useUTC, callback); case 'DateTime': return readDateTime(parser, options.useUTC, callback); case 'Real': return readReal(parser, callback); case 'Float': return readFloat(parser, callback); case 'SmallMoney': return readSmallMoney(parser, callback); case 'Money': return readMoney(parser, callback); case 'Date': return readDate(parser, options.useUTC, callback); case 'Time': return parser.readUInt8(scale => { return readTime(parser, dataLength, scale, options.useUTC, callback); }); case 'DateTime2': return parser.readUInt8(scale => { return readDateTime2(parser, dataLength, scale, options.useUTC, callback); }); case 'DateTimeOffset': return parser.readUInt8(scale => { return readDateTimeOffset(parser, dataLength, scale, callback); }); case 'VarBinary': case 'Binary': return parser.readUInt16LE(_maxLength => { readBinary(parser, dataLength, callback); }); case 'NumericN': case 'DecimalN': return parser.readUInt8(precision => { parser.readUInt8(scale => { readNumeric(parser, dataLength, precision, scale, callback); }); }); case 'VarChar': case 'Char': return parser.readUInt16LE(_maxLength => { (0, _metadataParser.readCollation)(parser, collation => { readChars(parser, dataLength, collation.codepage, callback); }); }); case 'NVarChar': case 'NChar': return parser.readUInt16LE(_maxLength => { (0, _metadataParser.readCollation)(parser, _collation => { readNChars(parser, dataLength, callback); }); }); default: throw new Error('Invalid type!'); } }); }); } function readBinary(parser, dataLength, callback) { return parser.readBuffer(dataLength, callback); } function readChars(parser, dataLength, codepage, callback) { if (codepage == null) { codepage = DEFAULT_ENCODING; } return parser.readBuffer(dataLength, data => { callback(_iconvLite.default.decode(data, codepage)); }); } function readNChars(parser, dataLength, callback) { parser.readBuffer(dataLength, data => { callback(data.toString('ucs2')); }); } function readMaxBinary(parser, callback) { return readMax(parser, callback); } function readMaxChars(parser, codepage, callback) { if (codepage == null) { codepage = DEFAULT_ENCODING; } readMax(parser, data => { if (data) { callback(_iconvLite.default.decode(data, codepage)); } else { callback(null); } }); } function readMaxNChars(parser, callback) { readMax(parser, data => { if (data) { callback(data.toString('ucs2')); } else { callback(null); } }); } function readMax(parser, callback) { parser.readBuffer(8, type => { if (type.equals(PLP_NULL)) { return callback(null); } else if (type.equals(UNKNOWN_PLP_LEN)) { return readMaxUnknownLength(parser, callback); } else { const low = type.readUInt32LE(0); const high = type.readUInt32LE(4); if (high >= 2 << 53 - 32) { console.warn('Read UInt64LE > 53 bits : high=' + high + ', low=' + low); } const expectedLength = low + 0x100000000 * high; return readMaxKnownLength(parser, expectedLength, callback); } }); } function readMaxKnownLength(parser, totalLength, callback) { const data = Buffer.alloc(totalLength, 0); let offset = 0; function next(done) { parser.readUInt32LE(chunkLength => { if (!chunkLength) { return done(); } parser.readBuffer(chunkLength, chunk => { chunk.copy(data, offset); offset += chunkLength; next(done); }); }); } next(() => { if (offset !== totalLength) { throw new Error('Partially Length-prefixed Bytes unmatched lengths : expected ' + totalLength + ', but got ' + offset + ' bytes'); } callback(data); }); } function readMaxUnknownLength(parser, callback) { const chunks = []; let length = 0; function next(done) { parser.readUInt32LE(chunkLength => { if (!chunkLength) { return done(); } parser.readBuffer(chunkLength, chunk => { chunks.push(chunk); length += chunkLength; next(done); }); }); } next(() => { callback(Buffer.concat(chunks, length)); }); } function readSmallDateTime(parser, useUTC, callback) { parser.readUInt16LE(days => { parser.readUInt16LE(minutes => { let value; if (useUTC) { value = new Date(Date.UTC(1900, 0, 1 + days, 0, minutes)); } else { value = new Date(1900, 0, 1 + days, 0, minutes); } callback(value); }); }); } function readDateTime(parser, useUTC, callback) { parser.readInt32LE(days => { parser.readUInt32LE(threeHundredthsOfSecond => { const milliseconds = Math.round(threeHundredthsOfSecond * THREE_AND_A_THIRD); let value; if (useUTC) { value = new Date(Date.UTC(1900, 0, 1 + days, 0, 0, 0, milliseconds)); } else { value = new Date(1900, 0, 1 + days, 0, 0, 0, milliseconds); } callback(value); }); }); } function readTime(parser, dataLength, scale, useUTC, callback) { let readValue; switch (dataLength) { case 3: readValue = parser.readUInt24LE; break; case 4: readValue = parser.readUInt32LE; break; case 5: readValue = parser.readUInt40LE; } readValue.call(parser, value => { if (scale < 7) { for (let i = scale; i < 7; i++) { value *= 10; } } let date; if (useUTC) { date = new Date(Date.UTC(1970, 0, 1, 0, 0, 0, value / 10000)); } else { date = new Date(1970, 0, 1, 0, 0, 0, value / 10000); } Object.defineProperty(date, 'nanosecondsDelta', { enumerable: false, value: value % 10000 / Math.pow(10, 7) }); callback(date); }); } function readDate(parser, useUTC, callback) { parser.readUInt24LE(days => { if (useUTC) { callback(new Date(Date.UTC(2000, 0, days - 730118))); } else { callback(new Date(2000, 0, days - 730118)); } }); } function readDateTime2(parser, dataLength, scale, useUTC, callback) { readTime(parser, dataLength - 3, scale, useUTC, time => { // TODO: 'input' is 'time', but TypeScript cannot find "time.nanosecondsDelta"; parser.readUInt24LE(days => { let date; if (useUTC) { date = new Date(Date.UTC(2000, 0, days - 730118, 0, 0, 0, +time)); } else { date = new Date(2000, 0, days - 730118, time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds()); } Object.defineProperty(date, 'nanosecondsDelta', { enumerable: false, value: time.nanosecondsDelta }); callback(date); }); }); } function readDateTimeOffset(parser, dataLength, scale, callback) { readTime(parser, dataLength - 5, scale, true, time => { parser.readUInt24LE(days => { // offset parser.readInt16LE(() => { const date = new Date(Date.UTC(2000, 0, days - 730118, 0, 0, 0, +time)); Object.defineProperty(date, 'nanosecondsDelta', { enumerable: false, value: time.nanosecondsDelta }); callback(date); }); }); }); } var _default = valueParse; exports.default = _default; module.exports = valueParse; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJOVUxMIiwiTUFYIiwiVEhSRUVfQU5EX0FfVEhJUkQiLCJNT05FWV9ESVZJU09SIiwiUExQX05VTEwiLCJCdWZmZXIiLCJmcm9tIiwiVU5LTk9XTl9QTFBfTEVOIiwiREVGQVVMVF9FTkNPRElORyIsInJlYWRUaW55SW50IiwicGFyc2VyIiwiY2FsbGJhY2siLCJyZWFkVUludDgiLCJyZWFkU21hbGxJbnQiLCJyZWFkSW50MTZMRSIsInJlYWRJbnQiLCJyZWFkSW50MzJMRSIsInJlYWRCaWdJbnQiLCJyZWFkQmlnSW50NjRMRSIsInZhbHVlIiwidG9TdHJpbmciLCJyZWFkUmVhbCIsInJlYWRGbG9hdExFIiwicmVhZEZsb2F0IiwicmVhZERvdWJsZUxFIiwicmVhZFNtYWxsTW9uZXkiLCJyZWFkTW9uZXkiLCJoaWdoIiwicmVhZFVJbnQzMkxFIiwibG93IiwicmVhZEJpdCIsInZhbHVlUGFyc2UiLCJtZXRhZGF0YSIsIm9wdGlvbnMiLCJ0eXBlIiwibmFtZSIsImRhdGFMZW5ndGgiLCJFcnJvciIsImNvZGVwYWdlIiwiY29sbGF0aW9uIiwicmVhZE1heENoYXJzIiwicmVhZFVJbnQxNkxFIiwicmVhZENoYXJzIiwicmVhZE1heE5DaGFycyIsInJlYWROQ2hhcnMiLCJyZWFkTWF4QmluYXJ5IiwicmVhZEJpbmFyeSIsInRleHRQb2ludGVyTGVuZ3RoIiwicmVhZEJ1ZmZlciIsIl90ZXh0UG9pbnRlciIsIl90aW1lc3RhbXAiLCJyZWFkU21hbGxEYXRlVGltZSIsInVzZVVUQyIsInJlYWREYXRlVGltZSIsInJlYWRUaW1lIiwic2NhbGUiLCJyZWFkRGF0ZSIsInJlYWREYXRlVGltZTIiLCJyZWFkRGF0ZVRpbWVPZmZzZXQiLCJyZWFkTnVtZXJpYyIsInByZWNpc2lvbiIsInJlYWRVbmlxdWVJZGVudGlmaWVyIiwicmVhZFZhcmlhbnQiLCJkYXRhIiwibG93ZXJDYXNlR3VpZHMiLCJfcHJlY2lzaW9uIiwic2lnbiIsInJlYWRWYWx1ZSIsInJlYWRVTnVtZXJpYzY0TEUiLCJyZWFkVU51bWVyaWM5NkxFIiwicmVhZFVOdW1lcmljMTI4TEUiLCJjYWxsIiwiTWF0aCIsInBvdyIsImJhc2VUeXBlIiwiVFlQRSIsInByb3BCeXRlcyIsIl9tYXhMZW5ndGgiLCJfY29sbGF0aW9uIiwiaWNvbnYiLCJkZWNvZGUiLCJyZWFkTWF4IiwiZXF1YWxzIiwicmVhZE1heFVua25vd25MZW5ndGgiLCJjb25zb2xlIiwid2FybiIsImV4cGVjdGVkTGVuZ3RoIiwicmVhZE1heEtub3duTGVuZ3RoIiwidG90YWxMZW5ndGgiLCJhbGxvYyIsIm9mZnNldCIsIm5leHQiLCJkb25lIiwiY2h1bmtMZW5ndGgiLCJjaHVuayIsImNvcHkiLCJjaHVua3MiLCJsZW5ndGgiLCJwdXNoIiwiY29uY2F0IiwiZGF5cyIsIm1pbnV0ZXMiLCJEYXRlIiwiVVRDIiwidGhyZWVIdW5kcmVkdGhzT2ZTZWNvbmQiLCJtaWxsaXNlY29uZHMiLCJyb3VuZCIsInJlYWRVSW50MjRMRSIsInJlYWRVSW50NDBMRSIsImkiLCJkYXRlIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwidGltZSIsImdldEhvdXJzIiwiZ2V0TWludXRlcyIsImdldFNlY29uZHMiLCJnZXRNaWxsaXNlY29uZHMiLCJuYW5vc2Vjb25kc0RlbHRhIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uL3NyYy92YWx1ZS1wYXJzZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFBhcnNlciwgeyBQYXJzZXJPcHRpb25zIH0gZnJvbSAnLi90b2tlbi9zdHJlYW0tcGFyc2VyJztcbmltcG9ydCB7IE1ldGFkYXRhLCByZWFkQ29sbGF0aW9uIH0gZnJvbSAnLi9tZXRhZGF0YS1wYXJzZXInO1xuaW1wb3J0IHsgVFlQRSB9IGZyb20gJy4vZGF0YS10eXBlJztcblxuaW1wb3J0IGljb252IGZyb20gJ2ljb252LWxpdGUnO1xuaW1wb3J0IHsgc3ByaW50ZiB9IGZyb20gJ3NwcmludGYtanMnO1xuaW1wb3J0IHsgYnVmZmVyVG9Mb3dlckNhc2VHdWlkLCBidWZmZXJUb1VwcGVyQ2FzZUd1aWQgfSBmcm9tICcuL2d1aWQtcGFyc2VyJztcblxuY29uc3QgTlVMTCA9ICgxIDw8IDE2KSAtIDE7XG5jb25zdCBNQVggPSAoMSA8PCAxNikgLSAxO1xuY29uc3QgVEhSRUVfQU5EX0FfVEhJUkQgPSAzICsgKDEgLyAzKTtcbmNvbnN0IE1PTkVZX0RJVklTT1IgPSAxMDAwMDtcbmNvbnN0IFBMUF9OVUxMID0gQnVmZmVyLmZyb20oWzB4RkYsIDB4RkYsIDB4RkYsIDB4RkYsIDB4RkYsIDB4RkYsIDB4RkYsIDB4RkZdKTtcbmNvbnN0IFVOS05PV05fUExQX0xFTiA9IEJ1ZmZlci5mcm9tKFsweEZFLCAweEZGLCAweEZGLCAweEZGLCAweEZGLCAweEZGLCAweEZGLCAweEZGXSk7XG5jb25zdCBERUZBVUxUX0VOQ09ESU5HID0gJ3V0ZjgnO1xuXG5mdW5jdGlvbiByZWFkVGlueUludChwYXJzZXI6IFBhcnNlciwgY2FsbGJhY2s6ICh2YWx1ZTogdW5rbm93bikgPT4gdm9pZCkge1xuICBwYXJzZXIucmVhZFVJbnQ4KGNhbGxiYWNrKTtcbn1cblxuZnVuY3Rpb24gcmVhZFNtYWxsSW50KHBhcnNlcjogUGFyc2VyLCBjYWxsYmFjazogKHZhbHVlOiB1bmtub3duKSA9PiB2b2lkKSB7XG4gIHBhcnNlci5yZWFkSW50MTZMRShjYWxsYmFjayk7XG59XG5cbmZ1bmN0aW9uIHJlYWRJbnQocGFyc2VyOiBQYXJzZXIsIGNhbGxiYWNrOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQpIHtcbiAgcGFyc2VyLnJlYWRJbnQzMkxFKGNhbGxiYWNrKTtcbn1cblxuZnVuY3Rpb24gcmVhZEJpZ0ludChwYXJzZXI6IFBhcnNlciwgY2FsbGJhY2s6ICh2YWx1ZTogdW5rbm93bikgPT4gdm9pZCkge1xuICBwYXJzZXIucmVhZEJpZ0ludDY0TEUoKHZhbHVlKSA9PiB7XG4gICAgY2FsbGJhY2sodmFsdWUudG9TdHJpbmcoKSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZWFkUmVhbChwYXJzZXI6IFBhcnNlciwgY2FsbGJhY2s6ICh2YWx1ZTogdW5rbm93bikgPT4gdm9pZCkge1xuICBwYXJzZXIucmVhZEZsb2F0TEUoY2FsbGJhY2spO1xufVxuXG5mdW5jdGlvbiByZWFkRmxvYXQocGFyc2VyOiBQYXJzZXIsIGNhbGxiYWNrOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQpIHtcbiAgcGFyc2VyLnJlYWREb3VibGVMRShjYWxsYmFjayk7XG59XG5cbmZ1bmN0aW9uIHJlYWRTbWFsbE1vbmV5KHBhcnNlcjogUGFyc2VyLCBjYWxsYmFjazogKHZhbHVlOiB1bmtub3duKSA9PiB2b2lkKSB7XG4gIHBhcnNlci5yZWFkSW50MzJMRSgodmFsdWUpID0+IHtcbiAgICBjYWxsYmFjayh2YWx1ZSAvIE1PTkVZX0RJVklTT1IpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gcmVhZE1vbmV5KHBhcnNlcjogUGFyc2VyLCBjYWxsYmFjazogKHZhbHVlOiB1bmtub3duKSA9PiB2b2lkKSB7XG4gIHBhcnNlci5yZWFkSW50MzJMRSgoaGlnaCkgPT4ge1xuICAgIHBhcnNlci5yZWFkVUludDMyTEUoKGxvdykgPT4ge1xuICAgICAgY2FsbGJhY2soKGxvdyArICgweDEwMDAwMDAwMCAqIGhpZ2gpKSAvIE1PTkVZX0RJVklTT1IpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gcmVhZEJpdChwYXJzZXI6IFBhcnNlciwgY2FsbGJhY2s6ICh2YWx1ZTogdW5rbm93bikgPT4gdm9pZCkge1xuICBwYXJzZXIucmVhZFVJbnQ4KCh2YWx1ZSkgPT4ge1xuICAgIGNhbGxiYWNrKCEhdmFsdWUpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVQYXJzZShwYXJzZXI6IFBhcnNlciwgbWV0YWRhdGE6IE1ldGFkYXRhLCBvcHRpb25zOiBQYXJzZXJPcHRpb25zLCBjYWxsYmFjazogKHZhbHVlOiB1bmtub3duKSA9PiB2b2lkKTogdm9pZCB7XG4gIGNvbnN0IHR5cGUgPSBtZXRhZGF0YS50eXBlO1xuXG4gIHN3aXRjaCAodHlwZS5uYW1lKSB7XG4gICAgY2FzZSAnTnVsbCc6XG4gICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG5cbiAgICBjYXNlICdUaW55SW50JzpcbiAgICAgIHJldHVybiByZWFkVGlueUludChwYXJzZXIsIGNhbGxiYWNrKTtcblxuICAgIGNhc2UgJ1NtYWxsSW50JzpcbiAgICAgIHJldHVybiByZWFkU21hbGxJbnQocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICBjYXNlICdJbnQnOlxuICAgICAgcmV0dXJuIHJlYWRJbnQocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICBjYXNlICdCaWdJbnQnOlxuICAgICAgcmV0dXJuIHJlYWRCaWdJbnQocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICBjYXNlICdJbnROJzpcbiAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQ4KChkYXRhTGVuZ3RoKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoZGF0YUxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKTtcblxuICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHJldHVybiByZWFkVGlueUludChwYXJzZXIsIGNhbGxiYWNrKTtcbiAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICByZXR1cm4gcmVhZFNtYWxsSW50KHBhcnNlciwgY2FsbGJhY2spO1xuICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgIHJldHVybiByZWFkSW50KHBhcnNlciwgY2FsbGJhY2spO1xuICAgICAgICAgIGNhc2UgODpcbiAgICAgICAgICAgIHJldHVybiByZWFkQmlnSW50KHBhcnNlciwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgZGF0YUxlbmd0aCAnICsgZGF0YUxlbmd0aCArICcgZm9yIEludE4nKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBjYXNlICdSZWFsJzpcbiAgICAgIHJldHVybiByZWFkUmVhbChwYXJzZXIsIGNhbGxiYWNrKTtcblxuICAgIGNhc2UgJ0Zsb2F0JzpcbiAgICAgIHJldHVybiByZWFkRmxvYXQocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICBjYXNlICdGbG9hdE4nOlxuICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKGRhdGFMZW5ndGgpID0+IHtcbiAgICAgICAgc3dpdGNoIChkYXRhTGVuZ3RoKSB7XG4gICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuXG4gICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgcmV0dXJuIHJlYWRSZWFsKHBhcnNlciwgY2FsbGJhY2spO1xuICAgICAgICAgIGNhc2UgODpcbiAgICAgICAgICAgIHJldHVybiByZWFkRmxvYXQocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBkYXRhTGVuZ3RoICcgKyBkYXRhTGVuZ3RoICsgJyBmb3IgRmxvYXROJyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgY2FzZSAnU21hbGxNb25leSc6XG4gICAgICByZXR1cm4gcmVhZFNtYWxsTW9uZXkocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICBjYXNlICdNb25leSc6XG4gICAgICByZXR1cm4gcmVhZE1vbmV5KHBhcnNlciwgY2FsbGJhY2spO1xuXG4gICAgY2FzZSAnTW9uZXlOJzpcbiAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQ4KChkYXRhTGVuZ3RoKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoZGF0YUxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKTtcblxuICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgIHJldHVybiByZWFkU21hbGxNb25leShwYXJzZXIsIGNhbGxiYWNrKTtcbiAgICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgICByZXR1cm4gcmVhZE1vbmV5KHBhcnNlciwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgZGF0YUxlbmd0aCAnICsgZGF0YUxlbmd0aCArICcgZm9yIE1vbmV5TicpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIGNhc2UgJ0JpdCc6XG4gICAgICByZXR1cm4gcmVhZEJpdChwYXJzZXIsIGNhbGxiYWNrKTtcblxuICAgIGNhc2UgJ0JpdE4nOlxuICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKGRhdGFMZW5ndGgpID0+IHtcbiAgICAgICAgc3dpdGNoIChkYXRhTGVuZ3RoKSB7XG4gICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuXG4gICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgcmV0dXJuIHJlYWRCaXQocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBkYXRhTGVuZ3RoICcgKyBkYXRhTGVuZ3RoICsgJyBmb3IgQml0TicpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIGNhc2UgJ1ZhckNoYXInOlxuICAgIGNhc2UgJ0NoYXInOlxuICAgICAgY29uc3QgY29kZXBhZ2UgPSBtZXRhZGF0YS5jb2xsYXRpb24hLmNvZGVwYWdlITtcbiAgICAgIGlmIChtZXRhZGF0YS5kYXRhTGVuZ3RoID09PSBNQVgpIHtcbiAgICAgICAgcmV0dXJuIHJlYWRNYXhDaGFycyhwYXJzZXIsIGNvZGVwYWdlLCBjYWxsYmFjayk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gcGFyc2VyLnJlYWRVSW50MTZMRSgoZGF0YUxlbmd0aCkgPT4ge1xuICAgICAgICAgIGlmIChkYXRhTGVuZ3RoID09PSBOVUxMKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmVhZENoYXJzKHBhcnNlciwgZGF0YUxlbmd0aCEsIGNvZGVwYWdlLCBjYWxsYmFjayk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgY2FzZSAnTlZhckNoYXInOlxuICAgIGNhc2UgJ05DaGFyJzpcbiAgICAgIGlmIChtZXRhZGF0YS5kYXRhTGVuZ3RoID09PSBNQVgpIHtcbiAgICAgICAgcmV0dXJuIHJlYWRNYXhOQ2hhcnMocGFyc2VyLCBjYWxsYmFjayk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gcGFyc2VyLnJlYWRVSW50MTZMRSgoZGF0YUxlbmd0aCkgPT4ge1xuICAgICAgICAgIGlmIChkYXRhTGVuZ3RoID09PSBOVUxMKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmVhZE5DaGFycyhwYXJzZXIsIGRhdGFMZW5ndGghLCBjYWxsYmFjayk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgY2FzZSAnVmFyQmluYXJ5JzpcbiAgICBjYXNlICdCaW5hcnknOlxuICAgICAgaWYgKG1ldGFkYXRhLmRhdGFMZW5ndGggPT09IE1BWCkge1xuICAgICAgICByZXR1cm4gcmVhZE1heEJpbmFyeShwYXJzZXIsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQxNkxFKChkYXRhTGVuZ3RoKSA9PiB7XG4gICAgICAgICAgaWYgKGRhdGFMZW5ndGggPT09IE5VTEwpIHtcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZWFkQmluYXJ5KHBhcnNlciwgZGF0YUxlbmd0aCEsIGNhbGxiYWNrKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICBjYXNlICdUZXh0JzpcbiAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQ4KCh0ZXh0UG9pbnRlckxlbmd0aCkgPT4ge1xuICAgICAgICBpZiAodGV4dFBvaW50ZXJMZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG4gICAgICAgIH1cblxuICAgICAgICBwYXJzZXIucmVhZEJ1ZmZlcih0ZXh0UG9pbnRlckxlbmd0aCwgKF90ZXh0UG9pbnRlcikgPT4ge1xuICAgICAgICAgIHBhcnNlci5yZWFkQnVmZmVyKDgsIChfdGltZXN0YW1wKSA9PiB7XG4gICAgICAgICAgICBwYXJzZXIucmVhZFVJbnQzMkxFKChkYXRhTGVuZ3RoKSA9PiB7XG4gICAgICAgICAgICAgIHJlYWRDaGFycyhwYXJzZXIsIGRhdGFMZW5ndGghLCBtZXRhZGF0YS5jb2xsYXRpb24hLmNvZGVwYWdlISwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICBjYXNlICdOVGV4dCc6XG4gICAgICByZXR1cm4gcGFyc2VyLnJlYWRVSW50OCgodGV4dFBvaW50ZXJMZW5ndGgpID0+IHtcbiAgICAgICAgaWYgKHRleHRQb2ludGVyTGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgcGFyc2VyLnJlYWRCdWZmZXIodGV4dFBvaW50ZXJMZW5ndGgsIChfdGV4dFBvaW50ZXIpID0+IHtcbiAgICAgICAgICBwYXJzZXIucmVhZEJ1ZmZlcig4LCAoX3RpbWVzdGFtcCkgPT4ge1xuICAgICAgICAgICAgcGFyc2VyLnJlYWRVSW50MzJMRSgoZGF0YUxlbmd0aCkgPT4ge1xuICAgICAgICAgICAgICByZWFkTkNoYXJzKHBhcnNlciwgZGF0YUxlbmd0aCEsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgY2FzZSAnSW1hZ2UnOlxuICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKHRleHRQb2ludGVyTGVuZ3RoKSA9PiB7XG4gICAgICAgIGlmICh0ZXh0UG9pbnRlckxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHBhcnNlci5yZWFkQnVmZmVyKHRleHRQb2ludGVyTGVuZ3RoLCAoX3RleHRQb2ludGVyKSA9PiB7XG4gICAgICAgICAgcGFyc2VyLnJlYWRCdWZmZXIoOCwgKF90aW1lc3RhbXApID0+IHtcbiAgICAgICAgICAgIHBhcnNlci5yZWFkVUludDMyTEUoKGRhdGFMZW5ndGgpID0+IHtcbiAgICAgICAgICAgICAgcmVhZEJpbmFyeShwYXJzZXIsIGRhdGFMZW5ndGghLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgIGNhc2UgJ1htbCc6XG4gICAgICByZXR1cm4gcmVhZE1heE5DaGFycyhwYXJzZXIsIGNhbGxiYWNrKTtcblxuICAgIGNhc2UgJ1NtYWxsRGF0ZVRpbWUnOlxuICAgICAgcmV0dXJuIHJlYWRTbWFsbERhdGVUaW1lKHBhcnNlciwgb3B0aW9ucy51c2VVVEMsIGNhbGxiYWNrKTtcblxuICAgIGNhc2UgJ0RhdGVUaW1lJzpcbiAgICAgIHJldHVybiByZWFkRGF0ZVRpbWUocGFyc2VyLCBvcHRpb25zLnVzZVVUQywgY2FsbGJhY2spO1xuXG4gICAgY2FzZSAnRGF0ZVRpbWVOJzpcbiAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQ4KChkYXRhTGVuZ3RoKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoZGF0YUxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKTtcblxuICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgIHJldHVybiByZWFkU21hbGxEYXRlVGltZShwYXJzZXIsIG9wdGlvbnMudXNlVVRDLCBjYWxsYmFjayk7XG4gICAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgcmV0dXJuIHJlYWREYXRlVGltZShwYXJzZXIsIG9wdGlvbnMudXNlVVRDLCBjYWxsYmFjayk7XG5cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBkYXRhTGVuZ3RoICcgKyBkYXRhTGVuZ3RoICsgJyBmb3IgRGF0ZVRpbWVOJyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgY2FzZSAnVGltZSc6XG4gICAgICByZXR1cm4gcGFyc2VyLnJlYWRVSW50OCgoZGF0YUxlbmd0aCkgPT4ge1xuICAgICAgICBpZiAoZGF0YUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gcmVhZFRpbWUocGFyc2VyLCBkYXRhTGVuZ3RoISwgbWV0YWRhdGEuc2NhbGUhLCBvcHRpb25zLnVzZVVUQywgY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKGRhdGFMZW5ndGgpID0+IHtcbiAgICAgICAgaWYgKGRhdGFMZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHJlYWREYXRlKHBhcnNlciwgb3B0aW9ucy51c2VVVEMsIGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBjYXNlICdEYXRlVGltZTInOlxuICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKGRhdGFMZW5ndGgpID0+IHtcbiAgICAgICAgaWYgKGRhdGFMZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHJlYWREYXRlVGltZTIocGFyc2VyLCBkYXRhTGVuZ3RoISwgbWV0YWRhdGEuc2NhbGUhLCBvcHRpb25zLnVzZVVUQywgY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIGNhc2UgJ0RhdGVUaW1lT2Zmc2V0JzpcbiAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQ4KChkYXRhTGVuZ3RoKSA9PiB7XG4gICAgICAgIGlmIChkYXRhTGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiByZWFkRGF0ZVRpbWVPZmZzZXQocGFyc2VyLCBkYXRhTGVuZ3RoISwgbWV0YWRhdGEuc2NhbGUhLCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgY2FzZSAnTnVtZXJpY04nOlxuICAgIGNhc2UgJ0RlY2ltYWxOJzpcbiAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQ4KChkYXRhTGVuZ3RoKSA9PiB7XG4gICAgICAgIGlmIChkYXRhTGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiByZWFkTnVtZXJpYyhwYXJzZXIsIGRhdGFMZW5ndGghLCBtZXRhZGF0YS5wcmVjaXNpb24hLCBtZXRhZGF0YS5zY2FsZSEsIGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBjYXNlICdVbmlxdWVJZGVudGlmaWVyJzpcbiAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQ4KChkYXRhTGVuZ3RoKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoZGF0YUxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKTtcblxuICAgICAgICAgIGNhc2UgMHgxMDpcbiAgICAgICAgICAgIHJldHVybiByZWFkVW5pcXVlSWRlbnRpZmllcihwYXJzZXIsIG9wdGlvbnMsIGNhbGxiYWNrKTtcblxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3Ioc3ByaW50ZignVW5zdXBwb3J0ZWQgZ3VpZCBzaXplICVkJywgZGF0YUxlbmd0aCEgLSAxKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgY2FzZSAnVURUJzpcbiAgICAgIHJldHVybiByZWFkTWF4QmluYXJ5KHBhcnNlciwgY2FsbGJhY2spO1xuXG4gICAgY2FzZSAnVmFyaWFudCc6XG4gICAgICByZXR1cm4gcGFyc2VyLnJlYWRVSW50MzJMRSgoZGF0YUxlbmd0aCkgPT4ge1xuICAgICAgICBpZiAoZGF0YUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlYWRWYXJpYW50KHBhcnNlciwgb3B0aW9ucywgZGF0YUxlbmd0aCEsIGNhbGxiYWNrKTtcbiAgICAgIH0pO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihzcHJpbnRmKCdVbnJlY29nbmlzZWQgdHlwZSAlcycsIHR5cGUubmFtZSkpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlYWRVbmlxdWVJZGVudGlmaWVyKHBhcnNlcjogUGFyc2VyLCBvcHRpb25zOiBQYXJzZXJPcHRpb25zLCBjYWxsYmFjazogKHZhbHVlOiB1bmtub3duKSA9PiB2b2lkKSB7XG4gIHBhcnNlci5yZWFkQnVmZmVyKDB4MTAsIChkYXRhKSA9PiB7XG4gICAgY2FsbGJhY2sob3B0aW9ucy5sb3dlckNhc2VHdWlkcyA/IGJ1ZmZlclRvTG93ZXJDYXNlR3VpZChkYXRhKSA6IGJ1ZmZlclRvVXBwZXJDYXNlR3VpZChkYXRhKSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZWFkTnVtZXJpYyhwYXJzZXI6IFBhcnNlciwgZGF0YUxlbmd0aDogbnVtYmVyLCBfcHJlY2lzaW9uOiBudW1iZXIsIHNjYWxlOiBudW1iZXIsIGNhbGxiYWNrOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQpIHtcbiAgcGFyc2VyLnJlYWRVSW50OCgoc2lnbikgPT4ge1xuICAgIHNpZ24gPSBzaWduID09PSAxID8gMSA6IC0xO1xuXG4gICAgbGV0IHJlYWRWYWx1ZTtcbiAgICBpZiAoZGF0YUxlbmd0aCA9PT0gNSkge1xuICAgICAgcmVhZFZhbHVlID0gcGFyc2VyLnJlYWRVSW50MzJMRTtcbiAgICB9IGVsc2UgaWYgKGRhdGFMZW5ndGggPT09IDkpIHtcbiAgICAgIHJlYWRWYWx1ZSA9IHBhcnNlci5yZWFkVU51bWVyaWM2NExFO1xuICAgIH0gZWxzZSBpZiAoZGF0YUxlbmd0aCA9PT0gMTMpIHtcbiAgICAgIHJlYWRWYWx1ZSA9IHBhcnNlci5yZWFkVU51bWVyaWM5NkxFO1xuICAgIH0gZWxzZSBpZiAoZGF0YUxlbmd0aCA9PT0gMTcpIHtcbiAgICAgIHJlYWRWYWx1ZSA9IHBhcnNlci5yZWFkVU51bWVyaWMxMjhMRTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKHNwcmludGYoJ1Vuc3VwcG9ydGVkIG51bWVyaWMgZGF0YUxlbmd0aCAlZCcsIGRhdGFMZW5ndGgpKTtcbiAgICB9XG5cbiAgICByZWFkVmFsdWUuY2FsbChwYXJzZXIsICh2YWx1ZSkgPT4ge1xuICAgICAgY2FsbGJhY2soKHZhbHVlICogc2lnbikgLyBNYXRoLnBvdygxMCwgc2NhbGUpKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRWYXJpYW50KHBhcnNlcjogUGFyc2VyLCBvcHRpb25zOiBQYXJzZXJPcHRpb25zLCBkYXRhTGVuZ3RoOiBudW1iZXIsIGNhbGxiYWNrOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQpIHtcbiAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKGJhc2VUeXBlKSA9PiB7XG4gICAgY29uc3QgdHlwZSA9IFRZUEVbYmFzZVR5cGVdO1xuXG4gICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKHByb3BCeXRlcykgPT4ge1xuICAgICAgZGF0YUxlbmd0aCA9IGRhdGFMZW5ndGggLSBwcm9wQnl0ZXMgLSAyO1xuXG4gICAgICBzd2l0Y2ggKHR5cGUubmFtZSkge1xuICAgICAgICBjYXNlICdVbmlxdWVJZGVudGlmaWVyJzpcbiAgICAgICAgICByZXR1cm4gcmVhZFVuaXF1ZUlkZW50aWZpZXIocGFyc2VyLCBvcHRpb25zLCBjYWxsYmFjayk7XG5cbiAgICAgICAgY2FzZSAnQml0JzpcbiAgICAgICAgICByZXR1cm4gcmVhZEJpdChwYXJzZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICBjYXNlICdUaW55SW50JzpcbiAgICAgICAgICByZXR1cm4gcmVhZFRpbnlJbnQocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgY2FzZSAnU21hbGxJbnQnOlxuICAgICAgICAgIHJldHVybiByZWFkU21hbGxJbnQocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgY2FzZSAnSW50JzpcbiAgICAgICAgICByZXR1cm4gcmVhZEludChwYXJzZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICBjYXNlICdCaWdJbnQnOlxuICAgICAgICAgIHJldHVybiByZWFkQmlnSW50KHBhcnNlciwgY2FsbGJhY2spO1xuXG4gICAgICAgIGNhc2UgJ1NtYWxsRGF0ZVRpbWUnOlxuICAgICAgICAgIHJldHVybiByZWFkU21hbGxEYXRlVGltZShwYXJzZXIsIG9wdGlvbnMudXNlVVRDLCBjYWxsYmFjayk7XG5cbiAgICAgICAgY2FzZSAnRGF0ZVRpbWUnOlxuICAgICAgICAgIHJldHVybiByZWFkRGF0ZVRpbWUocGFyc2VyLCBvcHRpb25zLnVzZVVUQywgY2FsbGJhY2spO1xuXG4gICAgICAgIGNhc2UgJ1JlYWwnOlxuICAgICAgICAgIHJldHVybiByZWFkUmVhbChwYXJzZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICBjYXNlICdGbG9hdCc6XG4gICAgICAgICAgcmV0dXJuIHJlYWRGbG9hdChwYXJzZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICBjYXNlICdTbWFsbE1vbmV5JzpcbiAgICAgICAgICByZXR1cm4gcmVhZFNtYWxsTW9uZXkocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgY2FzZSAnTW9uZXknOlxuICAgICAgICAgIHJldHVybiByZWFkTW9uZXkocGFyc2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgY2FzZSAnRGF0ZSc6XG4gICAgICAgICAgcmV0dXJuIHJlYWREYXRlKHBhcnNlciwgb3B0aW9ucy51c2VVVEMsIGNhbGxiYWNrKTtcblxuICAgICAgICBjYXNlICdUaW1lJzpcbiAgICAgICAgICByZXR1cm4gcGFyc2VyLnJlYWRVSW50OCgoc2NhbGUpID0+IHtcbiAgICAgICAgICAgIHJldHVybiByZWFkVGltZShwYXJzZXIsIGRhdGFMZW5ndGgsIHNjYWxlLCBvcHRpb25zLnVzZVVUQywgY2FsbGJhY2spO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIGNhc2UgJ0RhdGVUaW1lMic6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKHNjYWxlKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcmVhZERhdGVUaW1lMihwYXJzZXIsIGRhdGFMZW5ndGgsIHNjYWxlLCBvcHRpb25zLnVzZVVUQywgY2FsbGJhY2spO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIGNhc2UgJ0RhdGVUaW1lT2Zmc2V0JzpcbiAgICAgICAgICByZXR1cm4gcGFyc2VyLnJlYWRVSW50OCgoc2NhbGUpID0+IHtcbiAgICAgICAgICAgIHJldHVybiByZWFkRGF0ZVRpbWVPZmZzZXQocGFyc2VyLCBkYXRhTGVuZ3RoLCBzY2FsZSwgY2FsbGJhY2spO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIGNhc2UgJ1ZhckJpbmFyeSc6XG4gICAgICAgIGNhc2UgJ0JpbmFyeSc6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDE2TEUoKF9tYXhMZW5ndGgpID0+IHtcbiAgICAgICAgICAgIHJlYWRCaW5hcnkocGFyc2VyLCBkYXRhTGVuZ3RoLCBjYWxsYmFjayk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgY2FzZSAnTnVtZXJpY04nOlxuICAgICAgICBjYXNlICdEZWNpbWFsTic6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDgoKHByZWNpc2lvbikgPT4ge1xuICAgICAgICAgICAgcGFyc2VyLnJlYWRVSW50OCgoc2NhbGUpID0+IHtcbiAgICAgICAgICAgICAgcmVhZE51bWVyaWMocGFyc2VyLCBkYXRhTGVuZ3RoLCBwcmVjaXNpb24sIHNjYWxlLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICBjYXNlICdWYXJDaGFyJzpcbiAgICAgICAgY2FzZSAnQ2hhcic6XG4gICAgICAgICAgcmV0dXJuIHBhcnNlci5yZWFkVUludDE2TEUoKF9tYXhMZW5ndGgpID0+IHtcbiAgICAgICAgICAgIHJlYWRDb2xsYXRpb24ocGFyc2VyLCAoY29sbGF0aW9uKSA9PiB7XG4gICAgICAgICAgICAgIHJlYWRDaGFycyhwYXJzZXIsIGRhdGFMZW5ndGgsIGNvbGxhdGlvbi5jb2RlcGFnZSEsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIGNhc2UgJ05WYXJDaGFyJzpcbiAgICAgICAgY2FzZSAnTkNoYXInOlxuICAgICAgICAgIHJldHVybiBwYXJzZXIucmVhZFVJbnQxNkxFKChfbWF4TGVuZ3RoKSA9PiB7XG4gICAgICAgICAgICByZWFkQ29sbGF0aW9uKHBhcnNlciwgKF9jb2xsYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgcmVhZE5DaGFycyhwYXJzZXIsIGRhdGFMZW5ndGgsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHR5cGUhJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZWFkQmluYXJ5KHBhcnNlcjogUGFyc2VyLCBkYXRhTGVuZ3RoOiBudW1iZXIsIGNhbGxiYWNrOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQpIHtcbiAgcmV0dXJuIHBhcnNlci5yZWFkQnVmZmVyKGRhdGFMZW5ndGgsIGNhbGxiYWNrKTtcbn1cblxuZnVuY3Rpb24gcmVhZENoYXJzKHBhcnNlcjogUGFyc2VyLCBkYXRhTGVuZ3RoOiBudW1iZXIsIGNvZGVwYWdlOiBzdHJpbmcsIGNhbGxiYWNrOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQpIHtcbiAgaWYgKGNvZGVwYWdlID09IG51bGwpIHtcbiAgICBjb2RlcGFnZSA9IERFRkFVTFRfRU5DT0RJTkc7XG4gIH1cblxuICByZXR1cm4gcGFyc2VyLnJlYWRCdWZmZXIoZGF0YUxlbmd0aCwgKGRhdGEpID0+IHtcbiAgICBjYWxsYmFjayhpY29udi5kZWNvZGUoZGF0YSwgY29kZXBhZ2UpKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlYWROQ2hhcnMocGFyc2VyOiBQYXJzZXIsIGRhdGFMZW5ndGg6IG51bWJlciwgY2FsbGJhY2s6ICh2YWx1ZTogdW5rbm93bikgPT4gdm9pZCkge1xuICBwYXJzZXIucmVhZEJ1ZmZlcihkYXRhTGVuZ3RoLCAoZGF0YSkgPT4ge1xuICAgIGNhbGxiYWNrKGRhdGEudG9TdHJpbmcoJ3VjczInKSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZWFkTWF4QmluYXJ5KHBhcnNlcjogUGFyc2VyLCBjYWxsYmFjazogKHZhbHVlOiB1bmtub3duKSA9PiB2b2lkKSB7XG4gIHJldHVybiByZWFkTWF4KHBhcnNlciwgY2FsbGJhY2spO1xufVxuXG5mdW5jdGlvbiByZWFkTWF4Q2hhcnMocGFyc2VyOiBQYXJzZXIsIGNvZGVwYWdlOiBzdHJpbmcsIGNhbGxiYWNrOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQpIHtcbiAgaWYgKGNvZGVwYWdlID09IG51bGwpIHtcbiAgICBjb2RlcGFnZSA9IERFRkFVTFRfRU5DT0RJTkc7XG4gIH1cblxuICByZWFkTWF4KHBhcnNlciwgKGRhdGEpID0+IHtcbiAgICBpZiAoZGF0YSkge1xuICAgICAgY2FsbGJhY2soaWNvbnYuZGVjb2RlKGRhdGEsIGNvZGVwYWdlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKG51bGwpO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRNYXhOQ2hhcnMocGFyc2VyOiBQYXJzZXIsIGNhbGxiYWNrOiAodmFsdWU6IHN0cmluZyB8IG51bGwpID0+IHZvaWQpIHtcbiAgcmVhZE1heChwYXJzZXIsIChkYXRhKSA9PiB7XG4gICAgaWYgKGRhdGEpIHtcbiAgICAgIGNhbGxiYWNrKGRhdGEudG9TdHJpbmcoJ3VjczInKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKG51bGwpO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRNYXgocGFyc2VyOiBQYXJzZXIsIGNhbGxiYWNrOiAodmFsdWU6IG51bGwgfCBCdWZmZXIpID0+IHZvaWQpIHtcbiAgcGFyc2VyLnJlYWRCdWZmZXIoOCwgKHR5cGUpID0+IHtcbiAgICBpZiAodHlwZS5lcXVhbHMoUExQX05VTEwpKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG4gICAgfSBlbHNlIGlmICh0eXBlLmVxdWFscyhVTktOT1dOX1BMUF9MRU4pKSB7XG4gICAgICByZXR1cm4gcmVhZE1heFVua25vd25MZW5ndGgocGFyc2VyLCBjYWxsYmFjayk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGxvdyA9IHR5cGUucmVhZFVJbnQzMkxFKDApO1xuICAgICAgY29uc3QgaGlnaCA9IHR5cGUucmVhZFVJbnQzMkxFKDQpO1xuXG4gICAgICBpZiAoaGlnaCA+PSAoMiA8PCAoNTMgLSAzMikpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignUmVhZCBVSW50NjRMRSA+IDUzIGJpdHMgOiBoaWdoPScgKyBoaWdoICsgJywgbG93PScgKyBsb3cpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBleHBlY3RlZExlbmd0aCA9IGxvdyArICgweDEwMDAwMDAwMCAqIGhpZ2gpO1xuICAgICAgcmV0dXJuIHJlYWRNYXhLbm93bkxlbmd0aChwYXJzZXIsIGV4cGVjdGVkTGVuZ3RoLCBjYWxsYmFjayk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gcmVhZE1heEtub3duTGVuZ3RoKHBhcnNlcjogUGFyc2VyLCB0b3RhbExlbmd0aDogbnVtYmVyLCBjYWxsYmFjazogKHZhbHVlOiBudWxsIHwgQnVmZmVyKSA9PiB2b2lkKSB7XG4gIGNvbnN0IGRhdGEgPSBCdWZmZXIuYWxsb2ModG90YWxMZW5ndGgsIDApO1xuXG4gIGxldCBvZmZzZXQgPSAwO1xuICBmdW5jdGlvbiBuZXh0KGRvbmU6IGFueSkge1xuICAgIHBhcnNlci5yZWFkVUludDMyTEUoKGNodW5rTGVuZ3RoKSA9PiB7XG4gICAgICBpZiAoIWNodW5rTGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBkb25lKCk7XG4gICAgICB9XG5cbiAgICAgIHBhcnNlci5yZWFkQnVmZmVyKGNodW5rTGVuZ3RoLCAoY2h1bmspID0+IHtcbiAgICAgICAgY2h1bmsuY29weShkYXRhLCBvZmZzZXQpO1xuICAgICAgICBvZmZzZXQgKz0gY2h1bmtMZW5ndGg7XG5cbiAgICAgICAgbmV4dChkb25lKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgbmV4dCgoKSA9PiB7XG4gICAgaWYgKG9mZnNldCAhPT0gdG90YWxMZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUGFydGlhbGx5IExlbmd0aC1wcmVmaXhlZCBCeXRlcyB1bm1hdGNoZWQgbGVuZ3RocyA6IGV4cGVjdGVkICcgKyB0b3RhbExlbmd0aCArICcsIGJ1dCBnb3QgJyArIG9mZnNldCArICcgYnl0ZXMnKTtcbiAgICB9XG5cbiAgICBjYWxsYmFjayhkYXRhKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRNYXhVbmtub3duTGVuZ3RoKHBhcnNlcjogUGFyc2VyLCBjYWxsYmFjazogKHZhbHVlOiBudWxsIHwgQnVmZmVyKSA9PiB2b2lkKSB7XG4gIGNvbnN0IGNodW5rczogQnVmZmVyW10gPSBbXTtcblxuICBsZXQgbGVuZ3RoID0gMDtcbiAgZnVuY3Rpb24gbmV4dChkb25lOiBhbnkpIHtcbiAgICBwYXJzZXIucmVhZFVJbnQzMkxFKChjaHVua0xlbmd0aCkgPT4ge1xuICAgICAgaWYgKCFjaHVua0xlbmd0aCkge1xuICAgICAgICByZXR1cm4gZG9uZSgpO1xuICAgICAgfVxuXG4gICAgICBwYXJzZXIucmVhZEJ1ZmZlcihjaHVua0xlbmd0aCwgKGNodW5rKSA9PiB7XG4gICAgICAgIGNodW5rcy5wdXNoKGNodW5rKTtcbiAgICAgICAgbGVuZ3RoICs9IGNodW5rTGVuZ3RoO1xuXG4gICAgICAgIG5leHQoZG9uZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIG5leHQoKCkgPT4ge1xuICAgIGNhbGxiYWNrKEJ1ZmZlci5jb25jYXQoY2h1bmtzLCBsZW5ndGgpKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRTbWFsbERhdGVUaW1lKHBhcnNlcjogUGFyc2VyLCB1c2VVVEM6IGJvb2xlYW4sIGNhbGxiYWNrOiAodmFsdWU6IERhdGUpID0+IHZvaWQpIHtcbiAgcGFyc2VyLnJlYWRVSW50MTZMRSgoZGF5cykgPT4ge1xuICAgIHBhcnNlci5yZWFkVUludDE2TEUoKG1pbnV0ZXMpID0+IHtcbiAgICAgIGxldCB2YWx1ZTtcbiAgICAgIGlmICh1c2VVVEMpIHtcbiAgICAgICAgdmFsdWUgPSBuZXcgRGF0ZShEYXRlLlVUQygxOTAwLCAwLCAxICsgZGF5cywgMCwgbWludXRlcykpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWUgPSBuZXcgRGF0ZSgxOTAwLCAwLCAxICsgZGF5cywgMCwgbWludXRlcyk7XG4gICAgICB9XG4gICAgICBjYWxsYmFjayh2YWx1ZSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZWFkRGF0ZVRpbWUocGFyc2VyOiBQYXJzZXIsIHVzZVVUQzogYm9vbGVhbiwgY2FsbGJhY2s6ICh2YWx1ZTogRGF0ZSkgPT4gdm9pZCkge1xuICBwYXJzZXIucmVhZEludDMyTEUoKGRheXMpID0+IHtcbiAgICBwYXJzZXIucmVhZFVJbnQzMkxFKCh0aHJlZUh1bmRyZWR0aHNPZlNlY29uZCkgPT4ge1xuICAgICAgY29uc3QgbWlsbGlzZWNvbmRzID0gTWF0aC5yb3VuZCh0aHJlZUh1bmRyZWR0aHNPZlNlY29uZCAqIFRIUkVFX0FORF9BX1RISVJEKTtcblxuICAgICAgbGV0IHZhbHVlO1xuICAgICAgaWYgKHVzZVVUQykge1xuICAgICAgICB2YWx1ZSA9IG5ldyBEYXRlKERhdGUuVVRDKDE5MDAsIDAsIDEgKyBkYXlzLCAwLCAwLCAwLCBtaWxsaXNlY29uZHMpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbHVlID0gbmV3IERhdGUoMTkwMCwgMCwgMSArIGRheXMsIDAsIDAsIDAsIG1pbGxpc2Vjb25kcyk7XG4gICAgICB9XG5cbiAgICAgIGNhbGxiYWNrKHZhbHVlKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmludGVyZmFjZSBEYXRlV2l0aE5hbm9zZWNvbmRzRGVsdGEgZXh0ZW5kcyBEYXRlIHtcbiAgbmFub3NlY29uZHNEZWx0YTogbnVtYmVyO1xufVxuXG5mdW5jdGlvbiByZWFkVGltZShwYXJzZXI6IFBhcnNlciwgZGF0YUxlbmd0aDogbnVtYmVyLCBzY2FsZTogbnVtYmVyLCB1c2VVVEM6IGJvb2xlYW4sIGNhbGxiYWNrOiAodmFsdWU6IERhdGVXaXRoTmFub3NlY29uZHNEZWx0YSkgPT4gdm9pZCkge1xuICBsZXQgcmVhZFZhbHVlOiBhbnk7XG4gIHN3aXRjaCAoZGF0YUxlbmd0aCkge1xuICAgIGNhc2UgMzpcbiAgICAgIHJlYWRWYWx1ZSA9IHBhcnNlci5yZWFkVUludDI0TEU7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDQ6XG4gICAgICByZWFkVmFsdWUgPSBwYXJzZXIucmVhZFVJbnQzMkxFO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA1OlxuICAgICAgcmVhZFZhbHVlID0gcGFyc2VyLnJlYWRVSW50NDBMRTtcbiAgfVxuXG4gIHJlYWRWYWx1ZSEuY2FsbChwYXJzZXIsICh2YWx1ZTogbnVtYmVyKSA9PiB7XG4gICAgaWYgKHNjYWxlIDwgNykge1xuICAgICAgZm9yIChsZXQgaSA9IHNjYWxlOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgIHZhbHVlICo9IDEwO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBkYXRlO1xuICAgIGlmICh1c2VVVEMpIHtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQygxOTcwLCAwLCAxLCAwLCAwLCAwLCB2YWx1ZSAvIDEwMDAwKSkgYXMgRGF0ZVdpdGhOYW5vc2Vjb25kc0RlbHRhO1xuICAgIH0gZWxzZSB7XG4gICAgICBkYXRlID0gbmV3IERhdGUoMTk3MCwgMCwgMSwgMCwgMCwgMCwgdmFsdWUgLyAxMDAwMCkgYXMgRGF0ZVdpdGhOYW5vc2Vjb25kc0RlbHRhO1xuICAgIH1cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZGF0ZSwgJ25hbm9zZWNvbmRzRGVsdGEnLCB7XG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgIHZhbHVlOiAodmFsdWUgJSAxMDAwMCkgLyBNYXRoLnBvdygxMCwgNylcbiAgICB9KTtcbiAgICBjYWxsYmFjayhkYXRlKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlYWREYXRlKHBhcnNlcjogUGFyc2VyLCB1c2VVVEM6IGJvb2xlYW4sIGNhbGxiYWNrOiAodmFsdWU6IERhdGUpID0+IHZvaWQpIHtcbiAgcGFyc2VyLnJlYWRVSW50MjRMRSgoZGF5cykgPT4ge1xuICAgIGlmICh1c2VVVEMpIHtcbiAgICAgIGNhbGxiYWNrKG5ldyBEYXRlKERhdGUuVVRDKDIwMDAsIDAsIGRheXMgLSA3MzAxMTgpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKG5ldyBEYXRlKDIwMDAsIDAsIGRheXMgLSA3MzAxMTgpKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZWFkRGF0ZVRpbWUyKHBhcnNlcjogUGFyc2VyLCBkYXRhTGVuZ3RoOiBudW1iZXIsIHNjYWxlOiBudW1iZXIsIHVzZVVUQzogYm9vbGVhbiwgY2FsbGJhY2s6ICh2YWx1ZTogRGF0ZVdpdGhOYW5vc2Vjb25kc0RlbHRhKSA9PiB2b2lkKSB7XG4gIHJlYWRUaW1lKHBhcnNlciwgZGF0YUxlbmd0aCAtIDMsIHNjYWxlLCB1c2VVVEMsICh0aW1lKSA9PiB7IC8vIFRPRE86ICdpbnB1dCcgaXMgJ3RpbWUnLCBidXQgVHlwZVNjcmlwdCBjYW5ub3QgZmluZCBcInRpbWUubmFub3NlY29uZHNEZWx0YVwiO1xuICAgIHBhcnNlci5yZWFkVUludDI0TEUoKGRheXMpID0+IHtcbiAgICAgIGxldCBkYXRlO1xuICAgICAgaWYgKHVzZVVUQykge1xuICAgICAgICBkYXRlID0gbmV3IERhdGUoRGF0ZS5VVEMoMjAwMCwgMCwgZGF5cyAtIDczMDExOCwgMCwgMCwgMCwgK3RpbWUpKSBhcyBEYXRlV2l0aE5hbm9zZWNvbmRzRGVsdGE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkYXRlID0gbmV3IERhdGUoMjAwMCwgMCwgZGF5cyAtIDczMDExOCwgdGltZS5nZXRIb3VycygpLCB0aW1lLmdldE1pbnV0ZXMoKSwgdGltZS5nZXRTZWNvbmRzKCksIHRpbWUuZ2V0TWlsbGlzZWNvbmRzKCkpIGFzIERhdGVXaXRoTmFub3NlY29uZHNEZWx0YTtcbiAgICAgIH1cbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYXRlLCAnbmFub3NlY29uZHNEZWx0YScsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHZhbHVlOiB0aW1lLm5hbm9zZWNvbmRzRGVsdGFcbiAgICAgIH0pO1xuICAgICAgY2FsbGJhY2soZGF0ZSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZWFkRGF0ZVRpbWVPZmZzZXQocGFyc2VyOiBQYXJzZXIsIGRhdGFMZW5ndGg6IG51bWJlciwgc2NhbGU6IG51bWJlciwgY2FsbGJhY2s6ICh2YWx1ZTogRGF0ZVdpdGhOYW5vc2Vjb25kc0RlbHRhKSA9PiB2b2lkKSB7XG4gIHJlYWRUaW1lKHBhcnNlciwgZGF0YUxlbmd0aCAtIDUsIHNjYWxlLCB0cnVlLCAodGltZSkgPT4ge1xuICAgIHBhcnNlci5yZWFkVUludDI0TEUoKGRheXMpID0+IHtcbiAgICAgIC8vIG9mZnNldFxuICAgICAgcGFyc2VyLnJlYWRJbnQxNkxFKCgpID0+IHtcbiAgICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKDIwMDAsIDAsIGRheXMgLSA3MzAxMTgsIDAsIDAsIDAsICt0aW1lKSkgYXMgRGF0ZVdpdGhOYW5vc2Vjb25kc0RlbHRhO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZGF0ZSwgJ25hbm9zZWNvbmRzRGVsdGEnLCB7XG4gICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgdmFsdWU6IHRpbWUubmFub3NlY29uZHNEZWx0YVxuICAgICAgICB9KTtcbiAgICAgICAgY2FsbGJhY2soZGF0ZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHZhbHVlUGFyc2U7XG5tb2R1bGUuZXhwb3J0cyA9IHZhbHVlUGFyc2U7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQTs7QUFDQTs7QUFFQTs7QUFDQTs7QUFDQTs7OztBQUVBLE1BQU1BLElBQUksR0FBRyxDQUFDLEtBQUssRUFBTixJQUFZLENBQXpCO0FBQ0EsTUFBTUMsR0FBRyxHQUFHLENBQUMsS0FBSyxFQUFOLElBQVksQ0FBeEI7QUFDQSxNQUFNQyxpQkFBaUIsR0FBRyxJQUFLLElBQUksQ0FBbkM7QUFDQSxNQUFNQyxhQUFhLEdBQUcsS0FBdEI7QUFDQSxNQUFNQyxRQUFRLEdBQUdDLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZLENBQUMsSUFBRCxFQUFPLElBQVAsRUFBYSxJQUFiLEVBQW1CLElBQW5CLEVBQXlCLElBQXpCLEVBQStCLElBQS9CLEVBQXFDLElBQXJDLEVBQTJDLElBQTNDLENBQVosQ0FBakI7QUFDQSxNQUFNQyxlQUFlLEdBQUdGLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZLENBQUMsSUFBRCxFQUFPLElBQVAsRUFBYSxJQUFiLEVBQW1CLElBQW5CLEVBQXlCLElBQXpCLEVBQStCLElBQS9CLEVBQXFDLElBQXJDLEVBQTJDLElBQTNDLENBQVosQ0FBeEI7QUFDQSxNQUFNRSxnQkFBZ0IsR0FBRyxNQUF6Qjs7QUFFQSxTQUFTQyxXQUFULENBQXFCQyxNQUFyQixFQUFxQ0MsUUFBckMsRUFBeUU7RUFDdkVELE1BQU0sQ0FBQ0UsU0FBUCxDQUFpQkQsUUFBakI7QUFDRDs7QUFFRCxTQUFTRSxZQUFULENBQXNCSCxNQUF0QixFQUFzQ0MsUUFBdEMsRUFBMEU7RUFDeEVELE1BQU0sQ0FBQ0ksV0FBUCxDQUFtQkgsUUFBbkI7QUFDRDs7QUFFRCxTQUFTSSxPQUFULENBQWlCTCxNQUFqQixFQUFpQ0MsUUFBakMsRUFBcUU7RUFDbkVELE1BQU0sQ0FBQ00sV0FBUCxDQUFtQkwsUUFBbkI7QUFDRDs7QUFFRCxTQUFTTSxVQUFULENBQW9CUCxNQUFwQixFQUFvQ0MsUUFBcEMsRUFBd0U7RUFDdEVELE1BQU0sQ0FBQ1EsY0FBUCxDQUF1QkMsS0FBRCxJQUFXO0lBQy9CUixRQUFRLENBQUNRLEtBQUssQ0FBQ0MsUUFBTixFQUFELENBQVI7RUFDRCxDQUZEO0FBR0Q7O0FBRUQsU0FBU0MsUUFBVCxDQUFrQlgsTUFBbEIsRUFBa0NDLFFBQWxDLEVBQXNFO0VBQ3BFRCxNQUFNLENBQUNZLFdBQVAsQ0FBbUJYLFFBQW5CO0FBQ0Q7O0FBRUQsU0FBU1ksU0FBVCxDQUFtQmIsTUFBbkIsRUFBbUNDLFFBQW5DLEVBQXVFO0VBQ3JFRCxNQUFNLENBQUNjLFlBQVAsQ0FBb0JiLFFBQXBCO0FBQ0Q7