UNPKG

mix-async-generator

Version:

``` npm i mix-async-generator ```

229 lines 29.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MixAsyncGenerator = void 0; const evt_1 = require("evt"); const util_extends_promise_1 = require("@bfchain/util-extends-promise"); const FastQuene_1 = require("./FastQuene"); const DONE = Promise.resolve({ step: { value: undefined, done: true }, }); class MixAsyncGenerator { constructor() { this._allGenList = new FastQuene_1.FastQuene(); /**正在执行中的任务,等待返回后就从这个集合中移除 */ this._runnings = new Map(); /**候补队列 */ this._benchGen = new FastQuene_1.FastQuene(); /**自由队列 */ this._freeGen = new FastQuene_1.FastQuene(); this._genWaitter = new FastQuene_1.FastQuene(); // private _traceCount = 0; this._freeResult = new FastQuene_1.FastQuene(); this._benchResult = new FastQuene_1.FastQuene(); this._resultWaiter = new FastQuene_1.FastQuene(); this.onError = new evt_1.Evt(); } join(runner, opts) { let bench = false; let jumpGun; let name = `gen-${this._allGenList.size + 1}`; if (opts !== undefined) { opts.name !== undefined && (name = opts.name); opts.bench !== undefined && (bench = opts.bench); jumpGun = opts.jumpGun; } if (jumpGun === undefined) { jumpGun = bench ? 1 : 1; /**非惰性元素至少抢跑1步 */ } if (bench === false && jumpGun < 1) { throw new RangeError("when runner no in bench, jump gun should not be 0"); } return this._join({ runner, name, bench, jumpGun, currentStep: undefined, inQueueSteps: 0, }); } _join(gen) { this._allGenList.push(gen); /// 否则保存到惰性列表中,需要时再使用 if (gen.bench) { this._benchGen.push(gen); } /// 如果是非惰性的,那么直接启动迭代 else { this._handleGen(gen); } return gen; } remove(gen) { if (this._allGenList.remove(gen)) { /// 如果全部归空了,那么将其余在等待中的都关闭掉 if (this._allGenList.size === 0) { do { const waiter = this._resultWaiter.shift(); if (waiter === undefined) { break; } waiter.resolve(DONE); } while (true); } return true; } return false; } _enqueueGen(gen) { // 是否有在等待中的 const waiter = this._genWaitter.shift(); if (waiter) { waiter.resolve(gen); } /// 如果是惰性元素,那么回到惰性队列 else if (gen.bench) { this._benchGen.push(gen); } /// 如果是非惰性元素,那么回到自由队列 else { this._freeGen.push(gen); } } async _dequeueGen() { // 获取一个可用的迭代器 const gen = this._freeGen.shift() || this._benchGen.shift() || (await this._genWaitter.push(new util_extends_promise_1.PromiseOut()).promise); this._handleGen(gen); } _handleGen(gen) { const item = gen.runner.next(); this._runnings.set(item, gen); // 如果完成,则回到自由队列 util_extends_promise_1.safePromiseThen(item, (value) => { this._runnings.delete(item); // 缓存当前结果 gen.currentStep = value; /// 如果已经完结了,那么直接移除掉了 if (value.done) { this.remove(gen); /// 如果没有任何在执行中的元素,就需要继续从队列中读取出来执行,否则外面的Promise就永远无法resolve if (this._runnings.size === 0) { this._dequeueGen(); } } /// 否则回到队列中继续提供下一个迭代 else { // 传递到结果队列中 this._enqueueResult({ from: gen, step: value }); /// 如果可以偷跑,那么继续执行 if (gen.inQueueSteps < gen.jumpGun) { this._handleGen(gen); } else { // 回到空闲队列中 this._enqueueGen(gen); } } }, (reason) => { this._runnings.delete(item); // 如果已经出错,那么直接移除 this.remove(gen); // 向外传递错误 this.onError.post({ from: gen, reason }); }); } /**入列 * 这个函数与_handleGen是紧密关联的,是_handleGen的一部分 */ _enqueueResult(result) { /// 是否有在等待中的 const waiter = this._resultWaiter.shift(); if (waiter !== undefined) { /** * 因为本就是要直接返回的,所以这里直接将步数减去 * * Waiter模式不需要修改inQueueSteps,因为是预约的,直接返回 */ waiter.resolve(result); } else { result.from.bench ? this._benchResult.push(result) : this._freeResult.push(result); result.from.inQueueSteps += 1; } } /**出列 */ _dequeueResult() { /// 再从结果队列中读取 const resultWithFrom1 = this._freeResult.shift(); if (resultWithFrom1 !== undefined) { const gen = resultWithFrom1.from; gen.inQueueSteps -= 1; if (this._freeGen.remove(gen)) { this._handleGen(gen); } return resultWithFrom1; } const resultWithFrom2 = this._benchResult.shift(); if (resultWithFrom2 !== undefined) { const gen = resultWithFrom2.from; gen.inQueueSteps -= 1; if (this._benchGen.remove(gen)) { this._handleGen(gen); } /** * @TODO 使用了候补元素,那么就要对元素尽快进行补充 */ return resultWithFrom2; } // 否则排队进行等待,Waiter模式不需要修改inQueueSteps,因为是预约的,直接返回 const resultPromise = this._resultWaiter.push(new util_extends_promise_1.PromiseOut()).promise; /// 必要时,让选手出列 if ( // 如果没有任何一个在运行中的任务:那么立刻执行 this._runnings.size === 0 || // 如果自由队列为空,但是候补队列有存在的:那么也立刻执行 (this._freeGen.size === 0 && this._benchGen.size !== 0)) { this._dequeueGen(); } // console.log(++this._traceCount); // if (this._traceCount === 2) { // debugger; // } return resultPromise; } next() { if (this.isDone) { return DONE; } return this._dequeueResult(); } get isDone() { return ( /* _allGenList为空也就意味着_running为空 */ this._allGenList.size === 0 && this._freeResult.size === 0 && this._benchResult.size === 0); } async *toAsyncIterator() { while (true) { const result = await this.next(); if (result.step.done) { return; } yield result.step.value; } } async toPromise() { while (true) { const result = await this.next(); if (result.step.done) { return; } } } } exports.MixAsyncGenerator = MixAsyncGenerator; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWl4QXN5bmNHZW5lcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvTWl4QXN5bmNHZW5lcmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTBCO0FBQzFCLHdFQUE0RTtBQUM1RSwyQ0FBd0M7QUF1Q3hDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7SUFDM0IsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBYSxFQUFFO0NBQ2hELENBQUMsQ0FBQztBQUVILE1BQWEsaUJBQWlCO0lBQTlCO1FBR1UsZ0JBQVcsR0FBRyxJQUFJLHFCQUFTLEVBQTRCLENBQUM7UUFnRmhFLDZCQUE2QjtRQUNyQixjQUFTLEdBQUcsSUFBSSxHQUFHLEVBR3hCLENBQUM7UUE0Q0osVUFBVTtRQUNGLGNBQVMsR0FBRyxJQUFJLHFCQUFTLEVBQWtDLENBQUM7UUFDcEUsVUFBVTtRQUNGLGFBQVEsR0FBRyxJQUFJLHFCQUFTLEVBQW1DLENBQUM7UUFDNUQsZ0JBQVcsR0FBRyxJQUFJLHFCQUFTLEVBQXdDLENBQUM7UUFvRTVFLDJCQUEyQjtRQUNuQixnQkFBVyxHQUFHLElBQUkscUJBQVMsRUFFaEMsQ0FBQztRQUNJLGlCQUFZLEdBQUcsSUFBSSxxQkFBUyxFQUVqQyxDQUFDO1FBQ0ksa0JBQWEsR0FBRyxJQUFJLHFCQUFTLEVBRWxDLENBQUM7UUFDSyxZQUFPLEdBQUcsSUFBSSxTQUFHLEVBQThCLENBQUM7SUErQjNELENBQUM7SUFoUEMsSUFBSSxDQUNGLE1BQXdDLEVBQ3hDLElBQTJEO1FBRTNELElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNsQixJQUFJLE9BQTJCLENBQUM7UUFDaEMsSUFBSSxJQUFJLEdBQUcsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM5QyxJQUFJLElBQUksS0FBSyxTQUFTLEVBQUU7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LENBQUMsWUFBWSxDQUFDLElBQUksS0FBSyxDQUFDLENBQzdCLENBQUM7SUFDSixDQUFDO0lBQ0QsS0FBSyxDQUFDLENBQUMsZUFBZTtRQUNwQixPQUFPLElBQUksRUFBRTtZQUNYLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pDLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7Z0JBQ3BCLE9BQU87YUFDUjtZQUNELE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7U0FDekI7SUFDSCxDQUFDO0lBQ0QsS0FBSyxDQUFDLFNBQVM7UUFDYixPQUFPLElBQUksRUFBRTtZQUNYLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pDLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7Z0JBQ3BCLE9BQU87YUFDUjtTQUNGO0lBQ0gsQ0FBQztDQUNGO0FBcFBELDhDQW9QQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEV2dCB9IGZyb20gXCJldnRcIjtcclxuaW1wb3J0IHsgc2FmZVByb21pc2VUaGVuLCBQcm9taXNlT3V0IH0gZnJvbSBcIkBiZmNoYWluL3V0aWwtZXh0ZW5kcy1wcm9taXNlXCI7XHJcbmltcG9ydCB7IEZhc3RRdWVuZSB9IGZyb20gXCIuL0Zhc3RRdWVuZVwiO1xyXG5cclxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIE1peEFzeW5jR2VuZXJhdG9yIHtcclxuICB0eXBlIEFHPE5leHRPdXQgPSB1bmtub3duLCBSZXR1cm4gPSB1bmtub3duLCBOZXh0SW4gPSB1bmtub3duPiA9IFtcclxuICAgIE5leHRPdXQsXHJcbiAgICBSZXR1cm4sXHJcbiAgICBOZXh0SW5cclxuICBdO1xyXG4gIHR5cGUgR2VuPFQgZXh0ZW5kcyBBRywgQiBleHRlbmRzIGJvb2xlYW4gPSBib29sZWFuPiA9IHtcclxuICAgIG5hbWU6IHN0cmluZztcclxuICAgIHJ1bm5lcjogQXN5bmNHZW5lcmF0b3I8VFswXSwgVFsxXSwgVFsyXT47XHJcbiAgICAvKirmm7/ooaXlhYPntKAv5oOw5oCn5YWD57SgXHJcbiAgICAgKiDmhI/lkbPnnYDlj6rmnInliLDkuI3lvpfkuI3nlKjnmoTml7blgJnmiY3kvJrljrvkvb/nlKhcclxuICAgICAqL1xyXG4gICAgYmVuY2g6IEI7XHJcbiAgICAvKirlvZPliY3nmoTmraXkvJAgKi9cclxuICAgIGN1cnJlbnRTdGVwOiBJdGVyYXRvclJlc3VsdDxUWzBdLCBUWzFdPiB8IHVuZGVmaW5lZDtcclxuICAgIC8qKuWBt+i3keeahOatpeaVsO+8jOm7mOiupOaYrzBcclxuICAgICAqIOWBt+i3keaEj+WRs+edgOWug+Wni+e7iOS8muWKquWKm+aPkOS+m2p1bXBHdW7kuKpyZXN1bHRcclxuICAgICAqIOabv+ihpeWFg+e0oOS5n+WPr+S7peWBt+i3ke+8jOS9huWPquaciei9ruWIsOWug+S4iuWcuuaJjeiDveWBt+i3kVxyXG4gICAgICovXHJcbiAgICBqdW1wR3VuOiBudW1iZXI7XHJcbiAgICAvKirnvJPlrZjlnKjpmJ/liJfkuK3nmoTmraXkvJDmlbAgKi9cclxuICAgIGluUXVldWVTdGVwczogbnVtYmVyO1xyXG4gIH07XHJcbiAgdHlwZSBSZXN1bHQ8VCBleHRlbmRzIEFHPiA9IHtcclxuICAgIHN0ZXA6IEl0ZXJhdG9yUmVzdWx0PFRbMF0sIFRbMV0+O1xyXG4gICAgZnJvbT86IEdlbjxUPjtcclxuICB9O1xyXG4gIHR5cGUgUmVzdWx0V2l0aEZyb208VCBleHRlbmRzIEFHLCBCIGV4dGVuZHMgYm9vbGVhbiA9IGJvb2xlYW4+ID0ge1xyXG4gICAgc3RlcDogSXRlcmF0b3JSZXN1bHQ8VFswXSwgVFsxXT47XHJcbiAgICBmcm9tOiBHZW48VCwgQj47XHJcbiAgfTtcclxuICB0eXBlIEVycm9yPFQgZXh0ZW5kcyBBRz4gPSB7XHJcbiAgICBmcm9tOiBHZW48VD47XHJcbiAgICByZWFzb246IHVua25vd247XHJcbiAgfTtcclxufVxyXG5cclxuY29uc3QgRE9ORSA9IFByb21pc2UucmVzb2x2ZSh7XHJcbiAgc3RlcDogeyB2YWx1ZTogdW5kZWZpbmVkLCBkb25lOiB0cnVlIGFzIGNvbnN0IH0sXHJcbn0pO1xyXG5cclxuZXhwb3J0IGNsYXNzIE1peEFzeW5jR2VuZXJhdG9yPFxyXG4gIFQgZXh0ZW5kcyBNaXhBc3luY0dlbmVyYXRvci5BRyA9IE1peEFzeW5jR2VuZXJhdG9yLkFHXHJcbj4ge1xyXG4gIHByaXZhdGUgX2FsbEdlbkxpc3QgPSBuZXcgRmFzdFF1ZW5lPE1peEFzeW5jR2VuZXJhdG9yLkdlbjxUPj4oKTtcclxuICBqb2luKFxyXG4gICAgcnVubmVyOiBBc3luY0dlbmVyYXRvcjxUWzBdLCBUWzFdLCBUWzJdPixcclxuICAgIG9wdHM/OiB7IG5hbWU/OiBzdHJpbmc7IGJlbmNoPzogYm9vbGVhbjsganVtcEd1bj86IG51bWJlciB9XHJcbiAgKSB7XHJcbiAgICBsZXQgYmVuY2ggPSBmYWxzZTtcclxuICAgIGxldCBqdW1wR3VuOiBudW1iZXIgfCB1bmRlZmluZWQ7XHJcbiAgICBsZXQgbmFtZSA9IGBnZW4tJHt0aGlzLl9hbGxHZW5MaXN0LnNpemUgKyAxfWA7XHJcbiAgICBpZiAob3B0cyAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIG9wdHMubmFtZSAhPT0gdW5kZWZpbmVkICYmIChuYW1lID0gb3B0cy5uYW1lKTtcclxuICAgICAgb3B0cy5iZW5jaCAhPT0gdW5kZWZpbmVkICYmIChiZW5jaCA9IG9wdHMuYmVuY2gpO1xyXG4gICAgICBqdW1wR3VuID0gb3B0cy5qdW1wR3VuO1xyXG4gICAgfVxyXG4gICAgaWYgKGp1bXBHdW4gPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBqdW1wR3VuID0gYmVuY2ggPyAxIDogMTsgLyoq6Z2e5oOw5oCn5YWD57Sg6Iez5bCR5oqi6LeRMeatpSAqL1xyXG4gICAgfVxyXG4gICAgaWYgKGJlbmNoID09PSBmYWxzZSAmJiBqdW1wR3VuIDwgMSkge1xyXG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIndoZW4gcnVubmVyIG5vIGluIGJlbmNoLCBqdW1wIGd1biBzaG91bGQgbm90IGJlIDBcIik7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuX2pvaW4oe1xyXG4gICAgICBydW5uZXIsXHJcbiAgICAgIG5hbWUsXHJcbiAgICAgIGJlbmNoLFxyXG4gICAgICBqdW1wR3VuLFxyXG4gICAgICBjdXJyZW50U3RlcDogdW5kZWZpbmVkLFxyXG4gICAgICBpblF1ZXVlU3RlcHM6IDAsXHJcbiAgICB9KTtcclxuICB9XHJcbiAgcHJpdmF0ZSBfam9pbihnZW46IE1peEFzeW5jR2VuZXJhdG9yLkdlbjxUPikge1xyXG4gICAgdGhpcy5fYWxsR2VuTGlzdC5wdXNoKGdlbik7XHJcbiAgICAvLy8g5ZCm5YiZ5L+d5a2Y5Yiw5oOw5oCn5YiX6KGo5Lit77yM6ZyA6KaB5pe25YaN5L2/55SoXHJcbiAgICBpZiAoZ2VuLmJlbmNoKSB7XHJcbiAgICAgIHRoaXMuX2JlbmNoR2VuLnB1c2goZ2VuIGFzIE1peEFzeW5jR2VuZXJhdG9yLkdlbjxULCB0cnVlPik7XHJcbiAgICB9XHJcbiAgICAvLy8g5aaC5p6c5piv6Z2e5oOw5oCn55qE77yM6YKj5LmI55u05o6l5ZCv5Yqo6L+t5LujXHJcbiAgICBlbHNlIHtcclxuICAgICAgdGhpcy5faGFuZGxlR2VuKGdlbik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZ2VuO1xyXG4gIH1cclxuICByZW1vdmUoZ2VuOiBNaXhBc3luY0dlbmVyYXRvci5HZW48VD4pIHtcclxuICAgIGlmICh0aGlzLl9hbGxHZW5MaXN0LnJlbW92ZShnZW4pKSB7XHJcbiAgICAgIC8vLyDlpoLmnpzlhajpg6jlvZLnqbrkuobvvIzpgqPkuYjlsIblhbbkvZnlnKjnrYnlvoXkuK3nmoTpg73lhbPpl63mjolcclxuICAgICAgaWYgKHRoaXMuX2FsbEdlbkxpc3Quc2l6ZSA9PT0gMCkge1xyXG4gICAgICAgIGRvIHtcclxuICAgICAgICAgIGNvbnN0IHdhaXRlciA9IHRoaXMuX3Jlc3VsdFdhaXRlci5zaGlmdCgpO1xyXG4gICAgICAgICAgaWYgKHdhaXRlciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgd2FpdGVyLnJlc29sdmUoRE9ORSk7XHJcbiAgICAgICAgfSB3aGlsZSAodHJ1ZSk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG4gIHByaXZhdGUgX2VucXVldWVHZW4oZ2VuOiBNaXhBc3luY0dlbmVyYXRvci5HZW48VD4pIHtcclxuICAgIC8vIOaYr+WQpuacieWcqOetieW+heS4reeahFxyXG4gICAgY29uc3Qgd2FpdGVyID0gdGhpcy5fZ2VuV2FpdHRlci5zaGlmdCgpO1xyXG4gICAgaWYgKHdhaXRlcikge1xyXG4gICAgICB3YWl0ZXIucmVzb2x2ZShnZW4pO1xyXG4gICAgfVxyXG4gICAgLy8vIOWmguaenOaYr+aDsOaAp+WFg+e0oO+8jOmCo+S5iOWbnuWIsOaDsOaAp+mYn+WIl1xyXG4gICAgZWxzZSBpZiAoZ2VuLmJlbmNoKSB7XHJcbiAgICAgIHRoaXMuX2JlbmNoR2VuLnB1c2goZ2VuIGFzIE1peEFzeW5jR2VuZXJhdG9yLkdlbjxULCB0cnVlPik7XHJcbiAgICB9XHJcbiAgICAvLy8g5aaC5p6c5piv6Z2e5oOw5oCn5YWD57Sg77yM6YKj5LmI5Zue5Yiw6Ieq55Sx6Zif5YiXXHJcbiAgICBlbHNlIHtcclxuICAgICAgdGhpcy5fZnJlZUdlbi5wdXNoKGdlbiBhcyBNaXhBc3luY0dlbmVyYXRvci5HZW48VCwgZmFsc2U+KTtcclxuICAgIH1cclxuICB9XHJcbiAgcHJpdmF0ZSBhc3luYyBfZGVxdWV1ZUdlbigpIHtcclxuICAgIC8vIOiOt+WPluS4gOS4quWPr+eUqOeahOi/reS7o+WZqFxyXG4gICAgY29uc3QgZ2VuID1cclxuICAgICAgdGhpcy5fZnJlZUdlbi5zaGlmdCgpIHx8XHJcbiAgICAgIHRoaXMuX2JlbmNoR2VuLnNoaWZ0KCkgfHxcclxuICAgICAgKGF3YWl0IHRoaXMuX2dlbldhaXR0ZXIucHVzaChuZXcgUHJvbWlzZU91dCgpKS5wcm9taXNlKTtcclxuICAgIHRoaXMuX2hhbmRsZUdlbihnZW4pO1xyXG4gIH1cclxuICAvKirmraPlnKjmiafooYzkuK3nmoTku7vliqHvvIznrYnlvoXov5Tlm57lkI7lsLHku47ov5nkuKrpm4blkIjkuK3np7vpmaQgKi9cclxuICBwcml2YXRlIF9ydW5uaW5ncyA9IG5ldyBNYXA8XHJcbiAgICBQcm9taXNlPEl0ZXJhdG9yUmVzdWx0PFRbMF0sIFRbMV0+PixcclxuICAgIE1peEFzeW5jR2VuZXJhdG9yLkdlbjxUPlxyXG4gID4oKTtcclxuICBwcml2YXRlIF9oYW5kbGVHZW4oZ2VuOiBNaXhBc3luY0dlbmVyYXRvci5HZW48VD4pIHtcclxuICAgIGNvbnN0IGl0ZW0gPSBnZW4ucnVubmVyLm5leHQoKTtcclxuICAgIHRoaXMuX3J1bm5pbmdzLnNldChpdGVtLCBnZW4pO1xyXG4gICAgLy8g5aaC5p6c5a6M5oiQ77yM5YiZ5Zue5Yiw6Ieq55Sx6Zif5YiXXHJcbiAgICBzYWZlUHJvbWlzZVRoZW4oXHJcbiAgICAgIGl0ZW0sXHJcbiAgICAgICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgIHRoaXMuX3J1bm5pbmdzLmRlbGV0ZShpdGVtKTtcclxuICAgICAgICAvLyDnvJPlrZjlvZPliY3nu5PmnpxcclxuICAgICAgICBnZW4uY3VycmVudFN0ZXAgPSB2YWx1ZTtcclxuICAgICAgICAvLy8g5aaC5p6c5bey57uP5a6M57uT5LqG77yM6YKj5LmI55u05o6l56e76Zmk5o6J5LqGXHJcbiAgICAgICAgaWYgKHZhbHVlLmRvbmUpIHtcclxuICAgICAgICAgIHRoaXMucmVtb3ZlKGdlbik7XHJcblxyXG4gICAgICAgICAgLy8vIOWmguaenOayoeacieS7u+S9leWcqOaJp+ihjOS4reeahOWFg+e0oO+8jOWwsemcgOimgee7p+e7reS7jumYn+WIl+S4reivu+WPluWHuuadpeaJp+ihjO+8jOWQpuWImeWklumdoueahFByb21pc2XlsLHmsLjov5zml6Dms5VyZXNvbHZlXHJcbiAgICAgICAgICBpZiAodGhpcy5fcnVubmluZ3Muc2l6ZSA9PT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLl9kZXF1ZXVlR2VuKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vLyDlkKbliJnlm57liLDpmJ/liJfkuK3nu6fnu63mj5DkvpvkuIvkuIDkuKrov63ku6NcclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgIC8vIOS8oOmAkuWIsOe7k+aenOmYn+WIl+S4rVxyXG4gICAgICAgICAgdGhpcy5fZW5xdWV1ZVJlc3VsdCh7IGZyb206IGdlbiwgc3RlcDogdmFsdWUgfSk7XHJcblxyXG4gICAgICAgICAgLy8vIOWmguaenOWPr+S7peWBt+i3ke+8jOmCo+S5iOe7p+e7reaJp+ihjFxyXG4gICAgICAgICAgaWYgKGdlbi5pblF1ZXVlU3RlcHMgPCBnZW4uanVtcEd1bikge1xyXG4gICAgICAgICAgICB0aGlzLl9oYW5kbGVHZW4oZ2VuKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIOWbnuWIsOepuumXsumYn+WIl+S4rVxyXG4gICAgICAgICAgICB0aGlzLl9lbnF1ZXVlR2VuKGdlbik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9LFxyXG4gICAgICAocmVhc29uOiB1bmtub3duKSA9PiB7XHJcbiAgICAgICAgdGhpcy5fcnVubmluZ3MuZGVsZXRlKGl0ZW0pO1xyXG4gICAgICAgIC8vIOWmguaenOW3sue7j+WHuumUme+8jOmCo+S5iOebtOaOpeenu+mZpFxyXG4gICAgICAgIHRoaXMucmVtb3ZlKGdlbik7XHJcbiAgICAgICAgLy8g5ZCR5aSW5Lyg6YCS6ZSZ6K+vXHJcbiAgICAgICAgdGhpcy5vbkVycm9yLnBvc3QoeyBmcm9tOiBnZW4sIHJlYXNvbiB9KTtcclxuICAgICAgfVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKuWAmeihpemYn+WIlyAqL1xyXG4gIHByaXZhdGUgX2JlbmNoR2VuID0gbmV3IEZhc3RRdWVuZTxNaXhBc3luY0dlbmVyYXRvci5HZW48VCwgdHJ1ZT4+KCk7XHJcbiAgLyoq6Ieq55Sx6Zif5YiXICovXHJcbiAgcHJpdmF0ZSBfZnJlZUdlbiA9IG5ldyBGYXN0UXVlbmU8TWl4QXN5bmNHZW5lcmF0b3IuR2VuPFQsIGZhbHNlPj4oKTtcclxuICBwcml2YXRlIF9nZW5XYWl0dGVyID0gbmV3IEZhc3RRdWVuZTxQcm9taXNlT3V0PE1peEFzeW5jR2VuZXJhdG9yLkdlbjxUPj4+KCk7XHJcbiAgLyoq5YWl5YiXXHJcbiAgICog6L+Z5Liq5Ye95pWw5LiOX2hhbmRsZUdlbuaYr+e0p+WvhuWFs+iBlOeahO+8jOaYr19oYW5kbGVHZW7nmoTkuIDpg6jliIZcclxuICAgKi9cclxuICBwcml2YXRlIF9lbnF1ZXVlUmVzdWx0KHJlc3VsdDogTWl4QXN5bmNHZW5lcmF0b3IuUmVzdWx0V2l0aEZyb208VD4pIHtcclxuICAgIC8vLyDmmK/lkKbmnInlnKjnrYnlvoXkuK3nmoRcclxuICAgIGNvbnN0IHdhaXRlciA9IHRoaXMuX3Jlc3VsdFdhaXRlci5zaGlmdCgpO1xyXG4gICAgaWYgKHdhaXRlciAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIC8qKlxyXG4gICAgICAgKiDlm6DkuLrmnKzlsLHmmK/opoHnm7TmjqXov5Tlm57nmoTvvIzmiYDku6Xov5nph4znm7TmjqXlsIbmraXmlbDlh4/ljrtcclxuICAgICAgICpcclxuICAgICAgICogV2FpdGVy5qih5byP5LiN6ZyA6KaB5L+u5pS5aW5RdWV1ZVN0ZXBz77yM5Zug5Li65piv6aKE57qm55qE77yM55u05o6l6L+U5ZueXHJcbiAgICAgICAqL1xyXG4gICAgICB3YWl0ZXIucmVzb2x2ZShyZXN1bHQpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmVzdWx0LmZyb20uYmVuY2hcclxuICAgICAgICA/IHRoaXMuX2JlbmNoUmVzdWx0LnB1c2goXHJcbiAgICAgICAgICAgIHJlc3VsdCBhcyBNaXhBc3luY0dlbmVyYXRvci5SZXN1bHRXaXRoRnJvbTxULCB0cnVlPlxyXG4gICAgICAgICAgKVxyXG4gICAgICAgIDogdGhpcy5fZnJlZVJlc3VsdC5wdXNoKFxyXG4gICAgICAgICAgICByZXN1bHQgYXMgTWl4QXN5bmNHZW5lcmF0b3IuUmVzdWx0V2l0aEZyb208VCwgZmFsc2U+XHJcbiAgICAgICAgICApO1xyXG4gICAgICByZXN1bHQuZnJvbS5pblF1ZXVlU3RlcHMgKz0gMTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoq5Ye65YiXICovXHJcbiAgcHJpdmF0ZSBfZGVxdWV1ZVJlc3VsdCgpIHtcclxuICAgIC8vLyDlho3ku47nu5PmnpzpmJ/liJfkuK3or7vlj5ZcclxuICAgIGNvbnN0IHJlc3VsdFdpdGhGcm9tMSA9IHRoaXMuX2ZyZWVSZXN1bHQuc2hpZnQoKTtcclxuICAgIGlmIChyZXN1bHRXaXRoRnJvbTEgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBjb25zdCBnZW4gPSByZXN1bHRXaXRoRnJvbTEuZnJvbTtcclxuICAgICAgZ2VuLmluUXVldWVTdGVwcyAtPSAxO1xyXG4gICAgICBpZiAodGhpcy5fZnJlZUdlbi5yZW1vdmUoZ2VuKSkge1xyXG4gICAgICAgIHRoaXMuX2hhbmRsZUdlbihnZW4pO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiByZXN1bHRXaXRoRnJvbTE7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgcmVzdWx0V2l0aEZyb20yID0gdGhpcy5fYmVuY2hSZXN1bHQuc2hpZnQoKTtcclxuICAgIGlmIChyZXN1bHRXaXRoRnJvbTIgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBjb25zdCBnZW4gPSByZXN1bHRXaXRoRnJvbTIuZnJvbTtcclxuICAgICAgZ2VuLmluUXVldWVTdGVwcyAtPSAxO1xyXG4gICAgICBpZiAodGhpcy5fYmVuY2hHZW4ucmVtb3ZlKGdlbikpIHtcclxuICAgICAgICB0aGlzLl9oYW5kbGVHZW4oZ2VuKTtcclxuICAgICAgfVxyXG4gICAgICAvKipcclxuICAgICAgICogQFRPRE8g5L2/55So5LqG5YCZ6KGl5YWD57Sg77yM6YKj5LmI5bCx6KaB5a+55YWD57Sg5bC95b+r6L+b6KGM6KGl5YWFXHJcbiAgICAgICAqL1xyXG4gICAgICByZXR1cm4gcmVzdWx0V2l0aEZyb20yO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOWQpuWImeaOkumYn+i/m+ihjOetieW+he+8jFdhaXRlcuaooeW8j+S4jemcgOimgeS/ruaUuWluUXVldWVTdGVwc++8jOWboOS4uuaYr+mihOe6pueahO+8jOebtOaOpei/lOWbnlxyXG4gICAgY29uc3QgcmVzdWx0UHJvbWlzZSA9IHRoaXMuX3Jlc3VsdFdhaXRlci5wdXNoKG5ldyBQcm9taXNlT3V0KCkpLnByb21pc2U7XHJcbiAgICAvLy8g5b+F6KaB5pe277yM6K6p6YCJ5omL5Ye65YiXXHJcbiAgICBpZiAoXHJcbiAgICAgIC8vIOWmguaenOayoeacieS7u+S9leS4gOS4quWcqOi/kOihjOS4reeahOS7u+WKoe+8mumCo+S5iOeri+WIu+aJp+ihjFxyXG4gICAgICB0aGlzLl9ydW5uaW5ncy5zaXplID09PSAwIHx8XHJcbiAgICAgIC8vIOWmguaenOiHqueUsemYn+WIl+S4uuepuu+8jOS9huaYr+WAmeihpemYn+WIl+acieWtmOWcqOeahO+8mumCo+S5iOS5n+eri+WIu+aJp+ihjFxyXG4gICAgICAodGhpcy5fZnJlZUdlbi5zaXplID09PSAwICYmIHRoaXMuX2JlbmNoR2VuLnNpemUgIT09IDApXHJcbiAgICApIHtcclxuICAgICAgdGhpcy5fZGVxdWV1ZUdlbigpO1xyXG4gICAgfVxyXG4gICAgLy8gY29uc29sZS5sb2coKyt0aGlzLl90cmFjZUNvdW50KTtcclxuICAgIC8vIGlmICh0aGlzLl90cmFjZUNvdW50ID09PSAyKSB7XHJcbiAgICAvLyAgIGRlYnVnZ2VyO1xyXG4gICAgLy8gfVxyXG4gICAgcmV0dXJuIHJlc3VsdFByb21pc2U7XHJcbiAgfVxyXG4gIC8vIHByaXZhdGUgX3RyYWNlQ291bnQgPSAwO1xyXG4gIHByaXZhdGUgX2ZyZWVSZXN1bHQgPSBuZXcgRmFzdFF1ZW5lPFxyXG4gICAgTWl4QXN5bmNHZW5lcmF0b3IuUmVzdWx0V2l0aEZyb208VCwgZmFsc2U+XHJcbiAgPigpO1xyXG4gIHByaXZhdGUgX2JlbmNoUmVzdWx0ID0gbmV3IEZhc3RRdWVuZTxcclxuICAgIE1peEFzeW5jR2VuZXJhdG9yLlJlc3VsdFdpdGhGcm9tPFQsIHRydWU+XHJcbiAgPigpO1xyXG4gIHByaXZhdGUgX3Jlc3VsdFdhaXRlciA9IG5ldyBGYXN0UXVlbmU8XHJcbiAgICBQcm9taXNlT3V0PE1peEFzeW5jR2VuZXJhdG9yLlJlc3VsdDxUPj5cclxuICA+KCk7XHJcbiAgcmVhZG9ubHkgb25FcnJvciA9IG5ldyBFdnQ8TWl4QXN5bmNHZW5lcmF0b3IuRXJyb3I8VD4+KCk7XHJcbiAgbmV4dCgpIHtcclxuICAgIGlmICh0aGlzLmlzRG9uZSkge1xyXG4gICAgICByZXR1cm4gRE9ORSBhcyBQcm9taXNlPE1peEFzeW5jR2VuZXJhdG9yLlJlc3VsdDxUPj47XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5fZGVxdWV1ZVJlc3VsdCgpO1xyXG4gIH1cclxuICBnZXQgaXNEb25lKCkge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgLyogX2FsbEdlbkxpc3TkuLrnqbrkuZ/lsLHmhI/lkbPnnYBfcnVubmluZ+S4uuepuiAqLyB0aGlzLl9hbGxHZW5MaXN0LnNpemUgPT09IDAgJiZcclxuICAgICAgdGhpcy5fZnJlZVJlc3VsdC5zaXplID09PSAwICYmXHJcbiAgICAgIHRoaXMuX2JlbmNoUmVzdWx0LnNpemUgPT09IDBcclxuICAgICk7XHJcbiAgfVxyXG4gIGFzeW5jICp0b0FzeW5jSXRlcmF0b3IoKSB7XHJcbiAgICB3aGlsZSAodHJ1ZSkge1xyXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLm5leHQoKTtcclxuICAgICAgaWYgKHJlc3VsdC5zdGVwLmRvbmUpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgeWllbGQgcmVzdWx0LnN0ZXAudmFsdWU7XHJcbiAgICB9XHJcbiAgfVxyXG4gIGFzeW5jIHRvUHJvbWlzZSgpIHtcclxuICAgIHdoaWxlICh0cnVlKSB7XHJcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMubmV4dCgpO1xyXG4gICAgICBpZiAocmVzdWx0LnN0ZXAuZG9uZSkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0=