ts-generic-collections-linq
Version:
TypeScript library provides strongly-typed, queryable collections.
661 lines • 45.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { List } from './list';
import { Group, objCompare, ITEM_NOT_FOUND_MSG, MULTIPLE_INSTANCES_FOUND_MSG } from './common';
/**
* @record
* @template TKey, TValue
*/
export function IDictionary() { }
if (false) {
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
IDictionary.prototype.add = function (key, value) { };
/**
* @param {?} items
* @return {?}
*/
IDictionary.prototype.addRange = function (items) { };
/**
* @param {?} predicate
* @return {?}
*/
IDictionary.prototype.remove = function (predicate) { };
/**
* @param {?} index
* @return {?}
*/
IDictionary.prototype.removeAt = function (index) { };
/**
* @return {?}
*/
IDictionary.prototype.clear = function () { };
/**
* @param {?} key
* @return {?}
*/
IDictionary.prototype.containsKey = function (key) { };
/**
* @param {?} value
* @return {?}
*/
IDictionary.prototype.containsValue = function (value) { };
/**
* @param {?} key
* @return {?}
*/
IDictionary.prototype.tryGetValue = function (key) { };
}
/**
* @template TKey, TValue
*/
export class Dictionary {
/**
* @param {?=} list
*/
constructor(list = null) {
this.list = new Array();
if (list) {
this.list = list;
}
}
/* IList */
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
add(key, value) {
/** @type {?} */
let pair = new KeyValuePair(key, value);
if (this.containsKey(key)) {
throw "Duplicate key. Cannot add.";
}
this.list.push(pair);
}
/**
* @param {?} items
* @return {?}
*/
addRange(items) {
items.forEach((/**
* @param {?} x
* @return {?}
*/
x => this.add(x.key, x.value)));
}
/**
* @param {?} index
* @return {?}
*/
removeAt(index) {
this.list.splice(index, 1);
}
/**
* @return {?}
*/
clear() {
this.list = new Array();
}
/**
* @param {?} predicate
* @return {?}
*/
remove(predicate) {
/** @type {?} */
let temp = new Array();
this.list.forEach((/**
* @param {?} element
* @return {?}
*/
element => {
if (!predicate(element)) {
temp.push(element);
}
}));
this.list = temp;
}
/**
* @param {?} key
* @return {?}
*/
containsKey(key) {
return this.any((/**
* @param {?} x
* @return {?}
*/
x => objCompare(x.key, key)));
}
/**
* @param {?} value
* @return {?}
*/
containsValue(value) {
return this.any((/**
* @param {?} x
* @return {?}
*/
x => objCompare(x.value, value)));
}
/**
* @param {?} key
* @return {?}
*/
tryGetValue(key) {
/** @type {?} */
let item = this.singleOrDefault((/**
* @param {?} x
* @return {?}
*/
x => objCompare(x.key, key)));
if (item) {
return item.value;
}
return null;
}
/* IEnumerable */
/**
* @return {?}
*/
asEnumerable() {
return this;
}
/**
* @return {?}
*/
get length() {
return this.list.length;
}
/**
* @param {?} index
* @return {?}
*/
elementAt(index) {
try {
return this.list[index];
}
catch (e) {
return null;
}
}
/**
* @param {?=} predicate
* @return {?}
*/
any(predicate) {
if (!predicate) {
return this.list.length > 0;
}
for (let i = 0; i < this.list.length; i++) {
if (predicate(this.list[i])) {
return true;
}
}
return false;
}
/**
* @param {?=} predicate
* @return {?}
*/
all(predicate) {
if (!predicate) {
return this.list.length > 0;
}
for (let i = 0; i < this.list.length; i++) {
if (!predicate(this.list[i])) {
return false;
}
}
return true;
}
/**
* @param {?=} predicate
* @return {?}
*/
single(predicate = null) {
if (this.list.length <= 0) {
throw ITEM_NOT_FOUND_MSG;
}
if (predicate) {
/** @type {?} */
let item = this.singleOrDefault(predicate);
if (!item) {
throw ITEM_NOT_FOUND_MSG;
}
return item;
}
return this.list[0];
}
/**
* @param {?=} predicate
* @return {?}
*/
first(predicate = null) {
if (this.list.length <= 0) {
throw ITEM_NOT_FOUND_MSG;
}
if (predicate) {
/** @type {?} */
let item = this.firstOrDefault(predicate);
if (!item) {
throw ITEM_NOT_FOUND_MSG;
}
return item;
}
return this.list[0];
}
/**
* @param {?} predicate
* @return {?}
*/
last(predicate) {
if (this.list.length <= 0) {
throw ITEM_NOT_FOUND_MSG;
}
if (predicate) {
/** @type {?} */
let item = this.lastOrDefault(predicate);
if (!item) {
throw ITEM_NOT_FOUND_MSG;
}
return item;
}
return this.list[this.list.length - 1];
}
/**
* @param {?} predicate
* @return {?}
*/
singleOrDefault(predicate) {
/** @type {?} */
let temp = new Array();
this.list.filter((/**
* @param {?} element
* @return {?}
*/
element => {
if (predicate(element)) {
temp.push(element);
}
}));
if (temp.length > 1) {
throw MULTIPLE_INSTANCES_FOUND_MSG;
}
if (temp.length <= 0) {
return null;
}
return temp[0];
}
/**
* @param {?} predicate
* @return {?}
*/
firstOrDefault(predicate) {
for (let i = 0; i < this.length; i++) {
/** @type {?} */
let item = this.list[i];
if (predicate(item)) {
return item;
}
}
return null;
}
/**
* @param {?} predicate
* @return {?}
*/
lastOrDefault(predicate) {
for (let i = this.length; i >= 0; i--) {
/** @type {?} */
let item = this.list[i - 1];
if (predicate(item)) {
return item;
}
}
return null;
}
/**
* @param {?} predicate
* @return {?}
*/
where(predicate) {
/** @type {?} */
let temp = new Dictionary();
this.list.filter((/**
* @param {?} element
* @return {?}
*/
element => {
if (predicate(element)) {
temp.add(element.key, element.value);
}
}));
return temp;
}
/**
* @template TResult
* @param {?} predicate
* @return {?}
*/
select(predicate) {
/** @type {?} */
let temp = new List();
this.forEach((/**
* @param {?} x
* @return {?}
*/
x => temp.add(predicate(x))));
return temp;
}
/**
* @param {?} predicate
* @return {?}
*/
forEach(predicate) {
this.list.forEach((/**
* @param {?} x
* @return {?}
*/
x => predicate(x)));
}
/**
* @return {?}
*/
toArray() {
return this.list.slice();
}
/**
* @template TOuter, TMatch, TResult
* @param {?} outer
* @param {?} conditionInner
* @param {?} conditionOuter
* @param {?} select
* @param {?=} leftJoin
* @return {?}
*/
join(outer, conditionInner, conditionOuter, select, leftJoin = false) {
/** @type {?} */
let resultList = new List();
this.list.forEach((/**
* @param {?} x
* @return {?}
*/
x => {
/** @type {?} */
let outerEntries = outer.toArray().filter((/**
* @param {?} y
* @return {?}
*/
y => conditionInner(x) === conditionOuter(y)));
if (leftJoin && outerEntries && outerEntries.length <= 0) {
resultList.add(select(x, null));
}
else {
outerEntries.forEach((/**
* @param {?} z
* @return {?}
*/
z => resultList.add(select(x, z))));
}
}));
return resultList;
}
/**
* @param {?} predicate
* @return {?}
*/
groupBy(predicate) {
/** @type {?} */
let groups = {};
this.list.forEach((/**
* @param {?} o
* @return {?}
*/
function (o) {
/** @type {?} */
var group = JSON.stringify(predicate(o));
groups[group] = groups[group] || [];
groups[group].push(o);
}));
/** @type {?} */
let g = Object.keys(groups).map((/**
* @param {?} group
* @return {?}
*/
function (group) {
/** @type {?} */
let a = group.substr(1, group.length - 2);
/** @type {?} */
let grp = new Group(new List(a.split(',')).select((/**
* @param {?} x
* @return {?}
*/
x => x.replace(/^(")?(.*?)(")?$/ig, "$2"))).toArray(), groups[group]);
return grp;
}));
return new List(g);
}
/**
* @template TResult
* @param {?} predicate
* @return {?}
*/
selectMany(predicate) {
return this.list.reduce((/**
* @param {?} out
* @param {?} inx
* @return {?}
*/
(out, inx) => {
/** @type {?} */
var items = predicate(inx);
out.addRange(items);
return out;
}), new List(new Array()));
}
/**
* @param {?} comparer
* @return {?}
*/
orderBy(comparer) {
/** @type {?} */
let temp = this.list.sort((/**
* @param {?} x
* @param {?} y
* @return {?}
*/
(x, y) => comparer.compare(x, y)));
return new List(temp);
}
/**
* @param {?} comparer
* @return {?}
*/
distinct(comparer) {
/** @type {?} */
let uniques = new List();
this.forEach((/**
* @param {?} x
* @return {?}
*/
x => {
if (uniques.length > 0) {
if (!uniques.any((/**
* @param {?} y
* @return {?}
*/
y => comparer.equals(x, y)))) {
uniques.add(x);
}
}
else {
uniques.add(x);
}
}));
return uniques;
}
/**
* @param {?} list
* @return {?}
*/
union(list) {
this.addRange(list.toArray());
return this;
}
/**
* @return {?}
*/
reverse() {
return new List(this.list.slice().reverse());
}
/**
* @param {?} no
* @return {?}
*/
skip(no) {
if (no > 0) {
return new Dictionary(this.list.slice(no, this.list.length - 1));
}
return this;
}
/**
* @param {?} no
* @return {?}
*/
take(no) {
if (no > 0) {
return new Dictionary(this.list.slice(0, no));
}
return this;
}
/**
* @param {?} predicate
* @return {?}
*/
sum(predicate) {
/** @type {?} */
let sum = 0;
this.list.forEach((/**
* @param {?} x
* @return {?}
*/
x => sum = sum + predicate(x)));
return sum;
}
/**
* @param {?} predicate
* @return {?}
*/
avg(predicate) {
return this.sum(predicate) / this.length;
}
/**
* @param {?} predicate
* @return {?}
*/
min(predicate) {
/** @type {?} */
let min = 0;
/** @type {?} */
let i = 0;
this.list.forEach((/**
* @param {?} x
* @return {?}
*/
x => {
if (i == 0) {
min = predicate(x);
}
else {
/** @type {?} */
let val = predicate(x);
if (val < min) {
min = val;
}
}
i++;
}));
return min;
}
/**
* @param {?} predicate
* @return {?}
*/
max(predicate) {
/** @type {?} */
let max = 0;
/** @type {?} */
let i = 0;
this.list.forEach((/**
* @param {?} x
* @return {?}
*/
x => {
if (i == 0) {
max = predicate(x);
}
else {
/** @type {?} */
let val = predicate(x);
if (val > max) {
max = val;
}
}
i++;
}));
return max;
}
/**
* @param {?=} predicate
* @return {?}
*/
count(predicate = null) {
if (!predicate) {
return this.length;
}
/** @type {?} */
let count = 0;
this.list.forEach((/**
* @param {?} x
* @return {?}
*/
x => {
if (predicate(x)) {
count++;
}
}));
return count;
}
}
if (false) {
/**
* @type {?}
* @private
*/
Dictionary.prototype.list;
}
/**
* @template TKey, TValue
*/
export class KeyValuePair {
/**
* @param {?} key
* @param {?} value
*/
constructor(key, value) {
this.key = key;
this.value = value;
}
}
if (false) {
/** @type {?} */
KeyValuePair.prototype.key;
/** @type {?} */
KeyValuePair.prototype.value;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGljdGlvbmFyeS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL3RzLWdlbmVyaWMtY29sbGVjdGlvbnMtbGlucS8iLCJzb3VyY2VzIjpbImxpYi9kaWN0aW9uYXJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFDQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQzlCLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLGtCQUFrQixFQUFFLDRCQUE0QixFQUFFLE1BQU0sVUFBVSxDQUFDOzs7OztBQUUvRixpQ0FVQzs7Ozs7OztJQVRHLHNEQUFxQzs7Ozs7SUFDckMsc0RBQXFEOzs7OztJQUNyRCx3REFBdUU7Ozs7O0lBQ3ZFLHNEQUErQjs7OztJQUMvQiw4Q0FBZTs7Ozs7SUFFZix1REFBaUM7Ozs7O0lBQ2pDLDJEQUF1Qzs7Ozs7SUFDdkMsdURBQWdDOzs7OztBQUdwQyxNQUFNLE9BQU8sVUFBVTs7OztJQUluQixZQUFZLE9BQTBDLElBQUk7UUFGbEQsU0FBSSxHQUFzQyxJQUFJLEtBQUssRUFBOEIsQ0FBQztRQUd0RixJQUFJLElBQUksRUFBRTtZQUNOLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1NBQ3BCO0lBQ0wsQ0FBQzs7Ozs7OztJQUlELEdBQUcsQ0FBQyxHQUFTLEVBQUUsS0FBYTs7WUFDcEIsSUFBSSxHQUFHLElBQUksWUFBWSxDQUFlLEdBQUcsRUFBRSxLQUFLLENBQUM7UUFFckQsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ3ZCLE1BQU0sNEJBQTRCLENBQUE7U0FDckM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN6QixDQUFDOzs7OztJQUVELFFBQVEsQ0FBQyxLQUFtQztRQUN4QyxLQUFLLENBQUMsT0FBTzs7OztRQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FB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R0FBRyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN0QjtpQkFDSTs7b0JBQ0csR0FBRyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3RCLElBQUksR0FBRyxHQUFHLEdBQUcsRUFBRTtvQkFDWCxHQUFHLEdBQUcsR0FBRyxDQUFDO2lCQUNiO2FBQ0o7WUFDRCxDQUFDLEVBQUUsQ0FBQztRQUNSLENBQUMsRUFBQyxDQUFDO1FBRUgsT0FBTyxHQUFHLENBQUM7SUFDZixDQUFDOzs7OztJQUVELEtBQUssQ0FBQyxZQUEwRCxJQUFJO1FBQ2hFLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDWixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7U0FDdEI7O1lBRUcsS0FBSyxHQUFXLENBQUM7UUFDckIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPOzs7O1FBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDbEIsSUFBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQ2IsS0FBSyxFQUFFLENBQUM7YUFDWDtRQUNMLENBQUMsRUFBQyxDQUFDO1FBRUgsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztDQUNKOzs7Ozs7SUE3WUcsMEJBQTBGOzs7OztBQStZOUYsTUFBTSxPQUFPLFlBQVk7Ozs7O0lBSXJCLFlBQVksR0FBUyxFQUFFLEtBQWE7UUFDaEMsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUN2QixDQUFDO0NBQ0o7OztJQVBHLDJCQUFVOztJQUNWLDZCQUFjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSUVudW1lcmFibGUsIElDb21wYXJlciwgSUVxdWFsaXR5Q29tcGFyZXIgfSBmcm9tICcuL2ludGVyZmFjZXMnO1xyXG5pbXBvcnQgeyBMaXN0IH0gZnJvbSAnLi9saXN0JztcclxuaW1wb3J0IHsgR3JvdXAsIG9iakNvbXBhcmUsIElURU1fTk9UX0ZPVU5EX01TRywgTVVMVElQTEVfSU5TVEFOQ0VTX0ZPVU5EX01TRyB9IGZyb20gJy4vY29tbW9uJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSURpY3Rpb25hcnk8VEtleSwgVFZhbHVlPiBleHRlbmRzIElFbnVtZXJhYmxlPEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+PiB7XHJcbiAgICBhZGQoa2V5OiBUS2V5LCB2YWx1ZTogVFZhbHVlKSA6IHZvaWQ7XHJcbiAgICBhZGRSYW5nZShpdGVtczogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT5bXSkgOiB2b2lkO1xyXG4gICAgcmVtb3ZlKHByZWRpY2F0ZTogKGl0ZW06S2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pID0+IGJvb2xlYW4pIDogdm9pZDtcclxuICAgIHJlbW92ZUF0KGluZGV4OiBudW1iZXIpIDogdm9pZDtcclxuICAgIGNsZWFyKCkgOiB2b2lkO1xyXG5cclxuICAgIGNvbnRhaW5zS2V5KGtleTogVEtleSkgOiBib29sZWFuO1xyXG4gICAgY29udGFpbnNWYWx1ZSh2YWx1ZTogVFZhbHVlKSA6IGJvb2xlYW47XHJcbiAgICB0cnlHZXRWYWx1ZShrZXk6IFRLZXkpIDogVFZhbHVlO1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgRGljdGlvbmFyeTxUS2V5LCBUVmFsdWU+IGltcGxlbWVudHMgSURpY3Rpb25hcnk8VEtleSwgVFZhbHVlPlxyXG57XHJcbiAgICBwcml2YXRlIGxpc3Q6IEFycmF5PEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+PiA9IG5ldyBBcnJheTxLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPj4oKTtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihsaXN0OiBBcnJheTxLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPj4gPSBudWxsKSB7XHJcbiAgICAgICAgaWYgKGxpc3QpIHtcclxuICAgICAgICAgICAgdGhpcy5saXN0ID0gbGlzdDtcclxuICAgICAgICB9ICAgICAgICBcclxuICAgIH1cclxuXHJcbiAgICAvKiBJTGlzdCAqL1xyXG5cclxuICAgIGFkZChrZXk6IFRLZXksIHZhbHVlOiBUVmFsdWUpIDogdm9pZCB7XHJcbiAgICAgICAgbGV0IHBhaXIgPSBuZXcgS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4oa2V5LCB2YWx1ZSk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmNvbnRhaW5zS2V5KGtleSkpIHtcclxuICAgICAgICAgICAgdGhyb3cgXCJEdXBsaWNhdGUga2V5LiBDYW5ub3QgYWRkLlwiXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmxpc3QucHVzaChwYWlyKTtcclxuICAgIH1cclxuXHJcbiAgICBhZGRSYW5nZShpdGVtczogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT5bXSkgOiB2b2lkIHtcclxuICAgICAgICBpdGVtcy5mb3JFYWNoKHggPT4gdGhpcy5hZGQoeC5rZXksIHgudmFsdWUpKTtcclxuICAgIH1cclxuXHJcbiAgICByZW1vdmVBdChpbmRleDogbnVtYmVyKSA6IHZvaWQge1xyXG4gICAgICAgIHRoaXMubGlzdC5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgfVxyXG5cclxuICAgIGNsZWFyKCkgOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmxpc3QgPSBuZXcgQXJyYXk8S2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4+KCk7XHJcbiAgICB9ICAgIFxyXG5cclxuICAgIHJlbW92ZShwcmVkaWNhdGU6IChpdGVtOktleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KSA9PiBib29sZWFuKSA6IHZvaWQge1xyXG4gICAgICAgIGxldCB0ZW1wID0gbmV3IEFycmF5PEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+PigpO1xyXG5cclxuICAgICAgICB0aGlzLmxpc3QuZm9yRWFjaChlbGVtZW50ID0+IHtcclxuICAgICAgICAgICAgaWYgKCFwcmVkaWNhdGUoZWxlbWVudCkpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHRlbXAucHVzaChlbGVtZW50KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB0aGlzLmxpc3QgPSB0ZW1wO1xyXG4gICAgfSAgICBcclxuXHJcbiAgICBjb250YWluc0tleShrZXk6IFRLZXkpIDogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYW55KHggPT4gb2JqQ29tcGFyZSh4LmtleSwga2V5KSk7XHJcbiAgICB9XHJcblxyXG4gICAgY29udGFpbnNWYWx1ZSh2YWx1ZTogVFZhbHVlKSA6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmFueSh4ID0+IG9iakNvbXBhcmUoeC52YWx1ZSwgdmFsdWUpKTtcclxuICAgIH1cclxuXHJcbiAgICB0cnlHZXRWYWx1ZShrZXk6IFRLZXkpIDogVFZhbHVlIHtcclxuICAgICAgICBsZXQgaXRlbSA9IHRoaXMuc2luZ2xlT3JEZWZhdWx0KHggPT4gb2JqQ29tcGFyZSh4LmtleSwga2V5KSk7XHJcblxyXG4gICAgICAgIGlmIChpdGVtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBpdGVtLnZhbHVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyogSUVudW1lcmFibGUgKi9cclxuXHJcbiAgICBhc0VudW1lcmFibGUoKSA6IElFbnVtZXJhYmxlPEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IGxlbmd0aCgpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmxpc3QubGVuZ3RoO1xyXG4gICAgfVxyXG5cclxuICAgIGVsZW1lbnRBdChpbmRleDogbnVtYmVyKSA6IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5saXN0W2luZGV4XTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgfSAgICBcclxuXHJcbiAgICBhbnkocHJlZGljYXRlPzogKGl0ZW06IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KT0+IGJvb2xlYW4pIDogYm9vbGVhbiB7XHJcbiAgICAgICAgaWYgKCFwcmVkaWNhdGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGlzdC5sZW5ndGggPiAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChsZXQgaT0wOyBpPHRoaXMubGlzdC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAocHJlZGljYXRlKHRoaXMubGlzdFtpXSkpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBhbGwocHJlZGljYXRlPzogKGl0ZW06IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KT0+IGJvb2xlYW4pIDogYm9vbGVhbiB7XHJcbiAgICAgICAgaWYgKCFwcmVkaWNhdGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGlzdC5sZW5ndGggPiAwO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8dGhpcy5saXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmICghcHJlZGljYXRlKHRoaXMubGlzdFtpXSkpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH0gICAgXHJcblxyXG4gICAgc2luZ2xlKHByZWRpY2F0ZTogKGl0ZW06IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KT0+IGJvb2xlYW4gPSBudWxsKSA6IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+IHtcclxuICAgICAgICBpZiAodGhpcy5saXN0Lmxlbmd0aCA8PSAwKSB7XHJcbiAgICAgICAgICAgIHRocm93IElURU1fTk9UX0ZPVU5EX01TRztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcmVkaWNhdGUpIHtcclxuICAgICAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLnNpbmdsZU9yRGVmYXVsdChwcmVkaWNhdGUpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCFpdGVtKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBJVEVNX05PVF9GT1VORF9NU0c7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiBpdGVtO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICByZXR1cm4gdGhpcy5saXN0WzBdO1xyXG4gICAgfVxyXG5cclxuICAgIGZpcnN0KHByZWRpY2F0ZTogKGl0ZW06IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KT0+IGJvb2xlYW4gPSBudWxsKSA6IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+IHtcclxuICAgICAgICBpZiAodGhpcy5saXN0Lmxlbmd0aCA8PSAwKSB7XHJcbiAgICAgICAgICAgIHRocm93IElURU1fTk9UX0ZPVU5EX01TRztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcmVkaWNhdGUpIHtcclxuICAgICAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLmZpcnN0T3JEZWZhdWx0KHByZWRpY2F0ZSk7XHJcblxyXG4gICAgICAgICAgICBpZiAoIWl0ZW0pIHtcclxuICAgICAgICAgICAgICAgIHRocm93IElURU1fTk9UX0ZPVU5EX01TRztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIGl0ZW07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RbMF07XHJcbiAgICB9XHJcbiAgICBcclxuICAgIGxhc3QocHJlZGljYXRlOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gYm9vbGVhbikgOiBLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPiB7XHJcbiAgICAgICAgaWYgKHRoaXMubGlzdC5sZW5ndGggPD0gMCkge1xyXG4gICAgICAgICAgICB0aHJvdyBJVEVNX05PVF9GT1VORF9NU0c7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocHJlZGljYXRlKSB7XHJcbiAgICAgICAgICAgIGxldCBpdGVtID0gdGhpcy5sYXN0T3JEZWZhdWx0KHByZWRpY2F0ZSk7XHJcblxyXG4gICAgICAgICAgICBpZiAoIWl0ZW0pIHtcclxuICAgICAgICAgICAgICAgIHRocm93IElURU1fTk9UX0ZPVU5EX01TRztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIGl0ZW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5saXN0W3RoaXMubGlzdC5sZW5ndGggLSAxXTtcclxuICAgIH0gICAgXHJcblxyXG4gICAgc2luZ2xlT3JEZWZhdWx0KHByZWRpY2F0ZTogKGl0ZW06IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KT0+IGJvb2xlYW4pIDogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4ge1xyXG4gICAgICAgIGxldCB0ZW1wID0gbmV3IEFycmF5PEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+PigpO1xyXG5cclxuICAgICAgICB0aGlzLmxpc3QuZmlsdGVyKGVsZW1lbnQgPT4ge1xyXG4gICAgICAgICAgICBpZiAocHJlZGljYXRlKGVsZW1lbnQpKVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICB0ZW1wLnB1c2goZWxlbWVudCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgaWYgKHRlbXAubGVuZ3RoID4gMSkge1xyXG4gICAgICAgICAgICB0aHJvdyBNVUxUSVBMRV9JTlNUQU5DRVNfRk9VTkRfTVNHO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRlbXAubGVuZ3RoIDw9IDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGVtcFswXTtcclxuICAgIH0gICAgXHJcblxyXG4gICAgZmlyc3RPckRlZmF1bHQocHJlZGljYXRlOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gYm9vbGVhbikgOiBLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPiB7ICAgICAgICBcclxuICAgICAgICBmb3IgKGxldCBpPTA7IGk8dGhpcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgaXRlbSA9IHRoaXMubGlzdFtpXTtcclxuICAgICAgICAgICAgaWYgKHByZWRpY2F0ZShpdGVtKSlcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIGxhc3RPckRlZmF1bHQocHJlZGljYXRlOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gYm9vbGVhbikgOiBLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPiB7XHJcbiAgICAgICAgZm9yIChsZXQgaT10aGlzLmxlbmd0aDsgaT49MDsgaS0tKSB7XHJcbiAgICAgICAgICAgIGxldCBpdGVtID0gdGhpcy5saXN0W2kgLSAxXTtcclxuICAgICAgICAgICAgaWYgKHByZWRpY2F0ZShpdGVtKSlcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfSAgICBcclxuXHJcbiAgICB3aGVyZShwcmVkaWNhdGU6IChpdGVtOiBLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPik9PiBib29sZWFuKSA6IElEaWN0aW9uYXJ5PFRLZXksIFRWYWx1ZT4ge1xyXG4gICAgICAgIGxldCB0ZW1wID0gbmV3IERpY3Rpb25hcnk8VEtleSwgVFZhbHVlPigpO1xyXG5cclxuICAgICAgICB0aGlzLmxpc3QuZmlsdGVyKGVsZW1lbnQgPT4ge1xyXG4gICAgICAgICAgICBpZiAocHJlZGljYXRlKGVsZW1lbnQpKVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICB0ZW1wLmFkZChlbGVtZW50LmtleSwgZWxlbWVudC52YWx1ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRlbXA7XHJcbiAgICB9XHJcblxyXG4gICAgc2VsZWN0PFRSZXN1bHQ+KHByZWRpY2F0ZTogKGl0ZW06IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KT0+IFRSZXN1bHQpIDogSUVudW1lcmFibGU8VFJlc3VsdD4ge1xyXG4gICAgICAgIGxldCB0ZW1wID0gbmV3IExpc3Q8VFJlc3VsdD4oKTtcclxuXHJcbiAgICAgICAgdGhpcy5mb3JFYWNoKHggPT4gdGVtcC5hZGQocHJlZGljYXRlKHgpKSk7XHJcblxyXG4gICAgICAgIHJldHVybiB0ZW1wO1xyXG4gICAgfVxyXG5cclxuICAgIGZvckVhY2gocHJlZGljYXRlOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gdm9pZCkgOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmxpc3QuZm9yRWFjaCh4ID0+IHByZWRpY2F0ZSh4KSk7XHJcbiAgICB9XHJcblxyXG4gICAgdG9BcnJheSgpIDogQXJyYXk8S2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5saXN0LnNsaWNlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgam9pbjxUT3V0ZXIsIFRNYXRjaCwgVFJlc3VsdD4ob3V0ZXI6IElFbnVtZXJhYmxlPFRPdXRlcj4sIGNvbmRpdGlvbklubmVyOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gVE1hdGNoLCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZGl0aW9uT3V0ZXI6IChpdGVtOiBUT3V0ZXIpPT4gVE1hdGNoLCBzZWxlY3Q6ICh4OiBLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPiwgeTpUT3V0ZXIpPT4gVFJlc3VsdCwgbGVmdEpvaW46IGJvb2xlYW4gPSBmYWxzZSkgOiBJRW51bWVyYWJsZTxUUmVzdWx0PiB7XHJcbiAgICAgICAgbGV0IHJlc3VsdExpc3QgPSBuZXcgTGlzdDxUUmVzdWx0PigpO1xyXG5cclxuICAgICAgICB0aGlzLmxpc3QuZm9yRWFjaCh4ID0+IHtcclxuICAgICAgICAgICAgbGV0IG91dGVyRW50cmllcyA9IG91dGVyLnRvQXJyYXkoKS5maWx0ZXIoeSA9PiBjb25kaXRpb25Jbm5lcih4KSA9PT0gY29uZGl0aW9uT3V0ZXIoeSkpO1xyXG5cclxuICAgICAgICAgICAgaWYgKGxlZnRKb2luICYmIG91dGVyRW50cmllcyAmJiBvdXRlckVudHJpZXMubGVuZ3RoIDw9IDApIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdExpc3QuYWRkKHNlbGVjdCh4LCBudWxsKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBvdXRlckVudHJpZXMuZm9yRWFjaCh6ID0+IHJlc3VsdExpc3QuYWRkKHNlbGVjdCh4LCB6KSkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSlcclxuXHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdExpc3Q7XHJcbiAgICB9XHJcblxyXG4gICAgZ3JvdXBCeShwcmVkaWNhdGU6IChpdGVtOiBLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPikgPT4gQXJyYXk8YW55PikgOiBJRW51bWVyYWJsZTxHcm91cDxLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPj4+IHtcclxuICAgICAgICBsZXQgZ3JvdXBzID0ge307XHJcbiAgICAgICAgdGhpcy5saXN0LmZvckVhY2goZnVuY3Rpb24gKG8pIHtcclxuICAgICAgICAgIHZhciBncm91cCA9IEpTT04uc3RyaW5naWZ5KHByZWRpY2F0ZShvKSk7XHJcbiAgICAgICAgICBncm91cHNbZ3JvdXBdID0gZ3JvdXBzW2dyb3VwXSB8fCBbXTtcclxuICAgICAgICAgIGdyb3Vwc1tncm91cF0ucHVzaChvKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICBsZXQgZyA9IE9iamVjdC5rZXlzKGdyb3VwcykubWFwKGZ1bmN0aW9uIChncm91cCkgeyAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgbGV0IGEgPSBncm91cC5zdWJzdHIoMSwgZ3JvdXAubGVuZ3RoIC0gMik7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBsZXQgZ3JwPSBuZXcgR3JvdXA8S2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4+KG5ldyBMaXN0KGEuc3BsaXQoJywnKSkuc2VsZWN0KHggPT4geC5yZXBsYWNlKC9eKFwiKT8oLio/KShcIik/JC9pZywgXCIkMlwiKSkudG9BcnJheSgpLCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBzW2dyb3VwXSk7ICAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICByZXR1cm4gZ3JwO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gbmV3IExpc3Q8R3JvdXA8S2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4+PihnKTsgICAgICAgIFxyXG4gICAgfVxyXG5cclxuICAgIHNlbGVjdE1hbnk8VFJlc3VsdD4ocHJlZGljYXRlOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gQXJyYXk8VFJlc3VsdD4pIDogSUVudW1lcmFibGU8VFJlc3VsdD4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmxpc3QucmVkdWNlKChvdXQsIGlueCkgPT4ge1xyXG4gICAgICAgICAgICB2YXIgaXRlbXMgPSBwcmVkaWNhdGUoaW54KTtcclxuICAgICAgICAgICAgb3V0LmFkZFJhbmdlKGl0ZW1zKTtcclxuICAgICAgICAgICAgcmV0dXJuIG91dDtcclxuICAgICAgICAgIH0sIG5ldyBMaXN0PFRSZXN1bHQ+KG5ldyBBcnJheTxUUmVzdWx0PigpKSk7XHJcbiAgICB9XHJcblxyXG4gICAgb3JkZXJCeShjb21wYXJlcjogSUNvbXBhcmVyPEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+PikgOiBJRW51bWVyYWJsZTxLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPj4ge1xyXG4gICAgICAgIGxldCB0ZW1wID0gdGhpcy5saXN0LnNvcnQoKHgseSkgPT4gY29tcGFyZXIuY29tcGFyZSh4LCB5KSk7XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgTGlzdDxLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPj4odGVtcCk7XHJcbiAgICB9XHJcblxyXG4gICAgZGlzdGluY3QoY29tcGFyZXI6IElFcXVhbGl0eUNvbXBhcmVyPEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+PikgOiBJRW51bWVyYWJsZTxLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPj4ge1xyXG4gICAgICAgIGxldCB1bmlxdWVzID0gbmV3IExpc3Q8S2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4+KCk7XHJcbiAgICAgICAgdGhpcy5mb3JFYWNoKHggPT4ge1xyXG4gICAgICAgICAgICBpZiAodW5pcXVlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXVuaXF1ZXMuYW55KHkgPT4gY29tcGFyZXIuZXF1YWxzKHgsIHkpKSlcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICB1bmlxdWVzLmFkZCh4KTtcclxuICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHVuaXF1ZXMuYWRkKHgpO1xyXG4gICAgICAgICAgICB9ICAgICAgICAgICAgXHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiB1bmlxdWVzO1xyXG4gICAgfVxyXG5cclxuICAgIHVuaW9uKGxpc3Q6IElFbnVtZXJhYmxlPEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+PikgOiBJRGljdGlvbmFyeTxUS2V5LCBUVmFsdWU+IHtcclxuICAgICAgICAgdGhpcy5hZGRSYW5nZShsaXN0LnRvQXJyYXkoKSk7XHJcblxyXG4gICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH0gICAgXHJcblxyXG4gICAgcmV2ZXJzZSgpOiBJRW51bWVyYWJsZTxLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPj4ge1xyXG4gICAgICAgIHJldHVybiBuZXcgTGlzdDxLZXlWYWx1ZVBhaXI8VEtleSwgVFZhbHVlPj4odGhpcy5saXN0LnNsaWNlKCkucmV2ZXJzZSgpKTtcclxuICAgIH1cclxuXHJcbiAgICBza2lwKG5vOiBudW1iZXIpIDogSURpY3Rpb25hcnk8VEtleSwgVFZhbHVlPiB7XHJcbiAgICAgICAgaWYgKG5vID4gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbmV3IERpY3Rpb25hcnkodGhpcy5saXN0LnNsaWNlKG5vLCB0aGlzLmxpc3QubGVuZ3RoIC0gMSkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH1cclxuXHJcbiAgICB0YWtlKG5vOiBudW1iZXIpIDogSURpY3Rpb25hcnk8VEtleSwgVFZhbHVlPiB7XHJcbiAgICAgICAgaWYgKG5vID4gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbmV3IERpY3Rpb25hcnkodGhpcy5saXN0LnNsaWNlKDAsIG5vKSk7XHJcbiAgICAgICAgfSAgICAgICAgXHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfSAgICBcclxuXHJcbiAgICBzdW0ocHJlZGljYXRlOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gbnVtYmVyKSA6IG51bWJlciB7XHJcbiAgICAgICAgbGV0IHN1bTogbnVtYmVyID0gMDtcclxuICAgICAgICB0aGlzLmxpc3QuZm9yRWFjaCh4ID0+IHN1bSA9IHN1bSArIHByZWRpY2F0ZSh4KSk7XHJcblxyXG4gICAgICAgIHJldHVybiBzdW07XHJcbiAgICB9XHJcblxyXG4gICAgYXZnKHByZWRpY2F0ZTogKGl0ZW06IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KT0+IG51bWJlcikgOiBudW1iZXIgeyAgICAgICAgXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuc3VtKHByZWRpY2F0ZSkgLyB0aGlzLmxlbmd0aDtcclxuICAgIH1cclxuXHJcbiAgICBtaW4ocHJlZGljYXRlOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gbnVtYmVyKSA6IG51bWJlciB7XHJcbiAgICAgICAgbGV0IG1pbjogbnVtYmVyID0gMDtcclxuICAgICAgICBsZXQgaSA9IDA7XHJcbiAgICAgICAgdGhpcy5saXN0LmZvckVhY2goeCA9PiBcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGlmIChpID09IDApIHtcclxuICAgICAgICAgICAgICAgIG1pbiA9IHByZWRpY2F0ZSh4KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGxldCB2YWwgPSBwcmVkaWNhdGUoeCk7XHJcbiAgICAgICAgICAgICAgICBpZiAodmFsIDwgbWluKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWluID0gdmFsO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9ICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGkrKztcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIG1pbjtcclxuICAgIH1cclxuICAgIFxyXG4gICAgbWF4KHByZWRpY2F0ZTogKGl0ZW06IEtleVZhbHVlUGFpcjxUS2V5LCBUVmFsdWU+KT0+IG51bWJlcikgOiBudW1iZXIge1xyXG4gICAgICAgIGxldCBtYXg6IG51bWJlciA9IDA7XHJcbiAgICAgICAgbGV0IGkgPSAwO1xyXG4gICAgICAgIHRoaXMubGlzdC5mb3JFYWNoKHggPT4gXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBpZiAoaSA9PSAwKSB7XHJcbiAgICAgICAgICAgICAgICBtYXggPSBwcmVkaWNhdGUoeCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgdmFsID0gcHJlZGljYXRlKHgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHZhbCA+IG1heCkge1xyXG4gICAgICAgICAgICAgICAgICAgIG1heCA9IHZhbDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBpKys7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBtYXg7XHJcbiAgICB9XHJcblxyXG4gICAgY291bnQocHJlZGljYXRlOiAoaXRlbTogS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4pPT4gYm9vbGVhbiA9IG51bGwpIDogbnVtYmVyIHtcclxuICAgICAgICBpZiAoIXByZWRpY2F0ZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sZW5ndGg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgY291bnQ6IG51bWJlciA9IDA7XHJcbiAgICAgICAgdGhpcy5saXN0LmZvckVhY2goeCA9PiB7XHJcbiAgICAgICAgICAgIGlmKHByZWRpY2F0ZSh4KSkge1xyXG4gICAgICAgICAgICAgICAgY291bnQrKztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gY291bnQ7XHJcbiAgICB9ICAgIFxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgS2V5VmFsdWVQYWlyPFRLZXksIFRWYWx1ZT4ge1xyXG4gICAga2V5OiBUS2V5O1xyXG4gICAgdmFsdWU6IFRWYWx1ZTtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihrZXk6IFRLZXksIHZhbHVlOiBUVmFsdWUpIHtcclxuICAgICAgICB0aGlzLmtleSA9IGtleTtcclxuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XHJcbiAgICB9XHJcbn0iXX0=