UNPKG

faastjs

Version:

Serverless batch computing made simple.

291 lines 32.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SmallestN = exports.MaxHeap = exports.defined = exports.keysOf = exports.f2 = exports.f1 = exports.KB = exports.MB = exports.GB = exports.uuidv4Pattern = exports.roundTo100ms = exports.hasExpired = exports.computeHttpResponseBytes = exports.objectSize = exports.sum = exports.chomp = exports.streamToBuffer = exports.sleep = exports.ExponentiallyDecayingAverageValue = exports.Statistics = void 0; /** * Incrementally updated statistics on a set of values. * @public */ class Statistics { /** * Incrementally track mean, stdev, min, max, of a sequence of values. * @param printFixedPrecision - The number of decimal places to print in * {@link Statistics.toString}. */ constructor( /** The number of decimal places to print in {@link Statistics.toString} */ printFixedPrecision = 1) { this.printFixedPrecision = printFixedPrecision; /** Number of values observed. */ this.samples = 0; /** The maximum value observed. Initialized to `Number.NEGATIVE_INFINITY`. */ this.max = Number.NEGATIVE_INFINITY; /** The minimum value observed. Initialized to `Number.POSITIVE_INFINITY`. */ this.min = Number.POSITIVE_INFINITY; /** The variance of the values observed. */ this.variance = 0; /** The standard deviation of the values observed. */ this.stdev = 0; /** The mean (average) of the values observed. */ this.mean = NaN; } /** @internal */ clone() { const rv = new Statistics(this.printFixedPrecision); return Object.assign(rv, this); } /** * Update statistics with a new value in the sequence. */ update(value) { if (value === undefined) { return; } let previousMean = this.mean; // https://math.stackexchange.com/questions/374881/recursive-formula-for-variance let previousVariance = this.variance; if (this.samples === 0) { previousMean = 0; previousVariance = 0; } this.samples++; this.mean = previousMean + (value - previousMean) / this.samples; this.variance = ((previousVariance + (previousMean - value) ** 2 / this.samples) * (this.samples - 1)) / this.samples; this.stdev = Math.sqrt(this.variance); if (value > this.max) { this.max = value; } if (value < this.min) { this.min = value; } } /** * Print the mean of the observations seen, with the precision specified in * the constructor. */ toString() { return `${this.mean.toFixed(this.printFixedPrecision)}`; } } exports.Statistics = Statistics; class ExponentiallyDecayingAverageValue { constructor(smoothingFactor) { this.smoothingFactor = smoothingFactor; this.samples = 0; this.value = 0; } update(n) { // tslint:disable-next-line:prefer-conditional-expression if (this.samples++ === 0) { this.value = n; } else { this.value = this.smoothingFactor * n + (1 - this.smoothingFactor) * this.value; } } toString() { return this.value; } } exports.ExponentiallyDecayingAverageValue = ExponentiallyDecayingAverageValue; function sleep(ms, cancel = new Promise(() => { })) { let id; cancel.then(_ => clearTimeout(id)).catch(_ => clearTimeout(id)); return Promise.race([new Promise(resolve => (id = setTimeout(resolve, ms))), cancel]); } exports.sleep = sleep; function streamToBuffer(s) { return new Promise((resolve, reject) => { const buffers = []; s.on("error", reject); s.on("data", (data) => buffers.push(data)); s.on("end", () => resolve(Buffer.concat(buffers))); }); } exports.streamToBuffer = streamToBuffer; function chomp(s) { if (s.length > 0 && s[s.length - 1] === "\n") { s = s.slice(0, s.length - 1); } return s; } exports.chomp = chomp; const sum = (a) => a.reduce((total, n) => total + n, 0); exports.sum = sum; function objectSize(obj) { if (!obj) { return 0; } return (0, exports.sum)(Object.keys(obj).map(key => key.length + obj[key].length)); } exports.objectSize = objectSize; function computeHttpResponseBytes(headers, opts = { httpHeaders: true, min: 0 }) { const headerKeys = Object.keys(headers); let contentLength = 0; for (const key of headerKeys) { if (key.match(/^content-length$/i)) { contentLength = Number(headers[key]); break; } } if (!opts.httpHeaders) { return Math.max(contentLength, opts.min); } const headerLength = objectSize(headers) + headerKeys.length * ": ".length; const otherLength = 13; return Math.max(contentLength + headerLength + otherLength, opts.min); } exports.computeHttpResponseBytes = computeHttpResponseBytes; function hasExpired(date, retentionInDays) { if (retentionInDays <= 0) { return true; } const timestamp = typeof date === "string" ? Date.parse(date) : date || 0; return timestamp < Date.now() - retentionInDays * 24 * 60 * 60 * 1000; } exports.hasExpired = hasExpired; function roundTo100ms(n) { return Math.round(n / 100) * 100; } exports.roundTo100ms = roundTo100ms; exports.uuidv4Pattern = "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}"; exports.GB = 2 ** 30; exports.MB = 2 ** 20; exports.KB = 2 ** 10; function f1(n) { return n.toFixed(1); } exports.f1 = f1; function f2(n) { return n.toFixed(2); } exports.f2 = f2; function keysOf(obj) { return Object.keys(obj); } exports.keysOf = keysOf; function defined(arg) { return !!arg; } exports.defined = defined; class MaxHeap { constructor() { this._heap = []; } get size() { return this._heap.length; } clear() { this._heap = []; } peekMax() { return this._heap[0]; } insert(value) { const h = this._heap; h.push(value); let i = h.length - 1; const parentOf = (n) => Math.floor((n - 1) / 2); let parent = parentOf(i); while (parent >= 0 && h[i] > h[parent]) { const tmp = h[parent]; h[parent] = h[i]; h[i] = tmp; i = parent; parent = parentOf(i); } } extractMax() { const h = this._heap; if (h.length === 0) { throw new Error("extractMax called on empty heap"); } let i = 0; const rv = h[0]; h[0] = h[h.length - 1]; h.pop(); while (i < h.length) { const [left, right] = [i * 2 + 1, i * 2 + 2]; let maybe; if (h[i] < h[left] && !(h[right] > h[left])) { maybe = left; } else if (h[i] < h[right]) { maybe = right; } if (maybe === undefined) { break; } const [iValue, mValue] = [h[i], h[maybe]]; h[i] = mValue; h[maybe] = iValue; i = maybe; } return rv; } [Symbol.iterator]() { return this._heap[Symbol.iterator](); } } exports.MaxHeap = MaxHeap; class SmallestN { constructor(_size) { this._size = _size; this._heap = new MaxHeap(); this._map = []; } update(key, value) { if (this._heap.size < this._size) { this._heap.insert(key); this._map.push([key, value]); return; } if (key >= this._heap.peekMax()) { return; } this._heap.insert(key); this._map.push([key, value]); this.shrink(); } shrink() { const max = this._heap.extractMax(); let idx = this._map.length; while (--idx >= 0) { if (this._map[idx][0] === max) { break; } } if (idx === -1) { throw new Error(`SmallestN: could not find entry for key ${max}`); } this._map.splice(idx, 1); } [Symbol.iterator]() { return this._map[Symbol.iterator](); } entries() { return this._map[Symbol.iterator]; } keys() { return [...this._heap]; } get size() { return this._size; } clear() { this._heap.clear(); this._map = []; } setSize(newSize) { while (this._size > newSize) { this.shrink(); this._size--; } this._size = newSize; } } exports.SmallestN = SmallestN; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NoYXJlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7O0dBR0c7QUFDSCxNQUFhLFVBQVU7SUFjbkI7Ozs7T0FJRztJQUNIO0lBQ0ksMkVBQTJFO0lBQ2pFLHNCQUE4QixDQUFDO1FBQS9CLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBWTtRQXBCN0MsaUNBQWlDO1FBQ2pDLFlBQU8sR0FBRyxDQUFDLENBQUM7UUFDWiw2RUFBNkU7UUFDN0UsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQiw2RUFBNkU7UUFDN0UsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQiwyQ0FBMkM7UUFDM0MsYUFBUSxHQUFHLENBQUMsQ0FBQztRQUNiLHFEQUFxRDtRQUNyRCxVQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsaURBQWlEO1FBQ2pELFNBQUksR0FBRyxHQUFHLENBQUM7SUFVUixDQUFDO0lBRUosZ0JBQWdCO0lBQ2hCLEtBQUs7UUFDRCxNQUFNLEVBQUUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNwRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxLQUF5QjtRQUM1QixJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUU7WUFDckIsT0FBTztTQUNWO1FBQ0QsSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUM3QixpRkFBaUY7UUFDakYsSUFBSSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxDQUFDLEVBQUU7WUFDcEIsWUFBWSxHQUFHLENBQUMsQ0FBQztZQUNqQixnQkFBZ0IsR0FBRyxDQUFDLENB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ckU7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztRQUNiLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztJQUN4QyxDQUFDO0lBRUQsT0FBTztRQUNILE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELElBQUk7UUFDQSxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUVELElBQUksSUFBSTtRQUNKLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUN0QixDQUFDO0lBRUQsS0FBSztRQUNELElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU8sQ0FBQyxPQUFlO1FBQ25CLE9BQU8sSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLEVBQUU7WUFDekIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2QsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ2hCO1FBQ0QsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztDQUNKO0FBOURELDhCQThEQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogSW5jcmVtZW50YWxseSB1cGRhdGVkIHN0YXRpc3RpY3Mgb24gYSBzZXQgb2YgdmFsdWVzLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgU3RhdGlzdGljcyB7XG4gICAgLyoqIE51bWJlciBvZiB2YWx1ZXMgb2JzZXJ2ZWQuICovXG4gICAgc2FtcGxlcyA9IDA7XG4gICAgLyoqIFRoZSBtYXhpbXVtIHZhbHVlIG9ic2VydmVkLiBJbml0aWFsaXplZCB0byBgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZYC4gKi9cbiAgICBtYXggPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XG4gICAgLyoqIFRoZSBtaW5pbXVtIHZhbHVlIG9ic2VydmVkLiBJbml0aWFsaXplZCB0byBgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZYC4gKi9cbiAgICBtaW4gPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG4gICAgLyoqIFRoZSB2YXJpYW5jZSBvZiB0aGUgdmFsdWVzIG9ic2VydmVkLiAqL1xuICAgIHZhcmlhbmNlID0gMDtcbiAgICAvKiogVGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgdmFsdWVzIG9ic2VydmVkLiAqL1xuICAgIHN0ZGV2ID0gMDtcbiAgICAvKiogVGhlIG1lYW4gKGF2ZXJhZ2UpIG9mIHRoZSB2YWx1ZXMgb2JzZXJ2ZWQuICovXG4gICAgbWVhbiA9IE5hTjtcblxuICAgIC8qKlxuICAgICAqIEluY3JlbWVudGFsbHkgdHJhY2sgbWVhbiwgc3RkZXYsIG1pbiwgbWF4LCBvZiBhIHNlcXVlbmNlIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0gcHJpbnRGaXhlZFByZWNpc2lvbiAtIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gcHJpbnQgaW5cbiAgICAgKiB7QGxpbmsgU3RhdGlzdGljcy50b1N0cmluZ30uXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIC8qKiBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHByaW50IGluIHtAbGluayBTdGF0aXN0aWNzLnRvU3RyaW5nfSAqL1xuICAgICAgICBwcm90ZWN0ZWQgcHJpbnRGaXhlZFByZWNpc2lvbjogbnVtYmVyID0gMVxuICAgICkge31cblxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBjbG9uZSgpIHtcbiAgICAgICAgY29uc3QgcnYgPSBuZXcgU3RhdGlzdGljcyh0aGlzLnByaW50Rml4ZWRQcmVjaXNpb24pO1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihydiwgdGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHN0YXRpc3RpY3Mgd2l0aCBhIG5ldyB2YWx1ZSBpbiB0aGUgc2VxdWVuY2UuXG4gICAgICovXG4gICAgdXBkYXRlKHZhbHVlOiBudW1iZXIgfCB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcHJldmlvdXNNZWFuID0gdGhpcy5tZWFuO1xuICAgICAgICAvLyBodHRwczovL21hdGguc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzM3NDg4MS9yZWN1cnNpdmUtZm9ybXVsYS1mb3ItdmFyaWFuY2VcbiAgICAgICAgbGV0IHByZXZpb3VzVmFyaWFuY2UgPSB0aGlzLnZhcmlhbmNlO1xuICAgICAgICBpZiAodGhpcy5zYW1wbGVzID09PSAwKSB7XG4gICAgICAgICAgICBwcmV2aW91c01lYW4gPSAwO1xuICAgICAgICAgICAgcHJldmlvdXNWYXJpYW5jZSA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zYW1wbGVzKys7XG4gICAgICAgIHRoaXMubWVhbiA9IHByZXZpb3VzTWVhbiArICh2YWx1ZSAtIHByZXZpb3VzTWVhbikgLyB0aGlzLnNhbXBsZXM7XG4gICAgICAgIHRoaXMudmFyaWFuY2UgPVxuICAgICAgICAgICAgKChwcmV2aW91c1ZhcmlhbmNlICsgKHByZXZpb3VzTWVhbiAtIHZhbHVlKSAqKiAyIC8gdGhpcy5zYW1wbGVzKSAqXG4gICAgICAgICAgICAgICAgKHRoaXMuc2FtcGxlcyAtIDEpKSAvXG4gICAgICAgICAgICB0aGlzLnNhbXBsZXM7XG4gICAgICAgIHRoaXMuc3RkZXYgPSBNYXRoLnNxcnQodGhpcy52YXJpYW5jZSk7XG4gICAgICAgIGlmICh2YWx1ZSA+IHRoaXMubWF4KSB7XG4gICAgICAgICAgICB0aGlzLm1heCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSA8IHRoaXMubWluKSB7XG4gICAgICAgICAgICB0aGlzLm1pbiA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJpbnQgdGhlIG1lYW4gb2YgdGhlIG9ic2VydmF0aW9ucyBzZWVuLCB3aXRoIHRoZSBwcmVjaXNpb24gc3BlY2lmaWVkIGluXG4gICAgICogdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqL1xuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5tZWFuLnRvRml4ZWQodGhpcy5wcmludEZpeGVkUHJlY2lzaW9uKX1gO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEV4cG9uZW50aWFsbHlEZWNheWluZ0F2ZXJhZ2VWYWx1ZSB7XG4gICAgc2FtcGxlcyA9IDA7XG4gICAgdmFsdWUgPSAwO1xuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBzbW9vdGhpbmdGYWN0b3I6IG51bWJlcikge31cbiAgICB1cGRhdGUobjogbnVtYmVyKSB7XG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpwcmVmZXItY29uZGl0aW9uYWwtZXhwcmVzc2lvblxuICAgICAgICBpZiAodGhpcy5zYW1wbGVzKysgPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9XG4gICAgICAgICAgICAgICAgdGhpcy5zbW9vdGhpbmdGYWN0b3IgKiBuICsgKDEgLSB0aGlzLnNtb290aGluZ0ZhY3RvcikgKiB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzbGVlcChtczogbnVtYmVyLCBjYW5jZWwgPSBuZXcgUHJvbWlzZTx2b2lkPigoKSA9PiB7fSkpIHtcbiAgICBsZXQgaWQ6IE5vZGVKUy5UaW1lcjtcbiAgICBjYW5jZWwudGhlbihfID0+IGNsZWFyVGltZW91dChpZCkpLmNhdGNoKF8gPT4gY2xlYXJUaW1lb3V0KGlkKSk7XG4gICAgcmV0dXJuIFByb21pc2UucmFjZShbbmV3IFByb21pc2UocmVzb2x2ZSA9PiAoaWQgPSBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSkpLCBjYW5jZWxdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmVhbVRvQnVmZmVyKHM6IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxCdWZmZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgYnVmZmVyczogQnVmZmVyW10gPSBbXTtcbiAgICAgICAgcy5vbihcImVycm9yXCIsIHJlamVjdCk7XG4gICAgICAgIHMub24oXCJkYXRhXCIsIChkYXRhOiBCdWZmZXIpID0+IGJ1ZmZlcnMucHVzaChkYXRhKSk7XG4gICAgICAgIHMub24oXCJlbmRcIiwgKCkgPT4gcmVzb2x2ZShCdWZmZXIuY29uY2F0KGJ1ZmZlcnMpKSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjaG9tcChzOiBzdHJpbmcpIHtcbiAgICBpZiAocy5sZW5ndGggPiAwICYmIHNbcy5sZW5ndGggLSAxXSA9PT0gXCJcXG5cIikge1xuICAgICAgICBzID0gcy5zbGljZSgwLCBzLmxlbmd0aCAtIDEpO1xuICAgIH1cbiAgICByZXR1cm4gcztcbn1cblxuZXhwb3J0IGNvbnN0IHN1bSA9IChhOiBudW1iZXJbXSkgPT4gYS5yZWR1Y2UoKHRvdGFsLCBuKSA9PiB0b3RhbCArIG4sIDApO1xuXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0U2l6ZShvYmo/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KSB7XG4gICAgaWYgKCFvYmopIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIHJldHVybiBzdW0oT2JqZWN0LmtleXMob2JqKS5tYXAoa2V5ID0+IGtleS5sZW5ndGggKyBvYmpba2V5XS5sZW5ndGgpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVIdHRwUmVzcG9uc2VCeXRlcyhcbiAgICBoZWFkZXJzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9LFxuICAgIG9wdHMgPSB7IGh0dHBIZWFkZXJzOiB0cnVlLCBtaW46IDAgfVxuKSB7XG4gICAgY29uc3QgaGVhZGVyS2V5cyA9IE9iamVjdC5rZXlzKGhlYWRlcnMpO1xuICAgIGxldCBjb250ZW50TGVuZ3RoID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBoZWFkZXJLZXlzKSB7XG4gICAgICAgIGlmIChrZXkubWF0Y2goL15jb250ZW50LWxlbmd0aCQvaSkpIHtcbiAgICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSBOdW1iZXIoaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICghb3B0cy5odHRwSGVhZGVycykge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoY29udGVudExlbmd0aCwgb3B0cy5taW4pO1xuICAgIH1cbiAgICBjb25zdCBoZWFkZXJMZW5ndGggPSBvYmplY3RTaXplKGhlYWRlcnMpICsgaGVhZGVyS2V5cy5sZW5ndGggKiBcIjogXCIubGVuZ3RoO1xuICAgIGNvbnN0IG90aGVyTGVuZ3RoID0gMTM7XG4gICAgcmV0dXJuIE1hdGgubWF4KGNvbnRlbnRMZW5ndGggKyBoZWFkZXJMZW5ndGggKyBvdGhlckxlbmd0aCwgb3B0cy5taW4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzRXhwaXJlZChcbiAgICBkYXRlOiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQgfCBudWxsLFxuICAgIHJldGVudGlvbkluRGF5czogbnVtYmVyXG4pIHtcbiAgICBpZiAocmV0ZW50aW9uSW5EYXlzIDw9IDApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IHRpbWVzdGFtcCA9IHR5cGVvZiBkYXRlID09PSBcInN0cmluZ1wiID8gRGF0ZS5wYXJzZShkYXRlKSA6IGRhdGUgfHwgMDtcbiAgICByZXR1cm4gdGltZXN0YW1wIDwgRGF0ZS5ub3coKSAtIHJldGVudGlvbkluRGF5cyAqIDI0ICogNjAgKiA2MCAqIDEwMDA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByb3VuZFRvMTAwbXMobjogbnVtYmVyKSB7XG4gICAgcmV0dXJuIE1hdGgucm91bmQobiAvIDEwMCkgKiAxMDA7XG59XG5cbmV4cG9ydCBjb25zdCB1dWlkdjRQYXR0ZXJuID1cbiAgICBcIlthLWYwLTldezh9LVthLWYwLTldezR9LTRbYS1mMC05XXszfS1bODlhQWJCXVthLWYwLTldezN9LVthLWYwLTldezEyfVwiO1xuXG5leHBvcnQgY29uc3QgR0IgPSAyICoqIDMwO1xuZXhwb3J0IGNvbnN0IE1CID0gMiAqKiAyMDtcbmV4cG9ydCBjb25zdCBLQiA9IDIgKiogMTA7XG5cbmV4cG9ydCBmdW5jdGlvbiBmMShuOiBudW1iZXIpIHtcbiAgICByZXR1cm4gbi50b0ZpeGVkKDEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZjIobjogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG4udG9GaXhlZCgyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGtleXNPZjxLIGV4dGVuZHMgc3RyaW5nLCBPIGV4dGVuZHMgeyBba2V5IGluIEtdOiBhbnkgfT4oXG4gICAgb2JqOiBPXG4pOiBBcnJheTxrZXlvZiBPPjtcbmV4cG9ydCBmdW5jdGlvbiBrZXlzT2Y8TyBleHRlbmRzIG9iamVjdD4ob2JqOiBPKTogQXJyYXk8a2V5b2YgTz4ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhvYmopIGFzIEFycmF5PGtleW9mIE8+O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmaW5lZDxUPihhcmc6IFQgfCB1bmRlZmluZWQgfCBudWxsIHwgdm9pZCk6IGFyZyBpcyBUIHtcbiAgICByZXR1cm4gISFhcmc7XG59XG5cbmV4cG9ydCBjbGFzcyBNYXhIZWFwIHtcbiAgICBwcm90ZWN0ZWQgX2hlYXA6IG51bWJlcltdID0gW107XG5cbiAgICBnZXQgc2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYXAubGVuZ3RoO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLl9oZWFwID0gW107XG4gICAgfVxuXG4gICAgcGVla01heCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYXBbMF07XG4gICAgfVxuXG4gICAgaW5zZXJ0KHZhbHVlOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3QgaCA9IHRoaXMuX2hlYXA7XG4gICAgICAgIGgucHVzaCh2YWx1ZSk7XG4gICAgICAgIGxldCBpID0gaC5sZW5ndGggLSAxO1xuICAgICAgICBjb25zdCBwYXJlbnRPZiA9IChuOiBudW1iZXIpID0+IE1hdGguZmxvb3IoKG4gLSAxKSAvIDIpO1xuICAgICAgICBsZXQgcGFyZW50ID0gcGFyZW50T2YoaSk7XG4gICAgICAgIHdoaWxlIChwYXJlbnQgPj0gMCAmJiBoW2ldID4gaFtwYXJlbnRdKSB7XG4gICAgICAgICAgICBjb25zdCB0bXAgPSBoW3BhcmVudF07XG4gICAgICAgICAgICBoW3BhcmVudF0gPSBoW2ldO1xuICAgICAgICAgICAgaFtpXSA9IHRtcDtcbiAgICAgICAgICAgIGkgPSBwYXJlbnQ7XG4gICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnRPZihpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGV4dHJhY3RNYXgoKSB7XG4gICAgICAgIGNvbnN0IGggPSB0aGlzLl9oZWFwO1xuICAgICAgICBpZiAoaC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImV4dHJhY3RNYXggY2FsbGVkIG9uIGVtcHR5IGhlYXBcIik7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICBjb25zdCBydiA9IGhbMF07XG4gICAgICAgIGhbMF0gPSBoW2gubGVuZ3RoIC0gMV07XG4gICAgICAgIGgucG9wKCk7XG5cbiAgICAgICAgd2hpbGUgKGkgPCBoLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgW2xlZnQsIHJpZ2h0XSA9IFtpICogMiArIDEsIGkgKiAyICsgMl07XG4gICAgICAgICAgICBsZXQgbWF5YmU6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChoW2ldIDwgaFtsZWZ0XSAmJiAhKGhbcmlnaHRdID4gaFtsZWZ0XSkpIHtcbiAgICAgICAgICAgICAgICBtYXliZSA9IGxlZnQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhbaV0gPCBoW3JpZ2h0XSkge1xuICAgICAgICAgICAgICAgIG1heWJlID0gcmlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWF5YmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgW2lWYWx1ZSwgbVZhbHVlXSA9IFtoW2ldLCBoW21heWJlXV07XG4gICAgICAgICAgICBoW2ldID0gbVZhbHVlO1xuICAgICAgICAgICAgaFttYXliZV0gPSBpVmFsdWU7XG4gICAgICAgICAgICBpID0gbWF5YmU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcnY7XG4gICAgfVxuXG4gICAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oZWFwW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTbWFsbGVzdE48VCA9IHZvaWQ+IHtcbiAgICBwcm90ZWN0ZWQgX2hlYXAgPSBuZXcgTWF4SGVhcCgpO1xuICAgIHByb3RlY3RlZCBfbWFwOiBbbnVtYmVyLCBUXVtdID0gW107XG5cbiAgICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgX3NpemU6IG51bWJlcikge31cblxuICAgIHVwZGF0ZShrZXk6IG51bWJlciwgdmFsdWU6IFQpIHtcbiAgICAgICAgaWYgKHRoaXMuX2hlYXAuc2l6ZSA8IHRoaXMuX3NpemUpIHtcbiAgICAgICAgICAgIHRoaXMuX2hlYXAuaW5zZXJ0KGtleSk7XG4gICAgICAgICAgICB0aGlzLl9tYXAucHVzaChba2V5LCB2YWx1ZV0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXkgPj0gdGhpcy5faGVhcC5wZWVrTWF4KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9oZWFwLmluc2VydChrZXkpO1xuICAgICAgICB0aGlzLl9tYXAucHVzaChba2V5LCB2YWx1ZV0pO1xuICAgICAgICB0aGlzLnNocmluaygpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzaHJpbmsoKSB7XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMuX2hlYXAuZXh0cmFjdE1heCgpO1xuICAgICAgICBsZXQgaWR4ID0gdGhpcy5fbWFwLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKC0taWR4ID49IDApIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9tYXBbaWR4XVswXSA9PT0gbWF4KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU21hbGxlc3ROOiBjb3VsZCBub3QgZmluZCBlbnRyeSBmb3Iga2V5ICR7bWF4fWApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX21hcC5zcGxpY2UoaWR4LCAxKTtcbiAgICB9XG5cbiAgICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21hcFtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gICAgfVxuXG4gICAgZW50cmllcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21hcFtTeW1ib2wuaXRlcmF0b3JdO1xuICAgIH1cblxuICAgIGtleXMoKSB7XG4gICAgICAgIHJldHVybiBbLi4udGhpcy5faGVhcF07XG4gICAgfVxuXG4gICAgZ2V0IHNpemUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zaXplO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLl9oZWFwLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuX21hcCA9IFtdO1xuICAgIH1cblxuICAgIHNldFNpemUobmV3U2l6ZTogbnVtYmVyKSB7XG4gICAgICAgIHdoaWxlICh0aGlzLl9zaXplID4gbmV3U2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5zaHJpbmsoKTtcbiAgICAgICAgICAgIHRoaXMuX3NpemUtLTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zaXplID0gbmV3U2l6ZTtcbiAgICB9XG59XG4iXX0=