UNPKG

@light0x00/parser-generator

Version:

A Parser Generator

540 lines (406 loc) 41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProdsInjector = exports.ParsingTable = exports.Accept = exports.Reduce = exports.Goto = exports.Shift = exports.Operation = exports.AugmentedGrammar = exports.StateSet = exports.State = exports.ItemSet = exports.Item = void 0; var _Definition = require("../Definition"); var _shim = require("@light0x00/shim"); 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; } /* 项是所属项集中的一个成员,一个「项」由「产生式」和一个「点」组成,例如 A->a·B */ class Item { /* 由于lookaheadSet可能重复,所以使用Set来存储 为什么lookaheadSet可能重复? S->A A->BC B->b | 𝝴 C->b | 𝝴 S->·A , {$} A->·BC , {b,b,$} //重复 */ constructor(production, dot = 0, lookaheadSet = new Set()) { _defineProperty(this, "prod", void 0); _defineProperty(this, "_dot", 0); _defineProperty(this, "lookaheadSet", void 0); _defineProperty(this, "hashCodeCache", void 0); this.prod = production; /* 对于空推导(形如A->𝝴). 直接将 dot 置于末尾(A->𝝴·) */ this._dot = production.isEpsilon() ? production.length : dot; this.lookaheadSet = lookaheadSet; } get dotPos() { return this._dot; } hasNext() { return this._dot < this.prod.length; } nextSymbol() { if (!this.hasNext()) throw new Error(`${this} has no next item!`); return this.prod[this._dot]; } nextItem() { if (!this.hasNext()) throw new Error(`${this} has no next item!`); /* 😇New features to support LR 为什么当前项展望集应该被后继项继承? 考虑如下文法: S->As A->a I0 S->·As ,$ A->·a ,s I1 A->a· ,s 如上所示,I0输入a得到I1 其中「A->a· ,s」继承了「 A->·a ,s」的展望符 */ return new Item(this.prod, this._dot + 1, this.lookaheadSet); } toString() { let str = ""; let symbols = this.prod; for (let i = 0; i < symbols.length; i++) { if (this._dot == i) str += "·"; str += symbols[i]; } if (this._dot == symbols.length) str += "·"; str += ","; str += "{" + Array.from(this.lookaheadSet).join(",") + "}"; return `${this.prod.name}->${str}`; } equals(other) { /* 两个项是否相等, 1. 所含产生式一样 2. 「dot」所在位置一样 😇New features to support LR 3. 展望集(lookaheadSet)一样 */ if (other.prod.id != this.prod.id) return false; if (other._dot != this._dot) return false; if (other.lookaheadSet.size != this.lookaheadSet.size) return false; //n2复杂度 暂时不管 for (let t of this.lookaheadSet) { // let find = false // for (let o of other.lookaheadSet) { // if (o == t) { // find = true // break // } // } // if (!find) // return false if (!other.lookaheadSet.has(t)) { return false; } } return true; } /* 😇New features to support LALR */ isSameCoreWith(other) { if (other.prod.id != this.prod.id) return false; if (other._dot != this._dot) return false; return true; } hashCode() { if (this.hashCodeCache == null) { // this.hashCodeCache = this.prod.id + '' + this._dot + hash.keys(this.lookaheadSet) this.hashCodeCache = this.prod.id + "-" + this._dot; } return this.hashCodeCache; } // reducible() { // return this.dot == this.prod.length // } } exports.Item = Item; class ItemSet extends Array { //用于记录已经添加的项的Hash 防止逻辑上的重复 constructor(...items) { super(...items); _defineProperty(this, "added", new Map()); _defineProperty(this, "items", new Array()); for (let item of items) this.added.set(item.hashCode(), item); } contains(item) { return this.added.has(item.hashCode()); } pushOrMerge(item) { let existing = this.added.get(item.hashCode()); if (existing === undefined) { this.push(item); } else { //已经存在 则合并LR展望符集 (0, _shim.addAll_Set)(existing.lookaheadSet, item.lookaheadSet); } } //最好的办法是 将数组作为内部对象 而不是继承 push(item) { this.added.set(item.hashCode(), item); return super.push(item); } toString() { let str = ""; for (let item of this) { str += item.toString() + "\n"; } return str.replace(/\n$/, ""); } equals(other) { /* 两个项集A、B是否相等,取决于 1. 它们所包含的项个数相等 2. A、B中的每一个项在对方集合中都存在相等的项 */ if (other.length != this.length) return false; //又写出一个n2复杂度23333 !!更好的办法是用Set来存放 for (let o1 of this) { let hasMatched = false; for (let o2 of other) { if (o1.equals(o2)) { hasMatched = true; break; } } if (!hasMatched) return false; } return true; } /* 返回当前状态的后继符号集 例: 对于下状态(项集),其后继符号为: {E,T,F,(,id} I0 S->·E E->·E+T E->·T T->·T*F T->·F F->·(E) F->·id */ getNextSymbols() { let nextSymbols = new Set(); for (let item of this) { if (item.hasNext()) { nextSymbols.add(item.nextSymbol()); } } return nextSymbols; } } /* 状态基本等同于项集 唯一的区别是状态需要id 而项集不需要 */ exports.ItemSet = ItemSet; class State extends ItemSet { /* 描述当前状态在接受某个符号后去往的后继状态 */ constructor(id, items) { super(...items); _defineProperty(this, "id", void 0); _defineProperty(this, "mapping", new Map()); this.id = id; } toString() { return `<${this.id}>\n${super.toString()}`; } /** * 添加后继状态 * 添加当前状态输入「指定符号」后去往的「后继状态」 * * 原则上一个状态对于同一符号只能有一个后继状态,如果重复将抛出异常 * @param symbol 输入符号 * @param nextState 后继状态 */ addNextState(symbol, nextState) { (0, _shim.assert)(this.mapping.get(symbol) == null, `A state can only have one next state to the same symbol`); this.mapping.set(symbol, nextState); } getNextState(symbol) { return this.mapping.get(symbol); } } exports.State = State; class StateSet extends Array { constructor(...args) { super(...args); _defineProperty(this, "mapping", new Map()); } /* 判断状态集中是否已经存在 相同性质(参见ItemSet的equals方法) 的状态(项集) */ getExisting(state) { for (let existing of this) { if (existing.equals(state)) { return existing; } } return null; } satrtState() { (0, _shim.assert)(this[0] != null); return this[0]; } } /* LR\SLR 在构造状态时有所不同 因此将不同部分独立处理 */ exports.StateSet = StateSet; /** * * 将二维数组形式的产生式集(Symbol[][]) 转为带有编号的Production集合,并赋予指定的非终结符 * * 一个非终结符的产生式集可视为一个Symbol二维数组, * 为了便于实现LR分析表,需要将这个二维数组转为Production集合, * 且为每个Production赋予一个编号. */ class AugmentedGrammar extends _Definition.ActionGrammar { constructor(rawGrammar, traits) { super(rawGrammar, traits); } afterConstruct() { (0, _shim.assert)(this.startNT().length == 1 && this.startNT()[0].length == 1, "The start symbol of an augmented grammar has one and only one production, and the production contains only one symbol!"); } /* 开始符号的产生式 原则上只能有一个 */ get prodOfStartNT() { return this.startNT()[0]; } } /* 表示LR语法分析表格的操作 */ exports.AugmentedGrammar = AugmentedGrammar; class Operation { isReduce() { return false; } isShift() { return false; } isGoto() { return false; } isAccept() { return false; } } exports.Operation = Operation; class Shift extends Operation { constructor(nextState, prec = -1, assoc = false) { super(); _defineProperty(this, "nextState", void 0); _defineProperty(this, "prec", void 0); _defineProperty(this, "assoc", void 0); this.nextState = nextState; this.prec = prec; this.assoc = assoc; } setIfLarger(prec, assoc) { if (prec > this.prec) { this.prec = prec; this.assoc = assoc; } } toString() { return `shift ${this.nextState.id}`; } equals(obj) { return obj instanceof Shift && obj.nextState == this.nextState; } isShift() { return true; } } exports.Shift = Shift; class Goto extends Operation { constructor(nextState) { super(); _defineProperty(this, "nextState", void 0); this.nextState = nextState; } toString() { return `goto ${this.nextState.id}`; } equals(obj) { return obj instanceof Goto && obj.nextState == this.nextState; } isGoto() { return true; } } exports.Goto = Goto; class Reduce extends Operation { /* 用于归约的产生式 */ constructor(prod, prec = -1, leftAssoc = false) { super(); _defineProperty(this, "prod", void 0); _defineProperty(this, "prec", void 0); _defineProperty(this, "leftAssoc", void 0); this.prod = prod; this.prec = prec; this.leftAssoc = leftAssoc; } toString() { return `reduce ${this.prod.id}`; } equals(obj) { return obj instanceof Reduce && obj.prod == this.prod; } isReduce() { return true; } } exports.Reduce = Reduce; class Accept extends Operation { constructor() { super(); } equals(obj) { return obj instanceof Accept; } toString() { return `accept`; } isAccept() { return true; } } exports.Accept = Accept; class ParsingTable { constructor() { _defineProperty(this, "parsingTable", new Map()); } get table() { return this.parsingTable; } put(state, symbol, op) { let row = this.parsingTable.get(state); if (row == undefined) { row = new Map(); this.parsingTable.set(state, row); } row.set(symbol, op); } has(state, symbol, op) { let row = this.parsingTable.get(state); if (row == undefined) return false; let exstingOp = row.get(symbol); if (exstingOp == null) return false; return exstingOp.equals(op); } get(state, symbol) { let row = this.parsingTable.get(state); // assert(row != null, `state(${state.id}) is not found in parsing table!`) if (row == undefined) return undefined; return row.get(symbol); } getExpectedSymbols(state) { let row = this.parsingTable.get(state); if (row == undefined) return []; return Array.from(row.keys()); } getExpectedTokens(state) { let expS = this.getExpectedSymbols(state); return expS.filter(s => !(s instanceof _Definition.NonTerminal)); } } exports.ParsingTable = ParsingTable; class ProdsInjector { constructor() { _defineProperty(this, "prodIdCounter", 0); } inject(nt, rawProds) { for (let rawProd of rawProds) { nt.addProd(this.prodIdCounter++, rawProd); } } } exports.ProdsInjector = ProdsInjector; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MUi9EZWZpbml0aW9uLnRzIl0sIm5hbWVzIjpbIkl0ZW0iLCJjb25zdHJ1Y3RvciIsInByb2R1Y3Rpb24iLCJkb3QiLCJsb29rYWhlYWRTZXQiLCJTZXQiLCJwcm9kIiwiX2RvdCIsImlzRXBzaWxvbiIsImxlbmd0aCIsImRvdFBvcyIsImhhc05leHQiLCJuZXh0U3ltYm9sIiwiRXJyb3IiLCJuZXh0SXRlbSIsInRvU3RyaW5nIiwic3RyIiwic3ltYm9scyIsImkiLCJBcnJheSIsImZyb20iLCJqb2luIiwibmFtZSIsImVxdWFscyIsIm90aGVyIiwiaWQiLCJzaXplIiwidCIsImhhcyIsImlzU2FtZUNvcmVXaXRoIiwiaGFzaENvZGUiLCJoYXNoQ29kZUNhY2hlIiwiSXRlbVNldCIsIml0ZW1zIiwiTWFwIiwiaXRlbSIsImFkZGVkIiwic2V0IiwiY29udGFpbnMiLCJwdXNoT3JNZXJnZSIsImV4aXN0aW5nIiwiZ2V0IiwidW5kZWZpbmVkIiwicHVzaCIsInJlcGxhY2UiLCJvMSIsImhhc01hdGNoZWQiLCJvMiIsImdldE5leHRTeW1ib2xzIiwibmV4dFN5bWJvbHMiLCJhZGQiLCJTdGF0ZSIsImFkZE5leHRTdGF0ZSIsInN5bWJvbCIsIm5leHRTdGF0ZSIsIm1hcHBpbmciLCJnZXROZXh0U3RhdGUiLCJTdGF0ZVNldCIsImdldEV4aXN0aW5nIiwic3RhdGUiLCJzYXRydFN0YXRlIiwiQXVnbWVudGVkR3JhbW1hciIsIkFjdGlvbkdyYW1tYXIiLCJyYXdHcmFtbWFyIiwidHJhaXRzIiwiYWZ0ZXJDb25zdHJ1Y3QiLCJzdGFydE5UIiwicHJvZE9mU3RhcnROVCIsIk9wZXJhdGlvbiIsImlzUmVkdWNlIiwiaXNTaGlmdCIsImlzR290byIsImlzQWNjZXB0IiwiU2hpZnQiLCJwcmVjIiwiYXNzb2MiLCJzZXRJZkxhcmdlciIsIm9iaiIsIkdvdG8iLCJSZWR1Y2UiLCJsZWZ0QXNzb2MiLCJBY2NlcHQiLCJQYXJzaW5nVGFibGUiLCJ0YWJsZSIsInBhcnNpbmdUYWJsZSIsInB1dCIsIm9wIiwicm93IiwiZXhzdGluZ09wIiwiZ2V0RXhwZWN0ZWRTeW1ib2xzIiwia2V5cyIsImdldEV4cGVjdGVkVG9rZW5zIiwiZXhwUyIsImZpbHRlciIsInMiLCJOb25UZXJtaW5hbCIsIlByb2RzSW5qZWN0b3IiLCJpbmplY3QiLCJudCIsInJhd1Byb2RzIiwicmF3UHJvZCIsImFkZFByb2QiLCJwcm9kSWRDb3VudGVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7O0FBQ0E7Ozs7QUFHQTtBQUNPLE1BQU1BLElBQU4sQ0FBVztBQUlqQjs7Ozs7Ozs7OztBQWFBQyxFQUFBQSxXQUFXLENBQUNDLFVBQUQsRUFBeUJDLEdBQVcsR0FBRyxDQUF2QyxFQUEwQ0MsWUFBMkIsR0FBRyxJQUFJQyxHQUFKLEVBQXhFLEVBQTZGO0FBQUE7O0FBQUEsa0NBZGpGLENBY2lGOztBQUFBOztBQUFBOztBQUN2RyxTQUFLQyxJQUFMLEdBQVlKLFVBQVo7QUFDQTs7QUFDQSxTQUFLSyxJQUFMLEdBQVlMLFVBQVUsQ0FBQ00sU0FBWCxLQUF5Qk4sVUFBVSxDQUFDTyxNQUFwQyxHQUE2Q04sR0FBekQ7QUFDQSxTQUFLQyxZQUFMLEdBQW9CQSxZQUFwQjtBQUNBOztBQUVELE1BQUlNLE1BQUosR0FBYTtBQUNaLFdBQU8sS0FBS0gsSUFBWjtBQUNBOztBQUVESSxFQUFBQSxPQUFPLEdBQVk7QUFDbEIsV0FBTyxLQUFLSixJQUFMLEdBQVksS0FBS0QsSUFBTCxDQUFVRyxNQUE3QjtBQUNBOztBQUVERyxFQUFBQSxVQUFVLEdBQVc7QUFDcEIsUUFBSSxDQUFDLEtBQUtELE9BQUwsRUFBTCxFQUNDLE1BQU0sSUFBSUUsS0FBSixDQUFXLEdBQUUsSUFBSyxvQkFBbEIsQ0FBTjtBQUNELFdBQU8sS0FBS1AsSUFBTCxDQUFVLEtBQUtDLElBQWYsQ0FBUDtBQUNBOztBQUNETyxFQUFBQSxRQUFRLEdBQUc7QUFDVixRQUFJLENBQUMsS0FBS0gsT0FBTCxFQUFMLEVBQ0MsTUFBTSxJQUFJRSxLQUFK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RDs7QUFOeUIiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCB7IFByb2R1Y3Rpb24sIFRlcm1pbmFsLCBTeW1ib2wsIE5vblRlcm1pbmFsLCBBY3Rpb25HcmFtbWFyLCBSYXdBY3Rpb25HcmFtbWFyLCBUcmFpdHNUYWJsZSB9IGZyb20gXCIuLi9EZWZpbml0aW9uXCI7XG5pbXBvcnQgeyBhZGRBbGxfU2V0LCBhc3NlcnQgfSBmcm9tIFwiQGxpZ2h0MHgwMC9zaGltXCI7XG5pbXBvcnQgeyBJTGV4ZXIsIEFTVHJlZSB9IGZyb20gXCJAbGlnaHQweDAwL3BhcnNlci1kZWZpbml0aW9uXCI7XG5cbi8qIOmhueaYr+aJgOWxnumhuembhuS4reeahOS4gOS4quaIkOWRmCzkuIDkuKrjgIzpobnjgI3nlLHjgIzkuqfnlJ/lvI/jgI3lkozkuIDkuKrjgIzngrnjgI3nu4TmiJAs5L6L5aaCIEEtPmHCt0IgKi9cbmV4cG9ydCBjbGFzcyBJdGVtIHtcblxuXHRwcm9kOiBQcm9kdWN0aW9uO1xuXHRwcml2YXRlIF9kb3Q6IG51bWJlciA9IDA7XG5cdC8qXG4gICAg55Sx5LqObG9va2FoZWFkU2V05Y+v6IO96YeN5aSNLOaJgOS7peS9v+eUqFNldOadpeWtmOWCqFxuICAgIOS4uuS7gOS5iGxvb2thaGVhZFNldOWPr+iDvemHjeWkjT9cblxuICAgIFMtPkFcbiAgICBBLT5CQ1xuICAgIEItPmIgfCDwnZ20XG4gICAgQy0+YiB8IPCdnbRcblxuICAgIFMtPsK3QSAsIHskfVxuICAgIEEtPsK3QkMgLCB7YixiLCR9ICAvL+mHjeWkjVxuICAgICovXG5cdGxvb2thaGVhZFNldDogU2V0PFRlcm1pbmFsPlxuXHRjb25zdHJ1Y3Rvcihwcm9kdWN0aW9uOiBQcm9kdWN0aW9uLCBkb3Q6IG51bWJlciA9IDAsIGxvb2thaGVhZFNldDogU2V0PFRlcm1pbmFsPiA9IG5ldyBTZXQ8VGVybWluYWw+KCkpIHtcblx0XHR0aGlzLnByb2QgPSBwcm9kdWN0aW9uO1xuXHRcdC8qIOWvueS6juepuuaOqOWvvCjlvaLlpoJBLT7wnZ20KS4g55u05o6l5bCGIGRvdCDnva7kuo7mnKvlsL4oQS0+8J2dtMK3KSAqL1xuXHRcdHRoaXMuX2RvdCA9IHByb2R1Y3Rpb24uaXNFcHNpbG9uKCkgPyBwcm9kdWN0aW9uLmxlbmd0aCA6IGRvdDtcblx0XHR0aGlzLmxvb2thaGVhZFNldCA9IGxvb2thaGVhZFNldDtcblx0fVxuXG5cdGdldCBkb3RQb3MoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2RvdDtcblx0fVxuXG5cdGhhc05leHQoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuX2RvdCA8IHRoaXMucHJvZC5sZW5ndGg7XG5cdH1cblxuXHRuZXh0U3ltYm9sKCk6IFN5bWJvbCB7XG5cdFx0aWYgKCF0aGlzLmhhc05leHQoKSlcblx0XHRcdHRocm93IG5ldyBFcnJvcihgJHt0aGlzfSBoYXMgbm8gbmV4dCBpdGVtIWApO1xuXHRcdHJldHVybiB0aGlzLnByb2RbdGhpcy5fZG90XTtcblx0fVxuXHRuZXh0SXRlbSgpIHtcblx0XHRpZiAoIXRoaXMuaGFzTmV4dCgpKVxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGAke3RoaXN9IGhhcyBubyBuZXh0IGl0ZW0hYCk7XG5cdFx0Lypcblx0XHRcdPCfmIdOZXcgZmVhdHVyZXMgdG8gc3VwcG9ydCBMUlxuXG5cdFx0XHTkuLrku4DkuYjlvZPliY3pobnlsZXmnJvpm4blupTor6XooqvlkI7nu6fpobnnu6fmib8/XG5cblx0XHRcdOiAg+iZkeWmguS4i+aWh+azlTpcblx0XHRcdFMtPkFzXG5cdFx0XHRBLT5hXG5cblx0XHRcdEkwXG5cdFx0XHRTLT7Ct0FzICwkXG5cdFx0XHRBLT7Ct2EgLHNcblxuXHRcdFx0STFcblx0XHRcdEEtPmHCtyAsc1xuXG5cdFx0XHTlpoLkuIrmiYDnpLosSTDovpPlhaVh5b6X5YiwSTFcblx0XHRcdOWFtuS4reOAjEEtPmHCtyAsc+OAjee7p+aJv+S6huOAjCBBLT7Ct2EgLHPjgI3nmoTlsZXmnJvnrKZcblx0XHRcdCovXG5cdFx0cmV0dXJuIG5ldyBJdGVtKHRoaXMucHJvZCwgdGhpcy5fZG90ICsgMSwgdGhpcy5sb29rYWhlYWRTZXQpO1xuXHR9XG5cdHRvU3RyaW5nKCkge1xuXHRcdGxldCBzdHIgPSBcIlwiO1xuXHRcdGxldCBzeW1ib2xzID0gdGhpcy5wcm9kO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgc3ltYm9scy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKHRoaXMuX2RvdCA9PSBpKVxuXHRcdFx0XHRzdHIgKz0gXCLCt1wiO1xuXHRcdFx0c3RyICs9IHN5bWJvbHNbaV07XG5cdFx0fVxuXHRcdGlmICh0aGlzLl9kb3QgPT0gc3ltYm9scy5sZW5ndGgpXG5cdFx0XHRzdHIgKz0gXCLCt1wiO1xuXHRcdHN0ciArPSBcIixcIjtcblx0XHRzdHIgKz0gXCJ7XCIgKyBBcnJheS5mcm9tKHRoaXMubG9va2FoZWFkU2V0KS5qb2luKFwiLFwiKSArIFwifVwiO1xuXHRcdHJldHVybiBgJHt0aGlzLnByb2QubmFtZX0tPiR7c3RyfWA7XG5cdH1cblx0ZXF1YWxzKG90aGVyOiBJdGVtKSB7XG5cdFx0Lypcblx0XHRcdOS4pOS4qumhueaYr+WQpuebuOetiSxcblx0XHRcdDEuIOaJgOWQq+S6p+eUn+W8j+S4gOagt1xuXHRcdFx0Mi4g44CMZG9044CN5omA5Zyo5L2N572u5LiA5qC3XG5cblx0XHRcdPCfmIdOZXcgZmVhdHVyZXMgdG8gc3VwcG9ydCBMUlxuXHRcdFx0My4g5bGV5pyb6ZuGKGxvb2thaGVhZFNldCnkuIDmoLdcblx0XHRcdCovXG5cdFx0aWYgKG90aGVyLnByb2QuaWQgIT0gdGhpcy5wcm9kLmlkKVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdGlmIChvdGhlci5fZG90ICE9IHRoaXMuX2RvdClcblx0XHRcdHJldHVybiBmYWxzZTtcblxuXHRcdGlmIChvdGhlci5sb29rYWhlYWRTZXQuc2l6ZSAhPSB0aGlzLmxvb2thaGVhZFNldC5zaXplKVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdC8vbjLlpI3mnYLluqYg5pqC5pe25LiN566hXG5cdFx0Zm9yIChsZXQgdCBvZiB0aGlzLmxvb2thaGVhZFNldCkge1xuXHRcdFx0Ly8gbGV0IGZpbmQgPSBmYWxzZVxuXHRcdFx0Ly8gZm9yIChsZXQgbyBvZiBvdGhlci5sb29rYWhlYWRTZXQpIHtcblx0XHRcdC8vICAgICBpZiAobyA9PSB0KSB7XG5cdFx0XHQvLyAgICAgICAgIGZpbmQgPSB0cnVlXG5cdFx0XHQvLyAgICAgICAgIGJyZWFrXG5cdFx0XHQvLyAgICAgfVxuXHRcdFx0Ly8gfVxuXHRcdFx0Ly8gaWYgKCFmaW5kKVxuXHRcdFx0Ly8gICAgIHJldHVybiBmYWxzZVxuXHRcdFx0aWYgKCFvdGhlci5sb29rYWhlYWRTZXQuaGFzKHQpKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblx0LyogIPCfmIdOZXcgZmVhdHVyZXMgdG8gc3VwcG9ydCBMQUxSICovXG5cdGlzU2FtZUNvcmVXaXRoKG90aGVyOiBJdGVtKSB7XG5cdFx0aWYgKG90aGVyLnByb2QuaWQgIT0gdGhpcy5wcm9kLmlkKVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdGlmIChvdGhlci5fZG90ICE9IHRoaXMuX2RvdClcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHByaXZhdGUgaGFzaENvZGVDYWNoZTogc3RyaW5nXG5cdGhhc2hDb2RlKCk6IHN0cmluZyB7XG5cdFx0aWYgKHRoaXMuaGFzaENvZGVDYWNoZSA9PSBudWxsKSB7XG5cdFx0XHQvLyB0aGlzLmhhc2hDb2RlQ2FjaGUgPSB0aGlzLnByb2QuaWQgKyAnJyArIHRoaXMuX2RvdCArIGhhc2gua2V5cyh0aGlzLmxvb2thaGVhZFNldClcblx0XHRcdHRoaXMuaGFzaENvZGVDYWNoZSA9IHRoaXMucHJvZC5pZCArIFwiLVwiICsgdGhpcy5fZG90O1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5oYXNoQ29kZUNhY2hlO1xuXHR9XG5cblx0Ly8gcmVkdWNpYmxlKCkge1xuXHQvLyAgICAgcmV0dXJuIHRoaXMuZG90ID09IHRoaXMucHJvZC5sZW5ndGhcblx0Ly8gfVxufVxuXG5leHBvcnQgY2xhc3MgSXRlbVNldCBleHRlbmRzIEFycmF5PEl0ZW0+IHtcblx0Ly/nlKjkuo7orrDlvZXlt7Lnu4/mt7vliqDnmoTpobnnmoRIYXNoIOmYsuatoumAu+i+keS4iueahOmHjeWkjVxuXHRhZGRlZCA9IG5ldyBNYXA8c3RyaW5nLCBJdGVtPigpXG5cdGl0ZW1zID0gbmV3IEFycmF5PEl0ZW0+KClcblx0Y29uc3RydWN0b3IoLi4uaXRlbXM6IEl0ZW1bXSkge1xuXHRcdHN1cGVyKC4uLml0ZW1zKTtcblx0XHRmb3IgKGxldCBpdGVtIG9mIGl0ZW1zKVxuXHRcdFx0dGhpcy5hZGRlZC5zZXQoaXRlbS5oYXNoQ29kZSgpLCBpdGVtKTtcblx0fVxuXG5cdGNvbnRhaW5zKGl0ZW06IEl0ZW0pIHtcblx0XHRyZXR1cm4gdGhpcy5hZGRlZC5oYXMoaXRlbS5oYXNoQ29kZSgpKTtcblx0fVxuXG5cdHB1c2hPck1lcmdlKGl0ZW06IEl0ZW0pIHtcblx0XHRsZXQgZXhpc3RpbmcgPSB0aGlzLmFkZGVkLmdldChpdGVtLmhhc2hDb2RlKCkpO1xuXHRcdGlmIChleGlzdGluZyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHR0aGlzLnB1c2goaXRlbSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8v5bey57uP5a2Y5ZyoIOWImeWQiOW5tkxS5bGV5pyb56ym6ZuGXG5cdFx0XHRhZGRBbGxfU2V0KGV4aXN0aW5nLmxvb2thaGVhZFNldCwgaXRlbS5sb29rYWhlYWRTZXQpO1xuXHRcdH1cblx0fVxuXHQvL+acgOWlveeahOWKnuazleaYryDlsIbmlbDnu4TkvZzkuLrlhoXpg6jlr7nosaEg6ICM5LiN5piv57un5om/XG5cdHB1c2goaXRlbTogSXRlbSkge1xuXHRcdHRoaXMuYWRkZWQuc2V0KGl0ZW0uaGFzaENvZGUoKSwgaXRlbSk7XG5cdFx0cmV0dXJuIHN1cGVyLnB1c2goaXRlbSk7XG5cdH1cblxuXHR0b1N0cmluZygpIHtcblx0XHRsZXQgc3RyID0gXCJcIjtcblx0XHRmb3IgKGxldCBpdGVtIG9mIHRoaXMpIHtcblx0XHRcdHN0ciArPSBpdGVtLnRvU3RyaW5nKCkgKyBcIlxcblwiO1xuXHRcdH1cblx0XHRyZXR1cm4gc3RyLnJlcGxhY2UoL1xcbiQvLCBcIlwiKTtcblx0fVxuXHRlcXVhbHMob3RoZXI6IEl0ZW1TZXQpIHtcblx0XHQvKiDkuKTkuKrpobnpm4ZB44CBQuaYr+WQpuebuOetiSzlj5blhrPkuo5cblx0XHRcdCAgMS4g5a6D5Lus5omA5YyF5ZCr55qE6aG55Liq5pWw55u4562JXG5cdFx0XHQgIDIuIEHjgIFC5Lit55qE5q+P5LiA5Liq6aG55Zyo5a+55pa56ZuG5ZCI5Lit6YO95a2Y5Zyo55u4562J55qE6aG5XG5cdFx0ICAgKi9cblx0XHRpZiAob3RoZXIubGVuZ3RoICE9IHRoaXMubGVuZ3RoKVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdC8v5Y+I5YaZ5Ye65LiA5LiqbjLlpI3mnYLluqYyMzMzMyAgISHmm7Tlpb3nmoTlip7ms5XmmK/nlKhTZXTmnaXlrZjmlL5cblx0XHRmb3IgKGxldCBvMSBvZiB0aGlzKSB7XG5cdFx0XHRsZXQgaGFzTWF0Y2hlZCA9IGZhbHNlO1xuXHRcdFx0Zm9yIChsZXQgbzIgb2Ygb3RoZXIpIHtcblx0XHRcdFx0aWYgKG8xLmVxdWFscyhvMikpIHtcblx0XHRcdFx0XHRoYXNNYXRjaGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKCFoYXNNYXRjaGVkKVxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LypcbiAgICDov5Tlm57lvZPliY3nirbmgIHnmoTlkI7nu6fnrKblj7fpm4ZcbiAgICDkvos6IOWvueS6juS4i+eKtuaAgSjpobnpm4YpLOWFtuWQjue7p+espuWPt+S4ujoge0UsVCxGLCgsaWR9XG4gICAgSTBcbiAgICAgICAgUy0+wrdFXG4gICAgICAgIEUtPsK3RStUXG4gICAgICAgIEUtPsK3VFxuICAgICAgICBULT7Ct1QqRlxuICAgICAgICBULT7Ct0ZcbiAgICAgICAgRi0+wrcoRSlcbiAgICAgICAgRi0+wrdpZFxuICAgICAqL1xuXHRnZXROZXh0U3ltYm9scygpIHtcblx0XHRsZXQgbmV4dFN5bWJvbHMgPSBuZXcgU2V0PFN5bWJvbD4oKTtcblx0XHRmb3IgKGxldCBpdGVtIG9mIHRoaXMpIHtcblx0XHRcdGlmIChpdGVtLmhhc05leHQoKSkge1xuXHRcdFx0XHRuZXh0U3ltYm9scy5hZGQoaXRlbS5uZXh0U3ltYm9sKCkpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gbmV4dFN5bWJvbHM7XG5cdH1cblxufVxuLyog54q25oCB5Z+65pys562J5ZCM5LqO6aG56ZuGIOWUr+S4gOeahOWMuuWIq+aYr+eKtuaAgemcgOimgWlkIOiAjOmhuembhuS4jemcgOimgSAqL1xuZXhwb3J0IGNsYXNzIFN0YXRlIGV4dGVuZHMgSXRlbVNldCB7XG5cdGlkOiBudW1iZXJcblx0Lyog5o+P6L+w5b2T5YmN54q25oCB5Zyo5o6l5Y+X5p+Q5Liq56ym5Y+35ZCO5Y675b6A55qE5ZCO57un54q25oCBICovXG5cdG1hcHBpbmcgPSBuZXcgTWFwPFN5bWJvbCwgU3RhdGU+KClcblx0Y29uc3RydWN0b3IoaWQ6IG51bWJlciwgaXRlbXM6IEl0ZW1bXSkge1xuXHRcdHN1cGVyKC4uLml0ZW1zKTtcblx0XHR0aGlzLmlkID0gaWQ7XG5cdH1cblxuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gYDwke3RoaXMuaWR9PlxcbiR7c3VwZXIudG9TdHJpbmcoKX1gO1xuXHR9XG5cblx0LyoqXG4gICAgICog5re75Yqg5ZCO57un54q25oCBXG4gICAgICog5re75Yqg5b2T5YmN54q25oCB6L6T5YWl44CM5oyH5a6a56ym5Y+344CN5ZCO5Y675b6A55qE44CM5ZCO57un54q25oCB44CNXG4gICAgICpcbiAgICAgKiDljp/liJnkuIrkuIDkuKrnirbmgIHlr7nkuo7lkIzkuIDnrKblj7flj6rog73mnInkuIDkuKrlkI7nu6fnirbmgIEs5aaC5p6c6YeN5aSN5bCG5oqb5Ye65byC5bi4XG4gICAgICogQHBhcmFtIHN5bWJvbCDovpPlhaXnrKblj7dcbiAgICAgKiBAcGFyYW0gbmV4dFN0YXRlIOWQjue7p+eKtuaAgVxuICAgICAqL1xuXHRhZGROZXh0U3RhdGUoc3ltYm9sOiBTeW1ib2wsIG5leHRTdGF0ZTogU3RhdGUpIHtcblx0XHRhc3NlcnQodGhpcy5tYXBwaW5nLmdldChzeW1ib2wpID09IG51bGwsIGBBIHN0YXRlIGNhbiBvbmx5IGhhdmUgb25lIG5leHQgc3RhdGUgdG8gdGhlIHNhbWUgc3ltYm9sYCk7XG5cdFx0dGhpcy5tYXBwaW5nLnNldChzeW1ib2wsIG5leHRTdGF0ZSk7XG5cdH1cblxuXHRnZXROZXh0U3RhdGUoc3ltYm9sOiBTeW1ib2wpIHtcblx0XHRyZXR1cm4gdGhpcy5tYXBwaW5nLmdldChzeW1ib2wpO1xuXHR9XG5cbn1cblxuZXhwb3J0IGNsYXNzIFN0YXRlU2V0IGV4dGVuZHMgQXJyYXk8U3RhdGU+e1xuXHRtYXBwaW5nID0gbmV3IE1hcDxTdGF0ZSwgTWFwPFN5bWJvbCwgU3RhdGU+PigpXG5cdC8qIOWIpOaWreeKtuaAgembhuS4reaYr+WQpuW3sue7j+WtmOWcqCDnm7jlkIzmgKfotKgo5Y+C6KeBSXRlbVNldOeahGVxdWFsc+aWueazlSkg55qE54q25oCBKOmhuembhikgKi9cblx0Z2V0RXhpc3Rpbmcoc3RhdGU6IEl0ZW1TZXQpOiBudWxsIHwgU3RhdGUge1xuXHRcdGZvciAobGV0IGV4aXN0aW5nIG9mIHRoaXMpIHtcblx0XHRcdGlmIChleGlzdGluZy5lcXVhbHMoc3RhdGUpKSB7XG5cdFx0XHRcdHJldHVybiBleGlzdGluZztcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblx0c2F0cnRTdGF0ZSgpOiBTdGF0ZSB7XG5cdFx0YXNzZXJ0KHRoaXNbMF0gIT0gbnVsbCk7XG5cdFx0cmV0dXJuIHRoaXNbMF07XG5cdH1cbn1cbi8qXG5MUlxcU0xSIOWcqOaehOmAoOeKtuaAgeaXtuacieaJgOS4jeWQjCDlm6DmraTlsIbkuI3lkIzpg6jliIbni6znq4vlpITnkIZcbiovXG5leHBvcnQgaW50ZXJmYWNlIEF1dG9tYXRhVG9vbHMge1xuXHRHT1RPKEk6IEl0ZW1TZXQsIGlucHV0U3ltYm9sOiBTeW1ib2wpOiBJdGVtU2V0XG5cdGNsb3N1cmUoaXRlbVNldDogSXRlbVNldCk6IEl0ZW1TZXRcblx0Z2V0U3RhcnRTdGF0ZShncmFtbWFyOiBBY3Rpb25HcmFtbWFyKTogU3RhdGVcbn1cblxuLyoqXG4gKlxuICog5bCG5LqM57u05pWw57uE5b2i5byP55qE5Lqn55Sf5byP6ZuGKFN5bWJvbFtdW10pIOi9rOS4uuW4puaciee8luWPt+eahFByb2R1Y3Rpb27pm4blkIgs5bm26LWL5LqI5oyH5a6a55qE6Z2e57uI57uT56ymXG4gKlxuICog5LiA5Liq6Z2e57uI57uT56ym55qE5Lqn55Sf5byP6ZuG5Y+v6KeG5Li65LiA5LiqU3ltYm9s5LqM57u05pWw57uELFxuICog5Li65LqG5L6/5LqO5a6e546wTFLliIbmnpDooags6ZyA6KaB5bCG6L+Z5Liq5LqM57u05pWw57uE6L2s5Li6UHJvZHVjdGlvbumbhuWQiCxcbiAqIOS4lOS4uuavj+S4qlByb2R1Y3Rpb27otYvkuojkuIDkuKrnvJblj7cuXG4gKi9cbmV4cG9ydCBjbGFzcyBBdWdtZW50ZWRHcmFtbWFyIGV4dGVuZHMgQWN0aW9uR3JhbW1hciB7XG5cblx0Y29uc3RydWN0b3IocmF3R3JhbW1hcjogUmF3QWN0aW9uR3JhbW1hciwgdHJhaXRzOiBUcmFpdHNUYWJsZSkge1xuXHRcdHN1cGVyKHJhd0dyYW1tYXIsIHRyYWl0cyk7XG5cdH1cblxuXHRhZnRlckNvbnN0cnVjdCgpIHtcblx0XHRhc3NlcnQodGhpcy5zdGFydE5UKCkubGVuZ3RoID09IDEgJiYgdGhpcy5zdGFydE5UKClbMF0ubGVuZ3RoID09IDEsXG5cdFx0XHRcIlRoZSBzdGFydCBzeW1ib2wgb2YgYW4gYXVnbWVudGVkIGdyYW1tYXIgaGFzIG9uZSBhbmQgb25seSBvbmUgcHJvZHVjdGlvbiwgYW5kIHRoZSBwcm9kdWN0aW9uIGNvbnRhaW5zIG9ubHkgb25lIHN5bWJvbCFcIik7XG5cdH1cblx0Lyog5byA5aeL56ym5Y+355qE5Lqn55Sf5byPIOWOn+WImeS4iuWPquiDveacieS4gOS4qiAqL1xuXHRnZXQgcHJvZE9mU3RhcnROVCgpOiBQcm9kdWN0aW9uIHtcblx0XHRyZXR1cm4gdGhpcy5zdGFydE5UKClbMF07XG5cdH1cbn1cblxuLyog6KGo56S6TFLor63ms5XliIbmnpDooajmoLznmoTmk43kvZwgKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBPcGVyYXRpb24ge1xuXHRhYnN0cmFjdCBlcXVhbHMob2JqOiBPYmplY3QpOiBib29sZWFuXG5cblx0aXNSZWR1Y2UoKTogdGhpcyBpcyBSZWR1Y2Uge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRpc1NoaWZ0KCk6IHRoaXMgaXMgU2hpZnQge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGlzR290bygpOiB0aGlzIGlzIEdvdG8ge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGlzQWNjZXB0KCk6IHRoaXMgaXMgQWNjZXB0IHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFNoaWZ0IGV4dGVuZHMgT3BlcmF0aW9uIHtcblx0bmV4dFN0YXRlOiBTdGF0ZVxuXHRwcmVjOiBudW1iZXI7XG5cdGFzc29jOiBib29sZWFuO1xuXHRjb25zdHJ1Y3RvcihuZXh0U3RhdGU6IFN0YXRlLCBwcmVjOiBudW1iZXIgPSAtMSwgYXNzb2M6IGJvb2xlYW4gPSBmYWxzZSkge1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5uZXh0U3RhdGUgPSBuZXh0U3RhdGU7XG5cdFx0dGhpcy5wcmVjID0gcHJlYztcblx0XHR0aGlzLmFzc29jID0gYXNzb2M7XG5cdH1cblxuXHRzZXRJZkxhcmdlcihwcmVjOiBudW1iZXIsIGFzc29jOiBib29sZWFuKSB7XG5cdFx0aWYgKHByZWMgPiB0aGlzLnByZWMpIHtcblx0XHRcdHRoaXMucHJlYyA9IHByZWM7XG5cdFx0XHR0aGlzLmFzc29jID0gYXNzb2M7XG5cdFx0fVxuXHR9XG5cblx0dG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIGBzaGlmdCAke3RoaXMubmV4dFN0YXRlLmlkfWA7XG5cdH1cblx0ZXF1YWxzKG9iajogT2JqZWN0KSB7XG5cdFx0cmV0dXJuIG9iaiBpbnN0YW5jZW9mIFNoaWZ0ICYmIG9iai5uZXh0U3RhdGUgPT0gdGhpcy5uZXh0U3RhdGU7XG5cdH1cblx0aXNTaGlmdCgpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgR290byBleHRlbmRzIE9wZXJhdGlvbiB7XG5cdG5leHRTdGF0ZTogU3RhdGVcblxuXHRjb25zdHJ1Y3RvcihuZXh0U3RhdGU6IFN0YXRlKSB7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLm5leHRTdGF0ZSA9IG5leHRTdGF0ZTtcblx0fVxuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gYGdvdG8gJHt0aGlzLm5leHRTdGF0ZS5pZH1gO1xuXHR9XG5cdGVxdWFscyhvYmo6IE9iamVjdCkge1xuXHRcdHJldHVybiBvYmogaW5zdGFuY2VvZiBHb3RvICYmIG9iai5uZXh0U3RhdGUgPT0gdGhpcy5uZXh0U3RhdGU7XG5cdH1cblxuXHRpc0dvdG8oKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFJlZHVjZSBleHRlbmRzIE9wZXJhdGlvbiB7XG5cdC8qIOeUqOS6juW9kue6pueahOS6p+eUn+W8jyAqL1xuXHRwcm9kOiBQcm9kdWN0aW9uO1xuXHRwcmVjOiBudW1iZXI7XG5cdGxlZnRBc3NvYzogYm9vbGVhbjtcblx0Y29uc3RydWN0b3IocHJvZDogUHJvZHVjdGlvbiwgcHJlYzogbnVtYmVyID0gLTEsIGxlZnRBc3NvYzogYm9vbGVhbiA9IGZhbHNlKSB7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLnByb2QgPSBwcm9kO1xuXHRcdHRoaXMucHJlYyA9IHByZWM7XG5cdFx0dGhpcy5sZWZ0QXNzb2MgPSBsZWZ0QXNzb2M7XG5cdH1cblxuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gYHJlZHVjZSAke3RoaXMucHJvZC5pZH1gO1xuXHR9XG5cblx0ZXF1YWxzKG9iajogT2JqZWN0KSB7XG5cdFx0cmV0dXJuIG9iaiBpbnN0YW5jZW9mIFJlZHVjZSAmJiBvYmoucHJvZCA9PSB0aGlzLnByb2Q7XG5cdH1cblxuXHRpc1JlZHVjZSgpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQWNjZXB0IGV4dGVuZHMgT3BlcmF0aW9uIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblx0fVxuXHRlcXVhbHMob2JqOiBPYmplY3QpIHtcblx0XHRyZXR1cm4gb2JqIGluc3RhbmNlb2YgQWNjZXB0O1xuXHR9XG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiBgYWNjZXB0YDtcblx0fVxuXHRpc0FjY2VwdCgpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgUGFyc2luZ1RhYmxlIHtcblx0cHJpdmF0ZSBwYXJzaW5nVGFibGUgPSBuZXcgTWFwPFN0YXRlLCBNYXA8U3ltYm9sLCBPcGVyYXRpb24+PigpXG5cblx0Z2V0IHRhYmxlKCkge1xuXHRcdHJldHVybiB0aGlzLnBhcnNpbmdUYWJsZTtcblx0fVxuXG5cdHB1dChzdGF0ZTogU3RhdGUsIHN5bWJvbDogU3ltYm9sLCBvcDogT3BlcmF0aW9uKTogdm9pZCB7XG5cdFx0bGV0IHJvdyA9IHRoaXMucGFyc2luZ1RhYmxlLmdldChzdGF0ZSk7XG5cdFx0aWYgKHJvdyA9PSB1bmRlZmluZWQpIHtcblx0XHRcdHJvdyA9IG5ldyBNYXA8U3ltYm9sLCBPcGVyYXRpb24+KCk7XG5cdFx0XHR0aGlzLnBhcnNpbmdUYWJsZS5zZXQoc3RhdGUsIHJvdyk7XG5cdFx0fVxuXHRcdHJvdy5zZXQoc3ltYm9sLCBvcCk7XG5cdH1cblx0aGFzKHN0YXRlOiBTdGF0ZSwgc3ltYm9sOiBTeW1ib2wsIG9wOiBPcGVyYXRpb24pOiBib29sZWFuIHtcblx0XHRsZXQgcm93ID0gdGhpcy5wYXJzaW5nVGFibGUuZ2V0KHN0YXRlKTtcblx0XHRpZiAocm93ID09IHVuZGVmaW5lZClcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRsZXQgZXhzdGluZ09wID0gcm93LmdldChzeW1ib2wpO1xuXHRcdGlmIChleHN0aW5nT3AgPT0gbnVsbClcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRyZXR1cm4gZXhzdGluZ09wLmVxdWFscyhvcCk7XG5cdH1cblx0Z2V0KHN0YXRlOiBTdGF0ZSwgc3ltYm9sOiBTeW1ib2wpOiBPcGVyYXRpb24gfCB1bmRlZmluZWQge1xuXHRcdGxldCByb3cgPSB0aGlzLnBhcnNpbmdUYWJsZS5nZXQoc3RhdGUpO1xuXHRcdC8vIGFzc2VydChyb3cgIT0gbnVsbCwgYHN0YXRlKCR7c3RhdGUuaWR9KSBpcyBub3QgZm91bmQgaW4gcGFyc2luZyB0YWJsZSFgKVxuXHRcdGlmIChyb3cgPT0gdW5kZWZpbmVkKVxuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRyZXR1cm4gcm93LmdldChzeW1ib2wpO1xuXHR9XG5cblx0Z2V0RXhwZWN0ZWRTeW1ib2xzKHN0YXRlOiBTdGF0ZSk6IFN5bWJvbFtdIHtcblx0XHRsZXQgcm93ID0gdGhpcy5wYXJzaW5nVGFibGUuZ2V0KHN0YXRlKTtcblx0XHRpZiAocm93ID09IHVuZGVmaW5lZClcblx0XHRcdHJldHVybiBbXTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbShyb3cua2V5cygpKTtcblx0fVxuXG5cdGdldEV4cGVjdGVkVG9rZW5zKHN0YXRlOiBTdGF0ZSkge1xuXHRcdGxldCBleHBTID0gdGhpcy5nZXRFeHBlY3RlZFN5bWJvbHMoc3RhdGUpO1xuXHRcdHJldHVybiBleHBTLmZpbHRlcihzID0+ICEocyBpbnN0YW5jZW9mIE5vblRlcm1pbmFsKSk7XG5cdH1cblxufVxuXG5leHBvcnQgaW50ZXJmYWNlIElQYXJzZXIge1xuXHRwYXJzZShsZXhlcjogSUxleGVyKTogQVNUcmVlXG59XG5cbmV4cG9ydCBjbGFzcyBQcm9kc0luamVjdG9yIHtcblx0cHJvZElkQ291bnRlciA9IDBcblx0aW5qZWN0KG50OiBOb25UZXJtaW5hbCwgcmF3UHJvZHM6IFN5bWJvbFtdW10pIHtcblx0XHRmb3IgKGxldCByYXdQcm9kIG9mIHJhd1Byb2RzKSB7XG5cdFx0XHRudC5hZGRQcm9kKHRoaXMucHJvZElkQ291bnRlcisrLCByYXdQcm9kKTtcblx0XHR9XG5cdH1cbn1cblxuIl19