chain-able
Version:
interfaces that describe their intentions.
673 lines (628 loc) • 52.6 kB
JavaScript
/* eslint no-new-wrappers: "off" */
/* eslint eqeqeq: "off" */
/* eslint func-style: "off" */
/* eslint complexity: "off" */
var isObjStrict = require('./is/objStrict')
var isRegExp = require('./is/regexp')
var isError = require('./is/error')
var isBoolean = require('./is/boolean')
var isNumber = require('./is/number')
var isString = require('./is/string')
var isDate = require('./is/date')
var isUndefined = require('./is/undefined')
var isArray = require('./is/array')
var isMap = require('./is/map')
var isSet = require('./is/set')
var argumentor = require('./argumentor')
var ObjectKeys = require('./util/keys')
var hasOwnProperty = require('./util/hasOwnProperty')
var getPrototypeOf = require('./util/getPrototypeOf')
var reduce = require('./reduce')
var toarr = require('./to-arr')
/**
* @param {Array | Object | any} xs
* @param {Function} fn
* @TODO: unexpectedly breaks things iterating
* if you are relying on internal functionality
* (such as .path, .get, .value...) with map & set
*
* @NOTE if there is .forEach on the obj already, use it
* otherwise, call function for each
*
*/
var forEach = function(xs, fn) {
if (xs.forEach) { xs.forEach(fn) }
else { for (var i = 0; i < xs.length; i++) { fn(xs[i], i, xs) } }
}
/**
* {@link https://sourcemaking.com/design_patterns/chain_of_responsibility chainofresponsibility}
*
* @param {Traversable} obj object to traverse
*
* @constructor
*
* @example
*
* traverse({})
* //=> new Traverse(obj)
*
*/
var traverse = function(obj) {
return new Traverse(obj)
}
module.exports = traverse
/**
* @func
* @class TraverseJS
* @classdesc Traverse and transform objects by visiting every node on a recursive walk.
* @prop {any} value
*
* @category traverse
* @memberOf Traverse
* @see deps/traverse
* @category traverse
* @types traverse
* @tests traverse/*
*
* @TODO: symbol, map, set
* @tutorial https://github.com/substack/js-traverse
*
* @param {Traversable} obj any traversable value
*
* @example
*
* traverse({})
* //=> Traverser
*
*/
function Traverse(obj) {
this.value = obj
}
/**
* @desc Get the element at the array path.
*
* @param {Array<string>} ps paths
* @return {any} value at dot-prop
*
* @memberOf Traverse
* @see this.forEach
* @todo hasOwnProperty
*/
Traverse.prototype.get = function(ps) {
var node = this.value
for (var i = 0; i < ps.length; i++) {
var key = ps[i]
if (!node || !hasOwnProperty(node, key)) {
node = undefined
break
}
node = node[key]
}
return node
}
/**
* @desc Return whether the element at the array path exists.
*
* @param {Array<string>} pathsArray paths
* @return {boolean} has element at path
*
* @memberOf Traverse
* @see hasOwnProperty
*
* @example
*
* traverse({eh: true}).has(['eh'])
* //=> true
*
* @example
*
* traverse({eh: true}).has(['canada'])
* //=> false
*
*
* @example
*
* traverse([0]).has([2])
* //=> false
*
*/
Traverse.prototype.has = function(pathsArray) {
var node = this.value
for (var i = 0; i < pathsArray.length; i++) {
var key = pathsArray[i]
if (!node || !hasOwnProperty(node, key)) {
return false
}
node = node[key]
}
return true
}
/**
* @desc Set the element at the array path to value.
*
* @param {Array<string>} arrayPath paths
* @param {any} value any value to assign to the element @ the path
* @return {any} value passed in
*
* @memberOf Traverse
* @see deps/dot
*/
Traverse.prototype.set = function(arrayPath, value) {
var node = this.value
var i = 0
for (; i < arrayPath.length - 1; i++) {
var key = arrayPath[i]
if (!hasOwnProperty(node, key)) { node[key] = {} }
node = node[key]
}
node[arrayPath[i]] = value
return value
}
/**
* @desc Execute fn for each node in the object and return a new object with the results of the walk. To update nodes in the result use this.update(value).
*
* @method
* @memberOf Traverse
* @see walk
* @param {Function} cb fn for each node in the object
* @return {any}
*
* @example
* var {traverse} = require('chain-able')
*
* var obj = {a: 1, b: 2, c: [3, 4]}
* obj.c.push(obj)
*
* var scrubbed = traverse(obj).map(function(x) {
* if (this.circular) this.remove()
* })
* console.dir(scrubbed)
* //=> { a: 1, b: 2, c: [ 3, 4 ] }
*/
Traverse.prototype.map = function(cb) {
return walk(this.value, cb, true)
}
/**
* @desc Execute fn for each node in the object but unlike .map(), when this.update() is called it updates the object in-place.
* executes a provided function once for each traversed element.
*
* @param {Function} callback provided callback function
* @return {any} this.value
*
* @memberOf Traverse
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
*
* @example
*
* var {traverse} = require('chain-able')
*
* var obj = [5, 6, -3, [7, 8, -2, 1], {f: 10, g: -13}]
* traverse(obj).forEach(function(x) {
* if (x < 0) this.update(x + 128)
* })
*
* console.dir(obj)
* //=> [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]
*
*/
Traverse.prototype.forEach = function(callback) {
this.value = walk(this.value, callback, false)
return this.value
}
/**
* @desc applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.
* calls cb for each loop that is .notRoot
* defaults initial value to `this.value`
*
* @param {Function} cb callback forEach
* @param {Object | Array | any} init initial value
* @return {Object | Array | any}
*
* @see https://en.wikipedia.org/wiki/Fold_(higher-order_function)
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
* @memberOf Traverse
*
* @example
*
* var {traverse} = require('chain-able')
*
* var obj = {
* a: [1, 2, 3],
* b: 4,
* c: [5, 6],
* d: {e: [7, 8], f: 9},
* }
*
* var leaves = traverse(obj).reduce(function(acc, x) {
* if (this.isLeaf) acc.push(x)
* return acc
* }, [])
*
* console.dir(leaves)
* //=> [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
*
*/
Traverse.prototype.reduce = function(cb, init) {
var skip = arguments.length === 1
var acc = skip ? this.value : init
this.forEach(function(x) {
if (!this.isRoot || !skip) {
acc = cb.call(this, acc, x)
}
})
return acc
}
/**
* @desc Return an Array of every possible non-cyclic path in the object. Paths are Arrays of string keys.
* @return {Array<string>}
* @memberOf Traverse
* @tests traverse/keys
*/
Traverse.prototype.paths = function() {
var acc = []
this.forEach(function(x) {
acc.push(this.path)
})
return acc
}
/**
* @desc Return an Array of every node in the object.
* @memberOf Traverse
* @return {Array<any>}
*/
Traverse.prototype.nodes = function() {
var acc = []
this.forEach(function(x) {
acc.push(this.node)
})
return acc
}
/**
* @desc Create a deep clone of the object.
*
* @return {any}
*
* @memberOf Traverse
*
* @example
* const {traverse, eq} = require('chain-able')
*
* const obj = {eh: true, canada: [1]}
* const cloned = traverse(obj).clone()
* cloned.eh = false
* eq(cloned, obj)
* //=> false
*
*/
Traverse.prototype.clone = function() {
var parents = []
var nodes = []
return (function clone(src) {
for (var i = 0; i < parents.length; i++) {
if (parents[i] === src) {
return nodes[i]
}
}
if (isObjStrict(src)) {
var dst = copy(src)
parents.push(src)
nodes.push(dst)
forEach(ObjectKeys(src), function (key) {
dst[key] = clone(src[key])
})
parents.pop()
nodes.pop()
return dst
}
else {
return src
}
})(this.value)
}
/**
* @func
*
* @param {any} root root node
* @param {Function} cb callback for each
* @param {boolean} immutable should mutate or not
* @return {any}
*
* @see traverse.forEach
*/
function walk(root, cb, immutable) {
var path = []
var parents = []
var alive = true
/**
* @emits before
* @emits pre
* @emits post
* @emits after
*
* @param {any} node_
* @return {State} see types
*/
return (function walker(node_) {
// both are objs with properties that get changed but
var node = immutable ? copy(node_) : node_
var modifiers = {}
var keepGoing = true
/**
* Each method that takes a callback has a context (its this object) with these attributes:
* @prop {boolean} isRoot @alias isNotRoot Whether or not the present node is a leaf node (has no children)
* @type {Object}
*/
var state = {
/**
* The present node on the recursive walk
* @type {Array}
*/
node: node,
/**
* @see traverse.context.node
* @protected
* @type {Array}
*/
node_: node_,
/**
* An array of string keys from the root to the present node
* @type {Array}
*/
path: [].concat(path),
/**
* The context of the node's parent. This is undefined for the root node.
* @type {undefined | Primitive}
*/
parent: parents[parents.length - 1],
parents: parents,
/**
* The name of the key of the present node in its parent. This is undefined for the root node.
* @type {undefined | Primitive}
*/
key: path.slice(-1)[0],
/**
* Whether the present node is the root node
* @type {Boolean}
*/
isRoot: path.length === 0,
/**
* Depth of the node within the traversal
* @type {number}
*/
level: path.length,
/**
* If the node equals one of its parents, the circular attribute is set to the context of that parent and the traversal progresses no deeper.
* @type {null | boolean}
*/
circular: null,
/**
* Set a new value for the present node.
* All the elements in value will be recursively traversed unless stopHere is true.
*
* @param {Function} x
* @param {boolean} stopHere
* @return {void}
*/
update: function update(x, stopHere) {
if (!state.isRoot) {
state.parent.node[state.key] = x
}
state.node = x
if (stopHere) { keepGoing = false }
},
/**
* Delete the current element from its parent in the output. Calls delete even on Arrays.
* @param {boolean} stopHere
* @return {void}
*/
delete: function delete$1(stopHere) {
delete state.parent.node[state.key]
if (stopHere) { keepGoing = false }
},
/**
* Remove the current element from the output. If the node is in an Array it will be spliced off. Otherwise it will be deleted from its parent.
* @param {boolean} stopHere
* @return {void}
*/
remove: function remove(stopHere) {
// @NOTE safety
if (isUndefined(state.parent)) {
return
}
else if (isArray(state.parent.node)) {
state.parent.node.splice(state.key, 1)
}
else {
delete state.parent.node[state.key]
}
if (stopHere) { keepGoing = false }
},
keys: null,
/**
* Call this function before any of the children are traversed.
* You can assign into this.keys here to traverse in a custom order.
* @param {Function} fn
* @return {any}
*/
before: function before(fn) {
modifiers.before = fn
},
/**
* Call this function after any of the children are traversed.
* @param {Function} fn
* @return {any}
*/
after: function after(fn) {
modifiers.after = fn
},
/**
* Call this function before each of the children are traversed.
* @param {Function} fn
* @return {any}
*/
pre: function pre(fn) {
modifiers.pre = fn
},
/**
* Call this function after each of the children are traversed.
* @param {Function} fn
* @return {any}
*/
post: function post(fn) {
modifiers.post = fn
},
/**
* @modifies alive
* @protected
* @return {void}
*/
stop: function stop() {
alive = false
},
/**
* @modifies keepGoing
* @protected
* @return {void}
*/
block: function block() {
keepGoing = false
},
}
if (!alive) { return state }
/**
* @desc updates if needed:
* @modifies keys
* @modifies circular
* @modifies isLeaf
* @modifies notLeaf
* @modifies notRoot
* @return {void}
*/
function updateState() {
if (isObjStrict(state.node)) {
if (!state.keys || state.node_ !== state.node) {
state.keys = ObjectKeys(state.node)
}
// @NOTE was ==
state.isLeaf = state.keys.length === 0
for (var i = 0; i < parents.length; i++) {
if (parents[i].node_ === node_) {
state.circular = parents[i]
break
}
}
}
else {
state.isLeaf = true
state.keys = null
}
state.notLeaf = !state.isLeaf
state.notRoot = !state.isRoot
}
updateState()
// @NOTE added last `,state` arg to not have it have to use `this`,
// but broke some things so moved to another fn
//
// use return values to update if defined
var ret = cb.call(state, state.node)
if (!isUndefined(ret) && state.update) { state.update(ret) }
if (modifiers.before) { modifiers.before.call(state, state.node) }
if (!keepGoing) { return state }
// when it's some sort of itertable object, loop it further
if (isObjStrict(state.node) && !state.circular) {
parents.push(state)
updateState()
forEach(state.keys, function (key, i) {
path.push(key)
if (modifiers.pre) { modifiers.pre.call(state, state.node[key], key) }
var child = walker(state.node[key])
if (immutable && hasOwnProperty(state.node, key)) {
state.node[key] = child.node
}
// @NOTE was ==
child.isLast = i === state.keys.length - 1
child.isFirst = i === 0
if (modifiers.post) { modifiers.post.call(state, child) }
path.pop()
})
parents.pop()
}
if (modifiers.after) { modifiers.after.call(state, state.node) }
return state
})(root).node
}
/**
* @func
* @TODO does not respect ObjectDescriptors
* @NOTE wicked ternary
* @param {any} src
* @return {any}
*/
function copy(src) {
// require('fliplog').data(src).bold('copying').echo()
if (isObjStrict(src)) {
var dst
// require('fliplog').underline('is obj').echo()
if (isMap(src)) {
dst = reduce(src.entries())
}
else if (isSet(src)) {
dst = toarr(src)
}
if (isArray(src)) {
dst = []
}
else if (isDate(src)) {
dst = new Date(src.getTime ? src.getTime() : src)
}
else if (isRegExp(src)) {
dst = new RegExp(src)
}
else if (isError(src)) {
dst = {message: src.message}
}
else if (isBoolean(src)) {
dst = new Boolean(src)
}
else if (isNumber(src)) {
dst = new Number(src)
}
else if (isString(src)) {
dst = new String(src)
}
else {
//if (Object.create && Object.getPrototypeOf)
dst = Object.create(getPrototypeOf(src))
}
// else if (src.constructor === Object) {
// dst = {}
// }
// else {
// // @NOTE: only happens if above getPrototypeOf does not exist
// var proto = (src.constructor && src.constructor.prototype) ||
// src.__proto__ || {}
// var T = function() {}
// T.prototype = proto
// dst = new T()
// }
forEach(ObjectKeys(src), function (key) {
dst[key] = src[key]
})
return dst
}
else {
// require('fliplog').red('is NOT OBJ').echo()
return src
}
}
/**
* @desc adds methods to Traverser
*/
forEach(ObjectKeys(Traverse.prototype), function (key) {
traverse[key] = function(obj) {
var t = new Traverse(obj)
// args = argumentor.apply(null, arguments).slice(1)
return t[key].apply(t, argumentor.apply(null, arguments).slice(1))
}
})
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhdmVyc2UuanMiLCJzb3VyY2VzIjpbInRyYXZlcnNlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludCBuby1uZXctd3JhcHBlcnM6IFwib2ZmXCIgKi9cbi8qIGVzbGludCBlcWVxZXE6IFwib2ZmXCIgKi9cbi8qIGVzbGludCBmdW5jLXN0eWxlOiBcIm9mZlwiICovXG4vKiBlc2xpbnQgY29tcGxleGl0eTogXCJvZmZcIiAqL1xuY29uc3QgaXNPYmpTdHJpY3QgPSByZXF1aXJlKCcuL2lzL29ialN0cmljdCcpXG5jb25zdCBpc1JlZ0V4cCA9IHJlcXVpcmUoJy4vaXMvcmVnZXhwJylcbmNvbnN0IGlzRXJyb3IgPSByZXF1aXJlKCcuL2lzL2Vycm9yJylcbmNvbnN0IGlzQm9vbGVhbiA9IHJlcXVpcmUoJy4vaXMvYm9vbGVhbicpXG5jb25zdCBpc051bWJlciA9IHJlcXVpcmUoJy4vaXMvbnVtYmVyJylcbmNvbnN0IGlzU3RyaW5nID0gcmVxdWlyZSgnLi9pcy9zdHJpbmcnKVxuY29uc3QgaXNEYXRlID0gcmVxdWlyZSgnLi9pcy9kYXRlJylcbmNvbnN0IGlzVW5kZWZpbmVkID0gcmVxdWlyZSgnLi9pcy91bmRlZmluZWQnKVxuY29uc3QgaXNBcnJheSA9IHJlcXVpcmUoJy4vaXMvYXJyYXknKVxuY29uc3QgaXNNYXAgPSByZXF1aXJlKCcuL2lzL21hcCcpXG5jb25zdCBpc1NldCA9IHJlcXVpcmUoJy4vaXMvc2V0JylcbmNvbnN0IGFyZ3VtZW50b3IgPSByZXF1aXJlKCcuL2FyZ3VtZW50b3InKVxuY29uc3QgT2JqZWN0S2V5cyA9IHJlcXVpcmUoJy4vdXRpbC9rZXlzJylcbmNvbnN0IGhhc093blByb3BlcnR5ID0gcmVxdWlyZSgnLi91dGlsL2hhc093blByb3BlcnR5JylcbmNvbnN0IGdldFByb3RvdHlwZU9mID0gcmVxdWlyZSgnLi91dGlsL2dldFByb3RvdHlwZU9mJylcbmNvbnN0IHJlZHVjZSA9IHJlcXVpcmUoJy4vcmVkdWNlJylcbmNvbnN0IHRvYXJyID0gcmVxdWlyZSgnLi90by1hcnInKVxuXG4vKipcbiAqIEBwYXJhbSB7QXJyYXkgfCBPYmplY3QgfCBhbnl9IHhzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICogQFRPRE86IHVuZXhwZWN0ZWRseSBicmVha3MgdGhpbmdzIGl0ZXJhdGluZ1xuICogaWYgeW91IGFyZSByZWx5aW5nIG9uIGludGVybmFsIGZ1bmN0aW9uYWxpdHlcbiAqIChzdWNoIGFzIC5wYXRoLCAuZ2V0LCAudmFsdWUuLi4pIHdpdGggbWFwICYgc2V0XG4gKlxuICogQE5PVEUgaWYgdGhlcmUgaXMgLmZvckVhY2ggb24gdGhlIG9iaiBhbHJlYWR5LCB1c2UgaXRcbiAqIG90aGVyd2lzZSwgY2FsbCBmdW5jdGlvbiBmb3IgZWFjaFxuICpcbiAqL1xudmFyIGZvckVhY2ggPSBmdW5jdGlvbih4cywgZm4pIHtcbiAgaWYgKHhzLmZvckVhY2gpIHhzLmZvckVhY2goZm4pXG4gIGVsc2UgZm9yIChsZXQgaSA9IDA7IGkgPCB4cy5sZW5ndGg7IGkrKykgZm4oeHNbaV0sIGksIHhzKVxufVxuXG4vKipcbiAqIHtAbGluayBodHRwczovL3NvdXJjZW1ha2luZy5jb20vZGVzaWduX3BhdHRlcm5zL2NoYWluX29mX3Jlc3BvbnNpYmlsaXR5IGNoYWlub2ZyZXNwb25zaWJpbGl0eX1cbiAqXG4gKiBAcGFyYW0ge1RyYXZlcnNhYmxlfSBvYmogb2JqZWN0IHRvIHRyYXZlcnNlXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiAgICB0cmF2ZXJzZSh7fSlcbiAqICAgIC8vPT4gbmV3IFRyYXZlcnNlKG9iailcbiAqXG4gKi9cbnZhciB0cmF2ZXJzZSA9IGZ1bmN0aW9uKG9iaikge1xuICByZXR1cm4gbmV3IFRyYXZlcnNlKG9iailcbn1cbm1vZHVsZS5leHBvcnRzID0gdHJhdmVyc2VcblxuLyoqXG4gKiBAZnVuY1xuICogQGNsYXNzIFRyYXZlcnNlSlNcbiAqIEBjbGFzc2Rlc2MgVHJhdmVyc2UgYW5kIHRyYW5zZm9ybSBvYmplY3RzIGJ5IHZpc2l0aW5nIGV2ZXJ5IG5vZGUgb24gYSByZWN1cnNpdmUgd2Fsay5cbiAqIEBwcm9wIHthbnl9IHZhbHVlXG4gKlxuICogQGNhdGVnb3J5IHRyYXZlcnNlXG4gKiBAbWVtYmVyT2YgVHJhdmVyc2VcbiAqIEBzZWUgZGVwcy90cmF2ZXJzZVxuICogQGNhdGVnb3J5IHRyYXZlcnNlXG4gKiBAdHlwZXMgdHJhdmVyc2VcbiAqIEB0ZXN0cyB0cmF2ZXJzZS8qXG4gKlxuICogQFRPRE86IHN5bWJvbCwgbWFwLCBzZXRcbiAqIEB0dXRvcmlhbCBodHRwczovL2dpdGh1Yi5jb20vc3Vic3RhY2svanMtdHJhdmVyc2VcbiAqXG4gKiBAcGFyYW0ge1RyYXZlcnNhYmxlfSBvYmogYW55IHRyYXZlcnNhYmxlIHZhbHVlXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiAgIHRyYXZlcnNlKHt9KVxuICogICAvLz0+IFRyYXZlcnNlclxuICpcbiAqL1xuZnVuY3Rpb24gVHJhdmVyc2Uob2JqKSB7XG4gIHRoaXMudmFsdWUgPSBvYmpcbn1cblxuLyoqXG4gKiBAZGVzYyBHZXQgdGhlIGVsZW1lbnQgYXQgdGhlIGFycmF5IHBhdGguXG4gKlxuICogQHBhcmFtICB7QXJyYXk8c3RyaW5nPn0gcHMgcGF0aHNcbiAqIEByZXR1cm4ge2FueX0gdmFsdWUgYXQgZG90LXByb3BcbiAqXG4gKiBAbWVtYmVyT2YgVHJhdmVyc2VcbiAqIEBzZWUgdGhpcy5mb3JFYWNoXG4gKiBAdG9kbyBoYXNPd25Qcm9wZXJ0eVxuICovXG5UcmF2ZXJzZS5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24ocHMpIHtcbiAgbGV0IG5vZGUgPSB0aGlzLnZhbHVlXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcHMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBrZXkgPSBwc1tpXVxuICAgIGlmICghbm9kZSB8fCAhaGFzT3duUHJvcGVydHkobm9kZSwga2V5KSkge1xuICAgICAgbm9kZSA9IHVuZGVmaW5lZFxuICAgICAgYnJlYWtcbiAgICB9XG4gICAgbm9kZSA9IG5vZGVba2V5XVxuICB9XG4gIHJldHVybiBub2RlXG59XG5cbi8qKlxuICogQGRlc2MgUmV0dXJuIHdoZXRoZXIgdGhlIGVsZW1lbnQgYXQgdGhlIGFycmF5IHBhdGggZXhpc3RzLlxuICpcbiAqIEBwYXJhbSAge0FycmF5PHN0cmluZz59IHBhdGhzQXJyYXkgcGF0aHNcbiAqIEByZXR1cm4ge2Jvb2xlYW59IGhhcyBlbGVtZW50IGF0IHBhdGhcbiAqXG4gKiBAbWVtYmVyT2YgVHJhdmVyc2VcbiAqIEBzZWUgaGFzT3duUHJvcGVydHlcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIHRyYXZlcnNlKHtlaDogdHJ1ZX0pLmhhcyhbJ2VoJ10pXG4gKiAgICAvLz0+IHRydWVcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIHRyYXZlcnNlKHtlaDogdHJ1ZX0pLmhhcyhbJ2NhbmFkYSddKVxuICogICAgLy89PiBmYWxzZVxuICpcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIHRyYXZlcnNlKFswXSkuaGFzKFsyXSlcbiAqICAgIC8vPT4gZmFsc2VcbiAqXG4gKi9cblRyYXZlcnNlLnByb3RvdHlwZS5oYXMgPSBmdW5jdGlvbihwYXRoc0FycmF5KSB7XG4gIGxldCBub2RlID0gdGhpcy52YWx1ZVxuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdGhzQXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBrZXkgPSBwYXRoc0FycmF5W2ldXG4gICAgaWYgKCFub2RlIHx8ICFoYXNPd25Qcm9wZXJ0eShub2RlLCBrZXkpKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgbm9kZSA9IG5vZGVba2V5XVxuICB9XG4gIHJldHVybiB0cnVlXG59XG5cbi8qKlxuICogQGRlc2MgU2V0IHRoZSBlbGVtZW50IGF0IHRoZSBhcnJheSBwYXRoIHRvIHZhbHVlLlxuICpcbiAqIEBwYXJhbSAge0FycmF5PHN0cmluZz59IGFycmF5UGF0aCBwYXRoc1xuICogQHBhcmFtICB7YW55fSB2YWx1ZSBhbnkgdmFsdWUgdG8gYXNzaWduIHRvIHRoZSBlbGVtZW50IEAgdGhlIHBhdGhcbiAqIEByZXR1cm4ge2FueX0gdmFsdWUgcGFzc2VkIGluXG4gKlxuICogQG1lbWJlck9mIFRyYXZlcnNlXG4gKiBAc2VlIGRlcHMvZG90XG4gKi9cblRyYXZlcnNlLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbihhcnJheVBhdGgsIHZhbHVlKSB7XG4gIGxldCBub2RlID0gdGhpcy52YWx1ZVxuICBsZXQgaSA9IDBcbiAgZm9yICg7IGkgPCBhcnJheVBhdGgubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgY29uc3Qga2V5ID0gYXJyYXlQYXRoW2ldXG4gICAgaWYgKCFoYXNPd25Qcm9wZXJ0eShub2RlLCBrZXkpKSBub2RlW2tleV0gPSB7fVxuICAgIG5vZGUgPSBub2RlW2tleV1cbiAgfVxuICBub2RlW2FycmF5UGF0aFtpXV0gPSB2YWx1ZVxuICByZXR1cm4gdmFsdWVcbn1cblxuLyoqXG4gKiBAZGVzYyBFeGVjdXRlIGZuIGZvciBlYWNoIG5vZGUgaW4gdGhlIG9iamVjdCBhbmQgcmV0dXJuIGEgbmV3IG9iamVjdCB3aXRoIHRoZSByZXN1bHRzIG9mIHRoZSB3YWxrLiBUbyB1cGRhdGUgbm9kZXMgaW4gdGhlIHJlc3VsdCB1c2UgdGhpcy51cGRhdGUodmFsdWUpLlxuICpcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJPZiBUcmF2ZXJzZVxuICogQHNlZSB3YWxrXG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gY2IgZm4gZm9yIGVhY2ggbm9kZSBpbiB0aGUgb2JqZWN0XG4gKiBAcmV0dXJuIHthbnl9XG4gKlxuICogQGV4YW1wbGVcbiAqICAgIHZhciB7dHJhdmVyc2V9ID0gcmVxdWlyZSgnY2hhaW4tYWJsZScpXG4gKlxuICogICAgdmFyIG9iaiA9IHthOiAxLCBiOiAyLCBjOiBbMywgNF19XG4gKiAgICBvYmouYy5wdXNoKG9iailcbiAqXG4gKiAgICB2YXIgc2NydWJiZWQgPSB0cmF2ZXJzZShvYmopLm1hcChmdW5jdGlvbih4KSB7XG4gKiAgICAgIGlmICh0aGlzLmNpcmN1bGFyKSB0aGlzLnJlbW92ZSgpXG4gKiAgICB9KVxuICogICAgY29uc29sZS5kaXIoc2NydWJiZWQpXG4gKiAgICAvLz0+IHsgYTogMSwgYjogMiwgYzogWyAzLCA0IF0gfVxuICovXG5UcmF2ZXJzZS5wcm90b3R5cGUubWFwID0gZnVuY3Rpb24oY2IpIHtcbiAgcmV0dXJuIHdhbGsodGhpcy52YWx1ZSwgY2IsIHRydWUpXG59XG5cbi8qKlxuICogQGRlc2MgRXhlY3V0ZSBmbiBmb3IgZWFjaCBub2RlIGluIHRoZSBvYmplY3QgYnV0IHVubGlrZSAubWFwKCksIHdoZW4gdGhpcy51cGRhdGUoKSBpcyBjYWxsZWQgaXQgdXBkYXRlcyB0aGUgb2JqZWN0IGluLXBsYWNlLlxuICogICAgICAgZXhlY3V0ZXMgYSBwcm92aWRlZCBmdW5jdGlvbiBvbmNlIGZvciBlYWNoIHRyYXZlcnNlZCBlbGVtZW50LlxuICpcbiAqIEBwYXJhbSAge0Z1bmN0aW9ufSBjYWxsYmFjayBwcm92aWRlZCBjYWxsYmFjayBmdW5jdGlvblxuICogQHJldHVybiB7YW55fSB0aGlzLnZhbHVlXG4gKlxuICogQG1lbWJlck9mIFRyYXZlcnNlXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2ZvckVhY2hcbiAqXG4gKiAgQGV4YW1wbGVcbiAqXG4gKiAgICAgdmFyIHt0cmF2ZXJzZX0gPSByZXF1aXJlKCdjaGFpbi1hYmxlJylcbiAqXG4gKiAgICAgdmFyIG9iaiA9IFs1LCA2LCAtMywgWzcsIDgsIC0yLCAxXSwge2Y6IDEwLCBnOiAtMTN9XVxuICogICAgIHRyYXZlcnNlKG9iaikuZm9yRWFjaChmdW5jdGlvbih4KSB7XG4gKiAgICAgICBpZiAoeCA8IDApIHRoaXMudXBkYXRlKHggKyAxMjgpXG4gKiAgICAgfSlcbiAqXG4gKiAgICAgY29uc29sZS5kaXIob2JqKVxuICogICAgIC8vPT4gWyA1LCA2LCAxMjUsIFsgNywgOCwgMTI2LCAxIF0sIHsgZjogMTAsIGc6IDExNSB9IF1cbiAqXG4gKi9cblRyYXZlcnNlLnByb3RvdHlwZS5mb3JFYWNoID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgdGhpcy52YWx1ZSA9IHdhbGsodGhpcy52YWx1ZSwgY2FsbGJhY2ssIGZhbHNlKVxuICByZXR1cm4gdGhpcy52YWx1ZVxufVxuXG4vKipcbiAqIEBkZXNjIGFwcGxpZXMgYSBmdW5jdGlvbiBhZ2FpbnN0IGFuIGFjY3VtdWxhdG9yIGFuZCBlYWNoIGVsZW1lbnQgaW4gdGhlIGFycmF5IChmcm9tIGxlZnQgdG8gcmlnaHQpIHRvIHJlZHVjZSBpdCB0byBhIHNpbmdsZSB2YWx1ZS5cbiAqICAgICAgIGNhbGxzIGNiIGZvciBlYWNoIGxvb3AgdGhhdCBpcyAubm90Um9vdFxuICogICAgICAgZGVmYXVsdHMgaW5pdGlhbCB2YWx1ZSB0byBgdGhpcy52YWx1ZWBcbiAqXG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gY2IgY2FsbGJhY2sgZm9yRWFjaFxuICogQHBhcmFtICB7T2JqZWN0IHwgQXJyYXkgfCBhbnl9IGluaXQgaW5pdGlhbCB2YWx1ZVxuICogQHJldHVybiB7T2JqZWN0IHwgQXJyYXkgfCBhbnl9XG4gKlxuICogQHNlZSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Gb2xkXyhoaWdoZXItb3JkZXJfZnVuY3Rpb24pXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L1JlZHVjZVxuICogQG1lbWJlck9mIFRyYXZlcnNlXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiAgICB2YXIge3RyYXZlcnNlfSA9IHJlcXVpcmUoJ2NoYWluLWFibGUnKVxuICpcbiAqICAgIHZhciBvYmogPSB7XG4gKiAgICAgIGE6IFsxLCAyLCAzXSxcbiAqICAgICAgYjogNCxcbiAqICAgICAgYzogWzUsIDZdLFxuICogICAgICBkOiB7ZTogWzcsIDhdLCBmOiA5fSxcbiAqICAgIH1cbiAqXG4gKiAgICB2YXIgbGVhdmVzID0gdHJhdmVyc2Uob2JqKS5yZWR1Y2UoZnVuY3Rpb24oYWNjLCB4KSB7XG4gKiAgICAgIGlmICh0aGlzLmlzTGVhZikgYWNjLnB1c2goeClcbiAqICAgICAgcmV0dXJuIGFjY1xuICogICAgfSwgW10pXG4gKlxuICogICAgY29uc29sZS5kaXIobGVhdmVzKVxuICogICAgLy89PiBbIDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDkgXVxuICpcbiAqL1xuVHJhdmVyc2UucHJvdG90eXBlLnJlZHVjZSA9IGZ1bmN0aW9uKGNiLCBpbml0KSB7XG4gIGNvbnN0IHNraXAgPSBhcmd1bWVudHMubGVuZ3RoID09PSAxXG4gIGxldCBhY2MgPSBza2lwID8gdGhpcy52YWx1ZSA6IGluaXRcbiAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHgpIHtcbiAgICBpZiAoIXRoaXMuaXNSb290IHx8ICFza2lwKSB7XG4gICAgICBhY2MgPSBjYi5jYWxsKHRoaXMsIGFjYywgeClcbiAgICB9XG4gIH0pXG4gIHJldHVybiBhY2Ncbn1cblxuLyoqXG4gKiBAZGVzYyBSZXR1cm4gYW4gQXJyYXkgb2YgZXZlcnkgcG9zc2libGUgbm9uLWN5Y2xpYyBwYXRoIGluIHRoZSBvYmplY3QuIFBhdGhzIGFyZSBBcnJheXMgb2Ygc3RyaW5nIGtleXMuXG4gKiBAcmV0dXJuIHtBcnJheTxzdHJpbmc+fVxuICogQG1lbWJlck9mIFRyYXZlcnNlXG4gKiBAdGVzdHMgdHJhdmVyc2Uva2V5c1xuICovXG5UcmF2ZXJzZS5wcm90b3R5cGUucGF0aHMgPSBmdW5jdGlvbigpIHtcbiAgY29uc3QgYWNjID0gW11cbiAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHgpIHtcbiAgICBhY2MucHVzaCh0aGlzLnBhdGgpXG4gIH0pXG4gIHJldHVybiBhY2Ncbn1cblxuLyoqXG4gKiBAZGVzYyBSZXR1cm4gYW4gQXJyYXkgb2YgZXZlcnkgbm9kZSBpbiB0aGUgb2JqZWN0LlxuICogQG1lbWJlck9mIFRyYXZlcnNlXG4gKiBAcmV0dXJuIHtBcnJheTxhbnk+fVxuICovXG5UcmF2ZXJzZS5wcm90b3R5cGUubm9kZXMgPSBmdW5jdGlvbigpIHtcbiAgY29uc3QgYWNjID0gW11cbiAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHgpIHtcbiAgICBhY2MucHVzaCh0aGlzLm5vZGUpXG4gIH0pXG4gIHJldHVybiBhY2Ncbn1cblxuLyoqXG4gKiBAZGVzYyBDcmVhdGUgYSBkZWVwIGNsb25lIG9mIHRoZSBvYmplY3QuXG4gKlxuICogQHJldHVybiB7YW55fVxuICpcbiAqIEBtZW1iZXJPZiBUcmF2ZXJzZVxuICpcbiAqIEBleGFtcGxlXG4gKiAgICBjb25zdCB7dHJhdmVyc2UsIGVxfSA9IHJlcXVpcmUoJ2NoYWluLWFibGUnKVxuICpcbiAqICAgIGNvbnN0IG9iaiA9IHtlaDogdHJ1ZSwgY2FuYWRhOiBbMV19XG4gKiAgICBjb25zdCBjbG9uZWQgPSB0cmF2ZXJzZShvYmopLmNsb25lKClcbiAqICAgIGNsb25lZC5laCA9IGZhbHNlXG4gKiAgICBlcShjbG9uZWQsIG9iailcbiAqICAgIC8vPT4gZmFsc2VcbiAqXG4gKi9cblRyYXZlcnNlLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICBsZXQgcGFyZW50cyA9IFtdXG4gIGxldCBub2RlcyA9IFtdXG5cbiAgcmV0dXJuIChmdW5jdGlvbiBjbG9uZShzcmMpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChwYXJlbnRzW2ldID09PSBzcmMpIHtcbiAgICAgICAgcmV0dXJuIG5vZGVzW2ldXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlzT2JqU3RyaWN0KHNyYykpIHtcbiAgICAgIGxldCBkc3QgPSBjb3B5KHNyYylcblxuICAgICAgcGFyZW50cy5wdXNoKHNyYylcbiAgICAgIG5vZGVzLnB1c2goZHN0KVxuXG4gICAgICBmb3JFYWNoKE9iamVjdEtleXMoc3JjKSwga2V5ID0+IHtcbiAgICAgICAgZHN0W2tleV0gPSBjbG9uZShzcmNba2V5XSlcbiAgICAgIH0pXG5cbiAgICAgIHBhcmVudHMucG9wKClcbiAgICAgIG5vZGVzLnBvcCgpXG4gICAgICByZXR1cm4gZHN0XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmV0dXJuIHNyY1xuICAgIH1cbiAgfSkodGhpcy52YWx1ZSlcbn1cblxuLyoqXG4gKiBAZnVuY1xuICpcbiAqIEBwYXJhbSAge2FueX0gcm9vdCByb290IG5vZGVcbiAqIEBwYXJhbSAge0Z1bmN0aW9ufSBjYiBjYWxsYmFjayBmb3IgZWFjaFxuICogQHBhcmFtICB7Ym9vbGVhbn0gaW1tdXRhYmxlIHNob3VsZCBtdXRhdGUgb3Igbm90XG4gKiBAcmV0dXJuIHthbnl9XG4gKlxuICogQHNlZSB0cmF2ZXJzZS5mb3JFYWNoXG4gKi9cbmZ1bmN0aW9uIHdhbGsocm9vdCwgY2IsIGltbXV0YWJsZSkge1xuICBsZXQgcGF0aCA9IFtdXG4gIGxldCBwYXJlbnRzID0gW11cbiAgbGV0IGFsaXZlID0gdHJ1ZVxuXG4gIC8qKlxuICAgKiBAZW1pdHMgYmVmb3JlXG4gICAqIEBlbWl0cyBwcmVcbiAgICogQGVtaXRzIHBvc3RcbiAgICogQGVtaXRzIGFmdGVyXG4gICAqXG4gICAqIEBwYXJhbSAge2FueX0gbm9kZV9cbiAgICogQHJldHVybiB7U3RhdGV9IHNlZSB0eXBlc1xuICAgKi9cbiAgcmV0dXJuIChmdW5jdGlvbiB3YWxrZXIobm9kZV8pIHtcbiAgICAvLyBib3RoIGFyZSBvYmpzIHdpdGggcHJvcGVydGllcyB0aGF0IGdldCBjaGFuZ2VkIGJ1dFxuICAgIGNvbnN0IG5vZGUgPSBpbW11dGFibGUgPyBjb3B5KG5vZGVfKSA6IG5vZGVfXG4gICAgY29uc3QgbW9kaWZpZXJzID0ge31cbiAgICBsZXQga2VlcEdvaW5nID0gdHJ1ZVxuXG4gICAgLyoqXG4gICAgICogRWFjaCBtZXRob2QgdGhhdCB0YWtlcyBhIGNhbGxiYWNrIGhhcyBhIGNvbnRleHQgKGl0cyB0aGlzIG9iamVjdCkgd2l0aCB0aGVzZSBhdHRyaWJ1dGVzOlxuICAgICAqIEBwcm9wIHtib29sZWFufSBpc1Jvb3QgQGFsaWFzIGlzTm90Um9vdCBXaGV0aGVyIG9yIG5vdCB0aGUgcHJlc2VudCBub2RlIGlzIGEgbGVhZiBub2RlIChoYXMgbm8gY2hpbGRyZW4pXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKi9cbiAgICBjb25zdCBzdGF0ZSA9IHtcbiAgICAgIC8qKlxuICAgICAgICogVGhlIHByZXNlbnQgbm9kZSBvbiB0aGUgcmVjdXJzaXZlIHdhbGtcbiAgICAgICAqIEB0eXBlIHtBcnJheX1cbiAgICAgICAqL1xuICAgICAgbm9kZSxcbiAgICAgIC8qKlxuICAgICAgICogQHNlZSB0cmF2ZXJzZS5jb250ZXh0Lm5vZGVcbiAgICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgICAqIEB0eXBlIHtBcnJheX1cbiAgICAgICAqL1xuICAgICAgbm9kZV8sXG4gICAgICAvKipcbiAgICAgICAqIEFuIGFycmF5IG9mIHN0cmluZyBrZXlzIGZyb20gdGhlIHJvb3QgdG8gdGhlIHByZXNlbnQgbm9kZVxuICAgICAgICogQHR5cGUge0FycmF5fVxuICAgICAgICovXG4gICAgICBwYXRoOiBbXS5jb25jYXQocGF0aCksXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBjb250ZXh0IG9mIHRoZSBub2RlJ3MgcGFyZW50LiBUaGlzIGlzIHVuZGVmaW5lZCBmb3IgdGhlIHJvb3Qgbm9kZS5cbiAgICAgICAqIEB0eXBlIHt1bmRlZmluZWQgfCBQcmltaXRpdmV9XG4gICAgICAgKi9cbiAgICAgIHBhcmVudDogcGFyZW50c1twYXJlbnRzLmxlbmd0aCAtIDFdLFxuICAgICAgcGFyZW50cyxcbiAgICAgIC8qKlxuICAgICAgICogVGhlIG5hbWUgb2YgdGhlIGtleSBvZiB0aGUgcHJlc2VudCBub2RlIGluIGl0cyBwYXJlbnQuIFRoaXMgaXMgdW5kZWZpbmVkIGZvciB0aGUgcm9vdCBub2RlLlxuICAgICAgICogQHR5cGUge3VuZGVmaW5lZCB8IFByaW1pdGl2ZX1cbiAgICAgICAqL1xuICAgICAga2V5OiBwYXRoLnNsaWNlKC0xKVswXSxcbiAgICAgIC8qKlxuICAgICAgICogV2hldGhlciB0aGUgcHJlc2VudCBub2RlIGlzIHRoZSByb290IG5vZGVcbiAgICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAgICovXG4gICAgICBpc1Jvb3Q6IHBhdGgubGVuZ3RoID09PSAwLFxuICAgICAgLyoqXG4gICAgICAgKiBEZXB0aCBvZiB0aGUgbm9kZSB3aXRoaW4gdGhlIHRyYXZlcnNhbFxuICAgICAgICogQHR5cGUge251bWJlcn1cbiAgICAgICAqL1xuICAgICAgbGV2ZWw6IHBhdGgubGVuZ3RoLFxuICAgICAgLyoqXG4gICAgICAgKiBJZiB0aGUgbm9kZSBlcXVhbHMgb25lIG9mIGl0cyBwYXJlbnRzLCB0aGUgY2lyY3VsYXIgYXR0cmlidXRlIGlzIHNldCB0byB0aGUgY29udGV4dCBvZiB0aGF0IHBhcmVudCBhbmQgdGhlIHRyYXZlcnNhbCBwcm9ncmVzc2VzIG5vIGRlZXBlci5cbiAgICAgICAqIEB0eXBlIHtudWxsIHwgYm9vbGVhbn1cbiAgICAgICAqL1xuICAgICAgY2lyY3VsYXI6IG51bGwsXG4gICAgICAvKipcbiAgICAgICAqIFNldCBhIG5ldyB2YWx1ZSBmb3IgdGhlIHByZXNlbnQgbm9kZS5cbiAgICAgICAqIEFsbCB0aGUgZWxlbWVudHMgaW4gdmFsdWUgd2lsbCBiZSByZWN1cnNpdmVseSB0cmF2ZXJzZWQgdW5sZXNzIHN0b3BIZXJlIGlzIHRydWUuXG4gICAgICAgKlxuICAgICAgICogQHBhcmFtICB7RnVuY3Rpb259IHhcbiAgICAgICAqIEBwYXJhbSAge2Jvb2xlYW59IHN0b3BIZXJlXG4gICAgICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgICAgICovXG4gICAgICB1cGRhdGUoeCwgc3RvcEhlcmUpIHtcbiAgICAgICAgaWYgKCFzdGF0ZS5pc1Jvb3QpIHtcbiAgICAgICAgICBzdGF0ZS5wYXJlbnQubm9kZVtzdGF0ZS5rZXldID0geFxuICAgICAgICB9XG4gICAgICAgIHN0YXRlLm5vZGUgPSB4XG4gICAgICAgIGlmIChzdG9wSGVyZSkga2VlcEdvaW5nID0gZmFsc2VcbiAgICAgIH0sXG4gICAgICAvKipcbiAgICAgICAqIERlbGV0ZSB0aGUgY3VycmVudCBlbGVtZW50IGZyb20gaXRzIHBhcmVudCBpbiB0aGUgb3V0cHV0LiBDYWxscyBkZWxldGUgZXZlbiBvbiBBcnJheXMuXG4gICAgICAgKiBAcGFyYW0gIHtib29sZWFufSBzdG9wSGVyZVxuICAgICAgICogQHJldHVybiB7dm9pZH1cbiAgICAgICAqL1xuICAgICAgZGVsZXRlKHN0b3BIZXJlKSB7XG4gICAgICAgIGRlbGV0ZSBzdGF0ZS5wYXJlbnQubm9kZVtzdGF0ZS5rZXldXG4gICAgICAgIGlmIChzdG9wSGVyZSkga2VlcEdvaW5nID0gZmFsc2VcbiAgICAgIH0sXG4gICAgICAvKipcbiAgICAgICAqIFJlbW92ZSB0aGUgY3VycmVudCBlbGVtZW50IGZyb20gdGhlIG91dHB1dC4gSWYgdGhlIG5vZGUgaXMgaW4gYW4gQXJyYXkgaXQgd2lsbCBiZSBzcGxpY2VkIG9mZi4gT3RoZXJ3aXNlIGl0IHdpbGwgYmUgZGVsZXRlZCBmcm9tIGl0cyBwYXJlbnQuXG4gICAgICAgKiBAcGFyYW0gIHtib29sZWFufSBzdG9wSGVyZVxuICAgICAgICogQHJldHVybiB7dm9pZH1cbiAgICAgICAqL1xuICAgICAgcmVtb3ZlKHN0b3BIZXJlKSB7XG4gICAgICAgIC8vIEBOT1RFIHNhZmV0eVxuICAgICAgICBpZiAoaXNVbmRlZmluZWQoc3RhdGUucGFyZW50KSkge1xuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzQXJyYXkoc3RhdGUucGFyZW50Lm5vZGUpKSB7XG4gICAgICAgICAgc3RhdGUucGFyZW50Lm5vZGUuc3BsaWNlKHN0YXRlLmtleSwgMSlcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBkZWxldGUgc3RhdGUucGFyZW50Lm5vZGVbc3RhdGUua2V5XVxuICAgICAgICB9XG4gICAgICAgIGlmIChzdG9wSGVyZSkga2VlcEdvaW5nID0gZmFsc2VcbiAgICAgIH0sXG4gICAgICBrZXlzOiBudWxsLFxuICAgICAgLyoqXG4gICAgICAgKiBDYWxsIHRoaXMgZnVuY3Rpb24gYmVmb3JlIGFueSBvZiB0aGUgY2hpbGRyZW4gYXJlIHRyYXZlcnNlZC5cbiAgICAgICAqIFlvdSBjYW4gYXNzaWduIGludG8gdGhpcy5rZXlzIGhlcmUgdG8gdHJhdmVyc2UgaW4gYSBjdXN0b20gb3JkZXIuXG4gICAgICAgKiBAcGFyYW0gIHtGdW5jdGlvbn0gZm5cbiAgICAgICAqIEByZXR1cm4ge2FueX1cbiAgICAgICAqL1xuICAgICAgYmVmb3JlKGZuKSB7XG4gICAgICAgIG1vZGlmaWVycy5iZWZvcmUgPSBmblxuICAgICAgfSxcbiAgICAgIC8qKlxuICAgICAgICogQ2FsbCB0aGlzIGZ1bmN0aW9uIGFmdGVyIGFueSBvZiB0aGUgY2hpbGRyZW4gYXJlIHRyYXZlcnNlZC5cbiAgICAgICAqIEBwYXJhbSAge0Z1bmN0aW9ufSBmblxuICAgICAgICogQHJldHVybiB7YW55fVxuICAgICAgICovXG4gICAgICBhZnRlcihmbikge1xuICAgICAgICBtb2RpZmllcnMuYWZ0ZXIgPSBmblxuICAgICAgfSxcbiAgICAgIC8qKlxuICAgICAgICogQ2FsbCB0aGlzIGZ1bmN0aW9uIGJlZm9yZSBlYWNoIG9mIHRoZSBjaGlsZHJlbiBhcmUgdHJhdmVyc2VkLlxuICAgICAgICogQHBhcmFtICB7RnVuY3Rpb259IGZuXG4gICAgICAgKiBAcmV0dXJuIHthbnl9XG4gICAgICAgKi9cbiAgICAgIHByZShmbikge1xuICAgICAgICBtb2RpZmllcnMucHJlID0gZm5cbiAgICAgIH0sXG4gICAgICAvKipcbiAgICAgICAqIENhbGwgdGhpcyBmdW5jdGlvbiBhZnRlciBlYWNoIG9mIHRoZSBjaGlsZHJlbiBhcmUgdHJhdmVyc2VkLlxuICAgICAgICogQHBhcmFtICB7RnVuY3Rpb259IGZuXG4gICAgICAgKiBAcmV0dXJuIHthbnl9XG4gICAgICAgKi9cbiAgICAgIHBvc3QoZm4pIHtcbiAgICAgICAgbW9kaWZpZXJzLnBvc3QgPSBmblxuICAgICAgfSxcbiAgICAgIC8qKlxuICAgICAgICogQG1vZGlmaWVzIGFsaXZlXG4gICAgICAgKiBAcHJvdGVjdGVkXG4gICAgICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgICAgICovXG4gICAgICBzdG9wKCkge1xuICAgICAgICBhbGl2ZSA9IGZhbHNlXG4gICAgICB9LFxuICAgICAgLyoqXG4gICAgICAgKiBAbW9kaWZpZXMga2VlcEdvaW5nXG4gICAgICAgKiBAcHJvdGVjdGVkXG4gICAgICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgICAgICovXG4gICAgICBibG9jaygpIHtcbiAgICAgICAga2VlcEdvaW5nID0gZmFsc2VcbiAgICAgIH0sXG4gICAgfVxuXG4gICAgaWYgKCFhbGl2ZSkgcmV0dXJuIHN0YXRlXG5cbiAgICAvKipcbiAgICAgKiBAZGVzYyB1cGRhdGVzIGlmIG5lZWRlZDpcbiAgICAgKiAgICAgICBAbW9kaWZpZXMga2V5c1xuICAgICAqICAgICAgIEBtb2RpZmllcyBjaXJjdWxhclxuICAgICAqICAgICAgIEBtb2RpZmllcyBpc0xlYWZcbiAgICAgKiAgICAgICBAbW9kaWZpZXMgbm90TGVhZlxuICAgICAqICAgICAgIEBtb2RpZmllcyBub3RSb290XG4gICAgICogQHJldHVybiB7dm9pZH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1cGRhdGVTdGF0ZSgpIHtcbiAgICAgIGlmIChpc09ialN0cmljdChzdGF0ZS5ub2RlKSkge1xuICAgICAgICBpZiAoIXN0YXRlLmtleXMgfHwgc3RhdGUubm9kZV8gIT09IHN0YXRlLm5vZGUpIHtcbiAgICAgICAgICBzdGF0ZS5rZXlzID0gT2JqZWN0S2V5cyhzdGF0ZS5ub2RlKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQE5PVEUgd2FzID09XG4gICAgICAgIHN0YXRlLmlzTGVhZiA9IHN0YXRlLmtleXMubGVuZ3RoID09PSAwXG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJlbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKHBhcmVudHNbaV0ubm9kZV8gPT09IG5vZGVfKSB7XG4gICAgICAgICAgICBzdGF0ZS5jaXJjdWxhciA9IHBhcmVudHNbaV1cbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgc3RhdGUuaXNMZWFmID0gdHJ1ZVxuICAgICAgICBzdGF0ZS5rZXlzID0gbnVsbFxuICAgICAgfVxuXG4gICAgICBzdGF0ZS5ub3RMZWFmID0gIXN0YXRlLmlzTGVhZlxuICAgICAgc3RhdGUubm90Um9vdCA9ICFzdGF0ZS5pc1Jvb3RcbiAgICB9XG5cbiAgICB1cGRhdGVTdGF0ZSgpXG5cbiAgICAvLyBATk9URSBhZGRlZCBsYXN0IGAsc3RhdGVgIGFyZyB0byBub3QgaGF2ZSBpdCBoYXZlIHRvIHVzZSBgdGhpc2AsXG4gICAgLy8gYnV0IGJyb2tlIHNvbWUgdGhpbmdzIHNvIG1vdmVkIHRvIGFub3RoZXIgZm5cbiAgICAvL1xuICAgIC8vIHVzZSByZXR1cm4gdmFsdWVzIHRvIHVwZGF0ZSBpZiBkZWZpbmVkXG4gICAgbGV0IHJldCA9IGNiLmNhbGwoc3RhdGUsIHN0YXRlLm5vZGUpXG4gICAgaWYgKCFpc1VuZGVmaW5lZChyZXQpICYmIHN0YXRlLnVwZGF0ZSkgc3RhdGUudXBkYXRlKHJldClcblxuICAgIGlmIChtb2RpZmllcnMuYmVmb3JlKSBtb2RpZmllcnMuYmVmb3JlLmNhbGwoc3RhdGUsIHN0YXRlLm5vZGUpXG5cbiAgICBpZiAoIWtlZXBHb2luZykgcmV0dXJuIHN0YXRlXG5cbiAgICAvLyB3aGVuIGl0J3Mgc29tZSBzb3J0IG9mIGl0ZXJ0YWJsZSBvYmplY3QsIGxvb3AgaXQgZnVydGhlclxuICAgIGlmIChpc09ialN0cmljdChzdGF0ZS5ub2RlKSAmJiAhc3RhdGUuY2lyY3VsYXIpIHtcbiAgICAgIHBhcmVudHMucHVzaChzdGF0ZSlcblxuICAgICAgdXBkYXRlU3RhdGUoKVxuXG4gICAgICBmb3JFYWNoKHN0YXRlLmtleXMsIChrZXksIGkpID0+IHtcbiAgICAgICAgcGF0aC5wdXNoKGtleSlcblxuICAgICAgICBpZiAobW9kaWZpZXJzLnByZSkgbW9kaWZpZXJzLnByZS5jYWxsKHN0YXRlLCBzdGF0ZS5ub2RlW2tleV0sIGtleSlcblxuICAgICAgICBjb25zdCBjaGlsZCA9IHdhbGtlcihzdGF0ZS5ub2RlW2tleV0pXG4gICAgICAgIGlmIChpbW11dGFibGUgJiYgaGFzT3duUHJvcGVydHkoc3RhdGUubm9kZSwga2V5KSkge1xuICAgICAgICAgIHN0YXRlLm5vZGVba2V5XSA9IGNoaWxkLm5vZGVcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEBOT1RFIHdhcyA9PVxuICAgICAgICBjaGlsZC5pc0xhc3QgPSBpID09PSBzdGF0ZS5rZXlzLmxlbmd0aCAtIDFcbiAgICAgICAgY2hpbGQuaXNGaXJzdCA9IGkgPT09IDBcblxuICAgICAgICBpZiAobW9kaWZpZXJzLnBvc3QpIG1vZGlmaWVycy5wb3N0LmNhbGwoc3RhdGUsIGNoaWxkKVxuXG4gICAgICAgIHBhdGgucG9wKClcbiAgICAgIH0pXG4gICAgICBwYXJlbnRzLnBvcCgpXG4gICAgfVxuXG4gICAgaWYgKG1vZGlmaWVycy5hZnRlcikgbW9kaWZpZXJzLmFmdGVyLmNhbGwoc3RhdGUsIHN0YXRlLm5vZGUpXG5cbiAgICByZXR1cm4gc3RhdGVcbiAgfSkocm9vdCkubm9kZVxufVxuXG4vKipcbiAqIEBmdW5jXG4gKiBAVE9ETyAgIGRvZXMgbm90IHJlc3BlY3QgT2JqZWN0RGVzY3JpcHRvcnNcbiAqIEBOT1RFICAgd2lja2VkIHRlcm5hcnlcbiAqIEBwYXJhbSAge2FueX0gc3JjXG4gKiBAcmV0dXJuIHthbnl9XG4gKi9cbmZ1bmN0aW9uIGNvcHkoc3JjKSB7XG4gIC8vIHJlcXVpcmUoJ2ZsaXBsb2cnKS5kYXRhKHNyYykuYm9sZCgnY29weWluZycpLmVjaG8oKVxuICBpZiAoaXNPYmpTdHJpY3Qoc3JjKSkge1xuICAgIGxldCBkc3RcblxuICAgIC8vIHJlcXVpcmUoJ2ZsaXBsb2cnKS51bmRlcmxpbmUoJ2lzIG9iaicpLmVjaG8oKVxuICAgIGlmIChpc01hcChzcmMpKSB7XG4gICAgICBkc3QgPSByZWR1Y2Uoc3JjLmVudHJpZXMoKSlcbiAgICB9XG4gICAgZWxzZSBpZiAoaXNTZXQoc3JjKSkge1xuICAgICAgZHN0ID0gdG9hcnIoc3JjKVxuICAgIH1cbiAgICBpZiAoaXNBcnJheShzcmMpKSB7XG4gICAgICBkc3QgPSBbXVxuICAgIH1cbiAgICBlbHNlIGlmIChpc0RhdGUoc3JjKSkge1xuICAgICAgZHN0ID0gbmV3IERhdGUoc3JjLmdldFRpbWUgPyBzcmMuZ2V0VGltZSgpIDogc3JjKVxuICAgIH1cbiAgICBlbHNlIGlmIChpc1JlZ0V4cChzcmMpKSB7XG4gICAgICBkc3QgPSBuZXcgUmVnRXhwKHNyYylcbiAgICB9XG4gICAgZWxzZSBpZiAoaXNFcnJvcihzcmMpKSB7XG4gICAgICBkc3QgPSB7bWVzc2FnZTogc3JjLm1lc3NhZ2V9XG4gICAgfVxuICAgIGVsc2UgaWYgKGlzQm9vbGVhbihzcmMpKSB7XG4gICAgICBkc3QgPSBuZXcgQm9vbGVhbihzcmMpXG4gICAgfVxuICAgIGVsc2UgaWYgKGlzTnVtYmVyKHNyYykpIHtcbiAgICAgIGRzdCA9IG5ldyBOdW1iZXIoc3JjKVxuICAgIH1cbiAgICBlbHNlIGlmIChpc1N0cmluZyhzcmMpKSB7XG4gICAgICBkc3QgPSBuZXcgU3RyaW5nKHNyYylcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAvL2lmIChPYmplY3QuY3JlYXRlICYmIE9iamVjdC5nZXRQcm90b3R5cGVPZilcbiAgICAgIGRzdCA9IE9iamVjdC5jcmVhdGUoZ2V0UHJvdG90eXBlT2Yoc3JjKSlcbiAgICB9XG4gICAgLy8gZWxzZSBpZiAoc3JjLmNvbnN0cnVjdG9yID09PSBPYmplY3QpIHtcbiAgICAvLyAgIGRzdCA9IHt9XG4gICAgLy8gfVxuICAgIC8vIGVsc2Uge1xuICAgIC8vICAgLy8gQE5PVEU6IG9ubHkgaGFwcGVucyBpZiBhYm92ZSBnZXRQcm90b3R5cGVPZiBkb2VzIG5vdCBleGlzdFxuICAgIC8vICAgdmFyIHByb3RvID0gKHNyYy5jb25zdHJ1Y3RvciAmJiBzcmMuY29uc3RydWN0b3IucHJvdG90eXBlKSB8fFxuICAgIC8vICAgc3JjLl9fcHJvdG9fXyB8fCB7fVxuICAgIC8vICAgdmFyIFQgPSBmdW5jdGlvbigpIHt9XG4gICAgLy8gICBULnByb3RvdHlwZSA9IHByb3RvXG4gICAgLy8gICBkc3QgPSBuZXcgVCgpXG4gICAgLy8gfVxuXG4gICAgZm9yRWFjaChPYmplY3RLZXlzKHNyYyksIGtleSA9PiB7XG4gICAgICBkc3Rba2V5XSA9IHNyY1trZXldXG4gICAgfSlcbiAgICByZXR1cm4gZHN0XG4gIH1cbiAgZWxzZSB7XG4gICAgLy8gcmVxdWlyZSgnZmxpcGxvZycpLnJlZCgnaXMgTk9UIE9CSicpLmVjaG8oKVxuICAgIHJldHVybiBzcmNcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjIGFkZHMgbWV0aG9kcyB0byBUcmF2ZXJzZXJcbiAqL1xuZm9yRWFjaChPYmplY3RLZXlzKFRyYXZlcnNlLnByb3RvdHlwZSksIGtleSA9PiB7XG4gIHRyYXZlcnNlW2tleV0gPSBmdW5jdGlvbihvYmopIHtcbiAgICBjb25zdCB0ID0gbmV3IFRyYXZlcnNlKG9iailcblxuICAgIC8vIGFyZ3MgPSBhcmd1bWVudG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cykuc2xpY2UoMSlcbiAgICByZXR1cm4gdFtrZXldLmFwcGx5KHQsIGFyZ3VtZW50b3IuYXBwbHkobnVsbCwgYXJndW1lbnRzKS5zbGljZSgxKSlcbiAgfVxufSlcbiJd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QyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUFBLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUE7O0lBRXhELElBQUksU0FBUyxDQUFDLE1BQU0sRUFBRSxFQUFBLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUE7O0lBRTlELElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBQSxPQUFPLEtBQUssRUFBQTs7O0lBRzVCLElBQUksV0FBVyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUU7TUFDOUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7O01BRW5CLFdBQVcsRUFBRTs7TUFFYixPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxTQUFBLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxBQUFHO1FBQzlCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDOztRQUVkLElBQUksU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFBLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFBOztRQUVsRUQsR0FBSyxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNyQyxJQUFJLFNBQVMsSUFBSSxjQUFjLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRTtVQUNoRCxLQUFLLENBQ