socket-ipc
Version:
Message-based communications over UNIX sockets
117 lines (88 loc) • 13.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const PREAMBLE = 35; // '#' character
const LENGTH_LEN = 4; // Length of the length? WTF?
const HEADER_LEN = 1 + LENGTH_LEN; // 1 preamble byte + 4 length bytes
var DecodeState;
(function (DecodeState) {
DecodeState[DecodeState["Initial"] = 0] = "Initial";
DecodeState[DecodeState["ReadLength"] = 1] = "ReadLength";
DecodeState[DecodeState["ReadData"] = 2] = "ReadData";
})(DecodeState || (DecodeState = {}));
class MessageCodec {
constructor(options) {
_defineProperty(this, "binary", void 0);
_defineProperty(this, "decodeState", DecodeState.Initial);
_defineProperty(this, "lengthBuf", Buffer.alloc(LENGTH_LEN));
_defineProperty(this, "lengthBufPos", 0);
_defineProperty(this, "decodeBuf", void 0);
_defineProperty(this, "decodeBufPos", 0);
this.binary = Boolean(options.binary);
}
encode(data) {
const buffer = typeof data === 'string' ? Buffer.from(data) : data;
const encoded = Buffer.alloc(buffer.length + HEADER_LEN);
let pos = 0;
encoded.writeUInt8(PREAMBLE, pos++);
encoded.writeUInt32BE(buffer.length, pos);
pos += LENGTH_LEN;
buffer.copy(encoded, pos, 0, buffer.length);
return encoded;
}
decode(srcBuffer, onMessage) {
const messageComplete = buffer => onMessage(this.binary ? buffer : buffer.toString());
let srcPos = 0;
while (srcPos < srcBuffer.length) {
const srcRemain = srcBuffer.length - srcPos;
let bytesRead = 0;
switch (this.decodeState) {
case DecodeState.Initial:
const preamble = srcBuffer.readUInt8(srcPos);
bytesRead = 1;
if (PREAMBLE !== preamble) throw Error(`preamble did not match: expected ${PREAMBLE}, was ${preamble}`);
this.decodeState = DecodeState.ReadLength;
break;
case DecodeState.ReadLength:
bytesRead = Math.min(srcRemain, LENGTH_LEN - this.lengthBufPos);
srcBuffer.copy(this.lengthBuf, this.lengthBufPos, srcPos, srcPos + bytesRead);
this.lengthBufPos += bytesRead;
if (this.lengthBufPos >= LENGTH_LEN) {
const messageLength = this.lengthBuf.readUInt32BE(0);
if (messageLength) {
this.decodeBuf = Buffer.alloc(messageLength);
this.decodeBufPos = 0;
this.decodeState = DecodeState.ReadData;
} else {
// Empty message...
messageComplete(Buffer.alloc(0));
this.decodeState = DecodeState.Initial;
}
this.lengthBufPos = 0;
}
break;
case DecodeState.ReadData:
{
const decodeBuf = this.decodeBuf;
if (!decodeBuf) throw Error('unexpected missing decodeBuf');
bytesRead = Math.min(srcRemain, decodeBuf.length - this.decodeBufPos);
srcBuffer.copy(decodeBuf, this.decodeBufPos, srcPos, srcPos + bytesRead);
this.decodeBufPos += bytesRead;
if (this.decodeBufPos >= decodeBuf.length) {
messageComplete(decodeBuf);
this.decodeState = DecodeState.Initial;
this.decodeBuf = undefined;
}
}
break;
}
if (!bytesRead) throw Error('unexpected: bytesRead == 0');
srcPos += bytesRead;
}
}
}
exports.default = MessageCodec;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9NZXNzYWdlQ29kZWMudHMiXSwibmFtZXMiOlsiUFJFQU1CTEUiLCJMRU5HVEhfTEVOIiwiSEVBREVSX0xFTiIsIkRlY29kZVN0YXRlIiwiTWVzc2FnZUNvZGVjIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwiSW5pdGlhbCIsIkJ1ZmZlciIsImFsbG9jIiwiYmluYXJ5IiwiQm9vbGVhbiIsImVuY29kZSIsImRhdGEiLCJidWZmZXIiLCJmcm9tIiwiZW5jb2RlZCIsImxlbmd0aCIsInBvcyIsIndyaXRlVUludDgiLCJ3cml0ZVVJbnQzMkJFIiwiY29weSIsImRlY29kZSIsInNyY0J1ZmZlciIsIm9uTWVzc2FnZSIsIm1lc3NhZ2VDb21wbGV0ZSIsInRvU3RyaW5nIiwic3JjUG9zIiwic3JjUmVtYWluIiwiYnl0ZXNSZWFkIiwiZGVjb2RlU3RhdGUiLCJwcmVhbWJsZSIsInJlYWRVSW50OCIsIkVycm9yIiwiUmVhZExlbmd0aCIsIk1hdGgiLCJtaW4iLCJsZW5ndGhCdWZQb3MiLCJsZW5ndGhCdWYiLCJtZXNzYWdlTGVuZ3RoIiwicmVhZFVJbnQzMkJFIiwiZGVjb2RlQnVmIiwiZGVjb2RlQnVmUG9zIiwiUmVhZERhdGEiLCJ1bmRlZmluZWQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE1BQU1BLFFBQVEsR0FBRyxFQUFqQixDLENBQW9COztBQUNwQixNQUFNQyxVQUFVLEdBQUcsQ0FBbkIsQyxDQUFxQjs7QUFDckIsTUFBTUMsVUFBVSxHQUFHLElBQUlELFVBQXZCLEMsQ0FBa0M7O0lBRTdCRSxXOztXQUFBQSxXO0FBQUFBLEVBQUFBLFcsQ0FBQUEsVztBQUFBQSxFQUFBQSxXLENBQUFBLFc7QUFBQUEsRUFBQUEsVyxDQUFBQSxXO0dBQUFBLFcsS0FBQUEsVzs7QUFZVSxNQUFNQyxZQUFOLENBQW1CO0FBUWhDQyxFQUFBQSxXQUFXLENBQUNDLE9BQUQsRUFBK0I7QUFBQTs7QUFBQSx5Q0FOUEgsV0FBVyxDQUFDSSxPQU1MOztBQUFBLHVDQUxMQyxNQUFNLENBQUNDLEtBQVAsQ0FBYVIsVUFBYixDQUtLOztBQUFBLDBDQUpuQixDQUltQjs7QUFBQTs7QUFBQSwwQ0FGbkIsQ0FFbUI7O0FBQ3hDLFNBQUtTLE1BQUwsR0FBY0MsT0FBTyxDQUFDTCxPQUFPLENBQUNJLE1BQVQsQ0FBckI7QUFDRDs7QUFFREUsRUFBQUEsTUFBTSxDQUFDQyxJQUFELEVBQWdDO0FBQ3BDLFVBQU1DLE1BQWMsR0FBRyxPQUFPRCxJQUFQLEtBQWdCLFFBQWhCLEdBQTJCTCxNQUFNLENBQUNPLElBQVAsQ0FBWUYsSUFBWixDQUEzQixHQUErQ0EsSUFBdEU7QUFDQSxVQUFNRyxPQUFPLEdBQUdSLE1BQU0sQ0FBQ0MsS0FBUCxDQUFhSyxNQUFNLENBQUNHLE1BQVAsR0FBZ0JmLFVBQTdCLENBQWhCO0FBQ0EsUUFBSWdCLEdBQUcsR0FBRyxDQUFWO0FBQ0FGLElBQUFBLE9BQU8sQ0FBQ0csVUFBUixDQUFtQm5CLFFBQW5CLEVBQTZCa0IsR0FBRyxFQUFoQztBQUNBRixJQUFBQSxPQUFPLENBQUNJLGFBQVIsQ0FBc0JOLE1BQU0sQ0FBQ0csTUFBN0IsRUFBcUNDLEdBQXJDO0FBQ0FBLElBQUFBLEdBQUcsSUFBSWpCLFVBQVA7QUFDQWEsSUFBQUEsTUFBTSxDQUFDTyxJQUFQLENBQVlMLE9BQVosRUFBcUJFLEdBQXJCLEVBQTBCLENBQTFCLEVBQTZCSixNQUFNLENBQUNHLE1BQXBDO0FBQ0EsV0FBT0QsT0FBUDtBQUNEOztBQUVETSxFQUFBQSxNQUFNLENBQUNDLFNBQUQsRUFBb0JDLFNBQXBCLEVBQTZEO0FBQ2pFLFVBQU1DLGVBQWUsR0FBSVgsTUFBRCxJQUN0QlUsU0FBUyxDQUFDLEtBQUtkLE1BQUwsR0FBY0ksTUFBZCxHQUF1QkEsTUFBTSxDQUFDWSxRQUFQLEVBQXhCLENBRFg7O0FBR0EsUUFBSUMsTUFBTSxHQUFHLENBQWI7O0FBQ0EsV0FBT0EsTUFBTSxHQUFHSixTQUFTLENBQUNOLE1BQTFCLEVBQWtDO0FBQ2hDLFlBQU1XLFNBQVMsR0FBR0wsU0FBUyxDQUFDTixNQUFWLEdBQW1CVSxNQUFyQztBQUNBLFVBQUlFLFNBQVMsR0FBRyxDQUFoQjs7QUFDQSxjQUFRLEtBQUtDLFdBQWI7QUFDRSxhQUFLM0IsV0FBVyxDQUFDSSxPQUFqQjtBQUNFLGdCQUFNd0IsUUFBUSxHQUFHUixTQUFTLENBQUNTLFNBQVYsQ0FBb0JMLE1BQXBCLENBQWpCO0FBQ0FFLFVBQUFBLFNBQVMsR0FBRyxDQUFaO0FBQ0EsY0FBSTdCLFFBQVEsS0FBSytCLFFBQWpCLEVBQ0UsTUFBTUUsS0FBSyxDQUNSLG9DQUFtQ2pDLFFBQVMsU0FBUStCLFFBQVMsRUFEckQsQ0FBWDtBQUdGLGVBQUtELFdBQUwsR0FBbUIzQixXQUFXLENBQUMrQixVQUEvQjtBQUNBOztBQUNGLGFBQUsvQixXQUFXLENBQUMrQixVQUFqQjtBQUNFTCxVQUFBQSxTQUFTLEdBQUdNLElBQUksQ0FBQ0MsR0FBTCxDQUFTUixTQUFULEVBQW9CM0IsVUFBVSxHQUFHLEtBQUtvQyxZQUF0QyxDQUFaO0FBQ0FkLFVBQUFBLFNBQVMsQ0FBQ0YsSUFBVixDQUNFLEtBQUtpQixTQURQLEVBRUUsS0FBS0QsWUFGUCxFQUdFVixNQUhGLEVBSUVBLE1BQU0sR0FBR0UsU0FKWDtBQU1BLGVBQUtRLFlBQUwsSUFBcUJSLFNBQXJCOztBQUNBLGNBQUksS0FBS1EsWUFBTCxJQUFxQnBDLFVBQXpCLEVBQXFDO0FBQ25DLGtCQUFNc0MsYUFBYSxHQUFHLEtBQUtELFNBQUwsQ0FBZUUsWUFBZixDQUE0QixDQUE1QixDQUF0Qjs7QUFDQSxnQkFBSUQsYUFBSixFQUFtQjtBQUNqQixtQkFBS0UsU0FBTCxHQUFpQmpDLE1BQU0sQ0FBQ0MsS0FBUCxDQUFhOEIsYUFBYixDQUFqQjtBQUNBLG1CQUFLRyxZQUFMLEdBQW9CLENBQXBCO0FBQ0EsbUJBQUtaLFdBQUwsR0FBbUIzQixXQUFXLENBQUN3QyxRQUEvQjtBQUNELGFBSkQsTUFJTztBQUNMO0FBQ0FsQixjQUFBQSxlQUFlLENBQUNqQixNQUFNLENBQUNDLEtBQVAsQ0FBYSxDQUFiLENBQUQsQ0FBZjtBQUNBLG1CQUFLcUIsV0FBTCxHQUFtQjNCLFdBQVcsQ0FBQ0ksT0FBL0I7QUFDRDs7QUFDRCxpQkFBSzhCLFlBQUwsR0FBb0IsQ0FBcEI7QUFDRDs7QUFDRDs7QUFDRixhQUFLbEMsV0FBVyxDQUFDd0MsUUFBakI7QUFDRTtBQUNFLGtCQUFNRixTQUFTLEdBQUcsS0FBS0EsU0FBdkI7QUFDQSxnQkFBSSxDQUFDQSxTQUFMLEVBQWdCLE1BQU1SLEtBQUssQ0FBQyw4QkFBRCxDQUFYO0FBQ2hCSixZQUFBQSxTQUFTLEdBQUdNLElBQUksQ0FBQ0MsR0FBTCxDQUNWUixTQURVLEVBRVZhLFNBQVMsQ0FBQ3hCLE1BQVYsR0FBbUIsS0FBS3lCLFlBRmQsQ0FBWjtBQUlBbkIsWUFBQUEsU0FBUyxDQUFDRixJQUFWLENBQ0VvQixTQURGLEVBRUUsS0FBS0MsWUFGUCxFQUdFZixNQUhGLEVBSUVBLE1BQU0sR0FBR0UsU0FKWDtBQU1BLGlCQUFLYSxZQUFMLElBQXFCYixTQUFyQjs7QUFDQSxnQkFBSSxLQUFLYSxZQUFMLElBQXFCRCxTQUFTLENBQUN4QixNQUFuQyxFQUEyQztBQUN6Q1EsY0FBQUEsZUFBZSxDQUFDZ0IsU0FBRCxDQUFmO0FBQ0EsbUJBQUtYLFdBQUwsR0FBbUIzQixXQUFXLENBQUNJLE9BQS9CO0FBQ0EsbUJBQUtrQyxTQUFMLEdBQWlCRyxTQUFqQjtBQUNEO0FBQ0Y7QUFDRDtBQXRESjs7QUF3REEsVUFBSSxDQUFDZixTQUFMLEVBQWdCLE1BQU1JLEtBQUssQ0FBQyw0QkFBRCxDQUFYO0FBQ2hCTixNQUFBQSxNQUFNLElBQUlFLFNBQVY7QUFDRDtBQUNGOztBQTFGK0IiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBQUkVBTUJMRSA9IDM1IC8vICcjJyBjaGFyYWN0ZXJcbmNvbnN0IExFTkdUSF9MRU4gPSA0IC8vIExlbmd0aCBvZiB0aGUgbGVuZ3RoPyBXVEY/XG5jb25zdCBIRUFERVJfTEVOID0gMSArIExFTkdUSF9MRU4gLy8gMSBwcmVhbWJsZSBieXRlICsgNCBsZW5ndGggYnl0ZXNcblxuZW51bSBEZWNvZGVTdGF0ZSB7XG4gIEluaXRpYWwsXG4gIFJlYWRMZW5ndGgsXG4gIFJlYWREYXRhLFxufVxuXG5leHBvcnQgdHlwZSBNZXNzYWdlQ29kZWNPcHRpb25zID0ge1xuICBiaW5hcnk/OiBib29sZWFuXG59XG5cbmV4cG9ydCB0eXBlIE1lc3NhZ2VEZWNvZGVkQ2FsbGJhY2sgPSAobWVzc2FnZTogQnVmZmVyIHwgc3RyaW5nKSA9PiB2b2lkXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1lc3NhZ2VDb2RlYyB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYmluYXJ5OiBib29sZWFuXG4gIHByaXZhdGUgZGVjb2RlU3RhdGU6IERlY29kZVN0YXRlID0gRGVjb2RlU3RhdGUuSW5pdGlhbFxuICBwcml2YXRlIHJlYWRvbmx5IGxlbmd0aEJ1ZjogQnVmZmVyID0gQnVmZmVyLmFsbG9jKExFTkdUSF9MRU4pXG4gIHByaXZhdGUgbGVuZ3RoQnVmUG9zID0gMFxuICBwcml2YXRlIGRlY29kZUJ1ZjogQnVmZmVyIHwgdW5kZWZpbmVkXG4gIHByaXZhdGUgZGVjb2RlQnVmUG9zID0gMFxuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IE1lc3NhZ2VDb2RlY09wdGlvbnMpIHtcbiAgICB0aGlzLmJpbmFyeSA9IEJvb2xlYW4ob3B0aW9ucy5iaW5hcnkpXG4gIH1cblxuICBlbmNvZGUoZGF0YTogc3RyaW5nIHwgQnVmZmVyKTogQnVmZmVyIHtcbiAgICBjb25zdCBidWZmZXI6IEJ1ZmZlciA9IHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJyA/IEJ1ZmZlci5mcm9tKGRhdGEpIDogZGF0YVxuICAgIGNvbnN0IGVuY29kZWQgPSBCdWZmZXIuYWxsb2MoYnVmZmVyLmxlbmd0aCArIEhFQURFUl9MRU4pXG4gICAgbGV0IHBvcyA9IDBcbiAgICBlbmNvZGVkLndyaXRlVUludDgoUFJFQU1CTEUsIHBvcysrKVxuICAgIGVuY29kZWQud3JpdGVVSW50MzJCRShidWZmZXIubGVuZ3RoLCBwb3MpXG4gICAgcG9zICs9IExFTkdUSF9MRU5cbiAgICBidWZmZXIuY29weShlbmNvZGVkLCBwb3MsIDAsIGJ1ZmZlci5sZW5ndGgpXG4gICAgcmV0dXJuIGVuY29kZWRcbiAgfVxuXG4gIGRlY29kZShzcmNCdWZmZXI6IEJ1ZmZlciwgb25NZXNzYWdlOiBNZXNzYWdlRGVjb2RlZENhbGxiYWNrKTogdm9pZCB7XG4gICAgY29uc3QgbWVzc2FnZUNvbXBsZXRlID0gKGJ1ZmZlcjogQnVmZmVyKTogdm9pZCA9PlxuICAgICAgb25NZXNzYWdlKHRoaXMuYmluYXJ5ID8gYnVmZmVyIDogYnVmZmVyLnRvU3RyaW5nKCkpXG5cbiAgICBsZXQgc3JjUG9zID0gMFxuICAgIHdoaWxlIChzcmNQb3MgPCBzcmNCdWZmZXIubGVuZ3RoKSB7XG4gICAgICBjb25zdCBzcmNSZW1haW4gPSBzcmNCdWZmZXIubGVuZ3RoIC0gc3JjUG9zXG4gICAgICBsZXQgYnl0ZXNSZWFkID0gMFxuICAgICAgc3dpdGNoICh0aGlzLmRlY29kZVN0YXRlKSB7XG4gICAgICAgIGNhc2UgRGVjb2RlU3RhdGUuSW5pdGlhbDpcbiAgICAgICAgICBjb25zdCBwcmVhbWJsZSA9IHNyY0J1ZmZlci5yZWFkVUludDgoc3JjUG9zKVxuICAgICAgICAgIGJ5dGVzUmVhZCA9IDFcbiAgICAgICAgICBpZiAoUFJFQU1CTEUgIT09IHByZWFtYmxlKVxuICAgICAgICAgICAgdGhyb3cgRXJyb3IoXG4gICAgICAgICAgICAgIGBwcmVhbWJsZSBkaWQgbm90IG1hdGNoOiBleHBlY3RlZCAke1BSRUFNQkxFfSwgd2FzICR7cHJlYW1ibGV9YFxuICAgICAgICAgICAgKVxuICAgICAgICAgIHRoaXMuZGVjb2RlU3RhdGUgPSBEZWNvZGVTdGF0ZS5SZWFkTGVuZ3RoXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSBEZWNvZGVTdGF0ZS5SZWFkTGVuZ3RoOlxuICAgICAgICAgIGJ5dGVzUmVhZCA9IE1hdGgubWluKHNyY1JlbWFpbiwgTEVOR1RIX0xFTiAtIHRoaXMubGVuZ3RoQnVmUG9zKVxuICAgICAgICAgIHNyY0J1ZmZlci5jb3B5KFxuICAgICAgICAgICAgdGhpcy5sZW5ndGhCdWYsXG4gICAgICAgICAgICB0aGlzLmxlbmd0aEJ1ZlBvcyxcbiAgICAgICAgICAgIHNyY1BvcyxcbiAgICAgICAgICAgIHNyY1BvcyArIGJ5dGVzUmVhZFxuICAgICAgICAgIClcbiAgICAgICAgICB0aGlzLmxlbmd0aEJ1ZlBvcyArPSBieXRlc1JlYWRcbiAgICAgICAgICBpZiAodGhpcy5sZW5ndGhCdWZQb3MgPj0gTEVOR1RIX0xFTikge1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZUxlbmd0aCA9IHRoaXMubGVuZ3RoQnVmLnJlYWRVSW50MzJCRSgwKVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2VMZW5ndGgpIHtcbiAgICAgICAgICAgICAgdGhpcy5kZWNvZGVCdWYgPSBCdWZmZXIuYWxsb2MobWVzc2FnZUxlbmd0aClcbiAgICAgICAgICAgICAgdGhpcy5kZWNvZGVCdWZQb3MgPSAwXG4gICAgICAgICAgICAgIHRoaXMuZGVjb2RlU3RhdGUgPSBEZWNvZGVTdGF0ZS5SZWFkRGF0YVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gRW1wdHkgbWVzc2FnZS4uLlxuICAgICAgICAgICAgICBtZXNzYWdlQ29tcGxldGUoQnVmZmVyLmFsbG9jKDApKVxuICAgICAgICAgICAgICB0aGlzLmRlY29kZVN0YXRlID0gRGVjb2RlU3RhdGUuSW5pdGlhbFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5sZW5ndGhCdWZQb3MgPSAwXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgRGVjb2RlU3RhdGUuUmVhZERhdGE6XG4gICAgICAgICAge1xuICAgICAgICAgICAgY29uc3QgZGVjb2RlQnVmID0gdGhpcy5kZWNvZGVCdWZcbiAgICAgICAgICAgIGlmICghZGVjb2RlQnVmKSB0aHJvdyBFcnJvcigndW5leHBlY3RlZCBtaXNzaW5nIGRlY29kZUJ1ZicpXG4gICAgICAgICAgICBieXRlc1JlYWQgPSBNYXRoLm1pbihcbiAgICAgICAgICAgICAgc3JjUmVtYWluLFxuICAgICAgICAgICAgICBkZWNvZGVCdWYubGVuZ3RoIC0gdGhpcy5kZWNvZGVCdWZQb3NcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIHNyY0J1ZmZlci5jb3B5KFxuICAgICAgICAgICAgICBkZWNvZGVCdWYsXG4gICAgICAgICAgICAgIHRoaXMuZGVjb2RlQnVmUG9zLFxuICAgICAgICAgICAgICBzcmNQb3MsXG4gICAgICAgICAgICAgIHNyY1BvcyArIGJ5dGVzUmVhZFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgdGhpcy5kZWNvZGVCdWZQb3MgKz0gYnl0ZXNSZWFkXG4gICAgICAgICAgICBpZiAodGhpcy5kZWNvZGVCdWZQb3MgPj0gZGVjb2RlQnVmLmxlbmd0aCkge1xuICAgICAgICAgICAgICBtZXNzYWdlQ29tcGxldGUoZGVjb2RlQnVmKVxuICAgICAgICAgICAgICB0aGlzLmRlY29kZVN0YXRlID0gRGVjb2RlU3RhdGUuSW5pdGlhbFxuICAgICAgICAgICAgICB0aGlzLmRlY29kZUJ1ZiA9IHVuZGVmaW5lZFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgaWYgKCFieXRlc1JlYWQpIHRocm93IEVycm9yKCd1bmV4cGVjdGVkOiBieXRlc1JlYWQgPT0gMCcpXG4gICAgICBzcmNQb3MgKz0gYnl0ZXNSZWFkXG4gICAgfVxuICB9XG59XG4iXX0=