' + func(text) + '
';\n * });\n *\n * p('fred, barney, & pebbles');\n * // => 'fred, barney, & pebbles
'\n */\n function wrap(value, wrapper) {\n return partial(castFunction(wrapper), value);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Casts `value` as an array if it's not one.\n *\n * @static\n * @memberOf _\n * @since 4.4.0\n * @category Lang\n * @param {*} value The value to inspect.\n * @returns {Array} Returns the cast array.\n * @example\n *\n * _.castArray(1);\n * // => [1]\n *\n * _.castArray({ 'a': 1 });\n * // => [{ 'a': 1 }]\n *\n * _.castArray('abc');\n * // => ['abc']\n *\n * _.castArray(null);\n * // => [null]\n *\n * _.castArray(undefined);\n * // => [undefined]\n *\n * _.castArray();\n * // => []\n *\n * var array = [1, 2, 3];\n * console.log(_.castArray(array) === array);\n * // => true\n */\n function castArray() {\n if (!arguments.length) {\n return [];\n }\n var value = arguments[0];\n return isArray(value) ? value : [value];\n }\n\n /**\n * Creates a shallow clone of `value`.\n *\n * **Note:** This method is loosely based on the\n * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)\n * and supports cloning arrays, array buffers, booleans, date objects, maps,\n * numbers, `Object` objects, regexes, sets, strings, symbols, and typed\n * arrays. The own enumerable properties of `arguments` objects are cloned\n * as plain objects. An empty object is returned for uncloneable values such\n * as error objects, functions, DOM nodes, and WeakMaps.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to clone.\n * @returns {*} Returns the cloned value.\n * @see _.cloneDeep\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var shallow = _.clone(objects);\n * console.log(shallow[0] === objects[0]);\n * // => true\n */\n function clone(value) {\n return baseClone(value, CLONE_SYMBOLS_FLAG);\n }\n\n /**\n * This method is like `_.clone` except that it accepts `customizer` which\n * is invoked to produce the cloned value. If `customizer` returns `undefined`,\n * cloning is handled by the method instead. The `customizer` is invoked with\n * up to four arguments; (value [, index|key, object, stack]).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to clone.\n * @param {Function} [customizer] The function to customize cloning.\n * @returns {*} Returns the cloned value.\n * @see _.cloneDeepWith\n * @example\n *\n * function customizer(value) {\n * if (_.isElement(value)) {\n * return value.cloneNode(false);\n * }\n * }\n *\n * var el = _.cloneWith(document.body, customizer);\n *\n * console.log(el === document.body);\n * // => false\n * console.log(el.nodeName);\n * // => 'BODY'\n * console.log(el.childNodes.length);\n * // => 0\n */\n function cloneWith(value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);\n }\n\n /**\n * This method is like `_.clone` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @returns {*} Returns the deep cloned value.\n * @see _.clone\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var deep = _.cloneDeep(objects);\n * console.log(deep[0] === objects[0]);\n * // => false\n */\n function cloneDeep(value) {\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);\n }\n\n /**\n * This method is like `_.cloneWith` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @param {Function} [customizer] The function to customize cloning.\n * @returns {*} Returns the deep cloned value.\n * @see _.cloneWith\n * @example\n *\n * function customizer(value) {\n * if (_.isElement(value)) {\n * return value.cloneNode(true);\n * }\n * }\n *\n * var el = _.cloneDeepWith(document.body, customizer);\n *\n * console.log(el === document.body);\n * // => false\n * console.log(el.nodeName);\n * // => 'BODY'\n * console.log(el.childNodes.length);\n * // => 20\n */\n function cloneDeepWith(value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);\n }\n\n /**\n * Checks if `object` conforms to `source` by invoking the predicate\n * properties of `source` with the corresponding property values of `object`.\n *\n * **Note:** This method is equivalent to `_.conforms` when `source` is\n * partially applied.\n *\n * @static\n * @memberOf _\n * @since 4.14.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property predicates to conform to.\n * @returns {boolean} Returns `true` if `object` conforms, else `false`.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n *\n * _.conformsTo(object, { 'b': function(n) { return n > 1; } });\n * // => true\n *\n * _.conformsTo(object, { 'b': function(n) { return n > 2; } });\n * // => false\n */\n function conformsTo(object, source) {\n return source == null || baseConformsTo(object, source, keys(source));\n }\n\n /**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\n function eq(value, other) {\n return value === other || (value !== value && other !== other);\n }\n\n /**\n * Checks if `value` is greater than `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is greater than `other`,\n * else `false`.\n * @see _.lt\n * @example\n *\n * _.gt(3, 1);\n * // => true\n *\n * _.gt(3, 3);\n * // => false\n *\n * _.gt(1, 3);\n * // => false\n */\n var gt = createRelationalOperation(baseGt);\n\n /**\n * Checks if `value` is greater than or equal to `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is greater than or equal to\n * `other`, else `false`.\n * @see _.lte\n * @example\n *\n * _.gte(3, 1);\n * // => true\n *\n * _.gte(3, 3);\n * // => true\n *\n * _.gte(1, 3);\n * // => false\n */\n var gte = createRelationalOperation(function(value, other) {\n return value >= other;\n });\n\n /**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\n var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n };\n\n /**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\n var isArray = Array.isArray;\n\n /**\n * Checks if `value` is classified as an `ArrayBuffer` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.\n * @example\n *\n * _.isArrayBuffer(new ArrayBuffer(2));\n * // => true\n *\n * _.isArrayBuffer(new Array(2));\n * // => false\n */\n var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;\n\n /**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\n function isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n }\n\n /**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\n function isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n }\n\n /**\n * Checks if `value` is classified as a boolean primitive or object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.\n * @example\n *\n * _.isBoolean(false);\n * // => true\n *\n * _.isBoolean(null);\n * // => false\n */\n function isBoolean(value) {\n return value === true || value === false ||\n (isObjectLike(value) && baseGetTag(value) == boolTag);\n }\n\n /**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\n var isBuffer = nativeIsBuffer || stubFalse;\n\n /**\n * Checks if `value` is classified as a `Date` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a date object, else `false`.\n * @example\n *\n * _.isDate(new Date);\n * // => true\n *\n * _.isDate('Mon April 23 2012');\n * // => false\n */\n var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;\n\n /**\n * Checks if `value` is likely a DOM element.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.\n * @example\n *\n * _.isElement(document.body);\n * // => true\n *\n * _.isElement('');\n * // => false\n */\n function isElement(value) {\n return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);\n }\n\n /**\n * Checks if `value` is an empty object, collection, map, or set.\n *\n * Objects are considered empty if they have no own enumerable string keyed\n * properties.\n *\n * Array-like values such as `arguments` objects, arrays, buffers, strings, or\n * jQuery-like collections are considered empty if they have a `length` of `0`.\n * Similarly, maps and sets are considered empty if they have a `size` of `0`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is empty, else `false`.\n * @example\n *\n * _.isEmpty(null);\n * // => true\n *\n * _.isEmpty(true);\n * // => true\n *\n * _.isEmpty(1);\n * // => true\n *\n * _.isEmpty([1, 2, 3]);\n * // => false\n *\n * _.isEmpty({ 'a': 1 });\n * // => false\n */\n function isEmpty(value) {\n if (value == null) {\n return true;\n }\n if (isArrayLike(value) &&\n (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||\n isBuffer(value) || isTypedArray(value) || isArguments(value))) {\n return !value.length;\n }\n var tag = getTag(value);\n if (tag == mapTag || tag == setTag) {\n return !value.size;\n }\n if (isPrototype(value)) {\n return !baseKeys(value).length;\n }\n for (var key in value) {\n if (hasOwnProperty.call(value, key)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\n function isEqual(value, other) {\n return baseIsEqual(value, other);\n }\n\n /**\n * This method is like `_.isEqual` except that it accepts `customizer` which\n * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n * are handled by the method instead. The `customizer` is invoked with up to\n * six arguments: (objValue, othValue [, index|key, object, other, stack]).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * function isGreeting(value) {\n * return /^h(?:i|ello)$/.test(value);\n * }\n *\n * function customizer(objValue, othValue) {\n * if (isGreeting(objValue) && isGreeting(othValue)) {\n * return true;\n * }\n * }\n *\n * var array = ['hello', 'goodbye'];\n * var other = ['hi', 'goodbye'];\n *\n * _.isEqualWith(array, other, customizer);\n * // => true\n */\n function isEqualWith(value, other, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n var result = customizer ? customizer(value, other) : undefined;\n return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;\n }\n\n /**\n * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,\n * `SyntaxError`, `TypeError`, or `URIError` object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an error object, else `false`.\n * @example\n *\n * _.isError(new Error);\n * // => true\n *\n * _.isError(Error);\n * // => false\n */\n function isError(value) {\n if (!isObjectLike(value)) {\n return false;\n }\n var tag = baseGetTag(value);\n return tag == errorTag || tag == domExcTag ||\n (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));\n }\n\n /**\n * Checks if `value` is a finite primitive number.\n *\n * **Note:** This method is based on\n * [`Number.isFinite`](https://mdn.io/Number/isFinite).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.\n * @example\n *\n * _.isFinite(3);\n * // => true\n *\n * _.isFinite(Number.MIN_VALUE);\n * // => true\n *\n * _.isFinite(Infinity);\n * // => false\n *\n * _.isFinite('3');\n * // => false\n */\n function isFinite(value) {\n return typeof value == 'number' && nativeIsFinite(value);\n }\n\n /**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\n function isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n }\n\n /**\n * Checks if `value` is an integer.\n *\n * **Note:** This method is based on\n * [`Number.isInteger`](https://mdn.io/Number/isInteger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an integer, else `false`.\n * @example\n *\n * _.isInteger(3);\n * // => true\n *\n * _.isInteger(Number.MIN_VALUE);\n * // => false\n *\n * _.isInteger(Infinity);\n * // => false\n *\n * _.isInteger('3');\n * // => false\n */\n function isInteger(value) {\n return typeof value == 'number' && value == toInteger(value);\n }\n\n /**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\n function isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n }\n\n /**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\n function isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n }\n\n /**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\n function isObjectLike(value) {\n return value != null && typeof value == 'object';\n }\n\n /**\n * Checks if `value` is classified as a `Map` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n * @example\n *\n * _.isMap(new Map);\n * // => true\n *\n * _.isMap(new WeakMap);\n * // => false\n */\n var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;\n\n /**\n * Performs a partial deep comparison between `object` and `source` to\n * determine if `object` contains equivalent property values.\n *\n * **Note:** This method is equivalent to `_.matches` when `source` is\n * partially applied.\n *\n * Partial comparisons will match empty array and empty object `source`\n * values against any array or object value, respectively. See `_.isEqual`\n * for a list of supported value comparisons.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n *\n * _.isMatch(object, { 'b': 2 });\n * // => true\n *\n * _.isMatch(object, { 'b': 1 });\n * // => false\n */\n function isMatch(object, source) {\n return object === source || baseIsMatch(object, source, getMatchData(source));\n }\n\n /**\n * This method is like `_.isMatch` except that it accepts `customizer` which\n * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n * are handled by the method instead. The `customizer` is invoked with five\n * arguments: (objValue, srcValue, index|key, object, source).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n * @example\n *\n * function isGreeting(value) {\n * return /^h(?:i|ello)$/.test(value);\n * }\n *\n * function customizer(objValue, srcValue) {\n * if (isGreeting(objValue) && isGreeting(srcValue)) {\n * return true;\n * }\n * }\n *\n * var object = { 'greeting': 'hello' };\n * var source = { 'greeting': 'hi' };\n *\n * _.isMatchWith(object, source, customizer);\n * // => true\n */\n function isMatchWith(object, source, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseIsMatch(object, source, getMatchData(source), customizer);\n }\n\n /**\n * Checks if `value` is `NaN`.\n *\n * **Note:** This method is based on\n * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as\n * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for\n * `undefined` and other non-number values.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n * @example\n *\n * _.isNaN(NaN);\n * // => true\n *\n * _.isNaN(new Number(NaN));\n * // => true\n *\n * isNaN(undefined);\n * // => true\n *\n * _.isNaN(undefined);\n * // => false\n */\n function isNaN(value) {\n // An `NaN` primitive is the only value that is not equal to itself.\n // Perform the `toStringTag` check first to avoid errors with some\n // ActiveX objects in IE.\n return isNumber(value) && value != +value;\n }\n\n /**\n * Checks if `value` is a pristine native function.\n *\n * **Note:** This method can't reliably detect native functions in the presence\n * of the core-js package because core-js circumvents this kind of detection.\n * Despite multiple requests, the core-js maintainer has made it clear: any\n * attempt to fix the detection will be obstructed. As a result, we're left\n * with little choice but to throw an error. Unfortunately, this also affects\n * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),\n * which rely on core-js.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n * @example\n *\n * _.isNative(Array.prototype.push);\n * // => true\n *\n * _.isNative(_);\n * // => false\n */\n function isNative(value) {\n if (isMaskable(value)) {\n throw new Error(CORE_ERROR_TEXT);\n }\n return baseIsNative(value);\n }\n\n /**\n * Checks if `value` is `null`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `null`, else `false`.\n * @example\n *\n * _.isNull(null);\n * // => true\n *\n * _.isNull(void 0);\n * // => false\n */\n function isNull(value) {\n return value === null;\n }\n\n /**\n * Checks if `value` is `null` or `undefined`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is nullish, else `false`.\n * @example\n *\n * _.isNil(null);\n * // => true\n *\n * _.isNil(void 0);\n * // => true\n *\n * _.isNil(NaN);\n * // => false\n */\n function isNil(value) {\n return value == null;\n }\n\n /**\n * Checks if `value` is classified as a `Number` primitive or object.\n *\n * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are\n * classified as numbers, use the `_.isFinite` method.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a number, else `false`.\n * @example\n *\n * _.isNumber(3);\n * // => true\n *\n * _.isNumber(Number.MIN_VALUE);\n * // => true\n *\n * _.isNumber(Infinity);\n * // => true\n *\n * _.isNumber('3');\n * // => false\n */\n function isNumber(value) {\n return typeof value == 'number' ||\n (isObjectLike(value) && baseGetTag(value) == numberTag);\n }\n\n /**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\n function isPlainObject(value) {\n if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n funcToString.call(Ctor) == objectCtorString;\n }\n\n /**\n * Checks if `value` is classified as a `RegExp` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.\n * @example\n *\n * _.isRegExp(/abc/);\n * // => true\n *\n * _.isRegExp('/abc/');\n * // => false\n */\n var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;\n\n /**\n * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754\n * double precision number which isn't the result of a rounded unsafe integer.\n *\n * **Note:** This method is based on\n * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.\n * @example\n *\n * _.isSafeInteger(3);\n * // => true\n *\n * _.isSafeInteger(Number.MIN_VALUE);\n * // => false\n *\n * _.isSafeInteger(Infinity);\n * // => false\n *\n * _.isSafeInteger('3');\n * // => false\n */\n function isSafeInteger(value) {\n return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;\n }\n\n /**\n * Checks if `value` is classified as a `Set` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n * @example\n *\n * _.isSet(new Set);\n * // => true\n *\n * _.isSet(new WeakSet);\n * // => false\n */\n var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;\n\n /**\n * Checks if `value` is classified as a `String` primitive or object.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a string, else `false`.\n * @example\n *\n * _.isString('abc');\n * // => true\n *\n * _.isString(1);\n * // => false\n */\n function isString(value) {\n return typeof value == 'string' ||\n (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);\n }\n\n /**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\n function isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n }\n\n /**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\n var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\n /**\n * Checks if `value` is `undefined`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.\n * @example\n *\n * _.isUndefined(void 0);\n * // => true\n *\n * _.isUndefined(null);\n * // => false\n */\n function isUndefined(value) {\n return value === undefined;\n }\n\n /**\n * Checks if `value` is classified as a `WeakMap` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.\n * @example\n *\n * _.isWeakMap(new WeakMap);\n * // => true\n *\n * _.isWeakMap(new Map);\n * // => false\n */\n function isWeakMap(value) {\n return isObjectLike(value) && getTag(value) == weakMapTag;\n }\n\n /**\n * Checks if `value` is classified as a `WeakSet` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.\n * @example\n *\n * _.isWeakSet(new WeakSet);\n * // => true\n *\n * _.isWeakSet(new Set);\n * // => false\n */\n function isWeakSet(value) {\n return isObjectLike(value) && baseGetTag(value) == weakSetTag;\n }\n\n /**\n * Checks if `value` is less than `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is less than `other`,\n * else `false`.\n * @see _.gt\n * @example\n *\n * _.lt(1, 3);\n * // => true\n *\n * _.lt(3, 3);\n * // => false\n *\n * _.lt(3, 1);\n * // => false\n */\n var lt = createRelationalOperation(baseLt);\n\n /**\n * Checks if `value` is less than or equal to `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is less than or equal to\n * `other`, else `false`.\n * @see _.gte\n * @example\n *\n * _.lte(1, 3);\n * // => true\n *\n * _.lte(3, 3);\n * // => true\n *\n * _.lte(3, 1);\n * // => false\n */\n var lte = createRelationalOperation(function(value, other) {\n return value <= other;\n });\n\n /**\n * Converts `value` to an array.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Array} Returns the converted array.\n * @example\n *\n * _.toArray({ 'a': 1, 'b': 2 });\n * // => [1, 2]\n *\n * _.toArray('abc');\n * // => ['a', 'b', 'c']\n *\n * _.toArray(1);\n * // => []\n *\n * _.toArray(null);\n * // => []\n */\n function toArray(value) {\n if (!value) {\n return [];\n }\n if (isArrayLike(value)) {\n return isString(value) ? stringToArray(value) : copyArray(value);\n }\n if (symIterator && value[symIterator]) {\n return iteratorToArray(value[symIterator]());\n }\n var tag = getTag(value),\n func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);\n\n return func(value);\n }\n\n /**\n * Converts `value` to a finite number.\n *\n * @static\n * @memberOf _\n * @since 4.12.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted number.\n * @example\n *\n * _.toFinite(3.2);\n * // => 3.2\n *\n * _.toFinite(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toFinite(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toFinite('3.2');\n * // => 3.2\n */\n function toFinite(value) {\n if (!value) {\n return value === 0 ? value : 0;\n }\n value = toNumber(value);\n if (value === INFINITY || value === -INFINITY) {\n var sign = (value < 0 ? -1 : 1);\n return sign * MAX_INTEGER;\n }\n return value === value ? value : 0;\n }\n\n /**\n * Converts `value` to an integer.\n *\n * **Note:** This method is loosely based on\n * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toInteger(3.2);\n * // => 3\n *\n * _.toInteger(Number.MIN_VALUE);\n * // => 0\n *\n * _.toInteger(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toInteger('3.2');\n * // => 3\n */\n function toInteger(value) {\n var result = toFinite(value),\n remainder = result % 1;\n\n return result === result ? (remainder ? result - remainder : result) : 0;\n }\n\n /**\n * Converts `value` to an integer suitable for use as the length of an\n * array-like object.\n *\n * **Note:** This method is based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toLength(3.2);\n * // => 3\n *\n * _.toLength(Number.MIN_VALUE);\n * // => 0\n *\n * _.toLength(Infinity);\n * // => 4294967295\n *\n * _.toLength('3.2');\n * // => 3\n */\n function toLength(value) {\n return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;\n }\n\n /**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\n function toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = baseTrim(value);\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n }\n\n /**\n * Converts `value` to a plain object flattening inherited enumerable string\n * keyed properties of `value` to own properties of the plain object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Object} Returns the converted plain object.\n * @example\n *\n * function Foo() {\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.assign({ 'a': 1 }, new Foo);\n * // => { 'a': 1, 'b': 2 }\n *\n * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n * // => { 'a': 1, 'b': 2, 'c': 3 }\n */\n function toPlainObject(value) {\n return copyObject(value, keysIn(value));\n }\n\n /**\n * Converts `value` to a safe integer. A safe integer can be compared and\n * represented correctly.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toSafeInteger(3.2);\n * // => 3\n *\n * _.toSafeInteger(Number.MIN_VALUE);\n * // => 0\n *\n * _.toSafeInteger(Infinity);\n * // => 9007199254740991\n *\n * _.toSafeInteger('3.2');\n * // => 3\n */\n function toSafeInteger(value) {\n return value\n ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)\n : (value === 0 ? value : 0);\n }\n\n /**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\n function toString(value) {\n return value == null ? '' : baseToString(value);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Assigns own enumerable string keyed properties of source objects to the\n * destination object. Source objects are applied from left to right.\n * Subsequent sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object` and is loosely based on\n * [`Object.assign`](https://mdn.io/Object/assign).\n *\n * @static\n * @memberOf _\n * @since 0.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assignIn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assign({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'c': 3 }\n */\n var assign = createAssigner(function(object, source) {\n if (isPrototype(source) || isArrayLike(source)) {\n copyObject(source, keys(source), object);\n return;\n }\n for (var key in source) {\n if (hasOwnProperty.call(source, key)) {\n assignValue(object, key, source[key]);\n }\n }\n });\n\n /**\n * This method is like `_.assign` except that it iterates over own and\n * inherited source properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extend\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assign\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assignIn({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }\n */\n var assignIn = createAssigner(function(object, source) {\n copyObject(source, keysIn(source), object);\n });\n\n /**\n * This method is like `_.assignIn` except that it accepts `customizer`\n * which is invoked to produce the assigned values. If `customizer` returns\n * `undefined`, assignment is handled by the method instead. The `customizer`\n * is invoked with five arguments: (objValue, srcValue, key, object, source).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extendWith\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @see _.assignWith\n * @example\n *\n * function customizer(objValue, srcValue) {\n * return _.isUndefined(objValue) ? srcValue : objValue;\n * }\n *\n * var defaults = _.partialRight(_.assignInWith, customizer);\n *\n * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {\n copyObject(source, keysIn(source), object, customizer);\n });\n\n /**\n * This method is like `_.assign` except that it accepts `customizer`\n * which is invoked to produce the assigned values. If `customizer` returns\n * `undefined`, assignment is handled by the method instead. The `customizer`\n * is invoked with five arguments: (objValue, srcValue, key, object, source).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @see _.assignInWith\n * @example\n *\n * function customizer(objValue, srcValue) {\n * return _.isUndefined(objValue) ? srcValue : objValue;\n * }\n *\n * var defaults = _.partialRight(_.assignWith, customizer);\n *\n * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var assignWith = createAssigner(function(object, source, srcIndex, customizer) {\n copyObject(source, keys(source), object, customizer);\n });\n\n /**\n * Creates an array of values corresponding to `paths` of `object`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Array} Returns the picked values.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };\n *\n * _.at(object, ['a[0].b.c', 'a[1]']);\n * // => [3, 4]\n */\n var at = flatRest(baseAt);\n\n /**\n * Creates an object that inherits from the `prototype` object. If a\n * `properties` object is given, its own enumerable string keyed properties\n * are assigned to the created object.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Object\n * @param {Object} prototype The object to inherit from.\n * @param {Object} [properties] The properties to assign to the object.\n * @returns {Object} Returns the new object.\n * @example\n *\n * function Shape() {\n * this.x = 0;\n * this.y = 0;\n * }\n *\n * function Circle() {\n * Shape.call(this);\n * }\n *\n * Circle.prototype = _.create(Shape.prototype, {\n * 'constructor': Circle\n * });\n *\n * var circle = new Circle;\n * circle instanceof Circle;\n * // => true\n *\n * circle instanceof Shape;\n * // => true\n */\n function create(prototype, properties) {\n var result = baseCreate(prototype);\n return properties == null ? result : baseAssign(result, properties);\n }\n\n /**\n * Assigns own and inherited enumerable string keyed properties of source\n * objects to the destination object for all destination properties that\n * resolve to `undefined`. Source objects are applied from left to right.\n * Once a property is set, additional values of the same property are ignored.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaultsDeep\n * @example\n *\n * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var defaults = baseRest(function(object, sources) {\n object = Object(object);\n\n var index = -1;\n var length = sources.length;\n var guard = length > 2 ? sources[2] : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n length = 1;\n }\n\n while (++index < length) {\n var source = sources[index];\n var props = keysIn(source);\n var propsIndex = -1;\n var propsLength = props.length;\n\n while (++propsIndex < propsLength) {\n var key = props[propsIndex];\n var value = object[key];\n\n if (value === undefined ||\n (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n object[key] = source[key];\n }\n }\n }\n\n return object;\n });\n\n /**\n * This method is like `_.defaults` except that it recursively assigns\n * default properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaults\n * @example\n *\n * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });\n * // => { 'a': { 'b': 2, 'c': 3 } }\n */\n var defaultsDeep = baseRest(function(args) {\n args.push(undefined, customDefaultsMerge);\n return apply(mergeWith, undefined, args);\n });\n\n /**\n * This method is like `_.find` except that it returns the key of the first\n * element `predicate` returns truthy for instead of the element itself.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {string|undefined} Returns the key of the matched element,\n * else `undefined`.\n * @example\n *\n * var users = {\n * 'barney': { 'age': 36, 'active': true },\n * 'fred': { 'age': 40, 'active': false },\n * 'pebbles': { 'age': 1, 'active': true }\n * };\n *\n * _.findKey(users, function(o) { return o.age < 40; });\n * // => 'barney' (iteration order is not guaranteed)\n *\n * // The `_.matches` iteratee shorthand.\n * _.findKey(users, { 'age': 1, 'active': true });\n * // => 'pebbles'\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findKey(users, ['active', false]);\n * // => 'fred'\n *\n * // The `_.property` iteratee shorthand.\n * _.findKey(users, 'active');\n * // => 'barney'\n */\n function findKey(object, predicate) {\n return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);\n }\n\n /**\n * This method is like `_.findKey` except that it iterates over elements of\n * a collection in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {string|undefined} Returns the key of the matched element,\n * else `undefined`.\n * @example\n *\n * var users = {\n * 'barney': { 'age': 36, 'active': true },\n * 'fred': { 'age': 40, 'active': false },\n * 'pebbles': { 'age': 1, 'active': true }\n * };\n *\n * _.findLastKey(users, function(o) { return o.age < 40; });\n * // => returns 'pebbles' assuming `_.findKey` returns 'barney'\n *\n * // The `_.matches` iteratee shorthand.\n * _.findLastKey(users, { 'age': 36, 'active': true });\n * // => 'barney'\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findLastKey(users, ['active', false]);\n * // => 'fred'\n *\n * // The `_.property` iteratee shorthand.\n * _.findLastKey(users, 'active');\n * // => 'pebbles'\n */\n function findLastKey(object, predicate) {\n return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);\n }\n\n /**\n * Iterates over own and inherited enumerable string keyed properties of an\n * object and invokes `iteratee` for each property. The iteratee is invoked\n * with three arguments: (value, key, object). Iteratee functions may exit\n * iteration early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 0.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forInRight\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forIn(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).\n */\n function forIn(object, iteratee) {\n return object == null\n ? object\n : baseFor(object, getIteratee(iteratee, 3), keysIn);\n }\n\n /**\n * This method is like `_.forIn` except that it iterates over properties of\n * `object` in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forIn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forInRight(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.\n */\n function forInRight(object, iteratee) {\n return object == null\n ? object\n : baseForRight(object, getIteratee(iteratee, 3), keysIn);\n }\n\n /**\n * Iterates over own enumerable string keyed properties of an object and\n * invokes `iteratee` for each property. The iteratee is invoked with three\n * arguments: (value, key, object). Iteratee functions may exit iteration\n * early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 0.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forOwnRight\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forOwn(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a' then 'b' (iteration order is not guaranteed).\n */\n function forOwn(object, iteratee) {\n return object && baseForOwn(object, getIteratee(iteratee, 3));\n }\n\n /**\n * This method is like `_.forOwn` except that it iterates over properties of\n * `object` in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forOwn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forOwnRight(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.\n */\n function forOwnRight(object, iteratee) {\n return object && baseForOwnRight(object, getIteratee(iteratee, 3));\n }\n\n /**\n * Creates an array of function property names from own enumerable properties\n * of `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to inspect.\n * @returns {Array} Returns the function names.\n * @see _.functionsIn\n * @example\n *\n * function Foo() {\n * this.a = _.constant('a');\n * this.b = _.constant('b');\n * }\n *\n * Foo.prototype.c = _.constant('c');\n *\n * _.functions(new Foo);\n * // => ['a', 'b']\n */\n function functions(object) {\n return object == null ? [] : baseFunctions(object, keys(object));\n }\n\n /**\n * Creates an array of function property names from own and inherited\n * enumerable properties of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @returns {Array} Returns the function names.\n * @see _.functions\n * @example\n *\n * function Foo() {\n * this.a = _.constant('a');\n * this.b = _.constant('b');\n * }\n *\n * Foo.prototype.c = _.constant('c');\n *\n * _.functionsIn(new Foo);\n * // => ['a', 'b', 'c']\n */\n function functionsIn(object) {\n return object == null ? [] : baseFunctions(object, keysIn(object));\n }\n\n /**\n * Gets the value at `path` of `object`. If the resolved value is\n * `undefined`, the `defaultValue` is returned in its place.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.get(object, 'a[0].b.c');\n * // => 3\n *\n * _.get(object, ['a', '0', 'b', 'c']);\n * // => 3\n *\n * _.get(object, 'a.b.c', 'default');\n * // => 'default'\n */\n function get(object, path, defaultValue) {\n var result = object == null ? undefined : baseGet(object, path);\n return result === undefined ? defaultValue : result;\n }\n\n /**\n * Checks if `path` is a direct property of `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n * @example\n *\n * var object = { 'a': { 'b': 2 } };\n * var other = _.create({ 'a': _.create({ 'b': 2 }) });\n *\n * _.has(object, 'a');\n * // => true\n *\n * _.has(object, 'a.b');\n * // => true\n *\n * _.has(object, ['a', 'b']);\n * // => true\n *\n * _.has(other, 'a');\n * // => false\n */\n function has(object, path) {\n return object != null && hasPath(object, path, baseHas);\n }\n\n /**\n * Checks if `path` is a direct or inherited property of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n * @example\n *\n * var object = _.create({ 'a': _.create({ 'b': 2 }) });\n *\n * _.hasIn(object, 'a');\n * // => true\n *\n * _.hasIn(object, 'a.b');\n * // => true\n *\n * _.hasIn(object, ['a', 'b']);\n * // => true\n *\n * _.hasIn(object, 'b');\n * // => false\n */\n function hasIn(object, path) {\n return object != null && hasPath(object, path, baseHasIn);\n }\n\n /**\n * Creates an object composed of the inverted keys and values of `object`.\n * If `object` contains duplicate values, subsequent values overwrite\n * property assignments of previous values.\n *\n * @static\n * @memberOf _\n * @since 0.7.0\n * @category Object\n * @param {Object} object The object to invert.\n * @returns {Object} Returns the new inverted object.\n * @example\n *\n * var object = { 'a': 1, 'b': 2, 'c': 1 };\n *\n * _.invert(object);\n * // => { '1': 'c', '2': 'b' }\n */\n var invert = createInverter(function(result, value, key) {\n if (value != null &&\n typeof value.toString != 'function') {\n value = nativeObjectToString.call(value);\n }\n\n result[value] = key;\n }, constant(identity));\n\n /**\n * This method is like `_.invert` except that the inverted object is generated\n * from the results of running each element of `object` thru `iteratee`. The\n * corresponding inverted value of each inverted key is an array of keys\n * responsible for generating the inverted value. The iteratee is invoked\n * with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.1.0\n * @category Object\n * @param {Object} object The object to invert.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Object} Returns the new inverted object.\n * @example\n *\n * var object = { 'a': 1, 'b': 2, 'c': 1 };\n *\n * _.invertBy(object);\n * // => { '1': ['a', 'c'], '2': ['b'] }\n *\n * _.invertBy(object, function(value) {\n * return 'group' + value;\n * });\n * // => { 'group1': ['a', 'c'], 'group2': ['b'] }\n */\n var invertBy = createInverter(function(result, value, key) {\n if (value != null &&\n typeof value.toString != 'function') {\n value = nativeObjectToString.call(value);\n }\n\n if (hasOwnProperty.call(result, value)) {\n result[value].push(key);\n } else {\n result[value] = [key];\n }\n }, getIteratee);\n\n /**\n * Invokes the method at `path` of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the method to invoke.\n * @param {...*} [args] The arguments to invoke the method with.\n * @returns {*} Returns the result of the invoked method.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };\n *\n * _.invoke(object, 'a[0].b.c.slice', 1, 3);\n * // => [2, 3]\n */\n var invoke = baseRest(baseInvoke);\n\n /**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\n function keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n }\n\n /**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\n function keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n }\n\n /**\n * The opposite of `_.mapValues`; this method creates an object with the\n * same values as `object` and keys generated by running each own enumerable\n * string keyed property of `object` thru `iteratee`. The iteratee is invoked\n * with three arguments: (value, key, object).\n *\n * @static\n * @memberOf _\n * @since 3.8.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns the new mapped object.\n * @see _.mapValues\n * @example\n *\n * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {\n * return key + value;\n * });\n * // => { 'a1': 1, 'b2': 2 }\n */\n function mapKeys(object, iteratee) {\n var result = {};\n iteratee = getIteratee(iteratee, 3);\n\n baseForOwn(object, function(value, key, object) {\n baseAssignValue(result, iteratee(value, key, object), value);\n });\n return result;\n }\n\n /**\n * Creates an object with the same keys as `object` and values generated\n * by running each own enumerable string keyed property of `object` thru\n * `iteratee`. The iteratee is invoked with three arguments:\n * (value, key, object).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns the new mapped object.\n * @see _.mapKeys\n * @example\n *\n * var users = {\n * 'fred': { 'user': 'fred', 'age': 40 },\n * 'pebbles': { 'user': 'pebbles', 'age': 1 }\n * };\n *\n * _.mapValues(users, function(o) { return o.age; });\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n *\n * // The `_.property` iteratee shorthand.\n * _.mapValues(users, 'age');\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n */\n function mapValues(object, iteratee) {\n var result = {};\n iteratee = getIteratee(iteratee, 3);\n\n baseForOwn(object, function(value, key, object) {\n baseAssignValue(result, key, iteratee(value, key, object));\n });\n return result;\n }\n\n /**\n * This method is like `_.assign` except that it recursively merges own and\n * inherited enumerable string keyed properties of source objects into the\n * destination object. Source properties that resolve to `undefined` are\n * skipped if a destination value exists. Array and plain object properties\n * are merged recursively. Other objects and value types are overridden by\n * assignment. Source objects are applied from left to right. Subsequent\n * sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {\n * 'a': [{ 'b': 2 }, { 'd': 4 }]\n * };\n *\n * var other = {\n * 'a': [{ 'c': 3 }, { 'e': 5 }]\n * };\n *\n * _.merge(object, other);\n * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }\n */\n var merge = createAssigner(function(object, source, srcIndex) {\n baseMerge(object, source, srcIndex);\n });\n\n /**\n * This method is like `_.merge` except that it accepts `customizer` which\n * is invoked to produce the merged values of the destination and source\n * properties. If `customizer` returns `undefined`, merging is handled by the\n * method instead. The `customizer` is invoked with six arguments:\n * (objValue, srcValue, key, object, source, stack).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} customizer The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * function customizer(objValue, srcValue) {\n * if (_.isArray(objValue)) {\n * return objValue.concat(srcValue);\n * }\n * }\n *\n * var object = { 'a': [1], 'b': [2] };\n * var other = { 'a': [3], 'b': [4] };\n *\n * _.mergeWith(object, other, customizer);\n * // => { 'a': [1, 3], 'b': [2, 4] }\n */\n var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {\n baseMerge(object, source, srcIndex, customizer);\n });\n\n /**\n * The opposite of `_.pick`; this method creates an object composed of the\n * own and inherited enumerable property paths of `object` that are not omitted.\n *\n * **Note:** This method is considerably slower than `_.pick`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [paths] The property paths to omit.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.omit(object, ['a', 'c']);\n * // => { 'b': '2' }\n */\n var omit = flatRest(function(object, paths) {\n var result = {};\n if (object == null) {\n return result;\n }\n var isDeep = false;\n paths = arrayMap(paths, function(path) {\n path = castPath(path, object);\n isDeep || (isDeep = path.length > 1);\n return path;\n });\n copyObject(object, getAllKeysIn(object), result);\n if (isDeep) {\n result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);\n }\n var length = paths.length;\n while (length--) {\n baseUnset(result, paths[length]);\n }\n return result;\n });\n\n /**\n * The opposite of `_.pickBy`; this method creates an object composed of\n * the own and inherited enumerable string keyed properties of `object` that\n * `predicate` doesn't return truthy for. The predicate is invoked with two\n * arguments: (value, key).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The source object.\n * @param {Function} [predicate=_.identity] The function invoked per property.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.omitBy(object, _.isNumber);\n * // => { 'b': '2' }\n */\n function omitBy(object, predicate) {\n return pickBy(object, negate(getIteratee(predicate)));\n }\n\n /**\n * Creates an object composed of the picked `object` properties.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pick(object, ['a', 'c']);\n * // => { 'a': 1, 'c': 3 }\n */\n var pick = flatRest(function(object, paths) {\n return object == null ? {} : basePick(object, paths);\n });\n\n /**\n * Creates an object composed of the `object` properties `predicate` returns\n * truthy for. The predicate is invoked with two arguments: (value, key).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The source object.\n * @param {Function} [predicate=_.identity] The function invoked per property.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pickBy(object, _.isNumber);\n * // => { 'a': 1, 'c': 3 }\n */\n function pickBy(object, predicate) {\n if (object == null) {\n return {};\n }\n var props = arrayMap(getAllKeysIn(object), function(prop) {\n return [prop];\n });\n predicate = getIteratee(predicate);\n return basePickBy(object, props, function(value, path) {\n return predicate(value, path[0]);\n });\n }\n\n /**\n * This method is like `_.get` except that if the resolved value is a\n * function it's invoked with the `this` binding of its parent object and\n * its result is returned.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to resolve.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };\n *\n * _.result(object, 'a[0].b.c1');\n * // => 3\n *\n * _.result(object, 'a[0].b.c2');\n * // => 4\n *\n * _.result(object, 'a[0].b.c3', 'default');\n * // => 'default'\n *\n * _.result(object, 'a[0].b.c3', _.constant('default'));\n * // => 'default'\n */\n function result(object, path, defaultValue) {\n path = castPath(path, object);\n\n var index = -1,\n length = path.length;\n\n // Ensure the loop is entered when path is empty.\n if (!length) {\n length = 1;\n object = undefined;\n }\n while (++index < length) {\n var value = object == null ? undefined : object[toKey(path[index])];\n if (value === undefined) {\n index = length;\n value = defaultValue;\n }\n object = isFunction(value) ? value.call(object) : value;\n }\n return object;\n }\n\n /**\n * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,\n * it's created. Arrays are created for missing index properties while objects\n * are created for all other missing properties. Use `_.setWith` to customize\n * `path` creation.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.set(object, 'a[0].b.c', 4);\n * console.log(object.a[0].b.c);\n * // => 4\n *\n * _.set(object, ['x', '0', 'y', 'z'], 5);\n * console.log(object.x[0].y.z);\n * // => 5\n */\n function set(object, path, value) {\n return object == null ? object : baseSet(object, path, value);\n }\n\n /**\n * This method is like `_.set` except that it accepts `customizer` which is\n * invoked to produce the objects of `path`. If `customizer` returns `undefined`\n * path creation is handled by the method instead. The `customizer` is invoked\n * with three arguments: (nsValue, key, nsObject).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {};\n *\n * _.setWith(object, '[0][1]', 'a', Object);\n * // => { '0': { '1': 'a' } }\n */\n function setWith(object, path, value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return object == null ? object : baseSet(object, path, value, customizer);\n }\n\n /**\n * Creates an array of own enumerable string keyed-value pairs for `object`\n * which can be consumed by `_.fromPairs`. If `object` is a map or set, its\n * entries are returned.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias entries\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the key-value pairs.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.toPairs(new Foo);\n * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)\n */\n var toPairs = createToPairs(keys);\n\n /**\n * Creates an array of own and inherited enumerable string keyed-value pairs\n * for `object` which can be consumed by `_.fromPairs`. If `object` is a map\n * or set, its entries are returned.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias entriesIn\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the key-value pairs.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.toPairsIn(new Foo);\n * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)\n */\n var toPairsIn = createToPairs(keysIn);\n\n /**\n * An alternative to `_.reduce`; this method transforms `object` to a new\n * `accumulator` object which is the result of running each of its own\n * enumerable string keyed properties thru `iteratee`, with each invocation\n * potentially mutating the `accumulator` object. If `accumulator` is not\n * provided, a new object with the same `[[Prototype]]` will be used. The\n * iteratee is invoked with four arguments: (accumulator, value, key, object).\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 1.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [accumulator] The custom accumulator value.\n * @returns {*} Returns the accumulated value.\n * @example\n *\n * _.transform([2, 3, 4], function(result, n) {\n * result.push(n *= n);\n * return n % 2 == 0;\n * }, []);\n * // => [4, 9]\n *\n * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {\n * (result[value] || (result[value] = [])).push(key);\n * }, {});\n * // => { '1': ['a', 'c'], '2': ['b'] }\n */\n function transform(object, iteratee, accumulator) {\n var isArr = isArray(object),\n isArrLike = isArr || isBuffer(object) || isTypedArray(object);\n\n iteratee = getIteratee(iteratee, 4);\n if (accumulator == null) {\n var Ctor = object && object.constructor;\n if (isArrLike) {\n accumulator = isArr ? new Ctor : [];\n }\n else if (isObject(object)) {\n accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};\n }\n else {\n accumulator = {};\n }\n }\n (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {\n return iteratee(accumulator, value, index, object);\n });\n return accumulator;\n }\n\n /**\n * Removes the property at `path` of `object`.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to unset.\n * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 7 } }] };\n * _.unset(object, 'a[0].b.c');\n * // => true\n *\n * console.log(object);\n * // => { 'a': [{ 'b': {} }] };\n *\n * _.unset(object, ['a', '0', 'b', 'c']);\n * // => true\n *\n * console.log(object);\n * // => { 'a': [{ 'b': {} }] };\n */\n function unset(object, path) {\n return object == null ? true : baseUnset(object, path);\n }\n\n /**\n * This method is like `_.set` except that accepts `updater` to produce the\n * value to set. Use `_.updateWith` to customize `path` creation. The `updater`\n * is invoked with one argument: (value).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.6.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {Function} updater The function to produce the updated value.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.update(object, 'a[0].b.c', function(n) { return n * n; });\n * console.log(object.a[0].b.c);\n * // => 9\n *\n * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });\n * console.log(object.x[0].y.z);\n * // => 0\n */\n function update(object, path, updater) {\n return object == null ? object : baseUpdate(object, path, castFunction(updater));\n }\n\n /**\n * This method is like `_.update` except that it accepts `customizer` which is\n * invoked to produce the objects of `path`. If `customizer` returns `undefined`\n * path creation is handled by the method instead. The `customizer` is invoked\n * with three arguments: (nsValue, key, nsObject).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.6.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {Function} updater The function to produce the updated value.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {};\n *\n * _.updateWith(object, '[0][1]', _.constant('a'), Object);\n * // => { '0': { '1': 'a' } }\n */\n function updateWith(object, path, updater, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);\n }\n\n /**\n * Creates an array of the own enumerable string keyed property values of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property values.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.values(new Foo);\n * // => [1, 2] (iteration order is not guaranteed)\n *\n * _.values('hi');\n * // => ['h', 'i']\n */\n function values(object) {\n return object == null ? [] : baseValues(object, keys(object));\n }\n\n /**\n * Creates an array of the own and inherited enumerable string keyed property\n * values of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property values.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.valuesIn(new Foo);\n * // => [1, 2, 3] (iteration order is not guaranteed)\n */\n function valuesIn(object) {\n return object == null ? [] : baseValues(object, keysIn(object));\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Clamps `number` within the inclusive `lower` and `upper` bounds.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Number\n * @param {number} number The number to clamp.\n * @param {number} [lower] The lower bound.\n * @param {number} upper The upper bound.\n * @returns {number} Returns the clamped number.\n * @example\n *\n * _.clamp(-10, -5, 5);\n * // => -5\n *\n * _.clamp(10, -5, 5);\n * // => 5\n */\n function clamp(number, lower, upper) {\n if (upper === undefined) {\n upper = lower;\n lower = undefined;\n }\n if (upper !== undefined) {\n upper = toNumber(upper);\n upper = upper === upper ? upper : 0;\n }\n if (lower !== undefined) {\n lower = toNumber(lower);\n lower = lower === lower ? lower : 0;\n }\n return baseClamp(toNumber(number), lower, upper);\n }\n\n /**\n * Checks if `n` is between `start` and up to, but not including, `end`. If\n * `end` is not specified, it's set to `start` with `start` then set to `0`.\n * If `start` is greater than `end` the params are swapped to support\n * negative ranges.\n *\n * @static\n * @memberOf _\n * @since 3.3.0\n * @category Number\n * @param {number} number The number to check.\n * @param {number} [start=0] The start of the range.\n * @param {number} end The end of the range.\n * @returns {boolean} Returns `true` if `number` is in the range, else `false`.\n * @see _.range, _.rangeRight\n * @example\n *\n * _.inRange(3, 2, 4);\n * // => true\n *\n * _.inRange(4, 8);\n * // => true\n *\n * _.inRange(4, 2);\n * // => false\n *\n * _.inRange(2, 2);\n * // => false\n *\n * _.inRange(1.2, 2);\n * // => true\n *\n * _.inRange(5.2, 4);\n * // => false\n *\n * _.inRange(-3, -2, -6);\n * // => true\n */\n function inRange(number, start, end) {\n start = toFinite(start);\n if (end === undefined) {\n end = start;\n start = 0;\n } else {\n end = toFinite(end);\n }\n number = toNumber(number);\n return baseInRange(number, start, end);\n }\n\n /**\n * Produces a random number between the inclusive `lower` and `upper` bounds.\n * If only one argument is provided a number between `0` and the given number\n * is returned. If `floating` is `true`, or either `lower` or `upper` are\n * floats, a floating-point number is returned instead of an integer.\n *\n * **Note:** JavaScript follows the IEEE-754 standard for resolving\n * floating-point values which can produce unexpected results.\n *\n * @static\n * @memberOf _\n * @since 0.7.0\n * @category Number\n * @param {number} [lower=0] The lower bound.\n * @param {number} [upper=1] The upper bound.\n * @param {boolean} [floating] Specify returning a floating-point number.\n * @returns {number} Returns the random number.\n * @example\n *\n * _.random(0, 5);\n * // => an integer between 0 and 5\n *\n * _.random(5);\n * // => also an integer between 0 and 5\n *\n * _.random(5, true);\n * // => a floating-point number between 0 and 5\n *\n * _.random(1.2, 5.2);\n * // => a floating-point number between 1.2 and 5.2\n */\n function random(lower, upper, floating) {\n if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {\n upper = floating = undefined;\n }\n if (floating === undefined) {\n if (typeof upper == 'boolean') {\n floating = upper;\n upper = undefined;\n }\n else if (typeof lower == 'boolean') {\n floating = lower;\n lower = undefined;\n }\n }\n if (lower === undefined && upper === undefined) {\n lower = 0;\n upper = 1;\n }\n else {\n lower = toFinite(lower);\n if (upper === undefined) {\n upper = lower;\n lower = 0;\n } else {\n upper = toFinite(upper);\n }\n }\n if (lower > upper) {\n var temp = lower;\n lower = upper;\n upper = temp;\n }\n if (floating || lower % 1 || upper % 1) {\n var rand = nativeRandom();\n return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);\n }\n return baseRandom(lower, upper);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the camel cased string.\n * @example\n *\n * _.camelCase('Foo Bar');\n * // => 'fooBar'\n *\n * _.camelCase('--foo-bar--');\n * // => 'fooBar'\n *\n * _.camelCase('__FOO_BAR__');\n * // => 'fooBar'\n */\n var camelCase = createCompounder(function(result, word, index) {\n word = word.toLowerCase();\n return result + (index ? capitalize(word) : word);\n });\n\n /**\n * Converts the first character of `string` to upper case and the remaining\n * to lower case.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to capitalize.\n * @returns {string} Returns the capitalized string.\n * @example\n *\n * _.capitalize('FRED');\n * // => 'Fred'\n */\n function capitalize(string) {\n return upperFirst(toString(string).toLowerCase());\n }\n\n /**\n * Deburrs `string` by converting\n * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)\n * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)\n * letters to basic Latin letters and removing\n * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to deburr.\n * @returns {string} Returns the deburred string.\n * @example\n *\n * _.deburr('déjà vu');\n * // => 'deja vu'\n */\n function deburr(string) {\n string = toString(string);\n return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');\n }\n\n /**\n * Checks if `string` ends with the given target string.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {string} [target] The string to search for.\n * @param {number} [position=string.length] The position to search up to.\n * @returns {boolean} Returns `true` if `string` ends with `target`,\n * else `false`.\n * @example\n *\n * _.endsWith('abc', 'c');\n * // => true\n *\n * _.endsWith('abc', 'b');\n * // => false\n *\n * _.endsWith('abc', 'b', 2);\n * // => true\n */\n function endsWith(string, target, position) {\n string = toString(string);\n target = baseToString(target);\n\n var length = string.length;\n position = position === undefined\n ? length\n : baseClamp(toInteger(position), 0, length);\n\n var end = position;\n position -= target.length;\n return position >= 0 && string.slice(position, end) == target;\n }\n\n /**\n * Converts the characters \"&\", \"<\", \">\", '\"', and \"'\" in `string` to their\n * corresponding HTML entities.\n *\n * **Note:** No other characters are escaped. To escape additional\n * characters use a third-party library like [_he_](https://mths.be/he).\n *\n * Though the \">\" character is escaped for symmetry, characters like\n * \">\" and \"/\" don't need escaping in HTML and have no special meaning\n * unless they're part of a tag or unquoted attribute value. See\n * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)\n * (under \"semi-related fun fact\") for more details.\n *\n * When working with HTML you should always\n * [quote attribute values](http://wonko.com/post/html-escaping) to reduce\n * XSS vectors.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category String\n * @param {string} [string=''] The string to escape.\n * @returns {string} Returns the escaped string.\n * @example\n *\n * _.escape('fred, barney, & pebbles');\n * // => 'fred, barney, & pebbles'\n */\n function escape(string) {\n string = toString(string);\n return (string && reHasUnescapedHtml.test(string))\n ? string.replace(reUnescapedHtml, escapeHtmlChar)\n : string;\n }\n\n /**\n * Escapes the `RegExp` special characters \"^\", \"$\", \"\\\", \".\", \"*\", \"+\",\n * \"?\", \"(\", \")\", \"[\", \"]\", \"{\", \"}\", and \"|\" in `string`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to escape.\n * @returns {string} Returns the escaped string.\n * @example\n *\n * _.escapeRegExp('[lodash](https://lodash.com/)');\n * // => '\\[lodash\\]\\(https://lodash\\.com/\\)'\n */\n function escapeRegExp(string) {\n string = toString(string);\n return (string && reHasRegExpChar.test(string))\n ? string.replace(reRegExpChar, '\\\\$&')\n : string;\n }\n\n /**\n * Converts `string` to\n * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the kebab cased string.\n * @example\n *\n * _.kebabCase('Foo Bar');\n * // => 'foo-bar'\n *\n * _.kebabCase('fooBar');\n * // => 'foo-bar'\n *\n * _.kebabCase('__FOO_BAR__');\n * // => 'foo-bar'\n */\n var kebabCase = createCompounder(function(result, word, index) {\n return result + (index ? '-' : '') + word.toLowerCase();\n });\n\n /**\n * Converts `string`, as space separated words, to lower case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the lower cased string.\n * @example\n *\n * _.lowerCase('--Foo-Bar--');\n * // => 'foo bar'\n *\n * _.lowerCase('fooBar');\n * // => 'foo bar'\n *\n * _.lowerCase('__FOO_BAR__');\n * // => 'foo bar'\n */\n var lowerCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + word.toLowerCase();\n });\n\n /**\n * Converts the first character of `string` to lower case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.lowerFirst('Fred');\n * // => 'fred'\n *\n * _.lowerFirst('FRED');\n * // => 'fRED'\n */\n var lowerFirst = createCaseFirst('toLowerCase');\n\n /**\n * Pads `string` on the left and right sides if it's shorter than `length`.\n * Padding characters are truncated if they can't be evenly divided by `length`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.pad('abc', 8);\n * // => ' abc '\n *\n * _.pad('abc', 8, '_-');\n * // => '_-abc_-_'\n *\n * _.pad('abc', 3);\n * // => 'abc'\n */\n function pad(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n if (!length || strLength >= length) {\n return string;\n }\n var mid = (length - strLength) / 2;\n return (\n createPadding(nativeFloor(mid), chars) +\n string +\n createPadding(nativeCeil(mid), chars)\n );\n }\n\n /**\n * Pads `string` on the right side if it's shorter than `length`. Padding\n * characters are truncated if they exceed `length`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.padEnd('abc', 6);\n * // => 'abc '\n *\n * _.padEnd('abc', 6, '_-');\n * // => 'abc_-_'\n *\n * _.padEnd('abc', 3);\n * // => 'abc'\n */\n function padEnd(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n return (length && strLength < length)\n ? (string + createPadding(length - strLength, chars))\n : string;\n }\n\n /**\n * Pads `string` on the left side if it's shorter than `length`. Padding\n * characters are truncated if they exceed `length`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.padStart('abc', 6);\n * // => ' abc'\n *\n * _.padStart('abc', 6, '_-');\n * // => '_-_abc'\n *\n * _.padStart('abc', 3);\n * // => 'abc'\n */\n function padStart(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n return (length && strLength < length)\n ? (createPadding(length - strLength, chars) + string)\n : string;\n }\n\n /**\n * Converts `string` to an integer of the specified radix. If `radix` is\n * `undefined` or `0`, a `radix` of `10` is used unless `value` is a\n * hexadecimal, in which case a `radix` of `16` is used.\n *\n * **Note:** This method aligns with the\n * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category String\n * @param {string} string The string to convert.\n * @param {number} [radix=10] The radix to interpret `value` by.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.parseInt('08');\n * // => 8\n *\n * _.map(['6', '08', '10'], _.parseInt);\n * // => [6, 8, 10]\n */\n function parseInt(string, radix, guard) {\n if (guard || radix == null) {\n radix = 0;\n } else if (radix) {\n radix = +radix;\n }\n return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);\n }\n\n /**\n * Repeats the given string `n` times.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to repeat.\n * @param {number} [n=1] The number of times to repeat the string.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the repeated string.\n * @example\n *\n * _.repeat('*', 3);\n * // => '***'\n *\n * _.repeat('abc', 2);\n * // => 'abcabc'\n *\n * _.repeat('abc', 0);\n * // => ''\n */\n function repeat(string, n, guard) {\n if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {\n n = 1;\n } else {\n n = toInteger(n);\n }\n return baseRepeat(toString(string), n);\n }\n\n /**\n * Replaces matches for `pattern` in `string` with `replacement`.\n *\n * **Note:** This method is based on\n * [`String#replace`](https://mdn.io/String/replace).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to modify.\n * @param {RegExp|string} pattern The pattern to replace.\n * @param {Function|string} replacement The match replacement.\n * @returns {string} Returns the modified string.\n * @example\n *\n * _.replace('Hi Fred', 'Fred', 'Barney');\n * // => 'Hi Barney'\n */\n function replace() {\n var args = arguments,\n string = toString(args[0]);\n\n return args.length < 3 ? string : string.replace(args[1], args[2]);\n }\n\n /**\n * Converts `string` to\n * [snake case](https://en.wikipedia.org/wiki/Snake_case).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the snake cased string.\n * @example\n *\n * _.snakeCase('Foo Bar');\n * // => 'foo_bar'\n *\n * _.snakeCase('fooBar');\n * // => 'foo_bar'\n *\n * _.snakeCase('--FOO-BAR--');\n * // => 'foo_bar'\n */\n var snakeCase = createCompounder(function(result, word, index) {\n return result + (index ? '_' : '') + word.toLowerCase();\n });\n\n /**\n * Splits `string` by `separator`.\n *\n * **Note:** This method is based on\n * [`String#split`](https://mdn.io/String/split).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to split.\n * @param {RegExp|string} separator The separator pattern to split by.\n * @param {number} [limit] The length to truncate results to.\n * @returns {Array} Returns the string segments.\n * @example\n *\n * _.split('a-b-c', '-', 2);\n * // => ['a', 'b']\n */\n function split(string, separator, limit) {\n if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {\n separator = limit = undefined;\n }\n limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;\n if (!limit) {\n return [];\n }\n string = toString(string);\n if (string && (\n typeof separator == 'string' ||\n (separator != null && !isRegExp(separator))\n )) {\n separator = baseToString(separator);\n if (!separator && hasUnicode(string)) {\n return castSlice(stringToArray(string), 0, limit);\n }\n }\n return string.split(separator, limit);\n }\n\n /**\n * Converts `string` to\n * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).\n *\n * @static\n * @memberOf _\n * @since 3.1.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the start cased string.\n * @example\n *\n * _.startCase('--foo-bar--');\n * // => 'Foo Bar'\n *\n * _.startCase('fooBar');\n * // => 'Foo Bar'\n *\n * _.startCase('__FOO_BAR__');\n * // => 'FOO BAR'\n */\n var startCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + upperFirst(word);\n });\n\n /**\n * Checks if `string` starts with the given target string.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {string} [target] The string to search for.\n * @param {number} [position=0] The position to search from.\n * @returns {boolean} Returns `true` if `string` starts with `target`,\n * else `false`.\n * @example\n *\n * _.startsWith('abc', 'a');\n * // => true\n *\n * _.startsWith('abc', 'b');\n * // => false\n *\n * _.startsWith('abc', 'b', 1);\n * // => true\n */\n function startsWith(string, target, position) {\n string = toString(string);\n position = position == null\n ? 0\n : baseClamp(toInteger(position), 0, string.length);\n\n target = baseToString(target);\n return string.slice(position, position + target.length) == target;\n }\n\n /**\n * Creates a compiled template function that can interpolate data properties\n * in \"interpolate\" delimiters, HTML-escape interpolated data properties in\n * \"escape\" delimiters, and execute JavaScript in \"evaluate\" delimiters. Data\n * properties may be accessed as free variables in the template. If a setting\n * object is given, it takes precedence over `_.templateSettings` values.\n *\n * **Note:** In the development build `_.template` utilizes\n * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)\n * for easier debugging.\n *\n * For more information on precompiling templates see\n * [lodash's custom builds documentation](https://lodash.com/custom-builds).\n *\n * For more information on Chrome extension sandboxes see\n * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category String\n * @param {string} [string=''] The template string.\n * @param {Object} [options={}] The options object.\n * @param {RegExp} [options.escape=_.templateSettings.escape]\n * The HTML \"escape\" delimiter.\n * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]\n * The \"evaluate\" delimiter.\n * @param {Object} [options.imports=_.templateSettings.imports]\n * An object to import into the template as free variables.\n * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]\n * The \"interpolate\" delimiter.\n * @param {string} [options.sourceURL='lodash.templateSources[n]']\n * The sourceURL of the compiled template.\n * @param {string} [options.variable='obj']\n * The data object variable name.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the compiled template function.\n * @example\n *\n * // Use the \"interpolate\" delimiter to create a compiled template.\n * var compiled = _.template('hello <%= user %>!');\n * compiled({ 'user': 'fred' });\n * // => 'hello fred!'\n *\n * // Use the HTML \"escape\" delimiter to escape data property values.\n * var compiled = _.template('<%- value %>');\n * compiled({ 'value': '\n * ```\n *\n * Elements by their ID are made available by browsers on the `window` object,\n * which is a security risk.\n * Using a prefix solves this problem.\n *\n * More information on how to handle clobbering and the prefix is explained in\n * Example: headings (DOM clobbering) in `rehype-sanitize`.\n *\n * ###### Unknown nodes\n *\n * Unknown nodes are nodes with a type that isn’t in `handlers` or `passThrough`.\n * The default behavior for unknown nodes is:\n *\n * * when the node has a `value` (and doesn’t have `data.hName`,\n * `data.hProperties`, or `data.hChildren`, see later), create a hast `text`\n * node\n * * otherwise, create a `} */\n let marker\n\n return start\n\n /**\n * Before a sequence.\n *\n * ```markdown\n * > | **\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(\n code === codes.asterisk || code === codes.underscore,\n 'expected asterisk or underscore'\n )\n marker = code\n effects.enter('attentionSequence')\n return inside(code)\n }\n\n /**\n * In a sequence.\n *\n * ```markdown\n * > | **\n * ^^\n * ```\n *\n * @type {State}\n */\n function inside(code) {\n if (code === marker) {\n effects.consume(code)\n return inside\n }\n\n const token = effects.exit('attentionSequence')\n\n // To do: next major: move this to resolver, just like `markdown-rs`.\n const after = classifyCharacter(code)\n\n // Always populated by defaults.\n assert(attentionMarkers, 'expected `attentionMarkers` to be populated')\n\n const open =\n !after ||\n (after === constants.characterGroupPunctuation && before) ||\n attentionMarkers.includes(code)\n const close =\n !before ||\n (before === constants.characterGroupPunctuation && after) ||\n attentionMarkers.includes(previous)\n\n token._open = Boolean(\n marker === codes.asterisk ? open : open && (before || !close)\n )\n token._close = Boolean(\n marker === codes.asterisk ? close : close && (after || !open)\n )\n return ok(code)\n }\n}\n\n/**\n * Move a point a bit.\n *\n * Note: `move` only works inside lines! It’s not possible to move past other\n * chunks (replacement characters, tabs, or line endings).\n *\n * @param {Point} point\n * @param {number} offset\n * @returns {undefined}\n */\nfunction movePoint(point, offset) {\n point.column += offset\n point.offset += offset\n point._bufferIndex += offset\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {\n asciiAlpha,\n asciiAlphanumeric,\n asciiAtext,\n asciiControl\n} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const autolink = {name: 'autolink', tokenize: tokenizeAutolink}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeAutolink(effects, ok, nok) {\n let size = 0\n\n return start\n\n /**\n * Start of an autolink.\n *\n * ```markdown\n * > | ab\n * ^\n * > | ab\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.lessThan, 'expected `<`')\n effects.enter(types.autolink)\n effects.enter(types.autolinkMarker)\n effects.consume(code)\n effects.exit(types.autolinkMarker)\n effects.enter(types.autolinkProtocol)\n return open\n }\n\n /**\n * After `<`, at protocol or atext.\n *\n * ```markdown\n * > | ab\n * ^\n * > | ab\n * ^\n * ```\n *\n * @type {State}\n */\n function open(code) {\n if (asciiAlpha(code)) {\n effects.consume(code)\n return schemeOrEmailAtext\n }\n\n return emailAtext(code)\n }\n\n /**\n * At second byte of protocol or atext.\n *\n * ```markdown\n * > | ab\n * ^\n * > | ab\n * ^\n * ```\n *\n * @type {State}\n */\n function schemeOrEmailAtext(code) {\n // ASCII alphanumeric and `+`, `-`, and `.`.\n if (\n code === codes.plusSign ||\n code === codes.dash ||\n code === codes.dot ||\n asciiAlphanumeric(code)\n ) {\n // Count the previous alphabetical from `open` too.\n size = 1\n return schemeInsideOrEmailAtext(code)\n }\n\n return emailAtext(code)\n }\n\n /**\n * In ambiguous protocol or atext.\n *\n * ```markdown\n * > | ab\n * ^\n * > | ab\n * ^\n * ```\n *\n * @type {State}\n */\n function schemeInsideOrEmailAtext(code) {\n if (code === codes.colon) {\n effects.consume(code)\n size = 0\n return urlInside\n }\n\n // ASCII alphanumeric and `+`, `-`, and `.`.\n if (\n (code === codes.plusSign ||\n code === codes.dash ||\n code === codes.dot ||\n asciiAlphanumeric(code)) &&\n size++ < constants.autolinkSchemeSizeMax\n ) {\n effects.consume(code)\n return schemeInsideOrEmailAtext\n }\n\n size = 0\n return emailAtext(code)\n }\n\n /**\n * After protocol, in URL.\n *\n * ```markdown\n * > | ab\n * ^\n * ```\n *\n * @type {State}\n */\n function urlInside(code) {\n if (code === codes.greaterThan) {\n effects.exit(types.autolinkProtocol)\n effects.enter(types.autolinkMarker)\n effects.consume(code)\n effects.exit(types.autolinkMarker)\n effects.exit(types.autolink)\n return ok\n }\n\n // ASCII control, space, or `<`.\n if (\n code === codes.eof ||\n code === codes.space ||\n code === codes.lessThan ||\n asciiControl(code)\n ) {\n return nok(code)\n }\n\n effects.consume(code)\n return urlInside\n }\n\n /**\n * In email atext.\n *\n * ```markdown\n * > | ab\n * ^\n * ```\n *\n * @type {State}\n */\n function emailAtext(code) {\n if (code === codes.atSign) {\n effects.consume(code)\n return emailAtSignOrDot\n }\n\n if (asciiAtext(code)) {\n effects.consume(code)\n return emailAtext\n }\n\n return nok(code)\n }\n\n /**\n * In label, after at-sign or dot.\n *\n * ```markdown\n * > | ab\n * ^ ^\n * ```\n *\n * @type {State}\n */\n function emailAtSignOrDot(code) {\n return asciiAlphanumeric(code) ? emailLabel(code) : nok(code)\n }\n\n /**\n * In label, where `.` and `>` are allowed.\n *\n * ```markdown\n * > | ab\n * ^\n * ```\n *\n * @type {State}\n */\n function emailLabel(code) {\n if (code === codes.dot) {\n effects.consume(code)\n size = 0\n return emailAtSignOrDot\n }\n\n if (code === codes.greaterThan) {\n // Exit, then change the token type.\n effects.exit(types.autolinkProtocol).type = types.autolinkEmail\n effects.enter(types.autolinkMarker)\n effects.consume(code)\n effects.exit(types.autolinkMarker)\n effects.exit(types.autolink)\n return ok\n }\n\n return emailValue(code)\n }\n\n /**\n * In label, where `.` and `>` are *not* allowed.\n *\n * Though, this is also used in `emailLabel` to parse other values.\n *\n * ```markdown\n * > | ab\n * ^\n * ```\n *\n * @type {State}\n */\n function emailValue(code) {\n // ASCII alphanumeric or `-`.\n if (\n (code === codes.dash || asciiAlphanumeric(code)) &&\n size++ < constants.autolinkDomainSizeMax\n ) {\n const next = code === codes.dash ? emailValue : emailLabel\n effects.consume(code)\n return next\n }\n\n return nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding, markdownSpace} from 'micromark-util-character'\nimport {codes, types} from 'micromark-util-symbol'\n\n/** @type {Construct} */\nexport const blankLine = {tokenize: tokenizeBlankLine, partial: true}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeBlankLine(effects, ok, nok) {\n return start\n\n /**\n * Start of blank line.\n *\n * > 👉 **Note**: `␠` represents a space character.\n *\n * ```markdown\n * > | ␠␠␊\n * ^\n * > | ␊\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n return markdownSpace(code)\n ? factorySpace(effects, after, types.linePrefix)(code)\n : after(code)\n }\n\n /**\n * At eof/eol, after optional whitespace.\n *\n * > 👉 **Note**: `␠` represents a space character.\n *\n * ```markdown\n * > | ␠␠␊\n * ^\n * > | ␊\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n return code === codes.eof || markdownLineEnding(code) ? ok(code) : nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').Exiter} Exiter\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownSpace} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const blockQuote = {\n name: 'blockQuote',\n tokenize: tokenizeBlockQuoteStart,\n continuation: {tokenize: tokenizeBlockQuoteContinuation},\n exit\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeBlockQuoteStart(effects, ok, nok) {\n const self = this\n\n return start\n\n /**\n * Start of block quote.\n *\n * ```markdown\n * > | > a\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n if (code === codes.greaterThan) {\n const state = self.containerState\n\n assert(state, 'expected `containerState` to be defined in container')\n\n if (!state.open) {\n effects.enter(types.blockQuote, {_container: true})\n state.open = true\n }\n\n effects.enter(types.blockQuotePrefix)\n effects.enter(types.blockQuoteMarker)\n effects.consume(code)\n effects.exit(types.blockQuoteMarker)\n return after\n }\n\n return nok(code)\n }\n\n /**\n * After `>`, before optional whitespace.\n *\n * ```markdown\n * > | > a\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n if (markdownSpace(code)) {\n effects.enter(types.blockQuotePrefixWhitespace)\n effects.consume(code)\n effects.exit(types.blockQuotePrefixWhitespace)\n effects.exit(types.blockQuotePrefix)\n return ok\n }\n\n effects.exit(types.blockQuotePrefix)\n return ok(code)\n }\n}\n\n/**\n * Start of block quote continuation.\n *\n * ```markdown\n * | > a\n * > | > b\n * ^\n * ```\n *\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeBlockQuoteContinuation(effects, ok, nok) {\n const self = this\n\n return contStart\n\n /**\n * Start of block quote continuation.\n *\n * Also used to parse the first block quote opening.\n *\n * ```markdown\n * | > a\n * > | > b\n * ^\n * ```\n *\n * @type {State}\n */\n function contStart(code) {\n if (markdownSpace(code)) {\n // Always populated by defaults.\n assert(\n self.parser.constructs.disable.null,\n 'expected `disable.null` to be populated'\n )\n\n return factorySpace(\n effects,\n contBefore,\n types.linePrefix,\n self.parser.constructs.disable.null.includes('codeIndented')\n ? undefined\n : constants.tabSize\n )(code)\n }\n\n return contBefore(code)\n }\n\n /**\n * At `>`, after optional whitespace.\n *\n * Also used to parse the first block quote opening.\n *\n * ```markdown\n * | > a\n * > | > b\n * ^\n * ```\n *\n * @type {State}\n */\n function contBefore(code) {\n return effects.attempt(blockQuote, ok, nok)(code)\n }\n}\n\n/** @type {Exiter} */\nfunction exit(effects) {\n effects.exit(types.blockQuote)\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {asciiPunctuation} from 'micromark-util-character'\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const characterEscape = {\n name: 'characterEscape',\n tokenize: tokenizeCharacterEscape\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeCharacterEscape(effects, ok, nok) {\n return start\n\n /**\n * Start of character escape.\n *\n * ```markdown\n * > | a\\*b\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.backslash, 'expected `\\\\`')\n effects.enter(types.characterEscape)\n effects.enter(types.escapeMarker)\n effects.consume(code)\n effects.exit(types.escapeMarker)\n return inside\n }\n\n /**\n * After `\\`, at punctuation.\n *\n * ```markdown\n * > | a\\*b\n * ^\n * ```\n *\n * @type {State}\n */\n function inside(code) {\n // ASCII punctuation.\n if (asciiPunctuation(code)) {\n effects.enter(types.characterEscapeValue)\n effects.consume(code)\n effects.exit(types.characterEscapeValue)\n effects.exit(types.characterEscape)\n return ok\n }\n\n return nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {decodeNamedCharacterReference} from 'decode-named-character-reference'\nimport {\n asciiAlphanumeric,\n asciiDigit,\n asciiHexDigit\n} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const characterReference = {\n name: 'characterReference',\n tokenize: tokenizeCharacterReference\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeCharacterReference(effects, ok, nok) {\n const self = this\n let size = 0\n /** @type {number} */\n let max\n /** @type {(code: Code) => boolean} */\n let test\n\n return start\n\n /**\n * Start of character reference.\n *\n * ```markdown\n * > | a&b\n * ^\n * > | a{b\n * ^\n * > | a b\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.ampersand, 'expected `&`')\n effects.enter(types.characterReference)\n effects.enter(types.characterReferenceMarker)\n effects.consume(code)\n effects.exit(types.characterReferenceMarker)\n return open\n }\n\n /**\n * After `&`, at `#` for numeric references or alphanumeric for named\n * references.\n *\n * ```markdown\n * > | a&b\n * ^\n * > | a{b\n * ^\n * > | a b\n * ^\n * ```\n *\n * @type {State}\n */\n function open(code) {\n if (code === codes.numberSign) {\n effects.enter(types.characterReferenceMarkerNumeric)\n effects.consume(code)\n effects.exit(types.characterReferenceMarkerNumeric)\n return numeric\n }\n\n effects.enter(types.characterReferenceValue)\n max = constants.characterReferenceNamedSizeMax\n test = asciiAlphanumeric\n return value(code)\n }\n\n /**\n * After `#`, at `x` for hexadecimals or digit for decimals.\n *\n * ```markdown\n * > | a{b\n * ^\n * > | a b\n * ^\n * ```\n *\n * @type {State}\n */\n function numeric(code) {\n if (code === codes.uppercaseX || code === codes.lowercaseX) {\n effects.enter(types.characterReferenceMarkerHexadecimal)\n effects.consume(code)\n effects.exit(types.characterReferenceMarkerHexadecimal)\n effects.enter(types.characterReferenceValue)\n max = constants.characterReferenceHexadecimalSizeMax\n test = asciiHexDigit\n return value\n }\n\n effects.enter(types.characterReferenceValue)\n max = constants.characterReferenceDecimalSizeMax\n test = asciiDigit\n return value(code)\n }\n\n /**\n * After markers (``, ``, or `&`), in value, before `;`.\n *\n * The character reference kind defines what and how many characters are\n * allowed.\n *\n * ```markdown\n * > | a&b\n * ^^^\n * > | a{b\n * ^^^\n * > | a b\n * ^\n * ```\n *\n * @type {State}\n */\n function value(code) {\n if (code === codes.semicolon && size) {\n const token = effects.exit(types.characterReferenceValue)\n\n if (\n test === asciiAlphanumeric &&\n !decodeNamedCharacterReference(self.sliceSerialize(token))\n ) {\n return nok(code)\n }\n\n // To do: `markdown-rs` uses a different name:\n // `CharacterReferenceMarkerSemi`.\n effects.enter(types.characterReferenceMarker)\n effects.consume(code)\n effects.exit(types.characterReferenceMarker)\n effects.exit(types.characterReference)\n return ok\n }\n\n if (test(code) && size++ < max) {\n effects.consume(code)\n return value\n }\n\n return nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding, markdownSpace} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nconst nonLazyContinuation = {\n tokenize: tokenizeNonLazyContinuation,\n partial: true\n}\n\n/** @type {Construct} */\nexport const codeFenced = {\n name: 'codeFenced',\n tokenize: tokenizeCodeFenced,\n concrete: true\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeCodeFenced(effects, ok, nok) {\n const self = this\n /** @type {Construct} */\n const closeStart = {tokenize: tokenizeCloseStart, partial: true}\n let initialPrefix = 0\n let sizeOpen = 0\n /** @type {NonNullable} */\n let marker\n\n return start\n\n /**\n * Start of code.\n *\n * ```markdown\n * > | ~~~js\n * ^\n * | alert(1)\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function start(code) {\n // To do: parse whitespace like `markdown-rs`.\n return beforeSequenceOpen(code)\n }\n\n /**\n * In opening fence, after prefix, at sequence.\n *\n * ```markdown\n * > | ~~~js\n * ^\n * | alert(1)\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function beforeSequenceOpen(code) {\n assert(\n code === codes.graveAccent || code === codes.tilde,\n 'expected `` ` `` or `~`'\n )\n\n const tail = self.events[self.events.length - 1]\n initialPrefix =\n tail && tail[1].type === types.linePrefix\n ? tail[2].sliceSerialize(tail[1], true).length\n : 0\n\n marker = code\n effects.enter(types.codeFenced)\n effects.enter(types.codeFencedFence)\n effects.enter(types.codeFencedFenceSequence)\n return sequenceOpen(code)\n }\n\n /**\n * In opening fence sequence.\n *\n * ```markdown\n * > | ~~~js\n * ^\n * | alert(1)\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function sequenceOpen(code) {\n if (code === marker) {\n sizeOpen++\n effects.consume(code)\n return sequenceOpen\n }\n\n if (sizeOpen < constants.codeFencedSequenceSizeMin) {\n return nok(code)\n }\n\n effects.exit(types.codeFencedFenceSequence)\n return markdownSpace(code)\n ? factorySpace(effects, infoBefore, types.whitespace)(code)\n : infoBefore(code)\n }\n\n /**\n * In opening fence, after the sequence (and optional whitespace), before info.\n *\n * ```markdown\n * > | ~~~js\n * ^\n * | alert(1)\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function infoBefore(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.codeFencedFence)\n return self.interrupt\n ? ok(code)\n : effects.check(nonLazyContinuation, atNonLazyBreak, after)(code)\n }\n\n effects.enter(types.codeFencedFenceInfo)\n effects.enter(types.chunkString, {contentType: constants.contentTypeString})\n return info(code)\n }\n\n /**\n * In info.\n *\n * ```markdown\n * > | ~~~js\n * ^\n * | alert(1)\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function info(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.chunkString)\n effects.exit(types.codeFencedFenceInfo)\n return infoBefore(code)\n }\n\n if (markdownSpace(code)) {\n effects.exit(types.chunkString)\n effects.exit(types.codeFencedFenceInfo)\n return factorySpace(effects, metaBefore, types.whitespace)(code)\n }\n\n if (code === codes.graveAccent && code === marker) {\n return nok(code)\n }\n\n effects.consume(code)\n return info\n }\n\n /**\n * In opening fence, after info and whitespace, before meta.\n *\n * ```markdown\n * > | ~~~js eval\n * ^\n * | alert(1)\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function metaBefore(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n return infoBefore(code)\n }\n\n effects.enter(types.codeFencedFenceMeta)\n effects.enter(types.chunkString, {contentType: constants.contentTypeString})\n return meta(code)\n }\n\n /**\n * In meta.\n *\n * ```markdown\n * > | ~~~js eval\n * ^\n * | alert(1)\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function meta(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.chunkString)\n effects.exit(types.codeFencedFenceMeta)\n return infoBefore(code)\n }\n\n if (code === codes.graveAccent && code === marker) {\n return nok(code)\n }\n\n effects.consume(code)\n return meta\n }\n\n /**\n * At eol/eof in code, before a non-lazy closing fence or content.\n *\n * ```markdown\n * > | ~~~js\n * ^\n * > | alert(1)\n * ^\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function atNonLazyBreak(code) {\n assert(markdownLineEnding(code), 'expected eol')\n return effects.attempt(closeStart, after, contentBefore)(code)\n }\n\n /**\n * Before code content, not a closing fence, at eol.\n *\n * ```markdown\n * | ~~~js\n * > | alert(1)\n * ^\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function contentBefore(code) {\n assert(markdownLineEnding(code), 'expected eol')\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return contentStart\n }\n\n /**\n * Before code content, not a closing fence.\n *\n * ```markdown\n * | ~~~js\n * > | alert(1)\n * ^\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function contentStart(code) {\n return initialPrefix > 0 && markdownSpace(code)\n ? factorySpace(\n effects,\n beforeContentChunk,\n types.linePrefix,\n initialPrefix + 1\n )(code)\n : beforeContentChunk(code)\n }\n\n /**\n * Before code content, after optional prefix.\n *\n * ```markdown\n * | ~~~js\n * > | alert(1)\n * ^\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function beforeContentChunk(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n return effects.check(nonLazyContinuation, atNonLazyBreak, after)(code)\n }\n\n effects.enter(types.codeFlowValue)\n return contentChunk(code)\n }\n\n /**\n * In code content.\n *\n * ```markdown\n * | ~~~js\n * > | alert(1)\n * ^^^^^^^^\n * | ~~~\n * ```\n *\n * @type {State}\n */\n function contentChunk(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.codeFlowValue)\n return beforeContentChunk(code)\n }\n\n effects.consume(code)\n return contentChunk\n }\n\n /**\n * After code.\n *\n * ```markdown\n * | ~~~js\n * | alert(1)\n * > | ~~~\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n effects.exit(types.codeFenced)\n return ok(code)\n }\n\n /**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\n function tokenizeCloseStart(effects, ok, nok) {\n let size = 0\n\n return startBefore\n\n /**\n *\n *\n * @type {State}\n */\n function startBefore(code) {\n assert(markdownLineEnding(code), 'expected eol')\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return start\n }\n\n /**\n * Before closing fence, at optional whitespace.\n *\n * ```markdown\n * | ~~~js\n * | alert(1)\n * > | ~~~\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n // Always populated by defaults.\n assert(\n self.parser.constructs.disable.null,\n 'expected `disable.null` to be populated'\n )\n\n // To do: `enter` here or in next state?\n effects.enter(types.codeFencedFence)\n return markdownSpace(code)\n ? factorySpace(\n effects,\n beforeSequenceClose,\n types.linePrefix,\n self.parser.constructs.disable.null.includes('codeIndented')\n ? undefined\n : constants.tabSize\n )(code)\n : beforeSequenceClose(code)\n }\n\n /**\n * In closing fence, after optional whitespace, at sequence.\n *\n * ```markdown\n * | ~~~js\n * | alert(1)\n * > | ~~~\n * ^\n * ```\n *\n * @type {State}\n */\n function beforeSequenceClose(code) {\n if (code === marker) {\n effects.enter(types.codeFencedFenceSequence)\n return sequenceClose(code)\n }\n\n return nok(code)\n }\n\n /**\n * In closing fence sequence.\n *\n * ```markdown\n * | ~~~js\n * | alert(1)\n * > | ~~~\n * ^\n * ```\n *\n * @type {State}\n */\n function sequenceClose(code) {\n if (code === marker) {\n size++\n effects.consume(code)\n return sequenceClose\n }\n\n if (size >= sizeOpen) {\n effects.exit(types.codeFencedFenceSequence)\n return markdownSpace(code)\n ? factorySpace(effects, sequenceCloseAfter, types.whitespace)(code)\n : sequenceCloseAfter(code)\n }\n\n return nok(code)\n }\n\n /**\n * After closing fence sequence, after optional whitespace.\n *\n * ```markdown\n * | ~~~js\n * | alert(1)\n * > | ~~~\n * ^\n * ```\n *\n * @type {State}\n */\n function sequenceCloseAfter(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.codeFencedFence)\n return ok(code)\n }\n\n return nok(code)\n }\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeNonLazyContinuation(effects, ok, nok) {\n const self = this\n\n return start\n\n /**\n *\n *\n * @type {State}\n */\n function start(code) {\n if (code === codes.eof) {\n return nok(code)\n }\n\n assert(markdownLineEnding(code), 'expected eol')\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return lineStart\n }\n\n /**\n *\n *\n * @type {State}\n */\n function lineStart(code) {\n return self.parser.lazy[self.now().line] ? nok(code) : ok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding, markdownSpace} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const codeIndented = {\n name: 'codeIndented',\n tokenize: tokenizeCodeIndented\n}\n\n/** @type {Construct} */\nconst furtherStart = {tokenize: tokenizeFurtherStart, partial: true}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeCodeIndented(effects, ok, nok) {\n const self = this\n return start\n\n /**\n * Start of code (indented).\n *\n * > **Parsing note**: it is not needed to check if this first line is a\n * > filled line (that it has a non-whitespace character), because blank lines\n * > are parsed already, so we never run into that.\n *\n * ```markdown\n * > | aaa\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n // To do: manually check if interrupting like `markdown-rs`.\n assert(markdownSpace(code))\n effects.enter(types.codeIndented)\n // To do: use an improved `space_or_tab` function like `markdown-rs`,\n // so that we can drop the next state.\n return factorySpace(\n effects,\n afterPrefix,\n types.linePrefix,\n constants.tabSize + 1\n )(code)\n }\n\n /**\n * At start, after 1 or 4 spaces.\n *\n * ```markdown\n * > | aaa\n * ^\n * ```\n *\n * @type {State}\n */\n function afterPrefix(code) {\n const tail = self.events[self.events.length - 1]\n return tail &&\n tail[1].type === types.linePrefix &&\n tail[2].sliceSerialize(tail[1], true).length >= constants.tabSize\n ? atBreak(code)\n : nok(code)\n }\n\n /**\n * At a break.\n *\n * ```markdown\n * > | aaa\n * ^ ^\n * ```\n *\n * @type {State}\n */\n function atBreak(code) {\n if (code === codes.eof) {\n return after(code)\n }\n\n if (markdownLineEnding(code)) {\n return effects.attempt(furtherStart, atBreak, after)(code)\n }\n\n effects.enter(types.codeFlowValue)\n return inside(code)\n }\n\n /**\n * In code content.\n *\n * ```markdown\n * > | aaa\n * ^^^^\n * ```\n *\n * @type {State}\n */\n function inside(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.codeFlowValue)\n return atBreak(code)\n }\n\n effects.consume(code)\n return inside\n }\n\n /** @type {State} */\n function after(code) {\n effects.exit(types.codeIndented)\n // To do: allow interrupting like `markdown-rs`.\n // Feel free to interrupt.\n // tokenizer.interrupt = false\n return ok(code)\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeFurtherStart(effects, ok, nok) {\n const self = this\n\n return furtherStart\n\n /**\n * At eol, trying to parse another indent.\n *\n * ```markdown\n * > | aaa\n * ^\n * | bbb\n * ```\n *\n * @type {State}\n */\n function furtherStart(code) {\n // To do: improve `lazy` / `pierce` handling.\n // If this is a lazy line, it can’t be code.\n if (self.parser.lazy[self.now().line]) {\n return nok(code)\n }\n\n if (markdownLineEnding(code)) {\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return furtherStart\n }\n\n // To do: the code here in `micromark-js` is a bit different from\n // `markdown-rs` because there it can attempt spaces.\n // We can’t yet.\n //\n // To do: use an improved `space_or_tab` function like `markdown-rs`,\n // so that we can drop the next state.\n return factorySpace(\n effects,\n afterPrefix,\n types.linePrefix,\n constants.tabSize + 1\n )(code)\n }\n\n /**\n * At start, after 1 or 4 spaces.\n *\n * ```markdown\n * > | aaa\n * ^\n * ```\n *\n * @type {State}\n */\n function afterPrefix(code) {\n const tail = self.events[self.events.length - 1]\n return tail &&\n tail[1].type === types.linePrefix &&\n tail[2].sliceSerialize(tail[1], true).length >= constants.tabSize\n ? ok(code)\n : markdownLineEnding(code)\n ? furtherStart(code)\n : nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').Previous} Previous\n * @typedef {import('micromark-util-types').Resolver} Resolver\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').Token} Token\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const codeText = {\n name: 'codeText',\n tokenize: tokenizeCodeText,\n resolve: resolveCodeText,\n previous\n}\n\n// To do: next major: don’t resolve, like `markdown-rs`.\n/** @type {Resolver} */\nfunction resolveCodeText(events) {\n let tailExitIndex = events.length - 4\n let headEnterIndex = 3\n /** @type {number} */\n let index\n /** @type {number | undefined} */\n let enter\n\n // If we start and end with an EOL or a space.\n if (\n (events[headEnterIndex][1].type === types.lineEnding ||\n events[headEnterIndex][1].type === 'space') &&\n (events[tailExitIndex][1].type === types.lineEnding ||\n events[tailExitIndex][1].type === 'space')\n ) {\n index = headEnterIndex\n\n // And we have data.\n while (++index < tailExitIndex) {\n if (events[index][1].type === types.codeTextData) {\n // Then we have padding.\n events[headEnterIndex][1].type = types.codeTextPadding\n events[tailExitIndex][1].type = types.codeTextPadding\n headEnterIndex += 2\n tailExitIndex -= 2\n break\n }\n }\n }\n\n // Merge adjacent spaces and data.\n index = headEnterIndex - 1\n tailExitIndex++\n\n while (++index <= tailExitIndex) {\n if (enter === undefined) {\n if (\n index !== tailExitIndex &&\n events[index][1].type !== types.lineEnding\n ) {\n enter = index\n }\n } else if (\n index === tailExitIndex ||\n events[index][1].type === types.lineEnding\n ) {\n events[enter][1].type = types.codeTextData\n\n if (index !== enter + 2) {\n events[enter][1].end = events[index - 1][1].end\n events.splice(enter + 2, index - enter - 2)\n tailExitIndex -= index - enter - 2\n index = enter + 2\n }\n\n enter = undefined\n }\n }\n\n return events\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Previous}\n */\nfunction previous(code) {\n // If there is a previous code, there will always be a tail.\n return (\n code !== codes.graveAccent ||\n this.events[this.events.length - 1][1].type === types.characterEscape\n )\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeCodeText(effects, ok, nok) {\n const self = this\n let sizeOpen = 0\n /** @type {number} */\n let size\n /** @type {Token} */\n let token\n\n return start\n\n /**\n * Start of code (text).\n *\n * ```markdown\n * > | `a`\n * ^\n * > | \\`a`\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.graveAccent, 'expected `` ` ``')\n assert(previous.call(self, self.previous), 'expected correct previous')\n effects.enter(types.codeText)\n effects.enter(types.codeTextSequence)\n return sequenceOpen(code)\n }\n\n /**\n * In opening sequence.\n *\n * ```markdown\n * > | `a`\n * ^\n * ```\n *\n * @type {State}\n */\n function sequenceOpen(code) {\n if (code === codes.graveAccent) {\n effects.consume(code)\n sizeOpen++\n return sequenceOpen\n }\n\n effects.exit(types.codeTextSequence)\n return between(code)\n }\n\n /**\n * Between something and something else.\n *\n * ```markdown\n * > | `a`\n * ^^\n * ```\n *\n * @type {State}\n */\n function between(code) {\n // EOF.\n if (code === codes.eof) {\n return nok(code)\n }\n\n // To do: next major: don’t do spaces in resolve, but when compiling,\n // like `markdown-rs`.\n // Tabs don’t work, and virtual spaces don’t make sense.\n if (code === codes.space) {\n effects.enter('space')\n effects.consume(code)\n effects.exit('space')\n return between\n }\n\n // Closing fence? Could also be data.\n if (code === codes.graveAccent) {\n token = effects.enter(types.codeTextSequence)\n size = 0\n return sequenceClose(code)\n }\n\n if (markdownLineEnding(code)) {\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return between\n }\n\n // Data.\n effects.enter(types.codeTextData)\n return data(code)\n }\n\n /**\n * In data.\n *\n * ```markdown\n * > | `a`\n * ^\n * ```\n *\n * @type {State}\n */\n function data(code) {\n if (\n code === codes.eof ||\n code === codes.space ||\n code === codes.graveAccent ||\n markdownLineEnding(code)\n ) {\n effects.exit(types.codeTextData)\n return between(code)\n }\n\n effects.consume(code)\n return data\n }\n\n /**\n * In closing sequence.\n *\n * ```markdown\n * > | `a`\n * ^\n * ```\n *\n * @type {State}\n */\n function sequenceClose(code) {\n // More.\n if (code === codes.graveAccent) {\n effects.consume(code)\n size++\n return sequenceClose\n }\n\n // Done!\n if (size === sizeOpen) {\n effects.exit(types.codeTextSequence)\n effects.exit(types.codeText)\n return ok(code)\n }\n\n // More or less accents: mark as data.\n token.type = types.codeTextData\n return data(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').Resolver} Resolver\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').Token} Token\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {subtokenize} from 'micromark-util-subtokenize'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/**\n * No name because it must not be turned off.\n * @type {Construct}\n */\nexport const content = {tokenize: tokenizeContent, resolve: resolveContent}\n\n/** @type {Construct} */\nconst continuationConstruct = {tokenize: tokenizeContinuation, partial: true}\n\n/**\n * Content is transparent: it’s parsed right now. That way, definitions are also\n * parsed right now: before text in paragraphs (specifically, media) are parsed.\n *\n * @type {Resolver}\n */\nfunction resolveContent(events) {\n subtokenize(events)\n return events\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeContent(effects, ok) {\n /** @type {Token | undefined} */\n let previous\n\n return chunkStart\n\n /**\n * Before a content chunk.\n *\n * ```markdown\n * > | abc\n * ^\n * ```\n *\n * @type {State}\n */\n function chunkStart(code) {\n assert(\n code !== codes.eof && !markdownLineEnding(code),\n 'expected no eof or eol'\n )\n\n effects.enter(types.content)\n previous = effects.enter(types.chunkContent, {\n contentType: constants.contentTypeContent\n })\n return chunkInside(code)\n }\n\n /**\n * In a content chunk.\n *\n * ```markdown\n * > | abc\n * ^^^\n * ```\n *\n * @type {State}\n */\n function chunkInside(code) {\n if (code === codes.eof) {\n return contentEnd(code)\n }\n\n // To do: in `markdown-rs`, each line is parsed on its own, and everything\n // is stitched together resolving.\n if (markdownLineEnding(code)) {\n return effects.check(\n continuationConstruct,\n contentContinue,\n contentEnd\n )(code)\n }\n\n // Data.\n effects.consume(code)\n return chunkInside\n }\n\n /**\n *\n *\n * @type {State}\n */\n function contentEnd(code) {\n effects.exit(types.chunkContent)\n effects.exit(types.content)\n return ok(code)\n }\n\n /**\n *\n *\n * @type {State}\n */\n function contentContinue(code) {\n assert(markdownLineEnding(code), 'expected eol')\n effects.consume(code)\n effects.exit(types.chunkContent)\n assert(previous, 'expected previous token')\n previous.next = effects.enter(types.chunkContent, {\n contentType: constants.contentTypeContent,\n previous\n })\n previous = previous.next\n return chunkInside\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeContinuation(effects, ok, nok) {\n const self = this\n\n return startLookahead\n\n /**\n *\n *\n * @type {State}\n */\n function startLookahead(code) {\n assert(markdownLineEnding(code), 'expected a line ending')\n effects.exit(types.chunkContent)\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return factorySpace(effects, prefixed, types.linePrefix)\n }\n\n /**\n *\n *\n * @type {State}\n */\n function prefixed(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n return nok(code)\n }\n\n // Always populated by defaults.\n assert(\n self.parser.constructs.disable.null,\n 'expected `disable.null` to be populated'\n )\n\n const tail = self.events[self.events.length - 1]\n\n if (\n !self.parser.constructs.disable.null.includes('codeIndented') &&\n tail &&\n tail[1].type === types.linePrefix &&\n tail[2].sliceSerialize(tail[1], true).length >= constants.tabSize\n ) {\n return ok(code)\n }\n\n return effects.interrupt(self.parser.constructs.flow, nok, ok)(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factoryDestination} from 'micromark-factory-destination'\nimport {factoryLabel} from 'micromark-factory-label'\nimport {factorySpace} from 'micromark-factory-space'\nimport {factoryTitle} from 'micromark-factory-title'\nimport {factoryWhitespace} from 'micromark-factory-whitespace'\nimport {\n markdownLineEnding,\n markdownLineEndingOrSpace,\n markdownSpace\n} from 'micromark-util-character'\nimport {normalizeIdentifier} from 'micromark-util-normalize-identifier'\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const definition = {name: 'definition', tokenize: tokenizeDefinition}\n\n/** @type {Construct} */\nconst titleBefore = {tokenize: tokenizeTitleBefore, partial: true}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeDefinition(effects, ok, nok) {\n const self = this\n /** @type {string} */\n let identifier\n\n return start\n\n /**\n * At start of a definition.\n *\n * ```markdown\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n // Do not interrupt paragraphs (but do follow definitions).\n // To do: do `interrupt` the way `markdown-rs` does.\n // To do: parse whitespace the way `markdown-rs` does.\n effects.enter(types.definition)\n return before(code)\n }\n\n /**\n * After optional whitespace, at `[`.\n *\n * ```markdown\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function before(code) {\n // To do: parse whitespace the way `markdown-rs` does.\n assert(code === codes.leftSquareBracket, 'expected `[`')\n return factoryLabel.call(\n self,\n effects,\n labelAfter,\n // Note: we don’t need to reset the way `markdown-rs` does.\n nok,\n types.definitionLabel,\n types.definitionLabelMarker,\n types.definitionLabelString\n )(code)\n }\n\n /**\n * After label.\n *\n * ```markdown\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function labelAfter(code) {\n identifier = normalizeIdentifier(\n self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1)\n )\n\n if (code === codes.colon) {\n effects.enter(types.definitionMarker)\n effects.consume(code)\n effects.exit(types.definitionMarker)\n return markerAfter\n }\n\n return nok(code)\n }\n\n /**\n * After marker.\n *\n * ```markdown\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function markerAfter(code) {\n // Note: whitespace is optional.\n return markdownLineEndingOrSpace(code)\n ? factoryWhitespace(effects, destinationBefore)(code)\n : destinationBefore(code)\n }\n\n /**\n * Before destination.\n *\n * ```markdown\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function destinationBefore(code) {\n return factoryDestination(\n effects,\n destinationAfter,\n // Note: we don’t need to reset the way `markdown-rs` does.\n nok,\n types.definitionDestination,\n types.definitionDestinationLiteral,\n types.definitionDestinationLiteralMarker,\n types.definitionDestinationRaw,\n types.definitionDestinationString\n )(code)\n }\n\n /**\n * After destination.\n *\n * ```markdown\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function destinationAfter(code) {\n return effects.attempt(titleBefore, after, after)(code)\n }\n\n /**\n * After definition.\n *\n * ```markdown\n * > | [a]: b\n * ^\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n return markdownSpace(code)\n ? factorySpace(effects, afterWhitespace, types.whitespace)(code)\n : afterWhitespace(code)\n }\n\n /**\n * After definition, after optional whitespace.\n *\n * ```markdown\n * > | [a]: b\n * ^\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function afterWhitespace(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.definition)\n\n // Note: we don’t care about uniqueness.\n // It’s likely that that doesn’t happen very frequently.\n // It is more likely that it wastes precious time.\n self.parser.defined.push(identifier)\n\n // To do: `markdown-rs` interrupt.\n // // You’d be interrupting.\n // tokenizer.interrupt = true\n return ok(code)\n }\n\n return nok(code)\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeTitleBefore(effects, ok, nok) {\n return titleBefore\n\n /**\n * After destination, at whitespace.\n *\n * ```markdown\n * > | [a]: b\n * ^\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function titleBefore(code) {\n return markdownLineEndingOrSpace(code)\n ? factoryWhitespace(effects, beforeMarker)(code)\n : nok(code)\n }\n\n /**\n * At title.\n *\n * ```markdown\n * | [a]: b\n * > | \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function beforeMarker(code) {\n return factoryTitle(\n effects,\n titleAfter,\n nok,\n types.definitionTitle,\n types.definitionTitleMarker,\n types.definitionTitleString\n )(code)\n }\n\n /**\n * After title.\n *\n * ```markdown\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function titleAfter(code) {\n return markdownSpace(code)\n ? factorySpace(\n effects,\n titleAfterOptionalWhitespace,\n types.whitespace\n )(code)\n : titleAfterOptionalWhitespace(code)\n }\n\n /**\n * After title, after optional whitespace.\n *\n * ```markdown\n * > | [a]: b \"c\"\n * ^\n * ```\n *\n * @type {State}\n */\n function titleAfterOptionalWhitespace(code) {\n return code === codes.eof || markdownLineEnding(code) ? ok(code) : nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const hardBreakEscape = {\n name: 'hardBreakEscape',\n tokenize: tokenizeHardBreakEscape\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeHardBreakEscape(effects, ok, nok) {\n return start\n\n /**\n * Start of a hard break (escape).\n *\n * ```markdown\n * > | a\\\n * ^\n * | b\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.backslash, 'expected `\\\\`')\n effects.enter(types.hardBreakEscape)\n effects.consume(code)\n return after\n }\n\n /**\n * After `\\`, at eol.\n *\n * ```markdown\n * > | a\\\n * ^\n * | b\n * ```\n *\n * @type {State}\n */\n function after(code) {\n if (markdownLineEnding(code)) {\n effects.exit(types.hardBreakEscape)\n return ok(code)\n }\n\n return nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').Resolver} Resolver\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').Token} Token\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {\n markdownLineEnding,\n markdownLineEndingOrSpace,\n markdownSpace\n} from 'micromark-util-character'\nimport {splice} from 'micromark-util-chunked'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const headingAtx = {\n name: 'headingAtx',\n tokenize: tokenizeHeadingAtx,\n resolve: resolveHeadingAtx\n}\n\n/** @type {Resolver} */\nfunction resolveHeadingAtx(events, context) {\n let contentEnd = events.length - 2\n let contentStart = 3\n /** @type {Token} */\n let content\n /** @type {Token} */\n let text\n\n // Prefix whitespace, part of the opening.\n if (events[contentStart][1].type === types.whitespace) {\n contentStart += 2\n }\n\n // Suffix whitespace, part of the closing.\n if (\n contentEnd - 2 > contentStart &&\n events[contentEnd][1].type === types.whitespace\n ) {\n contentEnd -= 2\n }\n\n if (\n events[contentEnd][1].type === types.atxHeadingSequence &&\n (contentStart === contentEnd - 1 ||\n (contentEnd - 4 > contentStart &&\n events[contentEnd - 2][1].type === types.whitespace))\n ) {\n contentEnd -= contentStart + 1 === contentEnd ? 2 : 4\n }\n\n if (contentEnd > contentStart) {\n content = {\n type: types.atxHeadingText,\n start: events[contentStart][1].start,\n end: events[contentEnd][1].end\n }\n text = {\n type: types.chunkText,\n start: events[contentStart][1].start,\n end: events[contentEnd][1].end,\n contentType: constants.contentTypeText\n }\n\n splice(events, contentStart, contentEnd - contentStart + 1, [\n ['enter', content, context],\n ['enter', text, context],\n ['exit', text, context],\n ['exit', content, context]\n ])\n }\n\n return events\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeHeadingAtx(effects, ok, nok) {\n let size = 0\n\n return start\n\n /**\n * Start of a heading (atx).\n *\n * ```markdown\n * > | ## aa\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n // To do: parse indent like `markdown-rs`.\n effects.enter(types.atxHeading)\n return before(code)\n }\n\n /**\n * After optional whitespace, at `#`.\n *\n * ```markdown\n * > | ## aa\n * ^\n * ```\n *\n * @type {State}\n */\n function before(code) {\n assert(code === codes.numberSign, 'expected `#`')\n effects.enter(types.atxHeadingSequence)\n return sequenceOpen(code)\n }\n\n /**\n * In opening sequence.\n *\n * ```markdown\n * > | ## aa\n * ^\n * ```\n *\n * @type {State}\n */\n function sequenceOpen(code) {\n if (\n code === codes.numberSign &&\n size++ < constants.atxHeadingOpeningFenceSizeMax\n ) {\n effects.consume(code)\n return sequenceOpen\n }\n\n // Always at least one `#`.\n if (code === codes.eof || markdownLineEndingOrSpace(code)) {\n effects.exit(types.atxHeadingSequence)\n return atBreak(code)\n }\n\n return nok(code)\n }\n\n /**\n * After something, before something else.\n *\n * ```markdown\n * > | ## aa\n * ^\n * ```\n *\n * @type {State}\n */\n function atBreak(code) {\n if (code === codes.numberSign) {\n effects.enter(types.atxHeadingSequence)\n return sequenceFurther(code)\n }\n\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.atxHeading)\n // To do: interrupt like `markdown-rs`.\n // // Feel free to interrupt.\n // tokenizer.interrupt = false\n return ok(code)\n }\n\n if (markdownSpace(code)) {\n return factorySpace(effects, atBreak, types.whitespace)(code)\n }\n\n // To do: generate `data` tokens, add the `text` token later.\n // Needs edit map, see: `markdown.rs`.\n effects.enter(types.atxHeadingText)\n return data(code)\n }\n\n /**\n * In further sequence (after whitespace).\n *\n * Could be normal “visible” hashes in the heading or a final sequence.\n *\n * ```markdown\n * > | ## aa ##\n * ^\n * ```\n *\n * @type {State}\n */\n function sequenceFurther(code) {\n if (code === codes.numberSign) {\n effects.consume(code)\n return sequenceFurther\n }\n\n effects.exit(types.atxHeadingSequence)\n return atBreak(code)\n }\n\n /**\n * In text.\n *\n * ```markdown\n * > | ## aa\n * ^\n * ```\n *\n * @type {State}\n */\n function data(code) {\n if (\n code === codes.eof ||\n code === codes.numberSign ||\n markdownLineEndingOrSpace(code)\n ) {\n effects.exit(types.atxHeadingText)\n return atBreak(code)\n }\n\n effects.consume(code)\n return data\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').Resolver} Resolver\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {\n asciiAlpha,\n asciiAlphanumeric,\n markdownLineEnding,\n markdownLineEndingOrSpace,\n markdownSpace\n} from 'micromark-util-character'\nimport {htmlBlockNames, htmlRawNames} from 'micromark-util-html-tag-name'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\nimport {blankLine} from './blank-line.js'\n\n/** @type {Construct} */\nexport const htmlFlow = {\n name: 'htmlFlow',\n tokenize: tokenizeHtmlFlow,\n resolveTo: resolveToHtmlFlow,\n concrete: true\n}\n\n/** @type {Construct} */\nconst blankLineBefore = {tokenize: tokenizeBlankLineBefore, partial: true}\nconst nonLazyContinuationStart = {\n tokenize: tokenizeNonLazyContinuationStart,\n partial: true\n}\n\n/** @type {Resolver} */\nfunction resolveToHtmlFlow(events) {\n let index = events.length\n\n while (index--) {\n if (\n events[index][0] === 'enter' &&\n events[index][1].type === types.htmlFlow\n ) {\n break\n }\n }\n\n if (index > 1 && events[index - 2][1].type === types.linePrefix) {\n // Add the prefix start to the HTML token.\n events[index][1].start = events[index - 2][1].start\n // Add the prefix start to the HTML line token.\n events[index + 1][1].start = events[index - 2][1].start\n // Remove the line prefix.\n events.splice(index - 2, 2)\n }\n\n return events\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeHtmlFlow(effects, ok, nok) {\n const self = this\n /** @type {number} */\n let marker\n /** @type {boolean} */\n let closingTag\n /** @type {string} */\n let buffer\n /** @type {number} */\n let index\n /** @type {Code} */\n let markerB\n\n return start\n\n /**\n * Start of HTML (flow).\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n // To do: parse indent like `markdown-rs`.\n return before(code)\n }\n\n /**\n * At `<`, after optional whitespace.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function before(code) {\n assert(code === codes.lessThan, 'expected `<`')\n effects.enter(types.htmlFlow)\n effects.enter(types.htmlFlowData)\n effects.consume(code)\n return open\n }\n\n /**\n * After `<`, at tag name or other stuff.\n *\n * ```markdown\n * > | \n * ^\n * > | \n * ^\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function open(code) {\n if (code === codes.exclamationMark) {\n effects.consume(code)\n return declarationOpen\n }\n\n if (code === codes.slash) {\n effects.consume(code)\n closingTag = true\n return tagCloseStart\n }\n\n if (code === codes.questionMark) {\n effects.consume(code)\n marker = constants.htmlInstruction\n // To do:\n // tokenizer.concrete = true\n // To do: use `markdown-rs` style interrupt.\n // While we’re in an instruction instead of a declaration, we’re on a `?`\n // right now, so we do need to search for `>`, similar to declarations.\n return self.interrupt ? ok : continuationDeclarationInside\n }\n\n // ASCII alphabetical.\n if (asciiAlpha(code)) {\n effects.consume(code)\n // @ts-expect-error: not null.\n buffer = String.fromCharCode(code)\n return tagName\n }\n\n return nok(code)\n }\n\n /**\n * After ` | \n * ^\n * > | \n * ^\n * > | &<]]>\n * ^\n * ```\n *\n * @type {State}\n */\n function declarationOpen(code) {\n if (code === codes.dash) {\n effects.consume(code)\n marker = constants.htmlComment\n return commentOpenInside\n }\n\n if (code === codes.leftSquareBracket) {\n effects.consume(code)\n marker = constants.htmlCdata\n index = 0\n return cdataOpenInside\n }\n\n // ASCII alphabetical.\n if (asciiAlpha(code)) {\n effects.consume(code)\n marker = constants.htmlDeclaration\n // // Do not form containers.\n // tokenizer.concrete = true\n return self.interrupt ? ok : continuationDeclarationInside\n }\n\n return nok(code)\n }\n\n /**\n * After ` | \n * ^\n * ```\n *\n * @type {State}\n */\n function commentOpenInside(code) {\n if (code === codes.dash) {\n effects.consume(code)\n // // Do not form containers.\n // tokenizer.concrete = true\n return self.interrupt ? ok : continuationDeclarationInside\n }\n\n return nok(code)\n }\n\n /**\n * After ` | &<]]>\n * ^^^^^^\n * ```\n *\n * @type {State}\n */\n function cdataOpenInside(code) {\n const value = constants.cdataOpeningString\n\n if (code === value.charCodeAt(index++)) {\n effects.consume(code)\n\n if (index === value.length) {\n // // Do not form containers.\n // tokenizer.concrete = true\n return self.interrupt ? ok : continuation\n }\n\n return cdataOpenInside\n }\n\n return nok(code)\n }\n\n /**\n * After ``, in closing tag, at tag name.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function tagCloseStart(code) {\n if (asciiAlpha(code)) {\n effects.consume(code)\n // @ts-expect-error: not null.\n buffer = String.fromCharCode(code)\n return tagName\n }\n\n return nok(code)\n }\n\n /**\n * In tag name.\n *\n * ```markdown\n * > | \n * ^^\n * > | \n * ^^\n * ```\n *\n * @type {State}\n */\n function tagName(code) {\n if (\n code === codes.eof ||\n code === codes.slash ||\n code === codes.greaterThan ||\n markdownLineEndingOrSpace(code)\n ) {\n const slash = code === codes.slash\n const name = buffer.toLowerCase()\n\n if (!slash && !closingTag && htmlRawNames.includes(name)) {\n marker = constants.htmlRaw\n // // Do not form containers.\n // tokenizer.concrete = true\n return self.interrupt ? ok(code) : continuation(code)\n }\n\n if (htmlBlockNames.includes(buffer.toLowerCase())) {\n marker = constants.htmlBasic\n\n if (slash) {\n effects.consume(code)\n return basicSelfClosing\n }\n\n // // Do not form containers.\n // tokenizer.concrete = true\n return self.interrupt ? ok(code) : continuation(code)\n }\n\n marker = constants.htmlComplete\n // Do not support complete HTML when interrupting.\n return self.interrupt && !self.parser.lazy[self.now().line]\n ? nok(code)\n : closingTag\n ? completeClosingTagAfter(code)\n : completeAttributeNameBefore(code)\n }\n\n // ASCII alphanumerical and `-`.\n if (code === codes.dash || asciiAlphanumeric(code)) {\n effects.consume(code)\n buffer += String.fromCharCode(code)\n return tagName\n }\n\n return nok(code)\n }\n\n /**\n * After closing slash of a basic tag name.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function basicSelfClosing(code) {\n if (code === codes.greaterThan) {\n effects.consume(code)\n // // Do not form containers.\n // tokenizer.concrete = true\n return self.interrupt ? ok : continuation\n }\n\n return nok(code)\n }\n\n /**\n * After closing slash of a complete tag name.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeClosingTagAfter(code) {\n if (markdownSpace(code)) {\n effects.consume(code)\n return completeClosingTagAfter\n }\n\n return completeEnd(code)\n }\n\n /**\n * At an attribute name.\n *\n * At first, this state is used after a complete tag name, after whitespace,\n * where it expects optional attributes or the end of the tag.\n * It is also reused after attributes, when expecting more optional\n * attributes.\n *\n * ```markdown\n * > | \n * ^\n * > | \n * ^\n * > | \n * ^\n * > | \n * ^\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeAttributeNameBefore(code) {\n if (code === codes.slash) {\n effects.consume(code)\n return completeEnd\n }\n\n // ASCII alphanumerical and `:` and `_`.\n if (code === codes.colon || code === codes.underscore || asciiAlpha(code)) {\n effects.consume(code)\n return completeAttributeName\n }\n\n if (markdownSpace(code)) {\n effects.consume(code)\n return completeAttributeNameBefore\n }\n\n return completeEnd(code)\n }\n\n /**\n * In attribute name.\n *\n * ```markdown\n * > | \n * ^\n * > | \n * ^\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeAttributeName(code) {\n // ASCII alphanumerical and `-`, `.`, `:`, and `_`.\n if (\n code === codes.dash ||\n code === codes.dot ||\n code === codes.colon ||\n code === codes.underscore ||\n asciiAlphanumeric(code)\n ) {\n effects.consume(code)\n return completeAttributeName\n }\n\n return completeAttributeNameAfter(code)\n }\n\n /**\n * After attribute name, at an optional initializer, the end of the tag, or\n * whitespace.\n *\n * ```markdown\n * > | \n * ^\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeAttributeNameAfter(code) {\n if (code === codes.equalsTo) {\n effects.consume(code)\n return completeAttributeValueBefore\n }\n\n if (markdownSpace(code)) {\n effects.consume(code)\n return completeAttributeNameAfter\n }\n\n return completeAttributeNameBefore(code)\n }\n\n /**\n * Before unquoted, double quoted, or single quoted attribute value, allowing\n * whitespace.\n *\n * ```markdown\n * > | \n * ^\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeAttributeValueBefore(code) {\n if (\n code === codes.eof ||\n code === codes.lessThan ||\n code === codes.equalsTo ||\n code === codes.greaterThan ||\n code === codes.graveAccent\n ) {\n return nok(code)\n }\n\n if (code === codes.quotationMark || code === codes.apostrophe) {\n effects.consume(code)\n markerB = code\n return completeAttributeValueQuoted\n }\n\n if (markdownSpace(code)) {\n effects.consume(code)\n return completeAttributeValueBefore\n }\n\n return completeAttributeValueUnquoted(code)\n }\n\n /**\n * In double or single quoted attribute value.\n *\n * ```markdown\n * > | \n * ^\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeAttributeValueQuoted(code) {\n if (code === markerB) {\n effects.consume(code)\n markerB = null\n return completeAttributeValueQuotedAfter\n }\n\n if (code === codes.eof || markdownLineEnding(code)) {\n return nok(code)\n }\n\n effects.consume(code)\n return completeAttributeValueQuoted\n }\n\n /**\n * In unquoted attribute value.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeAttributeValueUnquoted(code) {\n if (\n code === codes.eof ||\n code === codes.quotationMark ||\n code === codes.apostrophe ||\n code === codes.slash ||\n code === codes.lessThan ||\n code === codes.equalsTo ||\n code === codes.greaterThan ||\n code === codes.graveAccent ||\n markdownLineEndingOrSpace(code)\n ) {\n return completeAttributeNameAfter(code)\n }\n\n effects.consume(code)\n return completeAttributeValueUnquoted\n }\n\n /**\n * After double or single quoted attribute value, before whitespace or the\n * end of the tag.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeAttributeValueQuotedAfter(code) {\n if (\n code === codes.slash ||\n code === codes.greaterThan ||\n markdownSpace(code)\n ) {\n return completeAttributeNameBefore(code)\n }\n\n return nok(code)\n }\n\n /**\n * In certain circumstances of a complete tag where only an `>` is allowed.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeEnd(code) {\n if (code === codes.greaterThan) {\n effects.consume(code)\n return completeAfter\n }\n\n return nok(code)\n }\n\n /**\n * After `>` in a complete tag.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function completeAfter(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n // // Do not form containers.\n // tokenizer.concrete = true\n return continuation(code)\n }\n\n if (markdownSpace(code)) {\n effects.consume(code)\n return completeAfter\n }\n\n return nok(code)\n }\n\n /**\n * In continuation of any HTML kind.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function continuation(code) {\n if (code === codes.dash && marker === constants.htmlComment) {\n effects.consume(code)\n return continuationCommentInside\n }\n\n if (code === codes.lessThan && marker === constants.htmlRaw) {\n effects.consume(code)\n return continuationRawTagOpen\n }\n\n if (code === codes.greaterThan && marker === constants.htmlDeclaration) {\n effects.consume(code)\n return continuationClose\n }\n\n if (code === codes.questionMark && marker === constants.htmlInstruction) {\n effects.consume(code)\n return continuationDeclarationInside\n }\n\n if (code === codes.rightSquareBracket && marker === constants.htmlCdata) {\n effects.consume(code)\n return continuationCdataInside\n }\n\n if (\n markdownLineEnding(code) &&\n (marker === constants.htmlBasic || marker === constants.htmlComplete)\n ) {\n effects.exit(types.htmlFlowData)\n return effects.check(\n blankLineBefore,\n continuationAfter,\n continuationStart\n )(code)\n }\n\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.htmlFlowData)\n return continuationStart(code)\n }\n\n effects.consume(code)\n return continuation\n }\n\n /**\n * In continuation, at eol.\n *\n * ```markdown\n * > | \n * ^\n * | asd\n * ```\n *\n * @type {State}\n */\n function continuationStart(code) {\n return effects.check(\n nonLazyContinuationStart,\n continuationStartNonLazy,\n continuationAfter\n )(code)\n }\n\n /**\n * In continuation, at eol, before non-lazy content.\n *\n * ```markdown\n * > | \n * ^\n * | asd\n * ```\n *\n * @type {State}\n */\n function continuationStartNonLazy(code) {\n assert(markdownLineEnding(code))\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return continuationBefore\n }\n\n /**\n * In continuation, before non-lazy content.\n *\n * ```markdown\n * | \n * > | asd\n * ^\n * ```\n *\n * @type {State}\n */\n function continuationBefore(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n return continuationStart(code)\n }\n\n effects.enter(types.htmlFlowData)\n return continuation(code)\n }\n\n /**\n * In comment continuation, after one `-`, expecting another.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function continuationCommentInside(code) {\n if (code === codes.dash) {\n effects.consume(code)\n return continuationDeclarationInside\n }\n\n return continuation(code)\n }\n\n /**\n * In raw continuation, after `<`, at `/`.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function continuationRawTagOpen(code) {\n if (code === codes.slash) {\n effects.consume(code)\n buffer = ''\n return continuationRawEndTag\n }\n\n return continuation(code)\n }\n\n /**\n * In raw continuation, after ``, in a raw tag name.\n *\n * ```markdown\n * > | \n * ^^^^^^\n * ```\n *\n * @type {State}\n */\n function continuationRawEndTag(code) {\n if (code === codes.greaterThan) {\n const name = buffer.toLowerCase()\n\n if (htmlRawNames.includes(name)) {\n effects.consume(code)\n return continuationClose\n }\n\n return continuation(code)\n }\n\n if (asciiAlpha(code) && buffer.length < constants.htmlRawSizeMax) {\n effects.consume(code)\n // @ts-expect-error: not null.\n buffer += String.fromCharCode(code)\n return continuationRawEndTag\n }\n\n return continuation(code)\n }\n\n /**\n * In cdata continuation, after `]`, expecting `]>`.\n *\n * ```markdown\n * > | &<]]>\n * ^\n * ```\n *\n * @type {State}\n */\n function continuationCdataInside(code) {\n if (code === codes.rightSquareBracket) {\n effects.consume(code)\n return continuationDeclarationInside\n }\n\n return continuation(code)\n }\n\n /**\n * In declaration or instruction continuation, at `>`.\n *\n * ```markdown\n * > | \n * ^\n * > | >\n * ^\n * > | \n * ^\n * > | \n * ^\n * > | &<]]>\n * ^\n * ```\n *\n * @type {State}\n */\n function continuationDeclarationInside(code) {\n if (code === codes.greaterThan) {\n effects.consume(code)\n return continuationClose\n }\n\n // More dashes.\n if (code === codes.dash && marker === constants.htmlComment) {\n effects.consume(code)\n return continuationDeclarationInside\n }\n\n return continuation(code)\n }\n\n /**\n * In closed continuation: everything we get until the eol/eof is part of it.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function continuationClose(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.htmlFlowData)\n return continuationAfter(code)\n }\n\n effects.consume(code)\n return continuationClose\n }\n\n /**\n * Done.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function continuationAfter(code) {\n effects.exit(types.htmlFlow)\n // // Feel free to interrupt.\n // tokenizer.interrupt = false\n // // No longer concrete.\n // tokenizer.concrete = false\n return ok(code)\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeNonLazyContinuationStart(effects, ok, nok) {\n const self = this\n\n return start\n\n /**\n * At eol, before continuation.\n *\n * ```markdown\n * > | * ```js\n * ^\n * | b\n * ```\n *\n * @type {State}\n */\n function start(code) {\n if (markdownLineEnding(code)) {\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return after\n }\n\n return nok(code)\n }\n\n /**\n * A continuation.\n *\n * ```markdown\n * | * ```js\n * > | b\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n return self.parser.lazy[self.now().line] ? nok(code) : ok(code)\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeBlankLineBefore(effects, ok, nok) {\n return start\n\n /**\n * Before eol, expecting blank line.\n *\n * ```markdown\n * > | \n * ^\n * |\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(markdownLineEnding(code), 'expected a line ending')\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return effects.attempt(blankLine, ok, nok)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {\n asciiAlpha,\n asciiAlphanumeric,\n markdownLineEnding,\n markdownLineEndingOrSpace,\n markdownSpace\n} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const htmlText = {name: 'htmlText', tokenize: tokenizeHtmlText}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeHtmlText(effects, ok, nok) {\n const self = this\n /** @type {NonNullable | undefined} */\n let marker\n /** @type {number} */\n let index\n /** @type {State} */\n let returnState\n\n return start\n\n /**\n * Start of HTML (text).\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.lessThan, 'expected `<`')\n effects.enter(types.htmlText)\n effects.enter(types.htmlTextData)\n effects.consume(code)\n return open\n }\n\n /**\n * After `<`, at tag name or other stuff.\n *\n * ```markdown\n * > | a c\n * ^\n * > | a c\n * ^\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function open(code) {\n if (code === codes.exclamationMark) {\n effects.consume(code)\n return declarationOpen\n }\n\n if (code === codes.slash) {\n effects.consume(code)\n return tagCloseStart\n }\n\n if (code === codes.questionMark) {\n effects.consume(code)\n return instruction\n }\n\n // ASCII alphabetical.\n if (asciiAlpha(code)) {\n effects.consume(code)\n return tagOpen\n }\n\n return nok(code)\n }\n\n /**\n * After ` | a c\n * ^\n * > | a c\n * ^\n * > | a &<]]> c\n * ^\n * ```\n *\n * @type {State}\n */\n function declarationOpen(code) {\n if (code === codes.dash) {\n effects.consume(code)\n return commentOpenInside\n }\n\n if (code === codes.leftSquareBracket) {\n effects.consume(code)\n index = 0\n return cdataOpenInside\n }\n\n if (asciiAlpha(code)) {\n effects.consume(code)\n return declaration\n }\n\n return nok(code)\n }\n\n /**\n * In a comment, after ` | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function commentOpenInside(code) {\n if (code === codes.dash) {\n effects.consume(code)\n return commentEnd\n }\n\n return nok(code)\n }\n\n /**\n * In comment.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function comment(code) {\n if (code === codes.eof) {\n return nok(code)\n }\n\n if (code === codes.dash) {\n effects.consume(code)\n return commentClose\n }\n\n if (markdownLineEnding(code)) {\n returnState = comment\n return lineEndingBefore(code)\n }\n\n effects.consume(code)\n return comment\n }\n\n /**\n * In comment, after `-`.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function commentClose(code) {\n if (code === codes.dash) {\n effects.consume(code)\n return commentEnd\n }\n\n return comment(code)\n }\n\n /**\n * In comment, after `--`.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function commentEnd(code) {\n return code === codes.greaterThan\n ? end(code)\n : code === codes.dash\n ? commentClose(code)\n : comment(code)\n }\n\n /**\n * After ` | a &<]]> b\n * ^^^^^^\n * ```\n *\n * @type {State}\n */\n function cdataOpenInside(code) {\n const value = constants.cdataOpeningString\n\n if (code === value.charCodeAt(index++)) {\n effects.consume(code)\n return index === value.length ? cdata : cdataOpenInside\n }\n\n return nok(code)\n }\n\n /**\n * In CDATA.\n *\n * ```markdown\n * > | a &<]]> b\n * ^^^\n * ```\n *\n * @type {State}\n */\n function cdata(code) {\n if (code === codes.eof) {\n return nok(code)\n }\n\n if (code === codes.rightSquareBracket) {\n effects.consume(code)\n return cdataClose\n }\n\n if (markdownLineEnding(code)) {\n returnState = cdata\n return lineEndingBefore(code)\n }\n\n effects.consume(code)\n return cdata\n }\n\n /**\n * In CDATA, after `]`, at another `]`.\n *\n * ```markdown\n * > | a &<]]> b\n * ^\n * ```\n *\n * @type {State}\n */\n function cdataClose(code) {\n if (code === codes.rightSquareBracket) {\n effects.consume(code)\n return cdataEnd\n }\n\n return cdata(code)\n }\n\n /**\n * In CDATA, after `]]`, at `>`.\n *\n * ```markdown\n * > | a &<]]> b\n * ^\n * ```\n *\n * @type {State}\n */\n function cdataEnd(code) {\n if (code === codes.greaterThan) {\n return end(code)\n }\n\n if (code === codes.rightSquareBracket) {\n effects.consume(code)\n return cdataEnd\n }\n\n return cdata(code)\n }\n\n /**\n * In declaration.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function declaration(code) {\n if (code === codes.eof || code === codes.greaterThan) {\n return end(code)\n }\n\n if (markdownLineEnding(code)) {\n returnState = declaration\n return lineEndingBefore(code)\n }\n\n effects.consume(code)\n return declaration\n }\n\n /**\n * In instruction.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function instruction(code) {\n if (code === codes.eof) {\n return nok(code)\n }\n\n if (code === codes.questionMark) {\n effects.consume(code)\n return instructionClose\n }\n\n if (markdownLineEnding(code)) {\n returnState = instruction\n return lineEndingBefore(code)\n }\n\n effects.consume(code)\n return instruction\n }\n\n /**\n * In instruction, after `?`, at `>`.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function instructionClose(code) {\n return code === codes.greaterThan ? end(code) : instruction(code)\n }\n\n /**\n * After ``, in closing tag, at tag name.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function tagCloseStart(code) {\n // ASCII alphabetical.\n if (asciiAlpha(code)) {\n effects.consume(code)\n return tagClose\n }\n\n return nok(code)\n }\n\n /**\n * After ` | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function tagClose(code) {\n // ASCII alphanumerical and `-`.\n if (code === codes.dash || asciiAlphanumeric(code)) {\n effects.consume(code)\n return tagClose\n }\n\n return tagCloseBetween(code)\n }\n\n /**\n * In closing tag, after tag name.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function tagCloseBetween(code) {\n if (markdownLineEnding(code)) {\n returnState = tagCloseBetween\n return lineEndingBefore(code)\n }\n\n if (markdownSpace(code)) {\n effects.consume(code)\n return tagCloseBetween\n }\n\n return end(code)\n }\n\n /**\n * After ` | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function tagOpen(code) {\n // ASCII alphanumerical and `-`.\n if (code === codes.dash || asciiAlphanumeric(code)) {\n effects.consume(code)\n return tagOpen\n }\n\n if (\n code === codes.slash ||\n code === codes.greaterThan ||\n markdownLineEndingOrSpace(code)\n ) {\n return tagOpenBetween(code)\n }\n\n return nok(code)\n }\n\n /**\n * In opening tag, after tag name.\n *\n * ```markdown\n * > | a c\n * ^\n * ```\n *\n * @type {State}\n */\n function tagOpenBetween(code) {\n if (code === codes.slash) {\n effects.consume(code)\n return end\n }\n\n // ASCII alphabetical and `:` and `_`.\n if (code === codes.colon || code === codes.underscore || asciiAlpha(code)) {\n effects.consume(code)\n return tagOpenAttributeName\n }\n\n if (markdownLineEnding(code)) {\n returnState = tagOpenBetween\n return lineEndingBefore(code)\n }\n\n if (markdownSpace(code)) {\n effects.consume(code)\n return tagOpenBetween\n }\n\n return end(code)\n }\n\n /**\n * In attribute name.\n *\n * ```markdown\n * > | a d\n * ^\n * ```\n *\n * @type {State}\n */\n function tagOpenAttributeName(code) {\n // ASCII alphabetical and `-`, `.`, `:`, and `_`.\n if (\n code === codes.dash ||\n code === codes.dot ||\n code === codes.colon ||\n code === codes.underscore ||\n asciiAlphanumeric(code)\n ) {\n effects.consume(code)\n return tagOpenAttributeName\n }\n\n return tagOpenAttributeNameAfter(code)\n }\n\n /**\n * After attribute name, before initializer, the end of the tag, or\n * whitespace.\n *\n * ```markdown\n * > | a d\n * ^\n * ```\n *\n * @type {State}\n */\n function tagOpenAttributeNameAfter(code) {\n if (code === codes.equalsTo) {\n effects.consume(code)\n return tagOpenAttributeValueBefore\n }\n\n if (markdownLineEnding(code)) {\n returnState = tagOpenAttributeNameAfter\n return lineEndingBefore(code)\n }\n\n if (markdownSpace(code)) {\n effects.consume(code)\n return tagOpenAttributeNameAfter\n }\n\n return tagOpenBetween(code)\n }\n\n /**\n * Before unquoted, double quoted, or single quoted attribute value, allowing\n * whitespace.\n *\n * ```markdown\n * > | a e\n * ^\n * ```\n *\n * @type {State}\n */\n function tagOpenAttributeValueBefore(code) {\n if (\n code === codes.eof ||\n code === codes.lessThan ||\n code === codes.equalsTo ||\n code === codes.greaterThan ||\n code === codes.graveAccent\n ) {\n return nok(code)\n }\n\n if (code === codes.quotationMark || code === codes.apostrophe) {\n effects.consume(code)\n marker = code\n return tagOpenAttributeValueQuoted\n }\n\n if (markdownLineEnding(code)) {\n returnState = tagOpenAttributeValueBefore\n return lineEndingBefore(code)\n }\n\n if (markdownSpace(code)) {\n effects.consume(code)\n return tagOpenAttributeValueBefore\n }\n\n effects.consume(code)\n return tagOpenAttributeValueUnquoted\n }\n\n /**\n * In double or single quoted attribute value.\n *\n * ```markdown\n * > | a e\n * ^\n * ```\n *\n * @type {State}\n */\n function tagOpenAttributeValueQuoted(code) {\n if (code === marker) {\n effects.consume(code)\n marker = undefined\n return tagOpenAttributeValueQuotedAfter\n }\n\n if (code === codes.eof) {\n return nok(code)\n }\n\n if (markdownLineEnding(code)) {\n returnState = tagOpenAttributeValueQuoted\n return lineEndingBefore(code)\n }\n\n effects.consume(code)\n return tagOpenAttributeValueQuoted\n }\n\n /**\n * In unquoted attribute value.\n *\n * ```markdown\n * > | a e\n * ^\n * ```\n *\n * @type {State}\n */\n function tagOpenAttributeValueUnquoted(code) {\n if (\n code === codes.eof ||\n code === codes.quotationMark ||\n code === codes.apostrophe ||\n code === codes.lessThan ||\n code === codes.equalsTo ||\n code === codes.graveAccent\n ) {\n return nok(code)\n }\n\n if (\n code === codes.slash ||\n code === codes.greaterThan ||\n markdownLineEndingOrSpace(code)\n ) {\n return tagOpenBetween(code)\n }\n\n effects.consume(code)\n return tagOpenAttributeValueUnquoted\n }\n\n /**\n * After double or single quoted attribute value, before whitespace or the end\n * of the tag.\n *\n * ```markdown\n * > | a e\n * ^\n * ```\n *\n * @type {State}\n */\n function tagOpenAttributeValueQuotedAfter(code) {\n if (\n code === codes.slash ||\n code === codes.greaterThan ||\n markdownLineEndingOrSpace(code)\n ) {\n return tagOpenBetween(code)\n }\n\n return nok(code)\n }\n\n /**\n * In certain circumstances of a tag where only an `>` is allowed.\n *\n * ```markdown\n * > | a e\n * ^\n * ```\n *\n * @type {State}\n */\n function end(code) {\n if (code === codes.greaterThan) {\n effects.consume(code)\n effects.exit(types.htmlTextData)\n effects.exit(types.htmlText)\n return ok\n }\n\n return nok(code)\n }\n\n /**\n * At eol.\n *\n * > 👉 **Note**: we can’t have blank lines in text, so no need to worry about\n * > empty tokens.\n *\n * ```markdown\n * > | a \n * ```\n *\n * @type {State}\n */\n function lineEndingBefore(code) {\n assert(returnState, 'expected return state')\n assert(markdownLineEnding(code), 'expected eol')\n effects.exit(types.htmlTextData)\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return lineEndingAfter\n }\n\n /**\n * After eol, at optional whitespace.\n *\n * > 👉 **Note**: we can’t have blank lines in text, so no need to worry about\n * > empty tokens.\n *\n * ```markdown\n * | a \n * ^\n * ```\n *\n * @type {State}\n */\n function lineEndingAfter(code) {\n // Always populated by defaults.\n assert(\n self.parser.constructs.disable.null,\n 'expected `disable.null` to be populated'\n )\n return markdownSpace(code)\n ? factorySpace(\n effects,\n lineEndingAfterPrefix,\n types.linePrefix,\n self.parser.constructs.disable.null.includes('codeIndented')\n ? undefined\n : constants.tabSize\n )(code)\n : lineEndingAfterPrefix(code)\n }\n\n /**\n * After eol, after optional whitespace.\n *\n * > 👉 **Note**: we can’t have blank lines in text, so no need to worry about\n * > empty tokens.\n *\n * ```markdown\n * | a \n * ^\n * ```\n *\n * @type {State}\n */\n function lineEndingAfterPrefix(code) {\n effects.enter(types.htmlTextData)\n return returnState(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').Event} Event\n * @typedef {import('micromark-util-types').Resolver} Resolver\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').Token} Token\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factoryDestination} from 'micromark-factory-destination'\nimport {factoryLabel} from 'micromark-factory-label'\nimport {factoryTitle} from 'micromark-factory-title'\nimport {factoryWhitespace} from 'micromark-factory-whitespace'\nimport {markdownLineEndingOrSpace} from 'micromark-util-character'\nimport {push, splice} from 'micromark-util-chunked'\nimport {normalizeIdentifier} from 'micromark-util-normalize-identifier'\nimport {resolveAll} from 'micromark-util-resolve-all'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const labelEnd = {\n name: 'labelEnd',\n tokenize: tokenizeLabelEnd,\n resolveTo: resolveToLabelEnd,\n resolveAll: resolveAllLabelEnd\n}\n\n/** @type {Construct} */\nconst resourceConstruct = {tokenize: tokenizeResource}\n/** @type {Construct} */\nconst referenceFullConstruct = {tokenize: tokenizeReferenceFull}\n/** @type {Construct} */\nconst referenceCollapsedConstruct = {tokenize: tokenizeReferenceCollapsed}\n\n/** @type {Resolver} */\nfunction resolveAllLabelEnd(events) {\n let index = -1\n\n while (++index < events.length) {\n const token = events[index][1]\n\n if (\n token.type === types.labelImage ||\n token.type === types.labelLink ||\n token.type === types.labelEnd\n ) {\n // Remove the marker.\n events.splice(index + 1, token.type === types.labelImage ? 4 : 2)\n token.type = types.data\n index++\n }\n }\n\n return events\n}\n\n/** @type {Resolver} */\nfunction resolveToLabelEnd(events, context) {\n let index = events.length\n let offset = 0\n /** @type {Token} */\n let token\n /** @type {number | undefined} */\n let open\n /** @type {number | undefined} */\n let close\n /** @type {Array} */\n let media\n\n // Find an opening.\n while (index--) {\n token = events[index][1]\n\n if (open) {\n // If we see another link, or inactive link label, we’ve been here before.\n if (\n token.type === types.link ||\n (token.type === types.labelLink && token._inactive)\n ) {\n break\n }\n\n // Mark other link openings as inactive, as we can’t have links in\n // links.\n if (events[index][0] === 'enter' && token.type === types.labelLink) {\n token._inactive = true\n }\n } else if (close) {\n if (\n events[index][0] === 'enter' &&\n (token.type === types.labelImage || token.type === types.labelLink) &&\n !token._balanced\n ) {\n open = index\n\n if (token.type !== types.labelLink) {\n offset = 2\n break\n }\n }\n } else if (token.type === types.labelEnd) {\n close = index\n }\n }\n\n assert(open !== undefined, '`open` is supposed to be found')\n assert(close !== undefined, '`close` is supposed to be found')\n\n const group = {\n type: events[open][1].type === types.labelLink ? types.link : types.image,\n start: Object.assign({}, events[open][1].start),\n end: Object.assign({}, events[events.length - 1][1].end)\n }\n\n const label = {\n type: types.label,\n start: Object.assign({}, events[open][1].start),\n end: Object.assign({}, events[close][1].end)\n }\n\n const text = {\n type: types.labelText,\n start: Object.assign({}, events[open + offset + 2][1].end),\n end: Object.assign({}, events[close - 2][1].start)\n }\n\n media = [\n ['enter', group, context],\n ['enter', label, context]\n ]\n\n // Opening marker.\n media = push(media, events.slice(open + 1, open + offset + 3))\n\n // Text open.\n media = push(media, [['enter', text, context]])\n\n // Always populated by defaults.\n assert(\n context.parser.constructs.insideSpan.null,\n 'expected `insideSpan.null` to be populated'\n )\n // Between.\n media = push(\n media,\n resolveAll(\n context.parser.constructs.insideSpan.null,\n events.slice(open + offset + 4, close - 3),\n context\n )\n )\n\n // Text close, marker close, label close.\n media = push(media, [\n ['exit', text, context],\n events[close - 2],\n events[close - 1],\n ['exit', label, context]\n ])\n\n // Reference, resource, or so.\n media = push(media, events.slice(close + 1))\n\n // Media close.\n media = push(media, [['exit', group, context]])\n\n splice(events, open, events.length, media)\n\n return events\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeLabelEnd(effects, ok, nok) {\n const self = this\n let index = self.events.length\n /** @type {Token} */\n let labelStart\n /** @type {boolean} */\n let defined\n\n // Find an opening.\n while (index--) {\n if (\n (self.events[index][1].type === types.labelImage ||\n self.events[index][1].type === types.labelLink) &&\n !self.events[index][1]._balanced\n ) {\n labelStart = self.events[index][1]\n break\n }\n }\n\n return start\n\n /**\n * Start of label end.\n *\n * ```markdown\n * > | [a](b) c\n * ^\n * > | [a][b] c\n * ^\n * > | [a][] b\n * ^\n * > | [a] b\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.rightSquareBracket, 'expected `]`')\n\n // If there is not an okay opening.\n if (!labelStart) {\n return nok(code)\n }\n\n // If the corresponding label (link) start is marked as inactive,\n // it means we’d be wrapping a link, like this:\n //\n // ```markdown\n // > | a [b [c](d) e](f) g.\n // ^\n // ```\n //\n // We can’t have that, so it’s just balanced brackets.\n if (labelStart._inactive) {\n return labelEndNok(code)\n }\n\n defined = self.parser.defined.includes(\n normalizeIdentifier(\n self.sliceSerialize({start: labelStart.end, end: self.now()})\n )\n )\n effects.enter(types.labelEnd)\n effects.enter(types.labelMarker)\n effects.consume(code)\n effects.exit(types.labelMarker)\n effects.exit(types.labelEnd)\n return after\n }\n\n /**\n * After `]`.\n *\n * ```markdown\n * > | [a](b) c\n * ^\n * > | [a][b] c\n * ^\n * > | [a][] b\n * ^\n * > | [a] b\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n // Note: `markdown-rs` also parses GFM footnotes here, which for us is in\n // an extension.\n\n // Resource (`[asd](fgh)`)?\n if (code === codes.leftParenthesis) {\n return effects.attempt(\n resourceConstruct,\n labelEndOk,\n defined ? labelEndOk : labelEndNok\n )(code)\n }\n\n // Full (`[asd][fgh]`) or collapsed (`[asd][]`) reference?\n if (code === codes.leftSquareBracket) {\n return effects.attempt(\n referenceFullConstruct,\n labelEndOk,\n defined ? referenceNotFull : labelEndNok\n )(code)\n }\n\n // Shortcut (`[asd]`) reference?\n return defined ? labelEndOk(code) : labelEndNok(code)\n }\n\n /**\n * After `]`, at `[`, but not at a full reference.\n *\n * > 👉 **Note**: we only get here if the label is defined.\n *\n * ```markdown\n * > | [a][] b\n * ^\n * > | [a] b\n * ^\n * ```\n *\n * @type {State}\n */\n function referenceNotFull(code) {\n return effects.attempt(\n referenceCollapsedConstruct,\n labelEndOk,\n labelEndNok\n )(code)\n }\n\n /**\n * Done, we found something.\n *\n * ```markdown\n * > | [a](b) c\n * ^\n * > | [a][b] c\n * ^\n * > | [a][] b\n * ^\n * > | [a] b\n * ^\n * ```\n *\n * @type {State}\n */\n function labelEndOk(code) {\n // Note: `markdown-rs` does a bunch of stuff here.\n return ok(code)\n }\n\n /**\n * Done, it’s nothing.\n *\n * There was an okay opening, but we didn’t match anything.\n *\n * ```markdown\n * > | [a](b c\n * ^\n * > | [a][b c\n * ^\n * > | [a] b\n * ^\n * ```\n *\n * @type {State}\n */\n function labelEndNok(code) {\n labelStart._balanced = true\n return nok(code)\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeResource(effects, ok, nok) {\n return resourceStart\n\n /**\n * At a resource.\n *\n * ```markdown\n * > | [a](b) c\n * ^\n * ```\n *\n * @type {State}\n */\n function resourceStart(code) {\n assert(code === codes.leftParenthesis, 'expected left paren')\n effects.enter(types.resource)\n effects.enter(types.resourceMarker)\n effects.consume(code)\n effects.exit(types.resourceMarker)\n return resourceBefore\n }\n\n /**\n * In resource, after `(`, at optional whitespace.\n *\n * ```markdown\n * > | [a](b) c\n * ^\n * ```\n *\n * @type {State}\n */\n function resourceBefore(code) {\n return markdownLineEndingOrSpace(code)\n ? factoryWhitespace(effects, resourceOpen)(code)\n : resourceOpen(code)\n }\n\n /**\n * In resource, after optional whitespace, at `)` or a destination.\n *\n * ```markdown\n * > | [a](b) c\n * ^\n * ```\n *\n * @type {State}\n */\n function resourceOpen(code) {\n if (code === codes.rightParenthesis) {\n return resourceEnd(code)\n }\n\n return factoryDestination(\n effects,\n resourceDestinationAfter,\n resourceDestinationMissing,\n types.resourceDestination,\n types.resourceDestinationLiteral,\n types.resourceDestinationLiteralMarker,\n types.resourceDestinationRaw,\n types.resourceDestinationString,\n constants.linkResourceDestinationBalanceMax\n )(code)\n }\n\n /**\n * In resource, after destination, at optional whitespace.\n *\n * ```markdown\n * > | [a](b) c\n * ^\n * ```\n *\n * @type {State}\n */\n function resourceDestinationAfter(code) {\n return markdownLineEndingOrSpace(code)\n ? factoryWhitespace(effects, resourceBetween)(code)\n : resourceEnd(code)\n }\n\n /**\n * At invalid destination.\n *\n * ```markdown\n * > | [a](<<) b\n * ^\n * ```\n *\n * @type {State}\n */\n function resourceDestinationMissing(code) {\n return nok(code)\n }\n\n /**\n * In resource, after destination and whitespace, at `(` or title.\n *\n * ```markdown\n * > | [a](b ) c\n * ^\n * ```\n *\n * @type {State}\n */\n function resourceBetween(code) {\n if (\n code === codes.quotationMark ||\n code === codes.apostrophe ||\n code === codes.leftParenthesis\n ) {\n return factoryTitle(\n effects,\n resourceTitleAfter,\n nok,\n types.resourceTitle,\n types.resourceTitleMarker,\n types.resourceTitleString\n )(code)\n }\n\n return resourceEnd(code)\n }\n\n /**\n * In resource, after title, at optional whitespace.\n *\n * ```markdown\n * > | [a](b \"c\") d\n * ^\n * ```\n *\n * @type {State}\n */\n function resourceTitleAfter(code) {\n return markdownLineEndingOrSpace(code)\n ? factoryWhitespace(effects, resourceEnd)(code)\n : resourceEnd(code)\n }\n\n /**\n * In resource, at `)`.\n *\n * ```markdown\n * > | [a](b) d\n * ^\n * ```\n *\n * @type {State}\n */\n function resourceEnd(code) {\n if (code === codes.rightParenthesis) {\n effects.enter(types.resourceMarker)\n effects.consume(code)\n effects.exit(types.resourceMarker)\n effects.exit(types.resource)\n return ok\n }\n\n return nok(code)\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeReferenceFull(effects, ok, nok) {\n const self = this\n\n return referenceFull\n\n /**\n * In a reference (full), at the `[`.\n *\n * ```markdown\n * > | [a][b] d\n * ^\n * ```\n *\n * @type {State}\n */\n function referenceFull(code) {\n assert(code === codes.leftSquareBracket, 'expected left bracket')\n return factoryLabel.call(\n self,\n effects,\n referenceFullAfter,\n referenceFullMissing,\n types.reference,\n types.referenceMarker,\n types.referenceString\n )(code)\n }\n\n /**\n * In a reference (full), after `]`.\n *\n * ```markdown\n * > | [a][b] d\n * ^\n * ```\n *\n * @type {State}\n */\n function referenceFullAfter(code) {\n return self.parser.defined.includes(\n normalizeIdentifier(\n self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1)\n )\n )\n ? ok(code)\n : nok(code)\n }\n\n /**\n * In reference (full) that was missing.\n *\n * ```markdown\n * > | [a][b d\n * ^\n * ```\n *\n * @type {State}\n */\n function referenceFullMissing(code) {\n return nok(code)\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeReferenceCollapsed(effects, ok, nok) {\n return referenceCollapsedStart\n\n /**\n * In reference (collapsed), at `[`.\n *\n * > 👉 **Note**: we only get here if the label is defined.\n *\n * ```markdown\n * > | [a][] d\n * ^\n * ```\n *\n * @type {State}\n */\n function referenceCollapsedStart(code) {\n // We only attempt a collapsed label if there’s a `[`.\n assert(code === codes.leftSquareBracket, 'expected left bracket')\n effects.enter(types.reference)\n effects.enter(types.referenceMarker)\n effects.consume(code)\n effects.exit(types.referenceMarker)\n return referenceCollapsedOpen\n }\n\n /**\n * In reference (collapsed), at `]`.\n *\n * > 👉 **Note**: we only get here if the label is defined.\n *\n * ```markdown\n * > | [a][] d\n * ^\n * ```\n *\n * @type {State}\n */\n function referenceCollapsedOpen(code) {\n if (code === codes.rightSquareBracket) {\n effects.enter(types.referenceMarker)\n effects.consume(code)\n effects.exit(types.referenceMarker)\n effects.exit(types.reference)\n return ok\n }\n\n return nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\nimport {labelEnd} from './label-end.js'\n\n/** @type {Construct} */\nexport const labelStartImage = {\n name: 'labelStartImage',\n tokenize: tokenizeLabelStartImage,\n resolveAll: labelEnd.resolveAll\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeLabelStartImage(effects, ok, nok) {\n const self = this\n\n return start\n\n /**\n * Start of label (image) start.\n *\n * ```markdown\n * > | a ![b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.exclamationMark, 'expected `!`')\n effects.enter(types.labelImage)\n effects.enter(types.labelImageMarker)\n effects.consume(code)\n effects.exit(types.labelImageMarker)\n return open\n }\n\n /**\n * After `!`, at `[`.\n *\n * ```markdown\n * > | a ![b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function open(code) {\n if (code === codes.leftSquareBracket) {\n effects.enter(types.labelMarker)\n effects.consume(code)\n effects.exit(types.labelMarker)\n effects.exit(types.labelImage)\n return after\n }\n\n return nok(code)\n }\n\n /**\n * After `![`.\n *\n * ```markdown\n * > | a ![b] c\n * ^\n * ```\n *\n * This is needed in because, when GFM footnotes are enabled, images never\n * form when started with a `^`.\n * Instead, links form:\n *\n * ```markdown\n * \n *\n * ![^a][b]\n *\n * [b]: c\n * ```\n *\n * ```html\n * !^a
\n * !^a
\n * ```\n *\n * @type {State}\n */\n function after(code) {\n // To do: use a new field to do this, this is still needed for\n // `micromark-extension-gfm-footnote`, but the `label-start-link`\n // behavior isn’t.\n // Hidden footnotes hook.\n /* c8 ignore next 3 */\n return code === codes.caret &&\n '_hiddenFootnoteSupport' in self.parser.constructs\n ? nok(code)\n : ok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\nimport {labelEnd} from './label-end.js'\n\n/** @type {Construct} */\nexport const labelStartLink = {\n name: 'labelStartLink',\n tokenize: tokenizeLabelStartLink,\n resolveAll: labelEnd.resolveAll\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeLabelStartLink(effects, ok, nok) {\n const self = this\n\n return start\n\n /**\n * Start of label (link) start.\n *\n * ```markdown\n * > | a [b] c\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.leftSquareBracket, 'expected `[`')\n effects.enter(types.labelLink)\n effects.enter(types.labelMarker)\n effects.consume(code)\n effects.exit(types.labelMarker)\n effects.exit(types.labelLink)\n return after\n }\n\n /** @type {State} */\n function after(code) {\n // To do: this isn’t needed in `micromark-extension-gfm-footnote`,\n // remove.\n // Hidden footnotes hook.\n /* c8 ignore next 3 */\n return code === codes.caret &&\n '_hiddenFootnoteSupport' in self.parser.constructs\n ? nok(code)\n : ok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const lineEnding = {name: 'lineEnding', tokenize: tokenizeLineEnding}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeLineEnding(effects, ok) {\n return start\n\n /** @type {State} */\n function start(code) {\n assert(markdownLineEnding(code), 'expected eol')\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return factorySpace(effects, ok, types.linePrefix)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').ContainerState} ContainerState\n * @typedef {import('micromark-util-types').Exiter} Exiter\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {asciiDigit, markdownSpace} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\nimport {blankLine} from './blank-line.js'\nimport {thematicBreak} from './thematic-break.js'\n\n/** @type {Construct} */\nexport const list = {\n name: 'list',\n tokenize: tokenizeListStart,\n continuation: {tokenize: tokenizeListContinuation},\n exit: tokenizeListEnd\n}\n\n/** @type {Construct} */\nconst listItemPrefixWhitespaceConstruct = {\n tokenize: tokenizeListItemPrefixWhitespace,\n partial: true\n}\n\n/** @type {Construct} */\nconst indentConstruct = {tokenize: tokenizeIndent, partial: true}\n\n// To do: `markdown-rs` parses list items on their own and later stitches them\n// together.\n\n/**\n * @type {Tokenizer}\n * @this {TokenizeContext}\n */\nfunction tokenizeListStart(effects, ok, nok) {\n const self = this\n const tail = self.events[self.events.length - 1]\n let initialSize =\n tail && tail[1].type === types.linePrefix\n ? tail[2].sliceSerialize(tail[1], true).length\n : 0\n let size = 0\n\n return start\n\n /** @type {State} */\n function start(code) {\n assert(self.containerState, 'expected state')\n const kind =\n self.containerState.type ||\n (code === codes.asterisk || code === codes.plusSign || code === codes.dash\n ? types.listUnordered\n : types.listOrdered)\n\n if (\n kind === types.listUnordered\n ? !self.containerState.marker || code === self.containerState.marker\n : asciiDigit(code)\n ) {\n if (!self.containerState.type) {\n self.containerState.type = kind\n effects.enter(kind, {_container: true})\n }\n\n if (kind === types.listUnordered) {\n effects.enter(types.listItemPrefix)\n return code === codes.asterisk || code === codes.dash\n ? effects.check(thematicBreak, nok, atMarker)(code)\n : atMarker(code)\n }\n\n if (!self.interrupt || code === codes.digit1) {\n effects.enter(types.listItemPrefix)\n effects.enter(types.listItemValue)\n return inside(code)\n }\n }\n\n return nok(code)\n }\n\n /** @type {State} */\n function inside(code) {\n assert(self.containerState, 'expected state')\n if (asciiDigit(code) && ++size < constants.listItemValueSizeMax) {\n effects.consume(code)\n return inside\n }\n\n if (\n (!self.interrupt || size < 2) &&\n (self.containerState.marker\n ? code === self.containerState.marker\n : code === codes.rightParenthesis || code === codes.dot)\n ) {\n effects.exit(types.listItemValue)\n return atMarker(code)\n }\n\n return nok(code)\n }\n\n /**\n * @type {State}\n **/\n function atMarker(code) {\n assert(self.containerState, 'expected state')\n assert(code !== codes.eof, 'eof (`null`) is not a marker')\n effects.enter(types.listItemMarker)\n effects.consume(code)\n effects.exit(types.listItemMarker)\n self.containerState.marker = self.containerState.marker || code\n return effects.check(\n blankLine,\n // Can’t be empty when interrupting.\n self.interrupt ? nok : onBlank,\n effects.attempt(\n listItemPrefixWhitespaceConstruct,\n endOfPrefix,\n otherPrefix\n )\n )\n }\n\n /** @type {State} */\n function onBlank(code) {\n assert(self.containerState, 'expected state')\n self.containerState.initialBlankLine = true\n initialSize++\n return endOfPrefix(code)\n }\n\n /** @type {State} */\n function otherPrefix(code) {\n if (markdownSpace(code)) {\n effects.enter(types.listItemPrefixWhitespace)\n effects.consume(code)\n effects.exit(types.listItemPrefixWhitespace)\n return endOfPrefix\n }\n\n return nok(code)\n }\n\n /** @type {State} */\n function endOfPrefix(code) {\n assert(self.containerState, 'expected state')\n self.containerState.size =\n initialSize +\n self.sliceSerialize(effects.exit(types.listItemPrefix), true).length\n return ok(code)\n }\n}\n\n/**\n * @type {Tokenizer}\n * @this {TokenizeContext}\n */\nfunction tokenizeListContinuation(effects, ok, nok) {\n const self = this\n\n assert(self.containerState, 'expected state')\n self.containerState._closeFlow = undefined\n\n return effects.check(blankLine, onBlank, notBlank)\n\n /** @type {State} */\n function onBlank(code) {\n assert(self.containerState, 'expected state')\n assert(typeof self.containerState.size === 'number', 'expected size')\n self.containerState.furtherBlankLines =\n self.containerState.furtherBlankLines ||\n self.containerState.initialBlankLine\n\n // We have a blank line.\n // Still, try to consume at most the items size.\n return factorySpace(\n effects,\n ok,\n types.listItemIndent,\n self.containerState.size + 1\n )(code)\n }\n\n /** @type {State} */\n function notBlank(code) {\n assert(self.containerState, 'expected state')\n if (self.containerState.furtherBlankLines || !markdownSpace(code)) {\n self.containerState.furtherBlankLines = undefined\n self.containerState.initialBlankLine = undefined\n return notInCurrentItem(code)\n }\n\n self.containerState.furtherBlankLines = undefined\n self.containerState.initialBlankLine = undefined\n return effects.attempt(indentConstruct, ok, notInCurrentItem)(code)\n }\n\n /** @type {State} */\n function notInCurrentItem(code) {\n assert(self.containerState, 'expected state')\n // While we do continue, we signal that the flow should be closed.\n self.containerState._closeFlow = true\n // As we’re closing flow, we’re no longer interrupting.\n self.interrupt = undefined\n // Always populated by defaults.\n assert(\n self.parser.constructs.disable.null,\n 'expected `disable.null` to be populated'\n )\n return factorySpace(\n effects,\n effects.attempt(list, ok, nok),\n types.linePrefix,\n self.parser.constructs.disable.null.includes('codeIndented')\n ? undefined\n : constants.tabSize\n )(code)\n }\n}\n\n/**\n * @type {Tokenizer}\n * @this {TokenizeContext}\n */\nfunction tokenizeIndent(effects, ok, nok) {\n const self = this\n\n assert(self.containerState, 'expected state')\n assert(typeof self.containerState.size === 'number', 'expected size')\n\n return factorySpace(\n effects,\n afterPrefix,\n types.listItemIndent,\n self.containerState.size + 1\n )\n\n /** @type {State} */\n function afterPrefix(code) {\n assert(self.containerState, 'expected state')\n const tail = self.events[self.events.length - 1]\n return tail &&\n tail[1].type === types.listItemIndent &&\n tail[2].sliceSerialize(tail[1], true).length === self.containerState.size\n ? ok(code)\n : nok(code)\n }\n}\n\n/**\n * @type {Exiter}\n * @this {TokenizeContext}\n */\nfunction tokenizeListEnd(effects) {\n assert(this.containerState, 'expected state')\n assert(typeof this.containerState.type === 'string', 'expected type')\n effects.exit(this.containerState.type)\n}\n\n/**\n * @type {Tokenizer}\n * @this {TokenizeContext}\n */\nfunction tokenizeListItemPrefixWhitespace(effects, ok, nok) {\n const self = this\n\n // Always populated by defaults.\n assert(\n self.parser.constructs.disable.null,\n 'expected `disable.null` to be populated'\n )\n\n return factorySpace(\n effects,\n afterPrefix,\n types.listItemPrefixWhitespace,\n self.parser.constructs.disable.null.includes('codeIndented')\n ? undefined\n : constants.tabSize + 1\n )\n\n /** @type {State} */\n function afterPrefix(code) {\n const tail = self.events[self.events.length - 1]\n\n return !markdownSpace(code) &&\n tail &&\n tail[1].type === types.listItemPrefixWhitespace\n ? ok(code)\n : nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').Resolver} Resolver\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding, markdownSpace} from 'micromark-util-character'\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const setextUnderline = {\n name: 'setextUnderline',\n tokenize: tokenizeSetextUnderline,\n resolveTo: resolveToSetextUnderline\n}\n\n/** @type {Resolver} */\nfunction resolveToSetextUnderline(events, context) {\n // To do: resolve like `markdown-rs`.\n let index = events.length\n /** @type {number | undefined} */\n let content\n /** @type {number | undefined} */\n let text\n /** @type {number | undefined} */\n let definition\n\n // Find the opening of the content.\n // It’ll always exist: we don’t tokenize if it isn’t there.\n while (index--) {\n if (events[index][0] === 'enter') {\n if (events[index][1].type === types.content) {\n content = index\n break\n }\n\n if (events[index][1].type === types.paragraph) {\n text = index\n }\n }\n // Exit\n else {\n if (events[index][1].type === types.content) {\n // Remove the content end (if needed we’ll add it later)\n events.splice(index, 1)\n }\n\n if (!definition && events[index][1].type === types.definition) {\n definition = index\n }\n }\n }\n\n assert(text !== undefined, 'expected a `text` index to be found')\n assert(content !== undefined, 'expected a `text` index to be found')\n\n const heading = {\n type: types.setextHeading,\n start: Object.assign({}, events[text][1].start),\n end: Object.assign({}, events[events.length - 1][1].end)\n }\n\n // Change the paragraph to setext heading text.\n events[text][1].type = types.setextHeadingText\n\n // If we have definitions in the content, we’ll keep on having content,\n // but we need move it.\n if (definition) {\n events.splice(text, 0, ['enter', heading, context])\n events.splice(definition + 1, 0, ['exit', events[content][1], context])\n events[content][1].end = Object.assign({}, events[definition][1].end)\n } else {\n events[content][1] = heading\n }\n\n // Add the heading exit at the end.\n events.push(['exit', heading, context])\n\n return events\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeSetextUnderline(effects, ok, nok) {\n const self = this\n /** @type {NonNullable} */\n let marker\n\n return start\n\n /**\n * At start of heading (setext) underline.\n *\n * ```markdown\n * | aa\n * > | ==\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n let index = self.events.length\n /** @type {boolean | undefined} */\n let paragraph\n\n assert(\n code === codes.dash || code === codes.equalsTo,\n 'expected `=` or `-`'\n )\n\n // Find an opening.\n while (index--) {\n // Skip enter/exit of line ending, line prefix, and content.\n // We can now either have a definition or a paragraph.\n if (\n self.events[index][1].type !== types.lineEnding &&\n self.events[index][1].type !== types.linePrefix &&\n self.events[index][1].type !== types.content\n ) {\n paragraph = self.events[index][1].type === types.paragraph\n break\n }\n }\n\n // To do: handle lazy/pierce like `markdown-rs`.\n // To do: parse indent like `markdown-rs`.\n if (!self.parser.lazy[self.now().line] && (self.interrupt || paragraph)) {\n effects.enter(types.setextHeadingLine)\n marker = code\n return before(code)\n }\n\n return nok(code)\n }\n\n /**\n * After optional whitespace, at `-` or `=`.\n *\n * ```markdown\n * | aa\n * > | ==\n * ^\n * ```\n *\n * @type {State}\n */\n function before(code) {\n effects.enter(types.setextHeadingLineSequence)\n return inside(code)\n }\n\n /**\n * In sequence.\n *\n * ```markdown\n * | aa\n * > | ==\n * ^\n * ```\n *\n * @type {State}\n */\n function inside(code) {\n if (code === marker) {\n effects.consume(code)\n return inside\n }\n\n effects.exit(types.setextHeadingLineSequence)\n\n return markdownSpace(code)\n ? factorySpace(effects, after, types.lineSuffix)(code)\n : after(code)\n }\n\n /**\n * After sequence, after optional whitespace.\n *\n * ```markdown\n * | aa\n * > | ==\n * ^\n * ```\n *\n * @type {State}\n */\n function after(code) {\n if (code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.setextHeadingLine)\n return ok(code)\n }\n\n return nok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding, markdownSpace} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {Construct} */\nexport const thematicBreak = {\n name: 'thematicBreak',\n tokenize: tokenizeThematicBreak\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeThematicBreak(effects, ok, nok) {\n let size = 0\n /** @type {NonNullable} */\n let marker\n\n return start\n\n /**\n * Start of thematic break.\n *\n * ```markdown\n * > | ***\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n effects.enter(types.thematicBreak)\n // To do: parse indent like `markdown-rs`.\n return before(code)\n }\n\n /**\n * After optional whitespace, at marker.\n *\n * ```markdown\n * > | ***\n * ^\n * ```\n *\n * @type {State}\n */\n function before(code) {\n assert(\n code === codes.asterisk ||\n code === codes.dash ||\n code === codes.underscore,\n 'expected `*`, `-`, or `_`'\n )\n marker = code\n return atBreak(code)\n }\n\n /**\n * After something, before something else.\n *\n * ```markdown\n * > | ***\n * ^\n * ```\n *\n * @type {State}\n */\n function atBreak(code) {\n if (code === marker) {\n effects.enter(types.thematicBreakSequence)\n return sequence(code)\n }\n\n if (\n size >= constants.thematicBreakMarkerCountMin &&\n (code === codes.eof || markdownLineEnding(code))\n ) {\n effects.exit(types.thematicBreak)\n return ok(code)\n }\n\n return nok(code)\n }\n\n /**\n * In sequence.\n *\n * ```markdown\n * > | ***\n * ^\n * ```\n *\n * @type {State}\n */\n function sequence(code) {\n if (code === marker) {\n effects.consume(code)\n size++\n return sequence\n }\n\n effects.exit(types.thematicBreakSequence)\n return markdownSpace(code)\n ? factorySpace(effects, atBreak, types.whitespace)(code)\n : atBreak(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Effects} Effects\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenType} TokenType\n */\n\nimport {\n asciiControl,\n markdownLineEndingOrSpace,\n markdownLineEnding\n} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\n\n/**\n * Parse destinations.\n *\n * ###### Examples\n *\n * ```markdown\n * \n * b>\n * \n * \n * a\n * a\\)b\n * a(b)c\n * a(b)\n * ```\n *\n * @param {Effects} effects\n * Context.\n * @param {State} ok\n * State switched to when successful.\n * @param {State} nok\n * State switched to when unsuccessful.\n * @param {TokenType} type\n * Type for whole (`` or `b`).\n * @param {TokenType} literalType\n * Type when enclosed (``).\n * @param {TokenType} literalMarkerType\n * Type for enclosing (`<` and `>`).\n * @param {TokenType} rawType\n * Type when not enclosed (`b`).\n * @param {TokenType} stringType\n * Type for the value (`a` or `b`).\n * @param {number | undefined} [max=Infinity]\n * Depth of nested parens (inclusive).\n * @returns {State}\n * Start state.\n */\n// eslint-disable-next-line max-params\nexport function factoryDestination(\n effects,\n ok,\n nok,\n type,\n literalType,\n literalMarkerType,\n rawType,\n stringType,\n max\n) {\n const limit = max || Number.POSITIVE_INFINITY\n let balance = 0\n\n return start\n\n /**\n * Start of destination.\n *\n * ```markdown\n * > | \n * ^\n * > | aa\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n if (code === codes.lessThan) {\n effects.enter(type)\n effects.enter(literalType)\n effects.enter(literalMarkerType)\n effects.consume(code)\n effects.exit(literalMarkerType)\n return enclosedBefore\n }\n\n // ASCII control, space, closing paren.\n if (\n code === codes.eof ||\n code === codes.space ||\n code === codes.rightParenthesis ||\n asciiControl(code)\n ) {\n return nok(code)\n }\n\n effects.enter(type)\n effects.enter(rawType)\n effects.enter(stringType)\n effects.enter(types.chunkString, {contentType: constants.contentTypeString})\n return raw(code)\n }\n\n /**\n * After `<`, at an enclosed destination.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function enclosedBefore(code) {\n if (code === codes.greaterThan) {\n effects.enter(literalMarkerType)\n effects.consume(code)\n effects.exit(literalMarkerType)\n effects.exit(literalType)\n effects.exit(type)\n return ok\n }\n\n effects.enter(stringType)\n effects.enter(types.chunkString, {contentType: constants.contentTypeString})\n return enclosed(code)\n }\n\n /**\n * In enclosed destination.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function enclosed(code) {\n if (code === codes.greaterThan) {\n effects.exit(types.chunkString)\n effects.exit(stringType)\n return enclosedBefore(code)\n }\n\n if (\n code === codes.eof ||\n code === codes.lessThan ||\n markdownLineEnding(code)\n ) {\n return nok(code)\n }\n\n effects.consume(code)\n return code === codes.backslash ? enclosedEscape : enclosed\n }\n\n /**\n * After `\\`, at a special character.\n *\n * ```markdown\n * > | \n * ^\n * ```\n *\n * @type {State}\n */\n function enclosedEscape(code) {\n if (\n code === codes.lessThan ||\n code === codes.greaterThan ||\n code === codes.backslash\n ) {\n effects.consume(code)\n return enclosed\n }\n\n return enclosed(code)\n }\n\n /**\n * In raw destination.\n *\n * ```markdown\n * > | aa\n * ^\n * ```\n *\n * @type {State}\n */\n function raw(code) {\n if (\n !balance &&\n (code === codes.eof ||\n code === codes.rightParenthesis ||\n markdownLineEndingOrSpace(code))\n ) {\n effects.exit(types.chunkString)\n effects.exit(stringType)\n effects.exit(rawType)\n effects.exit(type)\n return ok(code)\n }\n\n if (balance < limit && code === codes.leftParenthesis) {\n effects.consume(code)\n balance++\n return raw\n }\n\n if (code === codes.rightParenthesis) {\n effects.consume(code)\n balance--\n return raw\n }\n\n // ASCII control (but *not* `\\0`) and space and `(`.\n // Note: in `markdown-rs`, `\\0` exists in codes, in `micromark-js` it\n // doesn’t.\n if (\n code === codes.eof ||\n code === codes.space ||\n code === codes.leftParenthesis ||\n asciiControl(code)\n ) {\n return nok(code)\n }\n\n effects.consume(code)\n return code === codes.backslash ? rawEscape : raw\n }\n\n /**\n * After `\\`, at special character.\n *\n * ```markdown\n * > | a\\*a\n * ^\n * ```\n *\n * @type {State}\n */\n function rawEscape(code) {\n if (\n code === codes.leftParenthesis ||\n code === codes.rightParenthesis ||\n code === codes.backslash\n ) {\n effects.consume(code)\n return raw\n }\n\n return raw(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Effects} Effects\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').TokenType} TokenType\n */\n\nimport {markdownLineEnding, markdownSpace} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/**\n * Parse labels.\n *\n * > 👉 **Note**: labels in markdown are capped at 999 characters in the string.\n *\n * ###### Examples\n *\n * ```markdown\n * [a]\n * [a\n * b]\n * [a\\]b]\n * ```\n *\n * @this {TokenizeContext}\n * Tokenize context.\n * @param {Effects} effects\n * Context.\n * @param {State} ok\n * State switched to when successful.\n * @param {State} nok\n * State switched to when unsuccessful.\n * @param {TokenType} type\n * Type of the whole label (`[a]`).\n * @param {TokenType} markerType\n * Type for the markers (`[` and `]`).\n * @param {TokenType} stringType\n * Type for the identifier (`a`).\n * @returns {State}\n * Start state.\n */\n// eslint-disable-next-line max-params\nexport function factoryLabel(effects, ok, nok, type, markerType, stringType) {\n const self = this\n let size = 0\n /** @type {boolean} */\n let seen\n\n return start\n\n /**\n * Start of label.\n *\n * ```markdown\n * > | [a]\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n assert(code === codes.leftSquareBracket, 'expected `[`')\n effects.enter(type)\n effects.enter(markerType)\n effects.consume(code)\n effects.exit(markerType)\n effects.enter(stringType)\n return atBreak\n }\n\n /**\n * In label, at something, before something else.\n *\n * ```markdown\n * > | [a]\n * ^\n * ```\n *\n * @type {State}\n */\n function atBreak(code) {\n if (\n size > constants.linkReferenceSizeMax ||\n code === codes.eof ||\n code === codes.leftSquareBracket ||\n (code === codes.rightSquareBracket && !seen) ||\n // To do: remove in the future once we’ve switched from\n // `micromark-extension-footnote` to `micromark-extension-gfm-footnote`,\n // which doesn’t need this.\n // Hidden footnotes hook.\n /* c8 ignore next 3 */\n (code === codes.caret &&\n !size &&\n '_hiddenFootnoteSupport' in self.parser.constructs)\n ) {\n return nok(code)\n }\n\n if (code === codes.rightSquareBracket) {\n effects.exit(stringType)\n effects.enter(markerType)\n effects.consume(code)\n effects.exit(markerType)\n effects.exit(type)\n return ok\n }\n\n // To do: indent? Link chunks and EOLs together?\n if (markdownLineEnding(code)) {\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return atBreak\n }\n\n effects.enter(types.chunkString, {contentType: constants.contentTypeString})\n return labelInside(code)\n }\n\n /**\n * In label, in text.\n *\n * ```markdown\n * > | [a]\n * ^\n * ```\n *\n * @type {State}\n */\n function labelInside(code) {\n if (\n code === codes.eof ||\n code === codes.leftSquareBracket ||\n code === codes.rightSquareBracket ||\n markdownLineEnding(code) ||\n size++ > constants.linkReferenceSizeMax\n ) {\n effects.exit(types.chunkString)\n return atBreak(code)\n }\n\n effects.consume(code)\n if (!seen) seen = !markdownSpace(code)\n return code === codes.backslash ? labelEscape : labelInside\n }\n\n /**\n * After `\\`, at a special character.\n *\n * ```markdown\n * > | [a\\*a]\n * ^\n * ```\n *\n * @type {State}\n */\n function labelEscape(code) {\n if (\n code === codes.leftSquareBracket ||\n code === codes.backslash ||\n code === codes.rightSquareBracket\n ) {\n effects.consume(code)\n size++\n return labelInside\n }\n\n return labelInside(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Effects} Effects\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenType} TokenType\n */\n\nimport {markdownSpace} from 'micromark-util-character'\n\n// To do: implement `spaceOrTab`, `spaceOrTabMinMax`, `spaceOrTabWithOptions`.\n\n/**\n * Parse spaces and tabs.\n *\n * There is no `nok` parameter:\n *\n * * spaces in markdown are often optional, in which case this factory can be\n * used and `ok` will be switched to whether spaces were found or not\n * * one line ending or space can be detected with `markdownSpace(code)` right\n * before using `factorySpace`\n *\n * ###### Examples\n *\n * Where `␉` represents a tab (plus how much it expands) and `␠` represents a\n * single space.\n *\n * ```markdown\n * ␉\n * ␠␠␠␠\n * ␉␠\n * ```\n *\n * @param {Effects} effects\n * Context.\n * @param {State} ok\n * State switched to when successful.\n * @param {TokenType} type\n * Type (`' \\t'`).\n * @param {number | undefined} [max=Infinity]\n * Max (exclusive).\n * @returns {State}\n * Start state.\n */\nexport function factorySpace(effects, ok, type, max) {\n const limit = max ? max - 1 : Number.POSITIVE_INFINITY\n let size = 0\n\n return start\n\n /** @type {State} */\n function start(code) {\n if (markdownSpace(code)) {\n effects.enter(type)\n return prefix(code)\n }\n\n return ok(code)\n }\n\n /** @type {State} */\n function prefix(code) {\n if (markdownSpace(code) && size++ < limit) {\n effects.consume(code)\n return prefix\n }\n\n effects.exit(type)\n return ok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Effects} Effects\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenType} TokenType\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\n\n/**\n * Parse titles.\n *\n * ###### Examples\n *\n * ```markdown\n * \"a\"\n * 'b'\n * (c)\n * \"a\n * b\"\n * 'a\n * b'\n * (a\\)b)\n * ```\n *\n * @param {Effects} effects\n * Context.\n * @param {State} ok\n * State switched to when successful.\n * @param {State} nok\n * State switched to when unsuccessful.\n * @param {TokenType} type\n * Type of the whole title (`\"a\"`, `'b'`, `(c)`).\n * @param {TokenType} markerType\n * Type for the markers (`\"`, `'`, `(`, and `)`).\n * @param {TokenType} stringType\n * Type for the value (`a`).\n * @returns {State}\n * Start state.\n */\n// eslint-disable-next-line max-params\nexport function factoryTitle(effects, ok, nok, type, markerType, stringType) {\n /** @type {NonNullable} */\n let marker\n\n return start\n\n /**\n * Start of title.\n *\n * ```markdown\n * > | \"a\"\n * ^\n * ```\n *\n * @type {State}\n */\n function start(code) {\n if (\n code === codes.quotationMark ||\n code === codes.apostrophe ||\n code === codes.leftParenthesis\n ) {\n effects.enter(type)\n effects.enter(markerType)\n effects.consume(code)\n effects.exit(markerType)\n marker = code === codes.leftParenthesis ? codes.rightParenthesis : code\n return begin\n }\n\n return nok(code)\n }\n\n /**\n * After opening marker.\n *\n * This is also used at the closing marker.\n *\n * ```markdown\n * > | \"a\"\n * ^\n * ```\n *\n * @type {State}\n */\n function begin(code) {\n if (code === marker) {\n effects.enter(markerType)\n effects.consume(code)\n effects.exit(markerType)\n effects.exit(type)\n return ok\n }\n\n effects.enter(stringType)\n return atBreak(code)\n }\n\n /**\n * At something, before something else.\n *\n * ```markdown\n * > | \"a\"\n * ^\n * ```\n *\n * @type {State}\n */\n function atBreak(code) {\n if (code === marker) {\n effects.exit(stringType)\n return begin(marker)\n }\n\n if (code === codes.eof) {\n return nok(code)\n }\n\n // Note: blank lines can’t exist in content.\n if (markdownLineEnding(code)) {\n // To do: use `space_or_tab_eol_with_options`, connect.\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return factorySpace(effects, atBreak, types.linePrefix)\n }\n\n effects.enter(types.chunkString, {contentType: constants.contentTypeString})\n return inside(code)\n }\n\n /**\n *\n *\n * @type {State}\n */\n function inside(code) {\n if (code === marker || code === codes.eof || markdownLineEnding(code)) {\n effects.exit(types.chunkString)\n return atBreak(code)\n }\n\n effects.consume(code)\n return code === codes.backslash ? escape : inside\n }\n\n /**\n * After `\\`, at a special character.\n *\n * ```markdown\n * > | \"a\\*b\"\n * ^\n * ```\n *\n * @type {State}\n */\n function escape(code) {\n if (code === marker || code === codes.backslash) {\n effects.consume(code)\n return inside\n }\n\n return inside(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Effects} Effects\n * @typedef {import('micromark-util-types').State} State\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding, markdownSpace} from 'micromark-util-character'\nimport {types} from 'micromark-util-symbol'\n\n/**\n * Parse spaces and tabs.\n *\n * There is no `nok` parameter:\n *\n * * line endings or spaces in markdown are often optional, in which case this\n * factory can be used and `ok` will be switched to whether spaces were found\n * or not\n * * one line ending or space can be detected with\n * `markdownLineEndingOrSpace(code)` right before using `factoryWhitespace`\n *\n * @param {Effects} effects\n * Context.\n * @param {State} ok\n * State switched to when successful.\n * @returns {State}\n * Start state.\n */\nexport function factoryWhitespace(effects, ok) {\n /** @type {boolean} */\n let seen\n\n return start\n\n /** @type {State} */\n function start(code) {\n if (markdownLineEnding(code)) {\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n seen = true\n return start\n }\n\n if (markdownSpace(code)) {\n return factorySpace(\n effects,\n start,\n seen ? types.linePrefix : types.lineSuffix\n )(code)\n }\n\n return ok(code)\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n */\n\nimport {codes} from 'micromark-util-symbol'\n\n/**\n * Check whether the character code represents an ASCII alpha (`a` through `z`,\n * case insensitive).\n *\n * An **ASCII alpha** is an ASCII upper alpha or ASCII lower alpha.\n *\n * An **ASCII upper alpha** is a character in the inclusive range U+0041 (`A`)\n * to U+005A (`Z`).\n *\n * An **ASCII lower alpha** is a character in the inclusive range U+0061 (`a`)\n * to U+007A (`z`).\n *\n * @param code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport const asciiAlpha = regexCheck(/[A-Za-z]/)\n\n/**\n * Check whether the character code represents an ASCII alphanumeric (`a`\n * through `z`, case insensitive, or `0` through `9`).\n *\n * An **ASCII alphanumeric** is an ASCII digit (see `asciiDigit`) or ASCII alpha\n * (see `asciiAlpha`).\n *\n * @param code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport const asciiAlphanumeric = regexCheck(/[\\dA-Za-z]/)\n\n/**\n * Check whether the character code represents an ASCII atext.\n *\n * atext is an ASCII alphanumeric (see `asciiAlphanumeric`), or a character in\n * the inclusive ranges U+0023 NUMBER SIGN (`#`) to U+0027 APOSTROPHE (`'`),\n * U+002A ASTERISK (`*`), U+002B PLUS SIGN (`+`), U+002D DASH (`-`), U+002F\n * SLASH (`/`), U+003D EQUALS TO (`=`), U+003F QUESTION MARK (`?`), U+005E\n * CARET (`^`) to U+0060 GRAVE ACCENT (`` ` ``), or U+007B LEFT CURLY BRACE\n * (`{`) to U+007E TILDE (`~`).\n *\n * See:\n * **\\[RFC5322]**:\n * [Internet Message Format](https://tools.ietf.org/html/rfc5322).\n * P. Resnick.\n * IETF.\n *\n * @param code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport const asciiAtext = regexCheck(/[#-'*+\\--9=?A-Z^-~]/)\n\n/**\n * Check whether a character code is an ASCII control character.\n *\n * An **ASCII control** is a character in the inclusive range U+0000 NULL (NUL)\n * to U+001F (US), or U+007F (DEL).\n *\n * @param {Code} code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport function asciiControl(code) {\n return (\n // Special whitespace codes (which have negative values), C0 and Control\n // character DEL\n code !== null && (code < codes.space || code === codes.del)\n )\n}\n\n/**\n * Check whether the character code represents an ASCII digit (`0` through `9`).\n *\n * An **ASCII digit** is a character in the inclusive range U+0030 (`0`) to\n * U+0039 (`9`).\n *\n * @param code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport const asciiDigit = regexCheck(/\\d/)\n\n/**\n * Check whether the character code represents an ASCII hex digit (`a` through\n * `f`, case insensitive, or `0` through `9`).\n *\n * An **ASCII hex digit** is an ASCII digit (see `asciiDigit`), ASCII upper hex\n * digit, or an ASCII lower hex digit.\n *\n * An **ASCII upper hex digit** is a character in the inclusive range U+0041\n * (`A`) to U+0046 (`F`).\n *\n * An **ASCII lower hex digit** is a character in the inclusive range U+0061\n * (`a`) to U+0066 (`f`).\n *\n * @param code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport const asciiHexDigit = regexCheck(/[\\dA-Fa-f]/)\n\n/**\n * Check whether the character code represents ASCII punctuation.\n *\n * An **ASCII punctuation** is a character in the inclusive ranges U+0021\n * EXCLAMATION MARK (`!`) to U+002F SLASH (`/`), U+003A COLON (`:`) to U+0040 AT\n * SIGN (`@`), U+005B LEFT SQUARE BRACKET (`[`) to U+0060 GRAVE ACCENT\n * (`` ` ``), or U+007B LEFT CURLY BRACE (`{`) to U+007E TILDE (`~`).\n *\n * @param code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport const asciiPunctuation = regexCheck(/[!-/:-@[-`{-~]/)\n\n/**\n * Check whether a character code is a markdown line ending.\n *\n * A **markdown line ending** is the virtual characters M-0003 CARRIAGE RETURN\n * LINE FEED (CRLF), M-0004 LINE FEED (LF) and M-0005 CARRIAGE RETURN (CR).\n *\n * In micromark, the actual character U+000A LINE FEED (LF) and U+000D CARRIAGE\n * RETURN (CR) are replaced by these virtual characters depending on whether\n * they occurred together.\n *\n * @param {Code} code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport function markdownLineEnding(code) {\n return code !== null && code < codes.horizontalTab\n}\n\n/**\n * Check whether a character code is a markdown line ending (see\n * `markdownLineEnding`) or markdown space (see `markdownSpace`).\n *\n * @param {Code} code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport function markdownLineEndingOrSpace(code) {\n return code !== null && (code < codes.nul || code === codes.space)\n}\n\n/**\n * Check whether a character code is a markdown space.\n *\n * A **markdown space** is the concrete character U+0020 SPACE (SP) and the\n * virtual characters M-0001 VIRTUAL SPACE (VS) and M-0002 HORIZONTAL TAB (HT).\n *\n * In micromark, the actual character U+0009 CHARACTER TABULATION (HT) is\n * replaced by one M-0002 HORIZONTAL TAB (HT) and between 0 and 3 M-0001 VIRTUAL\n * SPACE (VS) characters, depending on the column at which the tab occurred.\n *\n * @param {Code} code\n * Code.\n * @returns {boolean}\n * Whether it matches.\n */\nexport function markdownSpace(code) {\n return (\n code === codes.horizontalTab ||\n code === codes.virtualSpace ||\n code === codes.space\n )\n}\n\n// Size note: removing ASCII from the regex and using `asciiPunctuation` here\n// In fact adds to the bundle size.\n/**\n * Check whether the character code represents Unicode punctuation.\n *\n * A **Unicode punctuation** is a character in the Unicode `Pc` (Punctuation,\n * Connector), `Pd` (Punctuation, Dash), `Pe` (Punctuation, Close), `Pf`\n * (Punctuation, Final quote), `Pi` (Punctuation, Initial quote), `Po`\n * (Punctuation, Other), or `Ps` (Punctuation, Open) categories, or an ASCII\n * punctuation (see `asciiPunctuation`).\n *\n * See:\n * **\\[UNICODE]**:\n * [The Unicode Standard](https://www.unicode.org/versions/).\n * Unicode Consortium.\n *\n * @param code\n * Code.\n * @returns\n * Whether it matches.\n */\nexport const unicodePunctuation = regexCheck(/\\p{P}|\\p{S}/u)\n\n/**\n * Check whether the character code represents Unicode whitespace.\n *\n * Note that this does handle micromark specific markdown whitespace characters.\n * See `markdownLineEndingOrSpace` to check that.\n *\n * A **Unicode whitespace** is a character in the Unicode `Zs` (Separator,\n * Space) category, or U+0009 CHARACTER TABULATION (HT), U+000A LINE FEED (LF),\n * U+000C (FF), or U+000D CARRIAGE RETURN (CR) (**\\[UNICODE]**).\n *\n * See:\n * **\\[UNICODE]**:\n * [The Unicode Standard](https://www.unicode.org/versions/).\n * Unicode Consortium.\n *\n * @param code\n * Code.\n * @returns\n * Whether it matches.\n */\nexport const unicodeWhitespace = regexCheck(/\\s/)\n\n/**\n * Create a code check from a regex.\n *\n * @param {RegExp} regex\n * @returns {(code: Code) => boolean}\n */\nfunction regexCheck(regex) {\n return check\n\n /**\n * Check whether a code matches the bound regex.\n *\n * @param {Code} code\n * Character code.\n * @returns {boolean}\n * Whether the character code matches the bound regex.\n */\n function check(code) {\n return code !== null && code > -1 && regex.test(String.fromCharCode(code))\n }\n}\n","import {constants} from 'micromark-util-symbol'\n\n/**\n * Like `Array#splice`, but smarter for giant arrays.\n *\n * `Array#splice` takes all items to be inserted as individual argument which\n * causes a stack overflow in V8 when trying to insert 100k items for instance.\n *\n * Otherwise, this does not return the removed items, and takes `items` as an\n * array instead of rest parameters.\n *\n * @template {unknown} T\n * Item type.\n * @param {Array} list\n * List to operate on.\n * @param {number} start\n * Index to remove/insert at (can be negative).\n * @param {number} remove\n * Number of items to remove.\n * @param {Array} items\n * Items to inject into `list`.\n * @returns {undefined}\n * Nothing.\n */\nexport function splice(list, start, remove, items) {\n const end = list.length\n let chunkStart = 0\n /** @type {Array} */\n let parameters\n\n // Make start between zero and `end` (included).\n if (start < 0) {\n start = -start > end ? 0 : end + start\n } else {\n start = start > end ? end : start\n }\n\n remove = remove > 0 ? remove : 0\n\n // No need to chunk the items if there’s only a couple (10k) items.\n if (items.length < constants.v8MaxSafeChunkSize) {\n parameters = Array.from(items)\n parameters.unshift(start, remove)\n // @ts-expect-error Hush, it’s fine.\n list.splice(...parameters)\n } else {\n // Delete `remove` items starting from `start`\n if (remove) list.splice(start, remove)\n\n // Insert the items in chunks to not cause stack overflows.\n while (chunkStart < items.length) {\n parameters = items.slice(\n chunkStart,\n chunkStart + constants.v8MaxSafeChunkSize\n )\n parameters.unshift(start, 0)\n // @ts-expect-error Hush, it’s fine.\n list.splice(...parameters)\n\n chunkStart += constants.v8MaxSafeChunkSize\n start += constants.v8MaxSafeChunkSize\n }\n }\n}\n\n/**\n * Append `items` (an array) at the end of `list` (another array).\n * When `list` was empty, returns `items` instead.\n *\n * This prevents a potentially expensive operation when `list` is empty,\n * and adds items in batches to prevent V8 from hanging.\n *\n * @template {unknown} T\n * Item type.\n * @param {Array} list\n * List to operate on.\n * @param {Array} items\n * Items to add to `list`.\n * @returns {Array}\n * Either `list` or `items`.\n */\nexport function push(list, items) {\n if (list.length > 0) {\n splice(list, list.length, 0, items)\n return list\n }\n\n return items\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n */\n\nimport {\n markdownLineEndingOrSpace,\n unicodePunctuation,\n unicodeWhitespace\n} from 'micromark-util-character'\nimport {codes, constants} from 'micromark-util-symbol'\n\n/**\n * Classify whether a code represents whitespace, punctuation, or something\n * else.\n *\n * Used for attention (emphasis, strong), whose sequences can open or close\n * based on the class of surrounding characters.\n *\n * > 👉 **Note**: eof (`null`) is seen as whitespace.\n *\n * @param {Code} code\n * Code.\n * @returns {typeof constants.characterGroupWhitespace | typeof constants.characterGroupPunctuation | undefined}\n * Group.\n */\nexport function classifyCharacter(code) {\n if (\n code === codes.eof ||\n markdownLineEndingOrSpace(code) ||\n unicodeWhitespace(code)\n ) {\n return constants.characterGroupWhitespace\n }\n\n if (unicodePunctuation(code)) {\n return constants.characterGroupPunctuation\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Extension} Extension\n * @typedef {import('micromark-util-types').Handles} Handles\n * @typedef {import('micromark-util-types').HtmlExtension} HtmlExtension\n * @typedef {import('micromark-util-types').NormalizedExtension} NormalizedExtension\n */\n\nimport {splice} from 'micromark-util-chunked'\n\nconst hasOwnProperty = {}.hasOwnProperty\n\n/**\n * Combine multiple syntax extensions into one.\n *\n * @param {Array} extensions\n * List of syntax extensions.\n * @returns {NormalizedExtension}\n * A single combined extension.\n */\nexport function combineExtensions(extensions) {\n /** @type {NormalizedExtension} */\n const all = {}\n let index = -1\n\n while (++index < extensions.length) {\n syntaxExtension(all, extensions[index])\n }\n\n return all\n}\n\n/**\n * Merge `extension` into `all`.\n *\n * @param {NormalizedExtension} all\n * Extension to merge into.\n * @param {Extension} extension\n * Extension to merge.\n * @returns {undefined}\n */\nfunction syntaxExtension(all, extension) {\n /** @type {keyof Extension} */\n let hook\n\n for (hook in extension) {\n const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined\n /** @type {Record} */\n const left = maybe || (all[hook] = {})\n /** @type {Record | undefined} */\n const right = extension[hook]\n /** @type {string} */\n let code\n\n if (right) {\n for (code in right) {\n if (!hasOwnProperty.call(left, code)) left[code] = []\n const value = right[code]\n constructs(\n // @ts-expect-error Looks like a list.\n left[code],\n Array.isArray(value) ? value : value ? [value] : []\n )\n }\n }\n }\n}\n\n/**\n * Merge `list` into `existing` (both lists of constructs).\n * Mutates `existing`.\n *\n * @param {Array} existing\n * @param {Array} list\n * @returns {undefined}\n */\nfunction constructs(existing, list) {\n let index = -1\n /** @type {Array} */\n const before = []\n\n while (++index < list.length) {\n // @ts-expect-error Looks like an object.\n ;(list[index].add === 'after' ? existing : before).push(list[index])\n }\n\n splice(existing, 0, 0, before)\n}\n\n/**\n * Combine multiple HTML extensions into one.\n *\n * @param {Array} htmlExtensions\n * List of HTML extensions.\n * @returns {HtmlExtension}\n * A single combined HTML extension.\n */\nexport function combineHtmlExtensions(htmlExtensions) {\n /** @type {HtmlExtension} */\n const handlers = {}\n let index = -1\n\n while (++index < htmlExtensions.length) {\n htmlExtension(handlers, htmlExtensions[index])\n }\n\n return handlers\n}\n\n/**\n * Merge `extension` into `all`.\n *\n * @param {HtmlExtension} all\n * Extension to merge into.\n * @param {HtmlExtension} extension\n * Extension to merge.\n * @returns {undefined}\n */\nfunction htmlExtension(all, extension) {\n /** @type {keyof HtmlExtension} */\n let hook\n\n for (hook in extension) {\n const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined\n const left = maybe || (all[hook] = {})\n const right = extension[hook]\n /** @type {keyof Handles} */\n let type\n\n if (right) {\n for (type in right) {\n // @ts-expect-error assume document vs regular handler are managed correctly.\n left[type] = right[type]\n }\n }\n }\n}\n","import {codes, values} from 'micromark-util-symbol'\n\n/**\n * Turn the number (in string form as either hexa- or plain decimal) coming from\n * a numeric character reference into a character.\n *\n * Sort of like `String.fromCodePoint(Number.parseInt(value, base))`, but makes\n * non-characters and control characters safe.\n *\n * @param {string} value\n * Value to decode.\n * @param {number} base\n * Numeric base.\n * @returns {string}\n * Character.\n */\nexport function decodeNumericCharacterReference(value, base) {\n const code = Number.parseInt(value, base)\n\n if (\n // C0 except for HT, LF, FF, CR, space.\n code < codes.ht ||\n code === codes.vt ||\n (code > codes.cr && code < codes.space) ||\n // Control character (DEL) of C0, and C1 controls.\n (code > codes.tilde && code < 160) ||\n // Lone high surrogates and low surrogates.\n (code > 55_295 && code < 57_344) ||\n // Noncharacters.\n (code > 64_975 && code < 65_008) ||\n /* eslint-disable no-bitwise */\n (code & 65_535) === 65_535 ||\n (code & 65_535) === 65_534 ||\n /* eslint-enable no-bitwise */\n // Out of range\n code > 1_114_111\n ) {\n return values.replacementCharacter\n }\n\n return String.fromCodePoint(code)\n}\n","import {decodeNamedCharacterReference} from 'decode-named-character-reference'\nimport {decodeNumericCharacterReference} from 'micromark-util-decode-numeric-character-reference'\nimport {codes, constants} from 'micromark-util-symbol'\n\nconst characterEscapeOrReference =\n /\\\\([!-/:-@[-`{-~])|&(#(?:\\d{1,7}|x[\\da-f]{1,6})|[\\da-z]{1,31});/gi\n\n/**\n * Decode markdown strings (which occur in places such as fenced code info\n * strings, destinations, labels, and titles).\n *\n * The “string” content type allows character escapes and -references.\n * This decodes those.\n *\n * @param {string} value\n * Value to decode.\n * @returns {string}\n * Decoded value.\n */\nexport function decodeString(value) {\n return value.replace(characterEscapeOrReference, decode)\n}\n\n/**\n * @param {string} $0\n * @param {string} $1\n * @param {string} $2\n * @returns {string}\n */\nfunction decode($0, $1, $2) {\n if ($1) {\n // Escape.\n return $1\n }\n\n // Reference.\n const head = $2.charCodeAt(0)\n\n if (head === codes.numberSign) {\n const head = $2.charCodeAt(1)\n const hex = head === codes.lowercaseX || head === codes.uppercaseX\n return decodeNumericCharacterReference(\n $2.slice(hex ? 2 : 1),\n hex ? constants.numericBaseHexadecimal : constants.numericBaseDecimal\n )\n }\n\n return decodeNamedCharacterReference($2) || $0\n}\n","const characterReferences = {'\"': 'quot', '&': 'amp', '<': 'lt', '>': 'gt'}\n\n/**\n * Encode only the dangerous HTML characters.\n *\n * This ensures that certain characters which have special meaning in HTML are\n * dealt with.\n * Technically, we can skip `>` and `\"` in many cases, but CM includes them.\n *\n * @param {string} value\n * Value to encode.\n * @returns {string}\n * Encoded value.\n */\nexport function encode(value) {\n return value.replace(/[\"&<>]/g, replace)\n\n /**\n * @param {string} value\n * @returns {string}\n */\n function replace(value) {\n // @ts-expect-error Hush, it’s fine.\n return '&' + characterReferences[value] + ';'\n }\n}\n","/**\n * List of lowercase HTML “block” tag names.\n *\n * The list, when parsing HTML (flow), results in more relaxed rules (condition\n * 6).\n * Because they are known blocks, the HTML-like syntax doesn’t have to be\n * strictly parsed.\n * For tag names not in this list, a more strict algorithm (condition 7) is used\n * to detect whether the HTML-like syntax is seen as HTML (flow) or not.\n *\n * This is copied from:\n * .\n *\n * > 👉 **Note**: `search` was added in `CommonMark@0.31`.\n */\nexport const htmlBlockNames = [\n 'address',\n 'article',\n 'aside',\n 'base',\n 'basefont',\n 'blockquote',\n 'body',\n 'caption',\n 'center',\n 'col',\n 'colgroup',\n 'dd',\n 'details',\n 'dialog',\n 'dir',\n 'div',\n 'dl',\n 'dt',\n 'fieldset',\n 'figcaption',\n 'figure',\n 'footer',\n 'form',\n 'frame',\n 'frameset',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'head',\n 'header',\n 'hr',\n 'html',\n 'iframe',\n 'legend',\n 'li',\n 'link',\n 'main',\n 'menu',\n 'menuitem',\n 'nav',\n 'noframes',\n 'ol',\n 'optgroup',\n 'option',\n 'p',\n 'param',\n 'search',\n 'section',\n 'summary',\n 'table',\n 'tbody',\n 'td',\n 'tfoot',\n 'th',\n 'thead',\n 'title',\n 'tr',\n 'track',\n 'ul'\n]\n\n/**\n * List of lowercase HTML “raw” tag names.\n *\n * The list, when parsing HTML (flow), results in HTML that can include lines\n * without exiting, until a closing tag also in this list is found (condition\n * 1).\n *\n * This module is copied from:\n * .\n *\n * > 👉 **Note**: `textarea` was added in `CommonMark@0.30`.\n */\nexport const htmlRawNames = ['pre', 'script', 'style', 'textarea']\n","import {values} from 'micromark-util-symbol'\n\n/**\n * Normalize an identifier (as found in references, definitions).\n *\n * Collapses markdown whitespace, trim, and then lower- and uppercase.\n *\n * Some characters are considered “uppercase”, such as U+03F4 (`ϴ`), but if their\n * lowercase counterpart (U+03B8 (`θ`)) is uppercased will result in a different\n * uppercase character (U+0398 (`Θ`)).\n * So, to get a canonical form, we perform both lower- and uppercase.\n *\n * Using uppercase last makes sure keys will never interact with default\n * prototypal values (such as `constructor`): nothing in the prototype of\n * `Object` is uppercase.\n *\n * @param {string} value\n * Identifier to normalize.\n * @returns {string}\n * Normalized identifier.\n */\nexport function normalizeIdentifier(value) {\n return (\n value\n // Collapse markdown whitespace.\n .replace(/[\\t\\n\\r ]+/g, values.space)\n // Trim.\n .replace(/^ | $/g, '')\n // Some characters are considered “uppercase”, but if their lowercase\n // counterpart is uppercased will result in a different uppercase\n // character.\n // Hence, to get that form, we perform both lower- and uppercase.\n // Upper case makes sure keys will not interact with default prototypal\n // methods: no method is uppercase.\n .toLowerCase()\n .toUpperCase()\n )\n}\n","/**\n * @typedef {import('micromark-util-types').Event} Event\n * @typedef {import('micromark-util-types').Resolver} Resolver\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n */\n\n/**\n * Call all `resolveAll`s.\n *\n * @param {Array<{resolveAll?: Resolver | undefined}>} constructs\n * List of constructs, optionally with `resolveAll`s.\n * @param {Array} events\n * List of events.\n * @param {TokenizeContext} context\n * Context used by `tokenize`.\n * @returns {Array}\n * Changed events.\n */\nexport function resolveAll(constructs, events, context) {\n /** @type {Array} */\n const called = []\n let index = -1\n\n while (++index < constructs.length) {\n const resolve = constructs[index].resolveAll\n\n if (resolve && !called.includes(resolve)) {\n events = resolve(events, context)\n called.push(resolve)\n }\n }\n\n return events\n}\n","import {asciiAlphanumeric} from 'micromark-util-character'\nimport {encode} from 'micromark-util-encode'\nimport {codes, values} from 'micromark-util-symbol'\n\n/**\n * Make a value safe for injection as a URL.\n *\n * This encodes unsafe characters with percent-encoding and skips already\n * encoded sequences (see `normalizeUri`).\n * Further unsafe characters are encoded as character references (see\n * `micromark-util-encode`).\n *\n * A regex of allowed protocols can be given, in which case the URL is\n * sanitized.\n * For example, `/^(https?|ircs?|mailto|xmpp)$/i` can be used for `a[href]`, or\n * `/^https?$/i` for `img[src]` (this is what `github.com` allows).\n * If the URL includes an unknown protocol (one not matched by `protocol`, such\n * as a dangerous example, `javascript:`), the value is ignored.\n *\n * @param {string | null | undefined} url\n * URI to sanitize.\n * @param {RegExp | null | undefined} [protocol]\n * Allowed protocols.\n * @returns {string}\n * Sanitized URI.\n */\nexport function sanitizeUri(url, protocol) {\n const value = encode(normalizeUri(url || ''))\n\n if (!protocol) {\n return value\n }\n\n const colon = value.indexOf(':')\n const questionMark = value.indexOf('?')\n const numberSign = value.indexOf('#')\n const slash = value.indexOf('/')\n\n if (\n // If there is no protocol, it’s relative.\n colon < 0 ||\n // If the first colon is after a `?`, `#`, or `/`, it’s not a protocol.\n (slash > -1 && colon > slash) ||\n (questionMark > -1 && colon > questionMark) ||\n (numberSign > -1 && colon > numberSign) ||\n // It is a protocol, it should be allowed.\n protocol.test(value.slice(0, colon))\n ) {\n return value\n }\n\n return ''\n}\n\n/**\n * Normalize a URL.\n *\n * Encode unsafe characters with percent-encoding, skipping already encoded\n * sequences.\n *\n * @param {string} value\n * URI to normalize.\n * @returns {string}\n * Normalized URI.\n */\nexport function normalizeUri(value) {\n /** @type {Array} */\n const result = []\n let index = -1\n let start = 0\n let skip = 0\n\n while (++index < value.length) {\n const code = value.charCodeAt(index)\n /** @type {string} */\n let replace = ''\n\n // A correct percent encoded value.\n if (\n code === codes.percentSign &&\n asciiAlphanumeric(value.charCodeAt(index + 1)) &&\n asciiAlphanumeric(value.charCodeAt(index + 2))\n ) {\n skip = 2\n }\n // ASCII.\n else if (code < 128) {\n if (!/[!#$&-;=?-Z_a-z~]/.test(String.fromCharCode(code))) {\n replace = String.fromCharCode(code)\n }\n }\n // Astral.\n else if (code > 55_295 && code < 57_344) {\n const next = value.charCodeAt(index + 1)\n\n // A correct surrogate pair.\n if (code < 56_320 && next > 56_319 && next < 57_344) {\n replace = String.fromCharCode(code, next)\n skip = 1\n }\n // Lone surrogate.\n else {\n replace = values.replacementCharacter\n }\n }\n // Unicode.\n else {\n replace = String.fromCharCode(code)\n }\n\n if (replace) {\n result.push(value.slice(start, index), encodeURIComponent(replace))\n start = index + skip + 1\n replace = ''\n }\n\n if (skip) {\n index += skip\n skip = 0\n }\n }\n\n return result.join('') + value.slice(start)\n}\n","/**\n * @typedef {import('micromark-util-types').Chunk} Chunk\n * @typedef {import('micromark-util-types').Event} Event\n * @typedef {import('micromark-util-types').Token} Token\n */\n\nimport {splice} from 'micromark-util-chunked'\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/**\n * Tokenize subcontent.\n *\n * @param {Array} events\n * List of events.\n * @returns {boolean}\n * Whether subtokens were found.\n */\n// eslint-disable-next-line complexity\nexport function subtokenize(events) {\n /** @type {Record} */\n const jumps = {}\n let index = -1\n /** @type {Event} */\n let event\n /** @type {number | undefined} */\n let lineIndex\n /** @type {number} */\n let otherIndex\n /** @type {Event} */\n let otherEvent\n /** @type {Array} */\n let parameters\n /** @type {Array} */\n let subevents\n /** @type {boolean | undefined} */\n let more\n\n while (++index < events.length) {\n while (index in jumps) {\n index = jumps[index]\n }\n\n event = events[index]\n\n // Add a hook for the GFM tasklist extension, which needs to know if text\n // is in the first content of a list item.\n if (\n index &&\n event[1].type === types.chunkFlow &&\n events[index - 1][1].type === types.listItemPrefix\n ) {\n assert(event[1]._tokenizer, 'expected `_tokenizer` on subtokens')\n subevents = event[1]._tokenizer.events\n otherIndex = 0\n\n if (\n otherIndex < subevents.length &&\n subevents[otherIndex][1].type === types.lineEndingBlank\n ) {\n otherIndex += 2\n }\n\n if (\n otherIndex < subevents.length &&\n subevents[otherIndex][1].type === types.content\n ) {\n while (++otherIndex < subevents.length) {\n if (subevents[otherIndex][1].type === types.content) {\n break\n }\n\n if (subevents[otherIndex][1].type === types.chunkText) {\n subevents[otherIndex][1]._isInFirstContentOfListItem = true\n otherIndex++\n }\n }\n }\n }\n\n // Enter.\n if (event[0] === 'enter') {\n if (event[1].contentType) {\n Object.assign(jumps, subcontent(events, index))\n index = jumps[index]\n more = true\n }\n }\n // Exit.\n else if (event[1]._container) {\n otherIndex = index\n lineIndex = undefined\n\n while (otherIndex--) {\n otherEvent = events[otherIndex]\n\n if (\n otherEvent[1].type === types.lineEnding ||\n otherEvent[1].type === types.lineEndingBlank\n ) {\n if (otherEvent[0] === 'enter') {\n if (lineIndex) {\n events[lineIndex][1].type = types.lineEndingBlank\n }\n\n otherEvent[1].type = types.lineEnding\n lineIndex = otherIndex\n }\n } else {\n break\n }\n }\n\n if (lineIndex) {\n // Fix position.\n event[1].end = Object.assign({}, events[lineIndex][1].start)\n\n // Switch container exit w/ line endings.\n parameters = events.slice(lineIndex, index)\n parameters.unshift(event)\n splice(events, lineIndex, index - lineIndex + 1, parameters)\n }\n }\n }\n\n return !more\n}\n\n/**\n * Tokenize embedded tokens.\n *\n * @param {Array} events\n * @param {number} eventIndex\n * @returns {Record}\n */\nfunction subcontent(events, eventIndex) {\n const token = events[eventIndex][1]\n const context = events[eventIndex][2]\n let startPosition = eventIndex - 1\n /** @type {Array} */\n const startPositions = []\n assert(token.contentType, 'expected `contentType` on subtokens')\n const tokenizer =\n token._tokenizer || context.parser[token.contentType](token.start)\n const childEvents = tokenizer.events\n /** @type {Array<[number, number]>} */\n const jumps = []\n /** @type {Record} */\n const gaps = {}\n /** @type {Array} */\n let stream\n /** @type {Token | undefined} */\n let previous\n let index = -1\n /** @type {Token | undefined} */\n let current = token\n let adjust = 0\n let start = 0\n const breaks = [start]\n\n // Loop forward through the linked tokens to pass them in order to the\n // subtokenizer.\n while (current) {\n // Find the position of the event for this token.\n while (events[++startPosition][1] !== current) {\n // Empty.\n }\n\n assert(\n !previous || current.previous === previous,\n 'expected previous to match'\n )\n assert(!previous || previous.next === current, 'expected next to match')\n\n startPositions.push(startPosition)\n\n if (!current._tokenizer) {\n stream = context.sliceStream(current)\n\n if (!current.next) {\n stream.push(codes.eof)\n }\n\n if (previous) {\n tokenizer.defineSkip(current.start)\n }\n\n if (current._isInFirstContentOfListItem) {\n tokenizer._gfmTasklistFirstContentOfListItem = true\n }\n\n tokenizer.write(stream)\n\n if (current._isInFirstContentOfListItem) {\n tokenizer._gfmTasklistFirstContentOfListItem = undefined\n }\n }\n\n // Unravel the next token.\n previous = current\n current = current.next\n }\n\n // Now, loop back through all events (and linked tokens), to figure out which\n // parts belong where.\n current = token\n\n while (++index < childEvents.length) {\n if (\n // Find a void token that includes a break.\n childEvents[index][0] === 'exit' &&\n childEvents[index - 1][0] === 'enter' &&\n childEvents[index][1].type === childEvents[index - 1][1].type &&\n childEvents[index][1].start.line !== childEvents[index][1].end.line\n ) {\n assert(current, 'expected a current token')\n start = index + 1\n breaks.push(start)\n // Help GC.\n current._tokenizer = undefined\n current.previous = undefined\n current = current.next\n }\n }\n\n // Help GC.\n tokenizer.events = []\n\n // If there’s one more token (which is the cases for lines that end in an\n // EOF), that’s perfect: the last point we found starts it.\n // If there isn’t then make sure any remaining content is added to it.\n if (current) {\n // Help GC.\n current._tokenizer = undefined\n current.previous = undefined\n assert(!current.next, 'expected no next token')\n } else {\n breaks.pop()\n }\n\n // Now splice the events from the subtokenizer into the current events,\n // moving back to front so that splice indices aren’t affected.\n index = breaks.length\n\n while (index--) {\n const slice = childEvents.slice(breaks[index], breaks[index + 1])\n const start = startPositions.pop()\n assert(start !== undefined, 'expected a start position when splicing')\n jumps.unshift([start, start + slice.length - 1])\n splice(events, start, 2, slice)\n }\n\n index = -1\n\n while (++index < jumps.length) {\n gaps[adjust + jumps[index][0]] = adjust + jumps[index][1]\n adjust += jumps[index][1] - jumps[index][0] - 1\n }\n\n return gaps\n}\n","/**\n * Character codes.\n *\n * This module is compiled away!\n *\n * micromark works based on character codes.\n * This module contains constants for the ASCII block and the replacement\n * character.\n * A couple of them are handled in a special way, such as the line endings\n * (CR, LF, and CR+LF, commonly known as end-of-line: EOLs), the tab (horizontal\n * tab) and its expansion based on what column it’s at (virtual space),\n * and the end-of-file (eof) character.\n * As values are preprocessed before handling them, the actual characters LF,\n * CR, HT, and NUL (which is present as the replacement character), are\n * guaranteed to not exist.\n *\n * Unicode basic latin block.\n */\nexport const codes = /** @type {const} */ ({\n carriageReturn: -5,\n lineFeed: -4,\n carriageReturnLineFeed: -3,\n horizontalTab: -2,\n virtualSpace: -1,\n eof: null,\n nul: 0,\n soh: 1,\n stx: 2,\n etx: 3,\n eot: 4,\n enq: 5,\n ack: 6,\n bel: 7,\n bs: 8,\n ht: 9, // `\\t`\n lf: 10, // `\\n`\n vt: 11, // `\\v`\n ff: 12, // `\\f`\n cr: 13, // `\\r`\n so: 14,\n si: 15,\n dle: 16,\n dc1: 17,\n dc2: 18,\n dc3: 19,\n dc4: 20,\n nak: 21,\n syn: 22,\n etb: 23,\n can: 24,\n em: 25,\n sub: 26,\n esc: 27,\n fs: 28,\n gs: 29,\n rs: 30,\n us: 31,\n space: 32,\n exclamationMark: 33, // `!`\n quotationMark: 34, // `\"`\n numberSign: 35, // `#`\n dollarSign: 36, // `$`\n percentSign: 37, // `%`\n ampersand: 38, // `&`\n apostrophe: 39, // `'`\n leftParenthesis: 40, // `(`\n rightParenthesis: 41, // `)`\n asterisk: 42, // `*`\n plusSign: 43, // `+`\n comma: 44, // `,`\n dash: 45, // `-`\n dot: 46, // `.`\n slash: 47, // `/`\n digit0: 48, // `0`\n digit1: 49, // `1`\n digit2: 50, // `2`\n digit3: 51, // `3`\n digit4: 52, // `4`\n digit5: 53, // `5`\n digit6: 54, // `6`\n digit7: 55, // `7`\n digit8: 56, // `8`\n digit9: 57, // `9`\n colon: 58, // `:`\n semicolon: 59, // `;`\n lessThan: 60, // `<`\n equalsTo: 61, // `=`\n greaterThan: 62, // `>`\n questionMark: 63, // `?`\n atSign: 64, // `@`\n uppercaseA: 65, // `A`\n uppercaseB: 66, // `B`\n uppercaseC: 67, // `C`\n uppercaseD: 68, // `D`\n uppercaseE: 69, // `E`\n uppercaseF: 70, // `F`\n uppercaseG: 71, // `G`\n uppercaseH: 72, // `H`\n uppercaseI: 73, // `I`\n uppercaseJ: 74, // `J`\n uppercaseK: 75, // `K`\n uppercaseL: 76, // `L`\n uppercaseM: 77, // `M`\n uppercaseN: 78, // `N`\n uppercaseO: 79, // `O`\n uppercaseP: 80, // `P`\n uppercaseQ: 81, // `Q`\n uppercaseR: 82, // `R`\n uppercaseS: 83, // `S`\n uppercaseT: 84, // `T`\n uppercaseU: 85, // `U`\n uppercaseV: 86, // `V`\n uppercaseW: 87, // `W`\n uppercaseX: 88, // `X`\n uppercaseY: 89, // `Y`\n uppercaseZ: 90, // `Z`\n leftSquareBracket: 91, // `[`\n backslash: 92, // `\\`\n rightSquareBracket: 93, // `]`\n caret: 94, // `^`\n underscore: 95, // `_`\n graveAccent: 96, // `` ` ``\n lowercaseA: 97, // `a`\n lowercaseB: 98, // `b`\n lowercaseC: 99, // `c`\n lowercaseD: 100, // `d`\n lowercaseE: 101, // `e`\n lowercaseF: 102, // `f`\n lowercaseG: 103, // `g`\n lowercaseH: 104, // `h`\n lowercaseI: 105, // `i`\n lowercaseJ: 106, // `j`\n lowercaseK: 107, // `k`\n lowercaseL: 108, // `l`\n lowercaseM: 109, // `m`\n lowercaseN: 110, // `n`\n lowercaseO: 111, // `o`\n lowercaseP: 112, // `p`\n lowercaseQ: 113, // `q`\n lowercaseR: 114, // `r`\n lowercaseS: 115, // `s`\n lowercaseT: 116, // `t`\n lowercaseU: 117, // `u`\n lowercaseV: 118, // `v`\n lowercaseW: 119, // `w`\n lowercaseX: 120, // `x`\n lowercaseY: 121, // `y`\n lowercaseZ: 122, // `z`\n leftCurlyBrace: 123, // `{`\n verticalBar: 124, // `|`\n rightCurlyBrace: 125, // `}`\n tilde: 126, // `~`\n del: 127,\n // Unicode Specials block.\n byteOrderMarker: 65279,\n // Unicode Specials block.\n replacementCharacter: 65533 // `�`\n})\n","/**\n * This module is compiled away!\n *\n * Parsing markdown comes with a couple of constants, such as minimum or maximum\n * sizes of certain sequences.\n * Additionally, there are a couple symbols used inside micromark.\n * These are all defined here, but compiled away by scripts.\n */\nexport const constants = /** @type {const} */ ({\n attentionSideBefore: 1, // Symbol to mark an attention sequence as before content: `*a`\n attentionSideAfter: 2, // Symbol to mark an attention sequence as after content: `a*`\n atxHeadingOpeningFenceSizeMax: 6, // 6 number signs is fine, 7 isn’t.\n autolinkDomainSizeMax: 63, // 63 characters is fine, 64 is too many.\n autolinkSchemeSizeMax: 32, // 32 characters is fine, 33 is too many.\n cdataOpeningString: 'CDATA[', // And preceded by ``\n htmlComment: 2, // Symbol for ``\n htmlInstruction: 3, // Symbol for ``\n htmlDeclaration: 4, // Symbol for ``\n htmlCdata: 5, // Symbol for ``\n htmlBasic: 6, // Symbol for ``\n htmlRawSizeMax: 8, // Length of `textarea`.\n linkResourceDestinationBalanceMax: 32, // See: , \n linkReferenceSizeMax: 999, // See: \n listItemValueSizeMax: 10, // See: \n numericBaseDecimal: 10,\n numericBaseHexadecimal: 0x10,\n tabSize: 4, // Tabs have a hard-coded size of 4, per CommonMark.\n thematicBreakMarkerCountMin: 3, // At least 3 asterisks, dashes, or underscores are needed.\n v8MaxSafeChunkSize: 10000 // V8 (and potentially others) have problems injecting giant arrays into other arrays, hence we operate in chunks.\n})\n","/**\n * This module is compiled away!\n *\n * Here is the list of all types of tokens exposed by micromark, with a short\n * explanation of what they include and where they are found.\n * In picking names, generally, the rule is to be as explicit as possible\n * instead of reusing names.\n * For example, there is a `definitionDestination` and a `resourceDestination`,\n * instead of one shared name.\n */\n\n// Note: when changing the next record, you must also change `TokenTypeMap`\n// in `micromark-util-types/index.d.ts`.\nexport const types = /** @type {const} */ ({\n // Generic type for data, such as in a title, a destination, etc.\n data: 'data',\n\n // Generic type for syntactic whitespace (tabs, virtual spaces, spaces).\n // Such as, between a fenced code fence and an info string.\n whitespace: 'whitespace',\n\n // Generic type for line endings (line feed, carriage return, carriage return +\n // line feed).\n lineEnding: 'lineEnding',\n\n // A line ending, but ending a blank line.\n lineEndingBlank: 'lineEndingBlank',\n\n // Generic type for whitespace (tabs, virtual spaces, spaces) at the start of a\n // line.\n linePrefix: 'linePrefix',\n\n // Generic type for whitespace (tabs, virtual spaces, spaces) at the end of a\n // line.\n lineSuffix: 'lineSuffix',\n\n // Whole ATX heading:\n //\n // ```markdown\n // #\n // ## Alpha\n // ### Bravo ###\n // ```\n //\n // Includes `atxHeadingSequence`, `whitespace`, `atxHeadingText`.\n atxHeading: 'atxHeading',\n\n // Sequence of number signs in an ATX heading (`###`).\n atxHeadingSequence: 'atxHeadingSequence',\n\n // Content in an ATX heading (`alpha`).\n // Includes text.\n atxHeadingText: 'atxHeadingText',\n\n // Whole autolink (`` or ``)\n // Includes `autolinkMarker` and `autolinkProtocol` or `autolinkEmail`.\n autolink: 'autolink',\n\n // Email autolink w/o markers (`admin@example.com`)\n autolinkEmail: 'autolinkEmail',\n\n // Marker around an `autolinkProtocol` or `autolinkEmail` (`<` or `>`).\n autolinkMarker: 'autolinkMarker',\n\n // Protocol autolink w/o markers (`https://example.com`)\n autolinkProtocol: 'autolinkProtocol',\n\n // A whole character escape (`\\-`).\n // Includes `escapeMarker` and `characterEscapeValue`.\n characterEscape: 'characterEscape',\n\n // The escaped character (`-`).\n characterEscapeValue: 'characterEscapeValue',\n\n // A whole character reference (`&`, `≠`, or `𝌆`).\n // Includes `characterReferenceMarker`, an optional\n // `characterReferenceMarkerNumeric`, in which case an optional\n // `characterReferenceMarkerHexadecimal`, and a `characterReferenceValue`.\n characterReference: 'characterReference',\n\n // The start or end marker (`&` or `;`).\n characterReferenceMarker: 'characterReferenceMarker',\n\n // Mark reference as numeric (`#`).\n characterReferenceMarkerNumeric: 'characterReferenceMarkerNumeric',\n\n // Mark reference as numeric (`x` or `X`).\n characterReferenceMarkerHexadecimal: 'characterReferenceMarkerHexadecimal',\n\n // Value of character reference w/o markers (`amp`, `8800`, or `1D306`).\n characterReferenceValue: 'characterReferenceValue',\n\n // Whole fenced code:\n //\n // ````markdown\n // ```js\n // alert(1)\n // ```\n // ````\n codeFenced: 'codeFenced',\n\n // A fenced code fence, including whitespace, sequence, info, and meta\n // (` ```js `).\n codeFencedFence: 'codeFencedFence',\n\n // Sequence of grave accent or tilde characters (` ``` `) in a fence.\n codeFencedFenceSequence: 'codeFencedFenceSequence',\n\n // Info word (`js`) in a fence.\n // Includes string.\n codeFencedFenceInfo: 'codeFencedFenceInfo',\n\n // Meta words (`highlight=\"1\"`) in a fence.\n // Includes string.\n codeFencedFenceMeta: 'codeFencedFenceMeta',\n\n // A line of code.\n codeFlowValue: 'codeFlowValue',\n\n // Whole indented code:\n //\n // ```markdown\n // alert(1)\n // ```\n //\n // Includes `lineEnding`, `linePrefix`, and `codeFlowValue`.\n codeIndented: 'codeIndented',\n\n // A text code (``` `alpha` ```).\n // Includes `codeTextSequence`, `codeTextData`, `lineEnding`, and can include\n // `codeTextPadding`.\n codeText: 'codeText',\n\n codeTextData: 'codeTextData',\n\n // A space or line ending right after or before a tick.\n codeTextPadding: 'codeTextPadding',\n\n // A text code fence (` `` `).\n codeTextSequence: 'codeTextSequence',\n\n // Whole content:\n //\n // ```markdown\n // [a]: b\n // c\n // =\n // d\n // ```\n //\n // Includes `paragraph` and `definition`.\n content: 'content',\n // Whole definition:\n //\n // ```markdown\n // [micromark]: https://github.com/micromark/micromark\n // ```\n //\n // Includes `definitionLabel`, `definitionMarker`, `whitespace`,\n // `definitionDestination`, and optionally `lineEnding` and `definitionTitle`.\n definition: 'definition',\n\n // Destination of a definition (`https://github.com/micromark/micromark` or\n // ``).\n // Includes `definitionDestinationLiteral` or `definitionDestinationRaw`.\n definitionDestination: 'definitionDestination',\n\n // Enclosed destination of a definition\n // (``).\n // Includes `definitionDestinationLiteralMarker` and optionally\n // `definitionDestinationString`.\n definitionDestinationLiteral: 'definitionDestinationLiteral',\n\n // Markers of an enclosed definition destination (`<` or `>`).\n definitionDestinationLiteralMarker: 'definitionDestinationLiteralMarker',\n\n // Unenclosed destination of a definition\n // (`https://github.com/micromark/micromark`).\n // Includes `definitionDestinationString`.\n definitionDestinationRaw: 'definitionDestinationRaw',\n\n // Text in an destination (`https://github.com/micromark/micromark`).\n // Includes string.\n definitionDestinationString: 'definitionDestinationString',\n\n // Label of a definition (`[micromark]`).\n // Includes `definitionLabelMarker` and `definitionLabelString`.\n definitionLabel: 'definitionLabel',\n\n // Markers of a definition label (`[` or `]`).\n definitionLabelMarker: 'definitionLabelMarker',\n\n // Value of a definition label (`micromark`).\n // Includes string.\n definitionLabelString: 'definitionLabelString',\n\n // Marker between a label and a destination (`:`).\n definitionMarker: 'definitionMarker',\n\n // Title of a definition (`\"x\"`, `'y'`, or `(z)`).\n // Includes `definitionTitleMarker` and optionally `definitionTitleString`.\n definitionTitle: 'definitionTitle',\n\n // Marker around a title of a definition (`\"`, `'`, `(`, or `)`).\n definitionTitleMarker: 'definitionTitleMarker',\n\n // Data without markers in a title (`z`).\n // Includes string.\n definitionTitleString: 'definitionTitleString',\n\n // Emphasis (`*alpha*`).\n // Includes `emphasisSequence` and `emphasisText`.\n emphasis: 'emphasis',\n\n // Sequence of emphasis markers (`*` or `_`).\n emphasisSequence: 'emphasisSequence',\n\n // Emphasis text (`alpha`).\n // Includes text.\n emphasisText: 'emphasisText',\n\n // The character escape marker (`\\`).\n escapeMarker: 'escapeMarker',\n\n // A hard break created with a backslash (`\\\\n`).\n // Note: does not include the line ending.\n hardBreakEscape: 'hardBreakEscape',\n\n // A hard break created with trailing spaces (` \\n`).\n // Does not include the line ending.\n hardBreakTrailing: 'hardBreakTrailing',\n\n // Flow HTML:\n //\n // ```markdown\n // b`).\n // Includes `lineEnding`, `htmlTextData`.\n htmlText: 'htmlText',\n\n htmlTextData: 'htmlTextData',\n\n // Whole image (``, `![alpha][bravo]`, `![alpha][]`, or\n // `![alpha]`).\n // Includes `label` and an optional `resource` or `reference`.\n image: 'image',\n\n // Whole link label (`[*alpha*]`).\n // Includes `labelLink` or `labelImage`, `labelText`, and `labelEnd`.\n label: 'label',\n\n // Text in an label (`*alpha*`).\n // Includes text.\n labelText: 'labelText',\n\n // Start a link label (`[`).\n // Includes a `labelMarker`.\n labelLink: 'labelLink',\n\n // Start an image label (`![`).\n // Includes `labelImageMarker` and `labelMarker`.\n labelImage: 'labelImage',\n\n // Marker of a label (`[` or `]`).\n labelMarker: 'labelMarker',\n\n // Marker to start an image (`!`).\n labelImageMarker: 'labelImageMarker',\n\n // End a label (`]`).\n // Includes `labelMarker`.\n labelEnd: 'labelEnd',\n\n // Whole link (`[alpha](bravo)`, `[alpha][bravo]`, `[alpha][]`, or `[alpha]`).\n // Includes `label` and an optional `resource` or `reference`.\n link: 'link',\n\n // Whole paragraph:\n //\n // ```markdown\n // alpha\n // bravo.\n // ```\n //\n // Includes text.\n paragraph: 'paragraph',\n\n // A reference (`[alpha]` or `[]`).\n // Includes `referenceMarker` and an optional `referenceString`.\n reference: 'reference',\n\n // A reference marker (`[` or `]`).\n referenceMarker: 'referenceMarker',\n\n // Reference text (`alpha`).\n // Includes string.\n referenceString: 'referenceString',\n\n // A resource (`(https://example.com \"alpha\")`).\n // Includes `resourceMarker`, an optional `resourceDestination` with an optional\n // `whitespace` and `resourceTitle`.\n resource: 'resource',\n\n // A resource destination (`https://example.com`).\n // Includes `resourceDestinationLiteral` or `resourceDestinationRaw`.\n resourceDestination: 'resourceDestination',\n\n // A literal resource destination (``).\n // Includes `resourceDestinationLiteralMarker` and optionally\n // `resourceDestinationString`.\n resourceDestinationLiteral: 'resourceDestinationLiteral',\n\n // A resource destination marker (`<` or `>`).\n resourceDestinationLiteralMarker: 'resourceDestinationLiteralMarker',\n\n // A raw resource destination (`https://example.com`).\n // Includes `resourceDestinationString`.\n resourceDestinationRaw: 'resourceDestinationRaw',\n\n // Resource destination text (`https://example.com`).\n // Includes string.\n resourceDestinationString: 'resourceDestinationString',\n\n // A resource marker (`(` or `)`).\n resourceMarker: 'resourceMarker',\n\n // A resource title (`\"alpha\"`, `'alpha'`, or `(alpha)`).\n // Includes `resourceTitleMarker` and optionally `resourceTitleString`.\n resourceTitle: 'resourceTitle',\n\n // A resource title marker (`\"`, `'`, `(`, or `)`).\n resourceTitleMarker: 'resourceTitleMarker',\n\n // Resource destination title (`alpha`).\n // Includes string.\n resourceTitleString: 'resourceTitleString',\n\n // Whole setext heading:\n //\n // ```markdown\n // alpha\n // bravo\n // =====\n // ```\n //\n // Includes `setextHeadingText`, `lineEnding`, `linePrefix`, and\n // `setextHeadingLine`.\n setextHeading: 'setextHeading',\n\n // Content in a setext heading (`alpha\\nbravo`).\n // Includes text.\n setextHeadingText: 'setextHeadingText',\n\n // Underline in a setext heading, including whitespace suffix (`==`).\n // Includes `setextHeadingLineSequence`.\n setextHeadingLine: 'setextHeadingLine',\n\n // Sequence of equals or dash characters in underline in a setext heading (`-`).\n setextHeadingLineSequence: 'setextHeadingLineSequence',\n\n // Strong (`**alpha**`).\n // Includes `strongSequence` and `strongText`.\n strong: 'strong',\n\n // Sequence of strong markers (`**` or `__`).\n strongSequence: 'strongSequence',\n\n // Strong text (`alpha`).\n // Includes text.\n strongText: 'strongText',\n\n // Whole thematic break:\n //\n // ```markdown\n // * * *\n // ```\n //\n // Includes `thematicBreakSequence` and `whitespace`.\n thematicBreak: 'thematicBreak',\n\n // A sequence of one or more thematic break markers (`***`).\n thematicBreakSequence: 'thematicBreakSequence',\n\n // Whole block quote:\n //\n // ```markdown\n // > a\n // >\n // > b\n // ```\n //\n // Includes `blockQuotePrefix` and flow.\n blockQuote: 'blockQuote',\n // The `>` or `> ` of a block quote.\n blockQuotePrefix: 'blockQuotePrefix',\n // The `>` of a block quote prefix.\n blockQuoteMarker: 'blockQuoteMarker',\n // The optional ` ` of a block quote prefix.\n blockQuotePrefixWhitespace: 'blockQuotePrefixWhitespace',\n\n // Whole unordered list:\n //\n // ```markdown\n // - a\n // b\n // ```\n //\n // Includes `listItemPrefix`, flow, and optionally `listItemIndent` on further\n // lines.\n listOrdered: 'listOrdered',\n\n // Whole ordered list:\n //\n // ```markdown\n // 1. a\n // b\n // ```\n //\n // Includes `listItemPrefix`, flow, and optionally `listItemIndent` on further\n // lines.\n listUnordered: 'listUnordered',\n\n // The indent of further list item lines.\n listItemIndent: 'listItemIndent',\n\n // A marker, as in, `*`, `+`, `-`, `.`, or `)`.\n listItemMarker: 'listItemMarker',\n\n // The thing that starts a list item, such as `1. `.\n // Includes `listItemValue` if ordered, `listItemMarker`, and\n // `listItemPrefixWhitespace` (unless followed by a line ending).\n listItemPrefix: 'listItemPrefix',\n\n // The whitespace after a marker.\n listItemPrefixWhitespace: 'listItemPrefixWhitespace',\n\n // The numerical value of an ordered item.\n listItemValue: 'listItemValue',\n\n // Internal types used for subtokenizers, compiled away\n chunkDocument: 'chunkDocument',\n chunkContent: 'chunkContent',\n chunkFlow: 'chunkFlow',\n chunkText: 'chunkText',\n chunkString: 'chunkString'\n})\n","/**\n * This module is compiled away!\n *\n * While micromark works based on character codes, this module includes the\n * string versions of ’em.\n * The C0 block, except for LF, CR, HT, and w/ the replacement character added,\n * are available here.\n */\nexport const values = /** @type {const} */ ({\n ht: '\\t',\n lf: '\\n',\n cr: '\\r',\n space: ' ',\n exclamationMark: '!',\n quotationMark: '\"',\n numberSign: '#',\n dollarSign: '$',\n percentSign: '%',\n ampersand: '&',\n apostrophe: \"'\",\n leftParenthesis: '(',\n rightParenthesis: ')',\n asterisk: '*',\n plusSign: '+',\n comma: ',',\n dash: '-',\n dot: '.',\n slash: '/',\n digit0: '0',\n digit1: '1',\n digit2: '2',\n digit3: '3',\n digit4: '4',\n digit5: '5',\n digit6: '6',\n digit7: '7',\n digit8: '8',\n digit9: '9',\n colon: ':',\n semicolon: ';',\n lessThan: '<',\n equalsTo: '=',\n greaterThan: '>',\n questionMark: '?',\n atSign: '@',\n uppercaseA: 'A',\n uppercaseB: 'B',\n uppercaseC: 'C',\n uppercaseD: 'D',\n uppercaseE: 'E',\n uppercaseF: 'F',\n uppercaseG: 'G',\n uppercaseH: 'H',\n uppercaseI: 'I',\n uppercaseJ: 'J',\n uppercaseK: 'K',\n uppercaseL: 'L',\n uppercaseM: 'M',\n uppercaseN: 'N',\n uppercaseO: 'O',\n uppercaseP: 'P',\n uppercaseQ: 'Q',\n uppercaseR: 'R',\n uppercaseS: 'S',\n uppercaseT: 'T',\n uppercaseU: 'U',\n uppercaseV: 'V',\n uppercaseW: 'W',\n uppercaseX: 'X',\n uppercaseY: 'Y',\n uppercaseZ: 'Z',\n leftSquareBracket: '[',\n backslash: '\\\\',\n rightSquareBracket: ']',\n caret: '^',\n underscore: '_',\n graveAccent: '`',\n lowercaseA: 'a',\n lowercaseB: 'b',\n lowercaseC: 'c',\n lowercaseD: 'd',\n lowercaseE: 'e',\n lowercaseF: 'f',\n lowercaseG: 'g',\n lowercaseH: 'h',\n lowercaseI: 'i',\n lowercaseJ: 'j',\n lowercaseK: 'k',\n lowercaseL: 'l',\n lowercaseM: 'm',\n lowercaseN: 'n',\n lowercaseO: 'o',\n lowercaseP: 'p',\n lowercaseQ: 'q',\n lowercaseR: 'r',\n lowercaseS: 's',\n lowercaseT: 't',\n lowercaseU: 'u',\n lowercaseV: 'v',\n lowercaseW: 'w',\n lowercaseX: 'x',\n lowercaseY: 'y',\n lowercaseZ: 'z',\n leftCurlyBrace: '{',\n verticalBar: '|',\n rightCurlyBrace: '}',\n tilde: '~',\n replacementCharacter: '�'\n})\n","/**\n * @typedef {import('micromark-util-types').Extension} Extension\n */\n\nimport {\n attention,\n autolink,\n blockQuote,\n characterEscape,\n characterReference,\n codeFenced,\n codeIndented,\n codeText,\n definition,\n hardBreakEscape,\n headingAtx,\n htmlFlow,\n htmlText,\n labelEnd,\n labelStartImage,\n labelStartLink,\n lineEnding,\n list,\n setextUnderline,\n thematicBreak\n} from 'micromark-core-commonmark'\nimport {codes} from 'micromark-util-symbol'\nimport {resolver as resolveText} from './initialize/text.js'\n\n/** @satisfies {Extension['document']} */\nexport const document = {\n [codes.asterisk]: list,\n [codes.plusSign]: list,\n [codes.dash]: list,\n [codes.digit0]: list,\n [codes.digit1]: list,\n [codes.digit2]: list,\n [codes.digit3]: list,\n [codes.digit4]: list,\n [codes.digit5]: list,\n [codes.digit6]: list,\n [codes.digit7]: list,\n [codes.digit8]: list,\n [codes.digit9]: list,\n [codes.greaterThan]: blockQuote\n}\n\n/** @satisfies {Extension['contentInitial']} */\nexport const contentInitial = {\n [codes.leftSquareBracket]: definition\n}\n\n/** @satisfies {Extension['flowInitial']} */\nexport const flowInitial = {\n [codes.horizontalTab]: codeIndented,\n [codes.virtualSpace]: codeIndented,\n [codes.space]: codeIndented\n}\n\n/** @satisfies {Extension['flow']} */\nexport const flow = {\n [codes.numberSign]: headingAtx,\n [codes.asterisk]: thematicBreak,\n [codes.dash]: [setextUnderline, thematicBreak],\n [codes.lessThan]: htmlFlow,\n [codes.equalsTo]: setextUnderline,\n [codes.underscore]: thematicBreak,\n [codes.graveAccent]: codeFenced,\n [codes.tilde]: codeFenced\n}\n\n/** @satisfies {Extension['string']} */\nexport const string = {\n [codes.ampersand]: characterReference,\n [codes.backslash]: characterEscape\n}\n\n/** @satisfies {Extension['text']} */\nexport const text = {\n [codes.carriageReturn]: lineEnding,\n [codes.lineFeed]: lineEnding,\n [codes.carriageReturnLineFeed]: lineEnding,\n [codes.exclamationMark]: labelStartImage,\n [codes.ampersand]: characterReference,\n [codes.asterisk]: attention,\n [codes.lessThan]: [autolink, htmlText],\n [codes.leftSquareBracket]: labelStartLink,\n [codes.backslash]: [hardBreakEscape, characterEscape],\n [codes.rightSquareBracket]: labelEnd,\n [codes.underscore]: attention,\n [codes.graveAccent]: codeText\n}\n\n/** @satisfies {Extension['insideSpan']} */\nexport const insideSpan = {null: [attention, resolveText]}\n\n/** @satisfies {Extension['attentionMarkers']} */\nexport const attentionMarkers = {null: [codes.asterisk, codes.underscore]}\n\n/** @satisfies {Extension['disable']} */\nexport const disable = {null: []}\n","/**\n * @typedef {import('micromark-util-types').Chunk} Chunk\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').ConstructRecord} ConstructRecord\n * @typedef {import('micromark-util-types').Effects} Effects\n * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct\n * @typedef {import('micromark-util-types').ParseContext} ParseContext\n * @typedef {import('micromark-util-types').Point} Point\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').Token} Token\n * @typedef {import('micromark-util-types').TokenType} TokenType\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n */\n\n/**\n * @callback Restore\n * @returns {undefined}\n *\n * @typedef Info\n * @property {Restore} restore\n * @property {number} from\n *\n * @callback ReturnHandle\n * Handle a successful run.\n * @param {Construct} construct\n * @param {Info} info\n * @returns {undefined}\n */\n\nimport createDebug from 'debug'\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {push, splice} from 'micromark-util-chunked'\nimport {resolveAll} from 'micromark-util-resolve-all'\nimport {codes, values} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\nconst debug = createDebug('micromark')\n\n/**\n * Create a tokenizer.\n * Tokenizers deal with one type of data (e.g., containers, flow, text).\n * The parser is the object dealing with it all.\n * `initialize` works like other constructs, except that only its `tokenize`\n * function is used, in which case it doesn’t receive an `ok` or `nok`.\n * `from` can be given to set the point before the first character, although\n * when further lines are indented, they must be set with `defineSkip`.\n *\n * @param {ParseContext} parser\n * @param {InitialConstruct} initialize\n * @param {Omit | undefined} [from]\n * @returns {TokenizeContext}\n */\nexport function createTokenizer(parser, initialize, from) {\n /** @type {Point} */\n let point = Object.assign(\n from ? Object.assign({}, from) : {line: 1, column: 1, offset: 0},\n {_index: 0, _bufferIndex: -1}\n )\n /** @type {Record} */\n const columnStart = {}\n /** @type {Array} */\n const resolveAllConstructs = []\n /** @type {Array} */\n let chunks = []\n /** @type {Array} */\n let stack = []\n /** @type {boolean | undefined} */\n let consumed = true\n\n /**\n * Tools used for tokenizing.\n *\n * @type {Effects}\n */\n const effects = {\n consume,\n enter,\n exit,\n attempt: constructFactory(onsuccessfulconstruct),\n check: constructFactory(onsuccessfulcheck),\n interrupt: constructFactory(onsuccessfulcheck, {interrupt: true})\n }\n\n /**\n * State and tools for resolving and serializing.\n *\n * @type {TokenizeContext}\n */\n const context = {\n previous: codes.eof,\n code: codes.eof,\n containerState: {},\n events: [],\n parser,\n sliceStream,\n sliceSerialize,\n now,\n defineSkip,\n write\n }\n\n /**\n * The state function.\n *\n * @type {State | undefined}\n */\n let state = initialize.tokenize.call(context, effects)\n\n /**\n * Track which character we expect to be consumed, to catch bugs.\n *\n * @type {Code}\n */\n let expectedCode\n\n if (initialize.resolveAll) {\n resolveAllConstructs.push(initialize)\n }\n\n return context\n\n /** @type {TokenizeContext['write']} */\n function write(slice) {\n chunks = push(chunks, slice)\n\n main()\n\n // Exit if we’re not done, resolve might change stuff.\n if (chunks[chunks.length - 1] !== codes.eof) {\n return []\n }\n\n addResult(initialize, 0)\n\n // Otherwise, resolve, and exit.\n context.events = resolveAll(resolveAllConstructs, context.events, context)\n\n return context.events\n }\n\n //\n // Tools.\n //\n\n /** @type {TokenizeContext['sliceSerialize']} */\n function sliceSerialize(token, expandTabs) {\n return serializeChunks(sliceStream(token), expandTabs)\n }\n\n /** @type {TokenizeContext['sliceStream']} */\n function sliceStream(token) {\n return sliceChunks(chunks, token)\n }\n\n /** @type {TokenizeContext['now']} */\n function now() {\n // This is a hot path, so we clone manually instead of `Object.assign({}, point)`\n const {line, column, offset, _index, _bufferIndex} = point\n return {line, column, offset, _index, _bufferIndex}\n }\n\n /** @type {TokenizeContext['defineSkip']} */\n function defineSkip(value) {\n columnStart[value.line] = value.column\n accountForPotentialSkip()\n debug('position: define skip: `%j`', point)\n }\n\n //\n // State management.\n //\n\n /**\n * Main loop (note that `_index` and `_bufferIndex` in `point` are modified by\n * `consume`).\n * Here is where we walk through the chunks, which either include strings of\n * several characters, or numerical character codes.\n * The reason to do this in a loop instead of a call is so the stack can\n * drain.\n *\n * @returns {undefined}\n */\n function main() {\n /** @type {number} */\n let chunkIndex\n\n while (point._index < chunks.length) {\n const chunk = chunks[point._index]\n\n // If we’re in a buffer chunk, loop through it.\n if (typeof chunk === 'string') {\n chunkIndex = point._index\n\n if (point._bufferIndex < 0) {\n point._bufferIndex = 0\n }\n\n while (\n point._index === chunkIndex &&\n point._bufferIndex < chunk.length\n ) {\n go(chunk.charCodeAt(point._bufferIndex))\n }\n } else {\n go(chunk)\n }\n }\n }\n\n /**\n * Deal with one code.\n *\n * @param {Code} code\n * @returns {undefined}\n */\n function go(code) {\n assert(consumed === true, 'expected character to be consumed')\n consumed = undefined\n debug('main: passing `%s` to %s', code, state && state.name)\n expectedCode = code\n assert(typeof state === 'function', 'expected state')\n state = state(code)\n }\n\n /** @type {Effects['consume']} */\n function consume(code) {\n assert(code === expectedCode, 'expected given code to equal expected code')\n\n debug('consume: `%s`', code)\n\n assert(\n consumed === undefined,\n 'expected code to not have been consumed: this might be because `return x(code)` instead of `return x` was used'\n )\n assert(\n code === null\n ? context.events.length === 0 ||\n context.events[context.events.length - 1][0] === 'exit'\n : context.events[context.events.length - 1][0] === 'enter',\n 'expected last token to be open'\n )\n\n if (markdownLineEnding(code)) {\n point.line++\n point.column = 1\n point.offset += code === codes.carriageReturnLineFeed ? 2 : 1\n accountForPotentialSkip()\n debug('position: after eol: `%j`', point)\n } else if (code !== codes.virtualSpace) {\n point.column++\n point.offset++\n }\n\n // Not in a string chunk.\n if (point._bufferIndex < 0) {\n point._index++\n } else {\n point._bufferIndex++\n\n // At end of string chunk.\n // @ts-expect-error Points w/ non-negative `_bufferIndex` reference\n // strings.\n if (point._bufferIndex === chunks[point._index].length) {\n point._bufferIndex = -1\n point._index++\n }\n }\n\n // Expose the previous character.\n context.previous = code\n\n // Mark as consumed.\n consumed = true\n }\n\n /** @type {Effects['enter']} */\n function enter(type, fields) {\n /** @type {Token} */\n // @ts-expect-error Patch instead of assign required fields to help GC.\n const token = fields || {}\n token.type = type\n token.start = now()\n\n assert(typeof type === 'string', 'expected string type')\n assert(type.length > 0, 'expected non-empty string')\n debug('enter: `%s`', type)\n\n context.events.push(['enter', token, context])\n\n stack.push(token)\n\n return token\n }\n\n /** @type {Effects['exit']} */\n function exit(type) {\n assert(typeof type === 'string', 'expected string type')\n assert(type.length > 0, 'expected non-empty string')\n\n const token = stack.pop()\n assert(token, 'cannot close w/o open tokens')\n token.end = now()\n\n assert(type === token.type, 'expected exit token to match current token')\n\n assert(\n !(\n token.start._index === token.end._index &&\n token.start._bufferIndex === token.end._bufferIndex\n ),\n 'expected non-empty token (`' + type + '`)'\n )\n\n debug('exit: `%s`', token.type)\n context.events.push(['exit', token, context])\n\n return token\n }\n\n /**\n * Use results.\n *\n * @type {ReturnHandle}\n */\n function onsuccessfulconstruct(construct, info) {\n addResult(construct, info.from)\n }\n\n /**\n * Discard results.\n *\n * @type {ReturnHandle}\n */\n function onsuccessfulcheck(_, info) {\n info.restore()\n }\n\n /**\n * Factory to attempt/check/interrupt.\n *\n * @param {ReturnHandle} onreturn\n * @param {{interrupt?: boolean | undefined} | undefined} [fields]\n */\n function constructFactory(onreturn, fields) {\n return hook\n\n /**\n * Handle either an object mapping codes to constructs, a list of\n * constructs, or a single construct.\n *\n * @param {Array | Construct | ConstructRecord} constructs\n * @param {State} returnState\n * @param {State | undefined} [bogusState]\n * @returns {State}\n */\n function hook(constructs, returnState, bogusState) {\n /** @type {Array} */\n let listOfConstructs\n /** @type {number} */\n let constructIndex\n /** @type {Construct} */\n let currentConstruct\n /** @type {Info} */\n let info\n\n return Array.isArray(constructs)\n ? /* c8 ignore next 1 */\n handleListOfConstructs(constructs)\n : 'tokenize' in constructs\n ? // @ts-expect-error Looks like a construct.\n handleListOfConstructs([constructs])\n : handleMapOfConstructs(constructs)\n\n /**\n * Handle a list of construct.\n *\n * @param {ConstructRecord} map\n * @returns {State}\n */\n function handleMapOfConstructs(map) {\n return start\n\n /** @type {State} */\n function start(code) {\n const def = code !== null && map[code]\n const all = code !== null && map.null\n const list = [\n // To do: add more extension tests.\n /* c8 ignore next 2 */\n ...(Array.isArray(def) ? def : def ? [def] : []),\n ...(Array.isArray(all) ? all : all ? [all] : [])\n ]\n\n return handleListOfConstructs(list)(code)\n }\n }\n\n /**\n * Handle a list of construct.\n *\n * @param {Array} list\n * @returns {State}\n */\n function handleListOfConstructs(list) {\n listOfConstructs = list\n constructIndex = 0\n\n if (list.length === 0) {\n assert(bogusState, 'expected `bogusState` to be given')\n return bogusState\n }\n\n return handleConstruct(list[constructIndex])\n }\n\n /**\n * Handle a single construct.\n *\n * @param {Construct} construct\n * @returns {State}\n */\n function handleConstruct(construct) {\n return start\n\n /** @type {State} */\n function start(code) {\n // To do: not needed to store if there is no bogus state, probably?\n // Currently doesn’t work because `inspect` in document does a check\n // w/o a bogus, which doesn’t make sense. But it does seem to help perf\n // by not storing.\n info = store()\n currentConstruct = construct\n\n if (!construct.partial) {\n context.currentConstruct = construct\n }\n\n // Always populated by defaults.\n assert(\n context.parser.constructs.disable.null,\n 'expected `disable.null` to be populated'\n )\n\n if (\n construct.name &&\n context.parser.constructs.disable.null.includes(construct.name)\n ) {\n return nok(code)\n }\n\n return construct.tokenize.call(\n // If we do have fields, create an object w/ `context` as its\n // prototype.\n // This allows a “live binding”, which is needed for `interrupt`.\n fields ? Object.assign(Object.create(context), fields) : context,\n effects,\n ok,\n nok\n )(code)\n }\n }\n\n /** @type {State} */\n function ok(code) {\n assert(code === expectedCode, 'expected code')\n consumed = true\n onreturn(currentConstruct, info)\n return returnState\n }\n\n /** @type {State} */\n function nok(code) {\n assert(code === expectedCode, 'expected code')\n consumed = true\n info.restore()\n\n if (++constructIndex < listOfConstructs.length) {\n return handleConstruct(listOfConstructs[constructIndex])\n }\n\n return bogusState\n }\n }\n }\n\n /**\n * @param {Construct} construct\n * @param {number} from\n * @returns {undefined}\n */\n function addResult(construct, from) {\n if (construct.resolveAll && !resolveAllConstructs.includes(construct)) {\n resolveAllConstructs.push(construct)\n }\n\n if (construct.resolve) {\n splice(\n context.events,\n from,\n context.events.length - from,\n construct.resolve(context.events.slice(from), context)\n )\n }\n\n if (construct.resolveTo) {\n context.events = construct.resolveTo(context.events, context)\n }\n\n assert(\n construct.partial ||\n context.events.length === 0 ||\n context.events[context.events.length - 1][0] === 'exit',\n 'expected last token to end'\n )\n }\n\n /**\n * Store state.\n *\n * @returns {Info}\n */\n function store() {\n const startPoint = now()\n const startPrevious = context.previous\n const startCurrentConstruct = context.currentConstruct\n const startEventsIndex = context.events.length\n const startStack = Array.from(stack)\n\n return {restore, from: startEventsIndex}\n\n /**\n * Restore state.\n *\n * @returns {undefined}\n */\n function restore() {\n point = startPoint\n context.previous = startPrevious\n context.currentConstruct = startCurrentConstruct\n context.events.length = startEventsIndex\n stack = startStack\n accountForPotentialSkip()\n debug('position: restore: `%j`', point)\n }\n }\n\n /**\n * Move the current point a bit forward in the line when it’s on a column\n * skip.\n *\n * @returns {undefined}\n */\n function accountForPotentialSkip() {\n if (point.line in columnStart && point.column < 2) {\n point.column = columnStart[point.line]\n point.offset += columnStart[point.line] - 1\n }\n }\n}\n\n/**\n * Get the chunks from a slice of chunks in the range of a token.\n *\n * @param {Array} chunks\n * @param {Pick} token\n * @returns {Array}\n */\nfunction sliceChunks(chunks, token) {\n const startIndex = token.start._index\n const startBufferIndex = token.start._bufferIndex\n const endIndex = token.end._index\n const endBufferIndex = token.end._bufferIndex\n /** @type {Array} */\n let view\n\n if (startIndex === endIndex) {\n assert(endBufferIndex > -1, 'expected non-negative end buffer index')\n assert(startBufferIndex > -1, 'expected non-negative start buffer index')\n // @ts-expect-error `_bufferIndex` is used on string chunks.\n view = [chunks[startIndex].slice(startBufferIndex, endBufferIndex)]\n } else {\n view = chunks.slice(startIndex, endIndex)\n\n if (startBufferIndex > -1) {\n const head = view[0]\n if (typeof head === 'string') {\n view[0] = head.slice(startBufferIndex)\n } else {\n assert(startBufferIndex === 0, 'expected `startBufferIndex` to be `0`')\n view.shift()\n }\n }\n\n if (endBufferIndex > 0) {\n // @ts-expect-error `_bufferIndex` is used on string chunks.\n view.push(chunks[endIndex].slice(0, endBufferIndex))\n }\n }\n\n return view\n}\n\n/**\n * Get the string value of a slice of chunks.\n *\n * @param {Array} chunks\n * @param {boolean | undefined} [expandTabs=false]\n * @returns {string}\n */\nfunction serializeChunks(chunks, expandTabs) {\n let index = -1\n /** @type {Array} */\n const result = []\n /** @type {boolean | undefined} */\n let atTab\n\n while (++index < chunks.length) {\n const chunk = chunks[index]\n /** @type {string} */\n let value\n\n if (typeof chunk === 'string') {\n value = chunk\n } else\n switch (chunk) {\n case codes.carriageReturn: {\n value = values.cr\n\n break\n }\n\n case codes.lineFeed: {\n value = values.lf\n\n break\n }\n\n case codes.carriageReturnLineFeed: {\n value = values.cr + values.lf\n\n break\n }\n\n case codes.horizontalTab: {\n value = expandTabs ? values.space : values.ht\n\n break\n }\n\n case codes.virtualSpace: {\n if (!expandTabs && atTab) continue\n value = values.space\n\n break\n }\n\n default: {\n assert(typeof chunk === 'number', 'expected number')\n // Currently only replacement character.\n value = String.fromCharCode(chunk)\n }\n }\n\n atTab = chunk === codes.horizontalTab\n result.push(value)\n }\n\n return result.join('')\n}\n","/**\n * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct\n * @typedef {import('micromark-util-types').Initializer} Initializer\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').Token} Token\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {InitialConstruct} */\nexport const content = {tokenize: initializeContent}\n\n/**\n * @this {TokenizeContext}\n * @type {Initializer}\n */\nfunction initializeContent(effects) {\n const contentStart = effects.attempt(\n this.parser.constructs.contentInitial,\n afterContentStartConstruct,\n paragraphInitial\n )\n /** @type {Token} */\n let previous\n\n return contentStart\n\n /** @type {State} */\n function afterContentStartConstruct(code) {\n assert(\n code === codes.eof || markdownLineEnding(code),\n 'expected eol or eof'\n )\n\n if (code === codes.eof) {\n effects.consume(code)\n return\n }\n\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n return factorySpace(effects, contentStart, types.linePrefix)\n }\n\n /** @type {State} */\n function paragraphInitial(code) {\n assert(\n code !== codes.eof && !markdownLineEnding(code),\n 'expected anything other than a line ending or EOF'\n )\n effects.enter(types.paragraph)\n return lineStart(code)\n }\n\n /** @type {State} */\n function lineStart(code) {\n const token = effects.enter(types.chunkText, {\n contentType: constants.contentTypeText,\n previous\n })\n\n if (previous) {\n previous.next = token\n }\n\n previous = token\n\n return data(code)\n }\n\n /** @type {State} */\n function data(code) {\n if (code === codes.eof) {\n effects.exit(types.chunkText)\n effects.exit(types.paragraph)\n effects.consume(code)\n return\n }\n\n if (markdownLineEnding(code)) {\n effects.consume(code)\n effects.exit(types.chunkText)\n return lineStart\n }\n\n // Data.\n effects.consume(code)\n return data\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Construct} Construct\n * @typedef {import('micromark-util-types').ContainerState} ContainerState\n * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct\n * @typedef {import('micromark-util-types').Initializer} Initializer\n * @typedef {import('micromark-util-types').Point} Point\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').Token} Token\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n * @typedef {import('micromark-util-types').Tokenizer} Tokenizer\n */\n\n/**\n * @typedef {[Construct, ContainerState]} StackItem\n */\n\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {splice} from 'micromark-util-chunked'\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {InitialConstruct} */\nexport const document = {tokenize: initializeDocument}\n\n/** @type {Construct} */\nconst containerConstruct = {tokenize: tokenizeContainer}\n\n/**\n * @this {TokenizeContext}\n * @type {Initializer}\n */\nfunction initializeDocument(effects) {\n const self = this\n /** @type {Array} */\n const stack = []\n let continued = 0\n /** @type {TokenizeContext | undefined} */\n let childFlow\n /** @type {Token | undefined} */\n let childToken\n /** @type {number} */\n let lineStartOffset\n\n return start\n\n /** @type {State} */\n function start(code) {\n // First we iterate through the open blocks, starting with the root\n // document, and descending through last children down to the last open\n // block.\n // Each block imposes a condition that the line must satisfy if the block is\n // to remain open.\n // For example, a block quote requires a `>` character.\n // A paragraph requires a non-blank line.\n // In this phase we may match all or just some of the open blocks.\n // But we cannot close unmatched blocks yet, because we may have a lazy\n // continuation line.\n if (continued < stack.length) {\n const item = stack[continued]\n self.containerState = item[1]\n assert(\n item[0].continuation,\n 'expected `continuation` to be defined on container construct'\n )\n return effects.attempt(\n item[0].continuation,\n documentContinue,\n checkNewContainers\n )(code)\n }\n\n // Done.\n return checkNewContainers(code)\n }\n\n /** @type {State} */\n function documentContinue(code) {\n assert(\n self.containerState,\n 'expected `containerState` to be defined after continuation'\n )\n\n continued++\n\n // Note: this field is called `_closeFlow` but it also closes containers.\n // Perhaps a good idea to rename it but it’s already used in the wild by\n // extensions.\n if (self.containerState._closeFlow) {\n self.containerState._closeFlow = undefined\n\n if (childFlow) {\n closeFlow()\n }\n\n // Note: this algorithm for moving events around is similar to the\n // algorithm when dealing with lazy lines in `writeToChild`.\n const indexBeforeExits = self.events.length\n let indexBeforeFlow = indexBeforeExits\n /** @type {Point | undefined} */\n let point\n\n // Find the flow chunk.\n while (indexBeforeFlow--) {\n if (\n self.events[indexBeforeFlow][0] === 'exit' &&\n self.events[indexBeforeFlow][1].type === types.chunkFlow\n ) {\n point = self.events[indexBeforeFlow][1].end\n break\n }\n }\n\n assert(point, 'could not find previous flow chunk')\n\n exitContainers(continued)\n\n // Fix positions.\n let index = indexBeforeExits\n\n while (index < self.events.length) {\n self.events[index][1].end = Object.assign({}, point)\n index++\n }\n\n // Inject the exits earlier (they’re still also at the end).\n splice(\n self.events,\n indexBeforeFlow + 1,\n 0,\n self.events.slice(indexBeforeExits)\n )\n\n // Discard the duplicate exits.\n self.events.length = index\n\n return checkNewContainers(code)\n }\n\n return start(code)\n }\n\n /** @type {State} */\n function checkNewContainers(code) {\n // Next, after consuming the continuation markers for existing blocks, we\n // look for new block starts (e.g. `>` for a block quote).\n // If we encounter a new block start, we close any blocks unmatched in\n // step 1 before creating the new block as a child of the last matched\n // block.\n if (continued === stack.length) {\n // No need to `check` whether there’s a container, of `exitContainers`\n // would be moot.\n // We can instead immediately `attempt` to parse one.\n if (!childFlow) {\n return documentContinued(code)\n }\n\n // If we have concrete content, such as block HTML or fenced code,\n // we can’t have containers “pierce” into them, so we can immediately\n // start.\n if (childFlow.currentConstruct && childFlow.currentConstruct.concrete) {\n return flowStart(code)\n }\n\n // If we do have flow, it could still be a blank line,\n // but we’d be interrupting it w/ a new container if there’s a current\n // construct.\n // To do: next major: remove `_gfmTableDynamicInterruptHack` (no longer\n // needed in micromark-extension-gfm-table@1.0.6).\n self.interrupt = Boolean(\n childFlow.currentConstruct && !childFlow._gfmTableDynamicInterruptHack\n )\n }\n\n // Check if there is a new container.\n self.containerState = {}\n return effects.check(\n containerConstruct,\n thereIsANewContainer,\n thereIsNoNewContainer\n )(code)\n }\n\n /** @type {State} */\n function thereIsANewContainer(code) {\n if (childFlow) closeFlow()\n exitContainers(continued)\n return documentContinued(code)\n }\n\n /** @type {State} */\n function thereIsNoNewContainer(code) {\n self.parser.lazy[self.now().line] = continued !== stack.length\n lineStartOffset = self.now().offset\n return flowStart(code)\n }\n\n /** @type {State} */\n function documentContinued(code) {\n // Try new containers.\n self.containerState = {}\n return effects.attempt(\n containerConstruct,\n containerContinue,\n flowStart\n )(code)\n }\n\n /** @type {State} */\n function containerContinue(code) {\n assert(\n self.currentConstruct,\n 'expected `currentConstruct` to be defined on tokenizer'\n )\n assert(\n self.containerState,\n 'expected `containerState` to be defined on tokenizer'\n )\n continued++\n stack.push([self.currentConstruct, self.containerState])\n // Try another.\n return documentContinued(code)\n }\n\n /** @type {State} */\n function flowStart(code) {\n if (code === codes.eof) {\n if (childFlow) closeFlow()\n exitContainers(0)\n effects.consume(code)\n return\n }\n\n childFlow = childFlow || self.parser.flow(self.now())\n effects.enter(types.chunkFlow, {\n contentType: constants.contentTypeFlow,\n previous: childToken,\n _tokenizer: childFlow\n })\n\n return flowContinue(code)\n }\n\n /** @type {State} */\n function flowContinue(code) {\n if (code === codes.eof) {\n writeToChild(effects.exit(types.chunkFlow), true)\n exitContainers(0)\n effects.consume(code)\n return\n }\n\n if (markdownLineEnding(code)) {\n effects.consume(code)\n writeToChild(effects.exit(types.chunkFlow))\n // Get ready for the next line.\n continued = 0\n self.interrupt = undefined\n return start\n }\n\n effects.consume(code)\n return flowContinue\n }\n\n /**\n * @param {Token} token\n * @param {boolean | undefined} [eof]\n * @returns {undefined}\n */\n function writeToChild(token, eof) {\n assert(childFlow, 'expected `childFlow` to be defined when continuing')\n const stream = self.sliceStream(token)\n if (eof) stream.push(null)\n token.previous = childToken\n if (childToken) childToken.next = token\n childToken = token\n childFlow.defineSkip(token.start)\n childFlow.write(stream)\n\n // Alright, so we just added a lazy line:\n //\n // ```markdown\n // > a\n // b.\n //\n // Or:\n //\n // > ~~~c\n // d\n //\n // Or:\n //\n // > | e |\n // f\n // ```\n //\n // The construct in the second example (fenced code) does not accept lazy\n // lines, so it marked itself as done at the end of its first line, and\n // then the content construct parses `d`.\n // Most constructs in markdown match on the first line: if the first line\n // forms a construct, a non-lazy line can’t “unmake” it.\n //\n // The construct in the third example is potentially a GFM table, and\n // those are *weird*.\n // It *could* be a table, from the first line, if the following line\n // matches a condition.\n // In this case, that second line is lazy, which “unmakes” the first line\n // and turns the whole into one content block.\n //\n // We’ve now parsed the non-lazy and the lazy line, and can figure out\n // whether the lazy line started a new flow block.\n // If it did, we exit the current containers between the two flow blocks.\n if (self.parser.lazy[token.start.line]) {\n let index = childFlow.events.length\n\n while (index--) {\n if (\n // The token starts before the line ending…\n childFlow.events[index][1].start.offset < lineStartOffset &&\n // …and either is not ended yet…\n (!childFlow.events[index][1].end ||\n // …or ends after it.\n childFlow.events[index][1].end.offset > lineStartOffset)\n ) {\n // Exit: there’s still something open, which means it’s a lazy line\n // part of something.\n return\n }\n }\n\n // Note: this algorithm for moving events around is similar to the\n // algorithm when closing flow in `documentContinue`.\n const indexBeforeExits = self.events.length\n let indexBeforeFlow = indexBeforeExits\n /** @type {boolean | undefined} */\n let seen\n /** @type {Point | undefined} */\n let point\n\n // Find the previous chunk (the one before the lazy line).\n while (indexBeforeFlow--) {\n if (\n self.events[indexBeforeFlow][0] === 'exit' &&\n self.events[indexBeforeFlow][1].type === types.chunkFlow\n ) {\n if (seen) {\n point = self.events[indexBeforeFlow][1].end\n break\n }\n\n seen = true\n }\n }\n\n assert(point, 'could not find previous flow chunk')\n\n exitContainers(continued)\n\n // Fix positions.\n index = indexBeforeExits\n\n while (index < self.events.length) {\n self.events[index][1].end = Object.assign({}, point)\n index++\n }\n\n // Inject the exits earlier (they’re still also at the end).\n splice(\n self.events,\n indexBeforeFlow + 1,\n 0,\n self.events.slice(indexBeforeExits)\n )\n\n // Discard the duplicate exits.\n self.events.length = index\n }\n }\n\n /**\n * @param {number} size\n * @returns {undefined}\n */\n function exitContainers(size) {\n let index = stack.length\n\n // Exit open containers.\n while (index-- > size) {\n const entry = stack[index]\n self.containerState = entry[1]\n assert(\n entry[0].exit,\n 'expected `exit` to be defined on container construct'\n )\n entry[0].exit.call(self, effects)\n }\n\n stack.length = size\n }\n\n function closeFlow() {\n assert(\n self.containerState,\n 'expected `containerState` to be defined when closing flow'\n )\n assert(childFlow, 'expected `childFlow` to be defined when closing it')\n childFlow.write([codes.eof])\n childToken = undefined\n childFlow = undefined\n self.containerState._closeFlow = undefined\n }\n}\n\n/**\n * @this {TokenizeContext}\n * @type {Tokenizer}\n */\nfunction tokenizeContainer(effects, ok, nok) {\n // Always populated by defaults.\n assert(\n this.parser.constructs.disable.null,\n 'expected `disable.null` to be populated'\n )\n return factorySpace(\n effects,\n effects.attempt(this.parser.constructs.document, ok, nok),\n types.linePrefix,\n this.parser.constructs.disable.null.includes('codeIndented')\n ? undefined\n : constants.tabSize\n )\n}\n","/**\n * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct\n * @typedef {import('micromark-util-types').Initializer} Initializer\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n */\n\nimport {blankLine, content} from 'micromark-core-commonmark'\nimport {factorySpace} from 'micromark-factory-space'\nimport {markdownLineEnding} from 'micromark-util-character'\nimport {codes, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\n/** @type {InitialConstruct} */\nexport const flow = {tokenize: initializeFlow}\n\n/**\n * @this {TokenizeContext}\n * @type {Initializer}\n */\nfunction initializeFlow(effects) {\n const self = this\n const initial = effects.attempt(\n // Try to parse a blank line.\n blankLine,\n atBlankEnding,\n // Try to parse initial flow (essentially, only code).\n effects.attempt(\n this.parser.constructs.flowInitial,\n afterConstruct,\n factorySpace(\n effects,\n effects.attempt(\n this.parser.constructs.flow,\n afterConstruct,\n effects.attempt(content, afterConstruct)\n ),\n types.linePrefix\n )\n )\n )\n\n return initial\n\n /** @type {State} */\n function atBlankEnding(code) {\n assert(\n code === codes.eof || markdownLineEnding(code),\n 'expected eol or eof'\n )\n\n if (code === codes.eof) {\n effects.consume(code)\n return\n }\n\n effects.enter(types.lineEndingBlank)\n effects.consume(code)\n effects.exit(types.lineEndingBlank)\n self.currentConstruct = undefined\n return initial\n }\n\n /** @type {State} */\n function afterConstruct(code) {\n assert(\n code === codes.eof || markdownLineEnding(code),\n 'expected eol or eof'\n )\n\n if (code === codes.eof) {\n effects.consume(code)\n return\n }\n\n effects.enter(types.lineEnding)\n effects.consume(code)\n effects.exit(types.lineEnding)\n self.currentConstruct = undefined\n return initial\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct\n * @typedef {import('micromark-util-types').Initializer} Initializer\n * @typedef {import('micromark-util-types').Resolver} Resolver\n * @typedef {import('micromark-util-types').State} State\n * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext\n */\n\nimport {codes, constants, types} from 'micromark-util-symbol'\nimport {ok as assert} from 'devlop'\n\nexport const resolver = {resolveAll: createResolver()}\nexport const string = initializeFactory('string')\nexport const text = initializeFactory('text')\n\n/**\n * @param {'string' | 'text'} field\n * @returns {InitialConstruct}\n */\nfunction initializeFactory(field) {\n return {\n tokenize: initializeText,\n resolveAll: createResolver(\n field === 'text' ? resolveAllLineSuffixes : undefined\n )\n }\n\n /**\n * @this {TokenizeContext}\n * @type {Initializer}\n */\n function initializeText(effects) {\n const self = this\n const constructs = this.parser.constructs[field]\n const text = effects.attempt(constructs, start, notText)\n\n return start\n\n /** @type {State} */\n function start(code) {\n return atBreak(code) ? text(code) : notText(code)\n }\n\n /** @type {State} */\n function notText(code) {\n if (code === codes.eof) {\n effects.consume(code)\n return\n }\n\n effects.enter(types.data)\n effects.consume(code)\n return data\n }\n\n /** @type {State} */\n function data(code) {\n if (atBreak(code)) {\n effects.exit(types.data)\n return text(code)\n }\n\n // Data.\n effects.consume(code)\n return data\n }\n\n /**\n * @param {Code} code\n * @returns {boolean}\n */\n function atBreak(code) {\n if (code === codes.eof) {\n return true\n }\n\n const list = constructs[code]\n let index = -1\n\n if (list) {\n // Always populated by defaults.\n assert(Array.isArray(list), 'expected `disable.null` to be populated')\n\n while (++index < list.length) {\n const item = list[index]\n if (!item.previous || item.previous.call(self, self.previous)) {\n return true\n }\n }\n }\n\n return false\n }\n }\n}\n\n/**\n * @param {Resolver | undefined} [extraResolver]\n * @returns {Resolver}\n */\nfunction createResolver(extraResolver) {\n return resolveAllText\n\n /** @type {Resolver} */\n function resolveAllText(events, context) {\n let index = -1\n /** @type {number | undefined} */\n let enter\n\n // A rather boring computation (to merge adjacent `data` events) which\n // improves mm performance by 29%.\n while (++index <= events.length) {\n if (enter === undefined) {\n if (events[index] && events[index][1].type === types.data) {\n enter = index\n index++\n }\n } else if (!events[index] || events[index][1].type !== types.data) {\n // Don’t do anything if there is one data token.\n if (index !== enter + 2) {\n events[enter][1].end = events[index - 1][1].end\n events.splice(enter + 2, index - enter - 2)\n index = enter + 2\n }\n\n enter = undefined\n }\n }\n\n return extraResolver ? extraResolver(events, context) : events\n }\n}\n\n/**\n * A rather ugly set of instructions which again looks at chunks in the input\n * stream.\n * The reason to do this here is that it is *much* faster to parse in reverse.\n * And that we can’t hook into `null` to split the line suffix before an EOF.\n * To do: figure out if we can make this into a clean utility, or even in core.\n * As it will be useful for GFMs literal autolink extension (and maybe even\n * tables?)\n *\n * @type {Resolver}\n */\nfunction resolveAllLineSuffixes(events, context) {\n let eventIndex = 0 // Skip first.\n\n while (++eventIndex <= events.length) {\n if (\n (eventIndex === events.length ||\n events[eventIndex][1].type === types.lineEnding) &&\n events[eventIndex - 1][1].type === types.data\n ) {\n const data = events[eventIndex - 1][1]\n const chunks = context.sliceStream(data)\n let index = chunks.length\n let bufferIndex = -1\n let size = 0\n /** @type {boolean | undefined} */\n let tabs\n\n while (index--) {\n const chunk = chunks[index]\n\n if (typeof chunk === 'string') {\n bufferIndex = chunk.length\n\n while (chunk.charCodeAt(bufferIndex - 1) === codes.space) {\n size++\n bufferIndex--\n }\n\n if (bufferIndex) break\n bufferIndex = -1\n }\n // Number\n else if (chunk === codes.horizontalTab) {\n tabs = true\n size++\n } else if (chunk === codes.virtualSpace) {\n // Empty\n } else {\n // Replacement character, exit.\n index++\n break\n }\n }\n\n if (size) {\n const token = {\n type:\n eventIndex === events.length ||\n tabs ||\n size < constants.hardBreakPrefixSizeMin\n ? types.lineSuffix\n : types.hardBreakTrailing,\n start: {\n line: data.end.line,\n column: data.end.column - size,\n offset: data.end.offset - size,\n _index: data.start._index + index,\n _bufferIndex: index\n ? bufferIndex\n : data.start._bufferIndex + bufferIndex\n },\n end: Object.assign({}, data.end)\n }\n\n data.end = Object.assign({}, token.start)\n\n if (data.start.offset === data.end.offset) {\n Object.assign(data, token)\n } else {\n events.splice(\n eventIndex,\n 0,\n ['enter', token, context],\n ['exit', token, context]\n )\n eventIndex += 2\n }\n }\n\n eventIndex++\n }\n }\n\n return events\n}\n","/**\n * @typedef {import('micromark-util-types').Create} Create\n * @typedef {import('micromark-util-types').FullNormalizedExtension} FullNormalizedExtension\n * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct\n * @typedef {import('micromark-util-types').ParseContext} ParseContext\n * @typedef {import('micromark-util-types').ParseOptions} ParseOptions\n */\n\nimport {combineExtensions} from 'micromark-util-combine-extensions'\nimport {content} from './initialize/content.js'\nimport {document} from './initialize/document.js'\nimport {flow} from './initialize/flow.js'\nimport {string, text} from './initialize/text.js'\nimport {createTokenizer} from './create-tokenizer.js'\nimport * as defaultConstructs from './constructs.js'\n\n/**\n * @param {ParseOptions | null | undefined} [options]\n * @returns {ParseContext}\n */\nexport function parse(options) {\n const settings = options || {}\n const constructs = /** @type {FullNormalizedExtension} */ (\n combineExtensions([defaultConstructs, ...(settings.extensions || [])])\n )\n\n /** @type {ParseContext} */\n const parser = {\n defined: [],\n lazy: {},\n constructs,\n content: create(content),\n document: create(document),\n flow: create(flow),\n string: create(string),\n text: create(text)\n }\n\n return parser\n\n /**\n * @param {InitialConstruct} initial\n */\n function create(initial) {\n return creator\n /** @type {Create} */\n function creator(from) {\n return createTokenizer(parser, initial, from)\n }\n }\n}\n","/**\n * @typedef {import('micromark-util-types').Event} Event\n */\n\nimport {subtokenize} from 'micromark-util-subtokenize'\n\n/**\n * @param {Array} events\n * @returns {Array}\n */\nexport function postprocess(events) {\n while (!subtokenize(events)) {\n // Empty\n }\n\n return events\n}\n","/**\n * @typedef {import('micromark-util-types').Chunk} Chunk\n * @typedef {import('micromark-util-types').Code} Code\n * @typedef {import('micromark-util-types').Encoding} Encoding\n * @typedef {import('micromark-util-types').Value} Value\n */\n\n/**\n * @callback Preprocessor\n * @param {Value} value\n * @param {Encoding | null | undefined} [encoding]\n * @param {boolean | null | undefined} [end=false]\n * @returns {Array}\n */\n\nimport {codes, constants} from 'micromark-util-symbol'\n\nconst search = /[\\0\\t\\n\\r]/g\n\n/**\n * @returns {Preprocessor}\n */\nexport function preprocess() {\n let column = 1\n let buffer = ''\n /** @type {boolean | undefined} */\n let start = true\n /** @type {boolean | undefined} */\n let atCarriageReturn\n\n return preprocessor\n\n /** @type {Preprocessor} */\n // eslint-disable-next-line complexity\n function preprocessor(value, encoding, end) {\n /** @type {Array} */\n const chunks = []\n /** @type {RegExpMatchArray | null} */\n let match\n /** @type {number} */\n let next\n /** @type {number} */\n let startPosition\n /** @type {number} */\n let endPosition\n /** @type {Code} */\n let code\n\n value =\n buffer +\n (typeof value === 'string'\n ? value.toString()\n : new TextDecoder(encoding || undefined).decode(value))\n\n startPosition = 0\n buffer = ''\n\n if (start) {\n // To do: `markdown-rs` actually parses BOMs (byte order mark).\n if (value.charCodeAt(0) === codes.byteOrderMarker) {\n startPosition++\n }\n\n start = undefined\n }\n\n while (startPosition < value.length) {\n search.lastIndex = startPosition\n match = search.exec(value)\n endPosition =\n match && match.index !== undefined ? match.index : value.length\n code = value.charCodeAt(endPosition)\n\n if (!match) {\n buffer = value.slice(startPosition)\n break\n }\n\n if (\n code === codes.lf &&\n startPosition === endPosition &&\n atCarriageReturn\n ) {\n chunks.push(codes.carriageReturnLineFeed)\n atCarriageReturn = undefined\n } else {\n if (atCarriageReturn) {\n chunks.push(codes.carriageReturn)\n atCarriageReturn = undefined\n }\n\n if (startPosition < endPosition) {\n chunks.push(value.slice(startPosition, endPosition))\n column += endPosition - startPosition\n }\n\n switch (code) {\n case codes.nul: {\n chunks.push(codes.replacementCharacter)\n column++\n\n break\n }\n\n case codes.ht: {\n next = Math.ceil(column / constants.tabSize) * constants.tabSize\n chunks.push(codes.horizontalTab)\n while (column++ < next) chunks.push(codes.virtualSpace)\n\n break\n }\n\n case codes.lf: {\n chunks.push(codes.lineFeed)\n column = 1\n\n break\n }\n\n default: {\n atCarriageReturn = true\n column = 1\n }\n }\n }\n\n startPosition = endPosition + 1\n }\n\n if (end) {\n if (atCarriageReturn) chunks.push(codes.carriageReturn)\n if (buffer) chunks.push(buffer)\n chunks.push(codes.eof)\n }\n\n return chunks\n }\n}\n","var __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => {\n __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\n return value;\n};\nvar _a, _b, _c, _d, _e, _f;\nimport * as mobx from \"mobx\";\nimport { isObservableMap, isObservableSet, isObservableArray, isObservableObject, createAtom, runInAction, action, computed, isAction, set, reaction, isObservable, toJS, remove, observable, intercept, observe, when, values, get, has, keys, entries } from \"mobx\";\nconst dataModelActionRegistry = /* @__PURE__ */ new Map();\nfunction getDataModelAction(fullActionName) {\n return dataModelActionRegistry.get(fullActionName);\n}\nfunction setDataModelAction(fullActionName, modelClass2, fnName) {\n dataModelActionRegistry.set(fullActionName, {\n modelClass: modelClass2,\n fnName\n });\n}\nvar BuiltInAction;\n(function(BuiltInAction2) {\n BuiltInAction2[\"ApplyPatches\"] = \"$$applyPatches\";\n BuiltInAction2[\"ApplySnapshot\"] = \"$$applySnapshot\";\n BuiltInAction2[\"Detach\"] = \"$$detach\";\n BuiltInAction2[\"ApplySet\"] = \"$$applySet\";\n BuiltInAction2[\"ApplyDelete\"] = \"$$applyDelete\";\n BuiltInAction2[\"ApplyMethodCall\"] = \"$$applyMethodCall\";\n})(BuiltInAction || (BuiltInAction = {}));\nconst builtInActionValues = new Set(Object.values(BuiltInAction));\nfunction isBuiltInAction(actionName) {\n return builtInActionValues.has(actionName);\n}\nvar ActionContextActionType;\n(function(ActionContextActionType2) {\n ActionContextActionType2[\"Sync\"] = \"sync\";\n ActionContextActionType2[\"Async\"] = \"async\";\n})(ActionContextActionType || (ActionContextActionType = {}));\nvar ActionContextAsyncStepType;\n(function(ActionContextAsyncStepType2) {\n ActionContextAsyncStepType2[\"Spawn\"] = \"spawn\";\n ActionContextAsyncStepType2[\"Return\"] = \"return\";\n ActionContextAsyncStepType2[\"Resume\"] = \"resume\";\n ActionContextAsyncStepType2[\"ResumeError\"] = \"resumeError\";\n ActionContextAsyncStepType2[\"Throw\"] = \"throw\";\n})(ActionContextAsyncStepType || (ActionContextAsyncStepType = {}));\nlet currentActionContext;\nfunction getCurrentActionContext() {\n return currentActionContext;\n}\nfunction setCurrentActionContext(ctx) {\n currentActionContext = ctx;\n}\nconst modelActionSymbol = Symbol(\"modelAction\");\nfunction isModelAction(fn) {\n return typeof fn === \"function\" && modelActionSymbol in fn;\n}\nconst modelTypeKey = \"$modelType\";\nconst modelIdKey = \"$modelId\";\nfunction isReservedModelKey(key) {\n return key === modelTypeKey;\n}\nclass MobxKeystoneError extends Error {\n constructor(msg) {\n super(msg);\n Object.setPrototypeOf(this, MobxKeystoneError.prototype);\n }\n}\nfunction failure(msg) {\n return new MobxKeystoneError(msg);\n}\nconst writableHiddenPropDescriptor = {\n enumerable: false,\n writable: true,\n configurable: false,\n value: void 0\n};\nfunction addHiddenProp(object, propName, value, writable = true) {\n if (writable) {\n Object.defineProperty(object, propName, writableHiddenPropDescriptor);\n object[propName] = value;\n } else {\n Object.defineProperty(object, propName, {\n enumerable: false,\n writable,\n configurable: true,\n value\n });\n }\n}\nfunction makePropReadonly(object, propName, enumerable) {\n const propDesc = Object.getOwnPropertyDescriptor(object, propName);\n if (propDesc) {\n propDesc.enumerable = enumerable;\n if (propDesc.get) {\n delete propDesc.set;\n } else {\n propDesc.writable = false;\n }\n Object.defineProperty(object, propName, propDesc);\n }\n}\nfunction isPlainObject(value) {\n if (!isObject(value))\n return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\nfunction isObject(value) {\n return value !== null && typeof value === \"object\";\n}\nfunction isPrimitive(value) {\n switch (typeof value) {\n case \"number\":\n case \"string\":\n case \"boolean\":\n case \"undefined\":\n case \"bigint\":\n return true;\n }\n return value === null;\n}\nfunction isJSONPrimitive(value) {\n switch (typeof value) {\n case \"number\":\n return isFinite(value);\n case \"string\":\n case \"boolean\":\n return true;\n }\n return value === null;\n}\nfunction deleteFromArray(array, value) {\n let index = array.indexOf(value);\n if (index >= 0) {\n array.splice(index, 1);\n return true;\n }\n return false;\n}\nfunction isMap(val) {\n return val instanceof Map || isObservableMap(val);\n}\nfunction isSet(val) {\n return val instanceof Set || isObservableSet(val);\n}\nfunction isArray(val) {\n return Array.isArray(val) || isObservableArray(val);\n}\nconst inDevMode = process.env.NODE_ENV !== \"production\";\nfunction assertIsObject(value, argName) {\n if (!isObject(value)) {\n throw failure(`${argName} must be an object`);\n }\n}\nfunction assertIsPlainObject(value, argName) {\n if (!isPlainObject(value)) {\n throw failure(`${argName} must be a plain object`);\n }\n}\nfunction assertIsObservableObject(value, argName) {\n if (!isObservableObject(value)) {\n throw failure(`${argName} must be an observable object`);\n }\n}\nfunction assertIsObservableArray(value, argName) {\n if (!isObservableArray(value)) {\n throw failure(`${argName} must be an observable array`);\n }\n}\nfunction assertIsMap(value, argName) {\n if (!isMap(value)) {\n throw failure(`${argName} must be a map`);\n }\n}\nfunction assertIsSet(value, argName) {\n if (!isSet(value)) {\n throw failure(`${argName} must be a set`);\n }\n}\nfunction assertIsFunction(value, argName) {\n if (typeof value !== \"function\") {\n throw failure(`${argName} must be a function`);\n }\n}\nfunction assertIsPrimitive(value, argName) {\n if (!isPrimitive(value)) {\n throw failure(`${argName} must be a primitive`);\n }\n}\nfunction assertIsString(value, argName) {\n if (typeof value !== \"string\") {\n throw failure(`${argName} must be a string`);\n }\n}\nconst runAfterNewSymbol = Symbol(\"runAfterNew\");\nconst runBeforeOnInitSymbol = Symbol(\"runBeforeOnInit\");\nfunction addLateInitializationFunction(target, symbol, fn) {\n let array = target[symbol];\n if (!array || !Object.prototype.hasOwnProperty.call(target, symbol)) {\n array = array ? array.slice() : [];\n addHiddenProp(target, symbol, array);\n }\n array.push(fn);\n}\nfunction runLateInitializationFunctions(target, symbol) {\n const fns = target[symbol];\n if (fns) {\n for (const fn of fns) {\n fn(target);\n }\n }\n}\nconst warningsAlreadyDisplayed = /* @__PURE__ */ new Set();\nfunction logWarning(type, msg, uniqueKey) {\n if (uniqueKey) {\n if (warningsAlreadyDisplayed.has(uniqueKey)) {\n return;\n }\n warningsAlreadyDisplayed.add(uniqueKey);\n }\n msg = \"[mobx-keystone] \" + msg;\n switch (type) {\n case \"warn\":\n console.warn(msg);\n break;\n case \"error\":\n console.error(msg);\n break;\n default:\n throw failure(`unknown log type - ${type}`);\n }\n}\nfunction lazy(getter) {\n let memoizedValue;\n let memoized = false;\n return (...args) => {\n if (!memoized) {\n memoizedValue = getter(...args);\n memoized = true;\n }\n return memoizedValue;\n };\n}\nconst identityFn = (x) => x;\nconst mobx6 = {\n // eslint-disable-next-line no-useless-concat\n makeObservable: mobx[\n // just to ensure import * is kept properly\n String.fromCharCode(\"l\".charCodeAt(0) + 1) + \"akeObservable\"\n ]\n};\nfunction propNameToSetterName(propName) {\n return `set${propName[0].toUpperCase()}${propName.slice(1)}`;\n}\nfunction getMobxVersion() {\n if (mobx6.makeObservable) {\n return 6;\n } else {\n return 5;\n }\n}\nconst namespace$2 = \"mobx-keystone\";\nconst propsTypeSymbol = Symbol(\"propsType\");\nconst fromSnapshotOverrideTypeSymbol = Symbol(\"fromSnapshotOverrideType\");\nconst toSnapshotOverrideTypeSymbol = Symbol(\"toSnapshotOverrideType\");\nconst modelInitializedSymbol = Symbol(\"modelInitialized\");\nfunction modelClass(type) {\n return type;\n}\nconst modelInfoByName = {};\nconst modelInfoByClass = /* @__PURE__ */ new WeakMap();\nfunction getModelInfoForName(name) {\n return modelInfoByName[name];\n}\nfunction getOrCreate(map, key, create) {\n let value = map.get(key);\n if (value === void 0) {\n value = create();\n map.set(key, value);\n }\n return value;\n}\nconst objectParents = /* @__PURE__ */ new WeakMap();\nconst objectParentsAtoms = /* @__PURE__ */ new WeakMap();\nfunction parentPathEquals(parentPath1, parentPath2, comparePath = true) {\n if (!parentPath1 && !parentPath2)\n return true;\n if (!parentPath1 || !parentPath2)\n return false;\n const parentEquals = parentPath1.parent === parentPath2.parent;\n if (!parentEquals)\n return false;\n return comparePath ? parentPath1.path === parentPath2.path : true;\n}\nfunction createParentPathAtom(obj) {\n return getOrCreate(objectParentsAtoms, obj, () => createAtom(\"parentAtom\"));\n}\nfunction reportParentPathObserved(node) {\n createParentPathAtom(node).reportObserved();\n}\nfunction reportParentPathChanged(node) {\n createParentPathAtom(node).reportChanged();\n}\nconst dataObjectParent = /* @__PURE__ */ new WeakMap();\nfunction dataToModelNode(node) {\n const modelNode = dataObjectParent.get(node);\n return modelNode != null ? modelNode : node;\n}\nfunction modelToDataNode(node) {\n return isModel(node) ? node.$ : node;\n}\nconst tweakedObjects = /* @__PURE__ */ new WeakMap();\nfunction isTweakedObject(value, canBeDataObject) {\n if (!canBeDataObject && dataObjectParent.has(value)) {\n return false;\n }\n return tweakedObjects.has(value);\n}\nfunction isTreeNode(value) {\n return !isPrimitive(value) && isTweakedObject(value, false);\n}\nfunction assertTweakedObject(treeNode, argName, canBeDataObject = false) {\n if (!canBeDataObject && dataObjectParent.has(treeNode)) {\n throw failure(`${argName} must be the model object instance instead of the '$' sub-object`);\n }\n if (isPrimitive(treeNode) || !isTweakedObject(treeNode, true)) {\n throw failure(`${argName} must be a tree node (usually a model or a shallow / deep child part of a model 'data' object)`);\n }\n}\nfunction assertIsTreeNode(value, argName = \"argument\") {\n assertTweakedObject(value, argName, false);\n}\nlet runningWithoutSnapshotOrPatches = false;\nfunction runWithoutSnapshotOrPatches(fn) {\n const old = runningWithoutSnapshotOrPatches;\n runningWithoutSnapshotOrPatches = true;\n try {\n runInAction(() => {\n fn();\n });\n } finally {\n runningWithoutSnapshotOrPatches = old;\n }\n}\nconst modelMetadataSymbol = Symbol(\"modelMetadata\");\nconst modelUnwrappedClassSymbol = Symbol(\"modelUnwrappedClass\");\nconst runAfterModelDecoratorSymbol = Symbol(\"runAfterModelDecorator\");\nconst modelPropertiesSymbol = Symbol(\"modelProperties\");\nfunction getInternalModelClassPropsInfo(modelClass2) {\n return modelClass2[modelPropertiesSymbol];\n}\nfunction setInternalModelClassPropsInfo(modelClass2, props) {\n modelClass2[modelPropertiesSymbol] = props;\n}\nconst noDefaultValue = Symbol(\"noDefaultValue\");\nconst idProp = {\n _setter: false,\n _isId: true,\n withSetter(mode) {\n const obj = Object.create(this);\n obj._setter = mode != null ? mode : true;\n return obj;\n },\n typedAs() {\n return idProp;\n }\n};\nconst baseProp = {\n ...{},\n _defaultFn: noDefaultValue,\n _defaultValue: noDefaultValue,\n _typeChecker: void 0,\n _setter: false,\n _isId: false,\n _transform: void 0,\n _fromSnapshotProcessor: void 0,\n _toSnapshotProcessor: void 0,\n withSetter(mode) {\n const obj = Object.create(this);\n obj._setter = mode != null ? mode : true;\n return obj;\n },\n withTransform(transform) {\n const obj = Object.create(this);\n obj._transform = toFullTransform(transform);\n return obj;\n },\n withSnapshotProcessor({ fromSnapshot: fromSnapshot2, toSnapshot }) {\n let newFromSnapshot;\n if (this._fromSnapshotProcessor && fromSnapshot2) {\n const oldFn = this._fromSnapshotProcessor;\n const newFn = fromSnapshot2;\n newFromSnapshot = (sn) => oldFn(newFn(sn));\n } else if (fromSnapshot2) {\n newFromSnapshot = fromSnapshot2;\n } else {\n newFromSnapshot = this._fromSnapshotProcessor;\n }\n let newToSnapshot;\n if (this._toSnapshotProcessor && toSnapshot) {\n const oldFn = this._toSnapshotProcessor;\n const newFn = toSnapshot;\n newToSnapshot = (sn) => newFn(oldFn(sn));\n } else if (toSnapshot) {\n newToSnapshot = toSnapshot;\n } else {\n newToSnapshot = this._toSnapshotProcessor;\n }\n const obj = Object.create(this);\n obj._fromSnapshotProcessor = newFromSnapshot;\n obj._toSnapshotProcessor = newToSnapshot;\n return obj;\n }\n};\nfunction prop(def) {\n const hasDefaultValue = arguments.length >= 1;\n if (!hasDefaultValue) {\n return baseProp;\n }\n let p = propCache.get(def);\n if (!p) {\n p = Object.create(baseProp);\n if (typeof def === \"function\") {\n p._defaultFn = def;\n } else {\n p._defaultValue = def;\n }\n propCache.set(def, p);\n }\n return p;\n}\nconst propCache = /* @__PURE__ */ new Map();\nlet cacheTransformResult = false;\nconst cacheTransformedValueFn = () => {\n cacheTransformResult = true;\n};\nfunction toFullTransform(transformObject) {\n const cache = /* @__PURE__ */ new WeakMap();\n const transform = (params) => params.originalValue == null ? params.originalValue : transformObject.transform(params);\n const untransform = (params) => params.transformedValue == null ? params.transformedValue : transformObject.untransform(params);\n return {\n transform(originalValue, model2, propName, setOriginalValue) {\n const modelCache = getOrCreate(cache, model2, () => /* @__PURE__ */ new Map());\n let propCache2 = modelCache.get(propName);\n if ((propCache2 == null ? void 0 : propCache2.originalValue) !== originalValue) {\n modelCache.delete(propName);\n propCache2 = void 0;\n }\n const transformedValue = transform({\n originalValue,\n cachedTransformedValue: propCache2 == null ? void 0 : propCache2.transformedValue,\n setOriginalValue\n });\n modelCache.set(propName, {\n originalValue,\n transformedValue\n });\n return transformedValue;\n },\n untransform(transformedValue, model2, propName) {\n const modelCache = getOrCreate(cache, model2, () => /* @__PURE__ */ new Map());\n cacheTransformResult = false;\n const originalValue = untransform({\n transformedValue,\n cacheTransformedValue: cacheTransformedValueFn\n });\n if (cacheTransformResult) {\n modelCache.set(propName, { originalValue, transformedValue });\n } else {\n modelCache.delete(propName);\n }\n return originalValue;\n }\n };\n}\nfunction getModelPropDefaultValue(propData) {\n if (propData._defaultFn !== noDefaultValue) {\n return propData._defaultFn();\n }\n if (propData._defaultValue !== noDefaultValue) {\n return propData._defaultValue;\n }\n return noDefaultValue;\n}\nlet urlAlphabet = \"useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict\";\nlet nanoid = (size = 21) => {\n let id = \"\";\n let i = size;\n while (i--) {\n id += urlAlphabet[Math.random() * 64 | 0];\n }\n return id;\n};\nvar ModelAutoTypeCheckingMode;\n(function(ModelAutoTypeCheckingMode2) {\n ModelAutoTypeCheckingMode2[\"DevModeOnly\"] = \"devModeOnly\";\n ModelAutoTypeCheckingMode2[\"AlwaysOn\"] = \"alwaysOn\";\n ModelAutoTypeCheckingMode2[\"AlwaysOff\"] = \"alwaysOff\";\n})(ModelAutoTypeCheckingMode || (ModelAutoTypeCheckingMode = {}));\nlet localId = 0;\nconst localBaseId = nanoid();\nfunction defaultModelIdGenerator() {\n const id = localId.toString(36) + \"-\" + localBaseId;\n localId++;\n return id;\n}\nlet globalConfig = {\n modelAutoTypeChecking: ModelAutoTypeCheckingMode.DevModeOnly,\n modelIdGenerator: defaultModelIdGenerator,\n allowUndefinedArrayElements: false,\n showDuplicateModelNameWarnings: true\n};\nfunction setGlobalConfig(config) {\n globalConfig = Object.freeze({\n ...globalConfig,\n ...config\n });\n}\nfunction getGlobalConfig() {\n return globalConfig;\n}\nfunction isModelAutoTypeCheckingEnabled() {\n switch (getGlobalConfig().modelAutoTypeChecking) {\n case ModelAutoTypeCheckingMode.DevModeOnly:\n return inDevMode;\n case ModelAutoTypeCheckingMode.AlwaysOff:\n return false;\n case ModelAutoTypeCheckingMode.AlwaysOn:\n return true;\n default:\n throw failure(`invalid 'modelAutoTypeChecking' config value - ${globalConfig.modelAutoTypeChecking}`);\n }\n}\nconst objectChildren = /* @__PURE__ */ new WeakMap();\nfunction getObjectChildrenObject(node) {\n let obj = objectChildren.get(node);\n if (!obj) {\n obj = {\n shallow: /* @__PURE__ */ new Set(),\n shallowAtom: createAtom(\"shallowChildrenAtom\"),\n deep: /* @__PURE__ */ new Set(),\n deepDirty: true,\n deepAtom: createAtom(\"deepChildrenAtom\"),\n extensionsData: initExtensionsData()\n };\n objectChildren.set(node, obj);\n }\n return obj;\n}\nfunction getObjectChildren(node) {\n const obj = getObjectChildrenObject(node);\n obj.shallowAtom.reportObserved();\n return obj.shallow;\n}\nfunction getDeepObjectChildren(node) {\n const obj = getObjectChildrenObject(node);\n if (obj.deepDirty) {\n updateDeepObjectChildren(node);\n }\n obj.deepAtom.reportObserved();\n return obj;\n}\nfunction addNodeToDeepLists(node, data) {\n data.deep.add(node);\n extensions.forEach((extension, dataSymbol) => {\n extension.addNode(node, data.extensionsData.get(dataSymbol));\n });\n}\nconst updateDeepObjectChildren = action((node) => {\n const obj = getObjectChildrenObject(node);\n if (!obj.deepDirty) {\n return obj;\n }\n obj.deep = /* @__PURE__ */ new Set();\n obj.extensionsData = initExtensionsData();\n const childrenIterator = obj.shallow.values();\n let childrenIteratorResult = childrenIterator.next();\n while (!childrenIteratorResult.done) {\n addNodeToDeepLists(childrenIteratorResult.value, obj);\n const childDeepChildren = updateDeepObjectChildren(childrenIteratorResult.value).deep;\n const childDeepChildrenIterator = childDeepChildren.values();\n let childDeepChildrenIteratorResult = childDeepChildrenIterator.next();\n while (!childDeepChildrenIteratorResult.done) {\n addNodeToDeepLists(childDeepChildrenIteratorResult.value, obj);\n childDeepChildrenIteratorResult = childDeepChildrenIterator.next();\n }\n childrenIteratorResult = childrenIterator.next();\n }\n obj.deepDirty = false;\n obj.deepAtom.reportChanged();\n return obj;\n});\nconst addObjectChild = action((node, child) => {\n const obj = getObjectChildrenObject(node);\n obj.shallow.add(child);\n obj.shallowAtom.reportChanged();\n invalidateDeepChildren(node, obj);\n});\nconst removeObjectChild = action((node, child) => {\n const obj = getObjectChildrenObject(node);\n obj.shallow.delete(child);\n obj.shallowAtom.reportChanged();\n invalidateDeepChildren(node, obj);\n});\nfunction invalidateDeepChildren(node, obj) {\n let currentNode = node;\n let currentObj = obj;\n while (currentNode) {\n currentObj.deepDirty = true;\n currentObj.deepAtom.reportChanged();\n currentNode = fastGetParent(currentNode);\n if (currentNode) {\n currentObj = getObjectChildrenObject(currentNode);\n }\n }\n}\nconst extensions = /* @__PURE__ */ new Map();\nfunction registerDeepObjectChildrenExtension(extension) {\n const dataSymbol = {};\n extensions.set(dataSymbol, extension);\n return (data) => {\n return data.extensionsData.get(dataSymbol);\n };\n}\nfunction initExtensionsData() {\n const extensionsData = /* @__PURE__ */ new WeakMap();\n extensions.forEach((extension, dataSymbol) => {\n extensionsData.set(dataSymbol, extension.initData());\n });\n return extensionsData;\n}\nfunction canWrite() {\n return !getActionProtection() || !!getCurrentActionContext();\n}\nfunction assertCanWrite() {\n if (!canWrite()) {\n throw failure(\"data changes must be performed inside model actions\");\n }\n}\nlet actionProtection = true;\nfunction getActionProtection() {\n return actionProtection;\n}\nfunction setActionProtection(protection) {\n actionProtection = protection;\n}\nconst pendingActions = [];\nfunction isActionRunning() {\n return !getActionProtection() || !!getCurrentActionContext();\n}\nfunction enqueuePendingAction(action2) {\n if (isActionRunning()) {\n pendingActions.push(action2);\n } else {\n action2();\n }\n}\nlet pendingActionsRunning = false;\nfunction tryRunPendingActions() {\n if (isActionRunning() || pendingActionsRunning) {\n return;\n }\n pendingActionsRunning = true;\n try {\n while (pendingActions.length > 0) {\n const nextAction = pendingActions.shift();\n nextAction();\n }\n } finally {\n pendingActionsRunning = false;\n }\n}\nfunction getModelMetadata(modelClassOrInstance) {\n if (isModel(modelClassOrInstance)) {\n return modelClassOrInstance.constructor[modelMetadataSymbol];\n } else if (isModelClass(modelClassOrInstance)) {\n return modelClassOrInstance[modelMetadataSymbol];\n } else {\n throw failure(`modelClassOrInstance must be a model class or instance`);\n }\n}\nconst modelIdPropertyNameCache = /* @__PURE__ */ new WeakMap();\nfunction getModelIdPropertyName(modelClass2) {\n return getOrCreate(modelIdPropertyNameCache, modelClass2, () => getModelMetadata(modelClass2).modelIdProperty);\n}\nvar HookAction;\n(function(HookAction2) {\n HookAction2[\"OnInit\"] = \"$$onInit\";\n HookAction2[\"OnLazyInit\"] = \"$$onLazyInit\";\n HookAction2[\"OnAttachedToRootStore\"] = \"$$onAttachedToRootStore\";\n HookAction2[\"OnAttachedToRootStoreDisposer\"] = \"$$onAttachedToRootStoreDisposer\";\n})(HookAction || (HookAction = {}));\nconst hookActionValues = new Set(Object.values(HookAction));\nfunction isHookAction(actionName) {\n return hookActionValues.has(actionName);\n}\nvar WalkTreeMode;\n(function(WalkTreeMode2) {\n WalkTreeMode2[\"ParentFirst\"] = \"parentFirst\";\n WalkTreeMode2[\"ChildrenFirst\"] = \"childrenFirst\";\n})(WalkTreeMode || (WalkTreeMode = {}));\nfunction walkTree(root, visit, mode) {\n assertTweakedObject(root, \"root\");\n if (mode === WalkTreeMode.ParentFirst) {\n return walkTreeParentFirst(root, visit);\n } else {\n return walkTreeChildrenFirst(root, visit);\n }\n}\nfunction walkTreeParentFirst(root, visit) {\n const stack = [root];\n while (stack.length > 0) {\n const node = stack.pop();\n const ret = visit(node);\n if (ret !== void 0) {\n return ret;\n }\n const children = getObjectChildren(node);\n stack.length += children.size;\n let i = stack.length - 1;\n const childrenIter = children.values();\n let ch = childrenIter.next();\n while (!ch.done) {\n stack[i--] = ch.value;\n ch = childrenIter.next();\n }\n }\n return void 0;\n}\nfunction walkTreeChildrenFirst(root, visit) {\n const childrenIter = getObjectChildren(root).values();\n let ch = childrenIter.next();\n while (!ch.done) {\n const ret2 = walkTreeChildrenFirst(ch.value, visit);\n if (ret2 !== void 0) {\n return ret2;\n }\n ch = childrenIter.next();\n }\n const ret = visit(root);\n if (ret !== void 0) {\n return ret;\n }\n return void 0;\n}\nfunction getComputedTreeResult(computedFns, visit, tree) {\n let cmpted = computedFns.get(tree);\n if (!cmpted) {\n cmpted = computed(() => {\n return walkTreeAggregate(tree, visit, (ch) => getComputedTreeResult(computedFns, visit, ch));\n });\n computedFns.set(tree, cmpted);\n }\n return cmpted.get();\n}\nfunction computedWalkTreeAggregate(visit) {\n const computedFns = /* @__PURE__ */ new WeakMap();\n return {\n walk: (n) => getComputedTreeResult(computedFns, visit, n)\n };\n}\nfunction walkTreeAggregate(target, visit, recurse) {\n let map;\n const rootVal = visit(target);\n const childrenMap = getObjectChildren(target);\n const childrenIter = childrenMap.values();\n let ch = childrenIter.next();\n if (rootVal === void 0 && childrenMap.size === 1) {\n return recurse(ch.value);\n }\n while (!ch.done) {\n const childMap = recurse(ch.value);\n if (childMap) {\n if (!map) {\n map = /* @__PURE__ */ new Map();\n }\n const mapIter = childMap.keys();\n let mapCur = mapIter.next();\n while (!mapCur.done) {\n const key = mapCur.value;\n const val = childMap.get(key);\n map.set(key, val);\n mapCur = mapIter.next();\n }\n }\n ch = childrenIter.next();\n }\n if (rootVal !== void 0) {\n if (!map) {\n map = /* @__PURE__ */ new Map();\n }\n map.set(rootVal, target);\n }\n return map;\n}\nconst onAttachedDisposers = /* @__PURE__ */ new WeakMap();\nconst attachedToRootStore = /* @__PURE__ */ new WeakSet();\nconst attachToRootStore = action(\"attachToRootStore\", (rootStore, child) => {\n const childrenToCall = [];\n walkTree(child, (ch) => {\n if (attachedToRootStore.has(ch)) {\n return;\n }\n attachedToRootStore.add(ch);\n if (ch instanceof BaseModel && ch.onAttachedToRootStore) {\n wrapModelMethodInActionIfNeeded(ch, \"onAttachedToRootStore\", HookAction.OnAttachedToRootStore);\n childrenToCall.push(ch);\n }\n }, WalkTreeMode.ParentFirst);\n const childrenToCallLen = childrenToCall.length;\n for (let i = 0; i < childrenToCallLen; i++) {\n const ch = childrenToCall[i];\n const disposer = ch.onAttachedToRootStore(rootStore);\n if (disposer) {\n onAttachedDisposers.set(ch, disposer);\n }\n }\n});\nconst detachFromRootStore = action(\"detachFromRootStore\", (child) => {\n const disposersToCall = [];\n walkTree(child, (ch) => {\n if (!attachedToRootStore.delete(ch)) {\n return;\n }\n const disposer = onAttachedDisposers.get(ch);\n if (disposer) {\n const disposerAction = wrapInAction({\n nameOrNameFn: HookAction.OnAttachedToRootStoreDisposer,\n fn: disposer,\n actionType: ActionContextActionType.Sync\n }).bind(ch);\n onAttachedDisposers.delete(ch);\n disposersToCall.push(disposerAction);\n }\n }, WalkTreeMode.ChildrenFirst);\n const disposersToCallLen = disposersToCall.length;\n for (let i = 0; i < disposersToCallLen; i++) {\n disposersToCall[i]();\n }\n});\nconst rootStoreRegistry = /* @__PURE__ */ new WeakMap();\nconst getOrCreateRootStoreEntry = (node) => getOrCreate(rootStoreRegistry, node, () => ({\n atom: createAtom(\"rootStore\"),\n is: false\n}));\nconst registerRootStore = action(\"registerRootStore\", (node) => {\n assertTweakedObject(node, \"node\");\n const entry = getOrCreateRootStoreEntry(node);\n if (entry.is) {\n throw failure(\"object already registered as root store\");\n }\n if (!isRoot(node)) {\n throw failure(\"a root store must not have a parent\");\n }\n entry.is = true;\n attachToRootStore(node, node);\n entry.atom.reportChanged();\n return node;\n});\nconst unregisterRootStore = action(\"unregisterRootStore\", (node) => {\n if (!isRootStore(node)) {\n throw failure(\"not a root store\");\n }\n const entry = getOrCreateRootStoreEntry(node);\n entry.is = false;\n detachFromRootStore(node);\n entry.atom.reportChanged();\n});\nfunction isRootStore(node) {\n assertTweakedObject(node, \"node\");\n return fastIsRootStore(node);\n}\nfunction fastIsRootStore(node) {\n const entry = getOrCreateRootStoreEntry(node);\n entry.atom.reportObserved();\n return entry.is;\n}\nfunction getRootStore(node) {\n assertTweakedObject(node, \"node\");\n return fastGetRootStore(node);\n}\nfunction fastGetRootStore(node) {\n const root = fastGetRoot(node);\n return fastIsRootStore(root) ? root : void 0;\n}\nclass TypeCheckError {\n /**\n * Creates an instance of TypeError.\n * @param path Sub-path (where the root is the value being type checked) where the error occured.\n * @param expectedTypeName Name of the expected type.\n * @param actualValue Actual value.\n * @param typeCheckedValue The value where the type check was invoked.\n */\n constructor(path, expectedTypeName, actualValue, typeCheckedValue) {\n __publicField(this, \"path\");\n __publicField(this, \"expectedTypeName\");\n __publicField(this, \"actualValue\");\n __publicField(this, \"typeCheckedValue\");\n /**\n * The type check error message.\n */\n __publicField(this, \"message\");\n this.path = path;\n this.expectedTypeName = expectedTypeName;\n this.actualValue = actualValue;\n this.typeCheckedValue = typeCheckedValue;\n let rootPath = [];\n if (this.typeCheckedValue && isTweakedObject(this.typeCheckedValue, true)) {\n rootPath = fastGetRootPath(this.typeCheckedValue).path;\n }\n const actualValueSnapshot = isTweakedObject(this.actualValue, true) ? getSnapshot(this.actualValue) : this.actualValue;\n this.message = `TypeCheckError: [/${[...rootPath, ...this.path].join(\"/\")}] Expected a value of type <${this.expectedTypeName}> but got the value <${JSON.stringify(actualValueSnapshot)}> instead`;\n }\n /**\n * Throws the type check error as an actual error.\n */\n throw() {\n throw failure(this.message);\n }\n}\nconst emptyPath = [];\nconst typeCheckersWithCachedResultsOfObject = /* @__PURE__ */ new WeakMap();\nvar TypeCheckerBaseType;\n(function(TypeCheckerBaseType2) {\n TypeCheckerBaseType2[\"Object\"] = \"object\";\n TypeCheckerBaseType2[\"Array\"] = \"array\";\n TypeCheckerBaseType2[\"Primitive\"] = \"primitive\";\n TypeCheckerBaseType2[\"Any\"] = \"any\";\n})(TypeCheckerBaseType || (TypeCheckerBaseType = {}));\nfunction getTypeCheckerBaseTypeFromValue(value) {\n if (isArray(value))\n return TypeCheckerBaseType.Array;\n if (isObject(value))\n return TypeCheckerBaseType.Object;\n if (isPrimitive(value))\n return TypeCheckerBaseType.Primitive;\n return TypeCheckerBaseType.Any;\n}\nfunction invalidateCachedTypeCheckerResult(obj) {\n let current = obj;\n while (current) {\n const set2 = typeCheckersWithCachedResultsOfObject.get(current);\n if (set2) {\n typeCheckersWithCachedResultsOfObject.delete(current);\n set2.forEach((typeChecker) => typeChecker.invalidateCachedResult(current));\n }\n current = fastGetParentIncludingDataObjects(current);\n }\n}\nconst typeCheckersWithCachedSnapshotProcessorResultsOfObject = /* @__PURE__ */ new WeakMap();\nfunction invalidateCachedToSnapshotProcessorResult(obj) {\n const set2 = typeCheckersWithCachedSnapshotProcessorResultsOfObject.get(obj);\n if (set2) {\n set2.forEach((typeChecker) => typeChecker.invalidateSnapshotProcessorCachedResult(obj));\n typeCheckersWithCachedSnapshotProcessorResultsOfObject.delete(obj);\n }\n}\nclass TypeChecker {\n constructor(baseType, _check, getTypeName, typeInfoGen, snapshotType, _fromSnapshotProcessor, _toSnapshotProcessor) {\n __publicField(this, \"baseType\");\n __publicField(this, \"_check\");\n __publicField(this, \"getTypeName\");\n __publicField(this, \"typeInfoGen\");\n __publicField(this, \"snapshotType\");\n __publicField(this, \"_fromSnapshotProcessor\");\n __publicField(this, \"_toSnapshotProcessor\");\n __publicField(this, \"checkResultCache\");\n __publicField(this, \"unchecked\");\n __publicField(this, \"_cachedTypeInfoGen\");\n __publicField(this, \"fromSnapshotProcessor\", (sn) => {\n return this._fromSnapshotProcessor(sn);\n });\n __publicField(this, \"_toSnapshotProcessorCache\", /* @__PURE__ */ new WeakMap());\n __publicField(this, \"toSnapshotProcessor\", (sn) => {\n if (typeof sn !== \"object\" || sn === null) {\n return this._toSnapshotProcessor(sn);\n }\n if (this._toSnapshotProcessorCache.has(sn)) {\n return this._toSnapshotProcessorCache.get(sn);\n }\n const val = this._toSnapshotProcessor(sn);\n this._toSnapshotProcessorCache.set(sn, val);\n const typeCheckerSet = getOrCreate(typeCheckersWithCachedSnapshotProcessorResultsOfObject, sn, () => /* @__PURE__ */ new Set());\n typeCheckerSet.add(this);\n return val;\n });\n this.baseType = baseType;\n this._check = _check;\n this.getTypeName = getTypeName;\n this.typeInfoGen = typeInfoGen;\n this.snapshotType = snapshotType;\n this._fromSnapshotProcessor = _fromSnapshotProcessor;\n this._toSnapshotProcessor = _toSnapshotProcessor;\n this.unchecked = !_check;\n this._cachedTypeInfoGen = lazy(typeInfoGen);\n }\n createCacheIfNeeded() {\n if (!this.checkResultCache) {\n this.checkResultCache = /* @__PURE__ */ new WeakMap();\n }\n return this.checkResultCache;\n }\n setCachedResult(obj, newCacheValue) {\n this.createCacheIfNeeded().set(obj, newCacheValue);\n const typeCheckerSet = getOrCreate(typeCheckersWithCachedResultsOfObject, obj, () => /* @__PURE__ */ new Set());\n typeCheckerSet.add(this);\n }\n invalidateCachedResult(obj) {\n var _a2;\n (_a2 = this.checkResultCache) == null ? void 0 : _a2.delete(obj);\n }\n getCachedResult(obj) {\n var _a2;\n return (_a2 = this.checkResultCache) == null ? void 0 : _a2.get(obj);\n }\n check(value, path, typeCheckedValue) {\n if (this.unchecked) {\n return null;\n }\n if (!isTweakedObject(value, true)) {\n return this._check(value, path, typeCheckedValue);\n }\n let cachedResult = this.getCachedResult(value);\n if (cachedResult === void 0) {\n cachedResult = this._check(value, emptyPath, void 0);\n this.setCachedResult(value, cachedResult);\n }\n if (cachedResult) {\n return new TypeCheckError([...path, ...cachedResult.path], cachedResult.expectedTypeName, cachedResult.actualValue, typeCheckedValue);\n } else {\n return null;\n }\n }\n get typeInfo() {\n return this._cachedTypeInfoGen(this);\n }\n invalidateSnapshotProcessorCachedResult(obj) {\n this._toSnapshotProcessorCache.delete(obj);\n }\n}\nconst lateTypeCheckerSymbol = Symbol(\"lateTypeCheker\");\nfunction lateTypeChecker(fn, typeInfoGen) {\n let cached;\n const ltc = function() {\n if (cached) {\n return cached;\n }\n cached = fn();\n return cached;\n };\n ltc[lateTypeCheckerSymbol] = true;\n const cachedTypeInfoGen = lazy(typeInfoGen);\n Object.defineProperty(ltc, \"typeInfo\", {\n enumerable: true,\n configurable: true,\n get() {\n return cachedTypeInfoGen(ltc);\n }\n });\n return ltc;\n}\nfunction isLateTypeChecker(ltc) {\n return typeof ltc === \"function\" && lateTypeCheckerSymbol in ltc;\n}\nclass TypeInfo {\n constructor(thisType) {\n __publicField(this, \"thisType\");\n this.thisType = thisType;\n }\n}\nconst snapshots = /* @__PURE__ */ new WeakMap();\nconst frozenState = /* @__PURE__ */ new WeakMap();\nfunction getInternalSnapshot(value) {\n return snapshots.get(value);\n}\nfunction getInternalSnapshotParent(sn, parentPath) {\n if (!parentPath || !sn) {\n return void 0;\n }\n const parentSn = getInternalSnapshot(parentPath.parent);\n if (!parentSn) {\n return void 0;\n }\n return {\n parentSnapshot: parentSn,\n parentPath\n };\n}\nconst unsetInternalSnapshot = action(\"unsetInternalSnapshot\", (value) => {\n const oldSn = getInternalSnapshot(value);\n if (oldSn) {\n snapshots.delete(value);\n oldSn.atom.reportChanged();\n }\n});\nconst setNewInternalSnapshot = action(\"setNewInternalSnapshot\", (value, untransformed, transformFn, markAsFrozen = false) => {\n const sn = {\n untransformed,\n transformFn,\n transformed: transformFn ? transformFn(untransformed) : untransformed,\n atom: createAtom(\"snapshot\")\n };\n frozenState.set(sn.untransformed, markAsFrozen);\n if (sn.transformed !== void 0) {\n frozenState.set(sn.transformed, markAsFrozen);\n }\n snapshots.set(value, sn);\n sn.atom.reportChanged();\n});\nconst updateInternalSnapshot = action(\"updateInternalSnapshot\", (value, mutate) => {\n const sn = getInternalSnapshot(value);\n let untransformed = sn.untransformed;\n const snFrozen = frozenState.get(untransformed);\n if (snFrozen) {\n if (Array.isArray(untransformed)) {\n untransformed = untransformed.slice();\n } else {\n untransformed = Object.assign({}, untransformed);\n }\n } else {\n invalidateCachedToSnapshotProcessorResult(untransformed);\n }\n mutate(untransformed);\n sn.untransformed = untransformed;\n sn.transformed = sn.transformFn ? sn.transformFn(untransformed) : untransformed;\n frozenState.set(sn.untransformed, false);\n if (sn.transformed !== void 0) {\n frozenState.set(sn.transformed, false);\n }\n sn.atom.reportChanged();\n const parent = getInternalSnapshotParent(sn, fastGetParentPath(value));\n if (parent) {\n const { parentSnapshot, parentPath } = parent;\n if (parentSnapshot) {\n const path = parentPath.path;\n updateInternalSnapshot(parentPath.parent, (objOrArray) => {\n objOrArray[path] = sn.transformed;\n });\n }\n }\n});\nfunction reportInternalSnapshotObserved(sn) {\n sn.atom.reportObserved();\n}\nfunction freezeInternalSnapshot(data) {\n if (isPrimitive(data)) {\n return data;\n }\n const isFrozen = frozenState.get(data);\n if (isFrozen === void 0 || isFrozen === true) {\n return data;\n }\n if (Array.isArray(data)) {\n for (let i = 0; i < data.length; i++) {\n freezeInternalSnapshot(data[i]);\n }\n } else {\n const keys2 = Object.keys(data);\n for (let i = 0; i < keys2.length; i++) {\n freezeInternalSnapshot(data[keys2[i]]);\n }\n }\n frozenState.set(data, true);\n return data;\n}\nconst emptyPatchArray = [];\nclass InternalPatchRecorder {\n constructor() {\n __publicField(this, \"patches\", emptyPatchArray);\n __publicField(this, \"invPatches\", emptyPatchArray);\n }\n reset() {\n this.patches = emptyPatchArray;\n this.invPatches = emptyPatchArray;\n }\n record(patches, invPatches) {\n this.patches = patches;\n this.invPatches = invPatches;\n }\n emit(obj) {\n emitPatches(obj, this.patches, this.invPatches);\n this.reset();\n }\n}\nfunction emitPatches(obj, patches, invPatches) {\n if (patches.length > 0 || invPatches.length > 0) {\n emitGlobalPatch(obj, patches, invPatches);\n emitPatch(obj, patches, invPatches);\n }\n}\nconst patchListeners = /* @__PURE__ */ new WeakMap();\nconst globalPatchListeners = [];\nfunction onPatches(subtreeRoot, listener) {\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n assertIsFunction(listener, \"listener\");\n if (!isAction(listener)) {\n listener = action(listener.name || \"onPatchesListener\", listener);\n }\n let listenersForObject = patchListeners.get(subtreeRoot);\n if (!listenersForObject) {\n listenersForObject = [];\n patchListeners.set(subtreeRoot, listenersForObject);\n }\n listenersForObject.push(listener);\n return () => {\n deleteFromArray(listenersForObject, listener);\n };\n}\nfunction onGlobalPatches(listener) {\n assertIsFunction(listener, \"listener\");\n if (!isAction(listener)) {\n listener = action(listener.name || \"onGlobalPatchesListener\", listener);\n }\n globalPatchListeners.push(listener);\n return () => {\n deleteFromArray(globalPatchListeners, listener);\n };\n}\nfunction emitGlobalPatch(obj, patches, inversePatches) {\n for (let i = 0; i < globalPatchListeners.length; i++) {\n const listener = globalPatchListeners[i];\n listener(obj, patches, inversePatches);\n }\n}\nfunction emitPatchForTarget(obj, patches, inversePatches, pathPrefix) {\n const listenersForObject = patchListeners.get(obj);\n if (!listenersForObject || listenersForObject.length === 0) {\n return;\n }\n const fixPath = (patchesArray) => pathPrefix.length > 0 ? patchesArray.map((p) => addPathToPatch(p, pathPrefix)) : patchesArray;\n const patchesWithPathPrefix = fixPath(patches);\n const invPatchesWithPathPrefix = fixPath(inversePatches);\n for (let i = 0; i < listenersForObject.length; i++) {\n const listener = listenersForObject[i];\n listener(patchesWithPathPrefix, invPatchesWithPathPrefix);\n }\n}\nfunction emitPatch(obj, patches, inversePatches) {\n const pathPrefix = [];\n emitPatchForTarget(obj, patches, inversePatches, pathPrefix);\n let parentPath = fastGetParentPath(obj);\n while (parentPath) {\n pathPrefix.unshift(parentPath.path);\n emitPatchForTarget(parentPath.parent, patches, inversePatches, pathPrefix);\n parentPath = fastGetParentPath(parentPath.parent);\n }\n}\nfunction addPathToPatch(patch, pathPrefix) {\n return {\n ...patch,\n path: [...pathPrefix, ...patch.path]\n };\n}\nconst getValueSnapshotForPatch = (v) => {\n if (isPrimitive(v)) {\n return v;\n }\n const internalSnapshot = getInternalSnapshot(v);\n if (!internalSnapshot) {\n return v;\n }\n return freezeInternalSnapshot(internalSnapshot.transformed);\n};\nfunction createPatchForObjectValueChange(path, oldValue, newValue) {\n return newValue === void 0 ? { op: \"remove\", path } : oldValue === void 0 ? {\n op: \"add\",\n path,\n value: getValueSnapshotForPatch(newValue)\n } : {\n op: \"replace\",\n path,\n value: getValueSnapshotForPatch(newValue)\n };\n}\nfunction setIfDifferent(target, key, value) {\n const oldValue = target[key];\n if (oldValue !== value || value === void 0 && !(key in target)) {\n set(target, key, value);\n return true;\n }\n return false;\n}\nvar TweakerPriority;\n(function(TweakerPriority2) {\n TweakerPriority2[TweakerPriority2[\"Model\"] = 0] = \"Model\";\n TweakerPriority2[TweakerPriority2[\"Array\"] = 1] = \"Array\";\n TweakerPriority2[TweakerPriority2[\"PlainObject\"] = 2] = \"PlainObject\";\n TweakerPriority2[TweakerPriority2[\"Frozen\"] = 3] = \"Frozen\";\n})(TweakerPriority || (TweakerPriority = {}));\nfunction findParent(child, predicate, maxDepth = 0) {\n const foundParentPath = findParentPath(child, predicate, maxDepth);\n return foundParentPath ? foundParentPath.parent : void 0;\n}\nfunction findParentPath(child, predicate, maxDepth = 0) {\n assertTweakedObject(child, \"child\");\n const path = [];\n let current = child;\n let depth = 0;\n let parentPath;\n while (parentPath = fastGetParentPath(current)) {\n path.unshift(parentPath.path);\n current = parentPath.parent;\n if (predicate(current)) {\n return {\n parent: current,\n path\n };\n }\n depth++;\n if (maxDepth > 0 && depth === maxDepth) {\n break;\n }\n }\n return void 0;\n}\nfunction getChildrenObjects(node, options) {\n assertTweakedObject(node, \"node\");\n if (!options || !options.deep) {\n return getObjectChildren(node);\n } else {\n return getDeepObjectChildren(node).deep;\n }\n}\nfunction findChildren(root, predicate, options) {\n const children = getChildrenObjects(root, options);\n const set2 = /* @__PURE__ */ new Set();\n const iter = children.values();\n let cur = iter.next();\n while (!cur.done) {\n if (predicate(cur.value)) {\n set2.add(cur.value);\n }\n cur = iter.next();\n }\n return set2;\n}\nfunction onChildAttachedTo(target, fn, options) {\n assertIsFunction(target, \"target\");\n assertIsFunction(fn, \"fn\");\n const opts = {\n deep: false,\n runForCurrentChildren: true,\n ...options\n };\n const detachDisposers = /* @__PURE__ */ new WeakMap();\n const runDetachDisposer = (n) => {\n const detachDisposer = detachDisposers.get(n);\n if (detachDisposer) {\n detachDisposers.delete(n);\n detachDisposer();\n }\n };\n const addDetachDisposer = (n, disposer2) => {\n if (disposer2) {\n detachDisposers.set(n, disposer2);\n }\n };\n const getChildrenObjectOpts = { deep: opts.deep };\n const getCurrentChildren = () => {\n let t = target();\n assertTweakedObject(t, \"target()\");\n const children = getChildrenObjects(t, getChildrenObjectOpts);\n const set2 = /* @__PURE__ */ new Set();\n const iter = children.values();\n let cur = iter.next();\n while (!cur.done) {\n set2.add(cur.value);\n cur = iter.next();\n }\n return set2;\n };\n const currentChildren = opts.runForCurrentChildren ? /* @__PURE__ */ new Set() : getCurrentChildren();\n const disposer = reaction(() => getCurrentChildren(), (newChildren) => {\n const disposersToRun = [];\n const currentChildrenIter = currentChildren.values();\n let currentChildrenCur = currentChildrenIter.next();\n while (!currentChildrenCur.done) {\n const n = currentChildrenCur.value;\n if (!newChildren.has(n)) {\n currentChildren.delete(n);\n disposersToRun.push(n);\n }\n currentChildrenCur = currentChildrenIter.next();\n }\n if (disposersToRun.length > 0) {\n for (let i = disposersToRun.length - 1; i >= 0; i--) {\n runDetachDisposer(disposersToRun[i]);\n }\n }\n const newChildrenIter = newChildren.values();\n let newChildrenCur = newChildrenIter.next();\n while (!newChildrenCur.done) {\n const n = newChildrenCur.value;\n if (!currentChildren.has(n)) {\n currentChildren.add(n);\n addDetachDisposer(n, fn(n));\n }\n newChildrenCur = newChildrenIter.next();\n }\n }, {\n fireImmediately: true\n });\n return (runDetachDisposers) => {\n disposer();\n if (runDetachDisposers) {\n const currentChildrenIter = currentChildren.values();\n let currentChildrenCur = currentChildrenIter.next();\n while (!currentChildrenCur.done) {\n const n = currentChildrenCur.value;\n runDetachDisposer(n);\n currentChildrenCur = currentChildrenIter.next();\n }\n }\n currentChildren.clear();\n };\n}\nfunction isChildOfParent(child, parent) {\n assertTweakedObject(child, \"child\");\n assertTweakedObject(parent, \"parent\");\n let currentParent = fastGetParent(child);\n while (currentParent) {\n if (currentParent === parent) {\n return true;\n }\n currentParent = fastGetParent(currentParent);\n }\n return false;\n}\nfunction isParentOfChild(parent, child) {\n return isChildOfParent(child, parent);\n}\nlet typeCheckingAllowed = true;\nfunction withoutTypeChecking(fn) {\n let oldTypeCheckingAllowed = typeCheckingAllowed;\n typeCheckingAllowed = false;\n try {\n fn();\n } finally {\n typeCheckingAllowed = oldTypeCheckingAllowed;\n }\n}\nfunction isTypeCheckingAllowed() {\n return typeCheckingAllowed;\n}\nvar SnapshotterAndReconcilerPriority;\n(function(SnapshotterAndReconcilerPriority2) {\n SnapshotterAndReconcilerPriority2[SnapshotterAndReconcilerPriority2[\"Array\"] = 0] = \"Array\";\n SnapshotterAndReconcilerPriority2[SnapshotterAndReconcilerPriority2[\"Frozen\"] = 1] = \"Frozen\";\n SnapshotterAndReconcilerPriority2[SnapshotterAndReconcilerPriority2[\"Model\"] = 2] = \"Model\";\n SnapshotterAndReconcilerPriority2[SnapshotterAndReconcilerPriority2[\"PlainObject\"] = 3] = \"PlainObject\";\n})(SnapshotterAndReconcilerPriority || (SnapshotterAndReconcilerPriority = {}));\nfunction reconcileArraySnapshot(value, sn, modelPool) {\n if (!isArray(value)) {\n return fromSnapshot(sn);\n }\n const snapshotBeforeChanges = getSnapshot(value);\n withoutTypeChecking(() => {\n if (value.length > sn.length) {\n value.splice(sn.length, value.length - sn.length);\n }\n for (let i = 0; i < value.length; i++) {\n const oldValue = value[i];\n const newValue = reconcileSnapshot(oldValue, sn[i], modelPool, value);\n detachIfNeeded(newValue, oldValue, modelPool);\n setIfDifferent(value, i, newValue);\n }\n for (let i = value.length; i < sn.length; i++) {\n value.push(reconcileSnapshot(void 0, sn[i], modelPool, value));\n }\n });\n runTypeCheckingAfterChange(value, void 0, snapshotBeforeChanges);\n return value;\n}\nfunction registerArraySnapshotReconciler() {\n registerReconciler(SnapshotterAndReconcilerPriority.Array, (value, sn, modelPool) => {\n if (isArray(sn)) {\n return reconcileArraySnapshot(value, sn, modelPool);\n }\n return void 0;\n });\n}\nvar FrozenCheckMode;\n(function(FrozenCheckMode2) {\n FrozenCheckMode2[\"DevModeOnly\"] = \"devModeOnly\";\n FrozenCheckMode2[\"On\"] = \"on\";\n FrozenCheckMode2[\"Off\"] = \"off\";\n})(FrozenCheckMode || (FrozenCheckMode = {}));\nconst frozenKey = \"$frozen\";\nclass Frozen {\n /**\n * Creates an instance of Frozen.\n * Do not use directly, use `frozen` instead.\n *\n * @param dataToFreeze\n * @param checkMode\n */\n constructor(dataToFreeze, checkMode = FrozenCheckMode.DevModeOnly) {\n /**\n * Frozen data, deeply immutable.\n */\n __publicField(this, \"data\");\n const check = checkMode === FrozenCheckMode.On || inDevMode && checkMode === FrozenCheckMode.DevModeOnly;\n if (check) {\n checkDataIsSerializableAndFreeze(dataToFreeze);\n }\n this.data = dataToFreeze;\n if (check) {\n Object.freeze(this.data);\n }\n tweak(this, void 0);\n }\n}\nfunction frozen(data, checkMode = FrozenCheckMode.DevModeOnly) {\n return new Frozen(data, checkMode);\n}\nfunction checkDataIsSerializableAndFreeze(data) {\n if (isPrimitive(data)) {\n return;\n }\n if (Array.isArray(data)) {\n const arrLen = data.length;\n for (let i = 0; i < arrLen; i++) {\n const v = data[i];\n if (v === void 0 && !getGlobalConfig().allowUndefinedArrayElements) {\n throw failure(\"undefined is not supported inside arrays since it is not serializable in JSON, consider using null instead\");\n }\n checkDataIsSerializableAndFreeze(v);\n }\n Object.freeze(data);\n return;\n }\n if (isPlainObject(data)) {\n const dataKeys = Object.keys(data);\n const dataKeysLen = dataKeys.length;\n for (let i = 0; i < dataKeysLen; i++) {\n const k = dataKeys[i];\n const v = data[k];\n checkDataIsSerializableAndFreeze(k);\n checkDataIsSerializableAndFreeze(v);\n }\n Object.freeze(data);\n return;\n }\n throw failure(`frozen data must be plainly serializable to JSON, but ${data} is not`);\n}\nfunction isFrozenSnapshot(snapshot) {\n return isPlainObject(snapshot) && frozenKey in snapshot;\n}\nfunction reconcileFrozenSnapshot(value, sn) {\n if (value instanceof Frozen && value.data === sn.data) {\n return value;\n }\n return frozen(sn.data);\n}\nfunction registerFrozenSnapshotReconciler() {\n registerReconciler(SnapshotterAndReconcilerPriority.Frozen, (value, sn) => {\n if (isFrozenSnapshot(sn)) {\n return reconcileFrozenSnapshot(value, sn);\n }\n return void 0;\n });\n}\nfunction getDefaultExportFromCjs(x) {\n return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, \"default\") ? x[\"default\"] : x;\n}\nvar es6 = function equal(a, b) {\n if (a === b)\n return true;\n if (a && b && typeof a == \"object\" && typeof b == \"object\") {\n if (a.constructor !== b.constructor)\n return false;\n var length, i, keys2;\n if (Array.isArray(a)) {\n length = a.length;\n if (length != b.length)\n return false;\n for (i = length; i-- !== 0; )\n if (!equal(a[i], b[i]))\n return false;\n return true;\n }\n if (a instanceof Map && b instanceof Map) {\n if (a.size !== b.size)\n return false;\n for (i of a.entries())\n if (!b.has(i[0]))\n return false;\n for (i of a.entries())\n if (!equal(i[1], b.get(i[0])))\n return false;\n return true;\n }\n if (a instanceof Set && b instanceof Set) {\n if (a.size !== b.size)\n return false;\n for (i of a.entries())\n if (!b.has(i[0]))\n return false;\n return true;\n }\n if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {\n length = a.length;\n if (length != b.length)\n return false;\n for (i = length; i-- !== 0; )\n if (a[i] !== b[i])\n return false;\n return true;\n }\n if (a.constructor === RegExp)\n return a.source === b.source && a.flags === b.flags;\n if (a.valueOf !== Object.prototype.valueOf)\n return a.valueOf() === b.valueOf();\n if (a.toString !== Object.prototype.toString)\n return a.toString() === b.toString();\n keys2 = Object.keys(a);\n length = keys2.length;\n if (length !== Object.keys(b).length)\n return false;\n for (i = length; i-- !== 0; )\n if (!Object.prototype.hasOwnProperty.call(b, keys2[i]))\n return false;\n for (i = length; i-- !== 0; ) {\n var key = keys2[i];\n if (!equal(a[key], b[key]))\n return false;\n }\n return true;\n }\n return a !== a && b !== b;\n};\nconst fastDeepEqual = /* @__PURE__ */ getDefaultExportFromCjs(es6);\nfunction byModelTypeAndIdKey(modelType, modelId) {\n return modelType + \" \" + modelId;\n}\nclass ModelPool {\n constructor(root) {\n __publicField(this, \"pool\");\n var _a2;\n root = (_a2 = dataObjectParent.get(root)) != null ? _a2 : root;\n this.pool = getDeepChildrenModels(getDeepObjectChildren(root));\n }\n findModelByTypeAndId(modelType, modelId) {\n return modelId ? this.pool.get(byModelTypeAndIdKey(modelType, modelId)) : void 0;\n }\n findModelForSnapshot(sn) {\n if (!isModelSnapshot(sn)) {\n return void 0;\n }\n const modelType = sn[modelTypeKey];\n const modelInfo = getModelInfoForName(modelType);\n const modelIdPropertyName = getModelIdPropertyName(modelInfo.class);\n return modelIdPropertyName ? this.findModelByTypeAndId(modelType, sn[modelIdPropertyName]) : void 0;\n }\n}\nconst getDeepChildrenModels = registerDeepObjectChildrenExtension({\n initData() {\n return /* @__PURE__ */ new Map();\n },\n addNode(node, data) {\n if (isModel(node)) {\n const id = node[modelIdKey];\n if (id) {\n data.set(byModelTypeAndIdKey(node[modelTypeKey], id), node);\n }\n }\n }\n});\nfunction applySnapshot(node, snapshot) {\n assertTweakedObject(node, \"node\");\n assertIsObject(snapshot, \"snapshot\");\n wrappedInternalApplySnapshot().call(node, snapshot);\n}\nfunction internalApplySnapshot(sn) {\n const obj = this;\n const reconcile = () => {\n const modelPool = new ModelPool(obj);\n const ret = reconcileSnapshot(obj, sn, modelPool, void 0);\n if (inDevMode) {\n if (ret !== obj) {\n throw failure(\"assertion failed: reconciled object has to be the same\");\n }\n }\n };\n if (isArray(sn)) {\n if (!isArray(obj)) {\n throw failure(\"if the snapshot is an array the target must be an array too\");\n }\n return reconcile();\n }\n if (isFrozenSnapshot(sn)) {\n throw failure(\"applySnapshot cannot be used over frozen objects\");\n }\n if (isPlainObject(sn) && sn[modelTypeKey] === void 0 && isModel(obj)) {\n const modelInfo = modelInfoByClass.get(obj.constructor);\n sn = { ...sn, [modelTypeKey]: modelInfo.name };\n }\n if (isModelSnapshot(sn)) {\n const type = sn[modelTypeKey];\n const modelInfo = getModelInfoForName(type);\n if (!modelInfo) {\n throw failure(`model with name \"${type}\" not found in the registry`);\n }\n if (!isModel(obj)) {\n throw failure(`the target for a model snapshot must be a model instance`);\n }\n if (obj[modelTypeKey] !== type) {\n throw failure(`snapshot model type '${type}' does not match target model type '${obj[modelTypeKey]}'`);\n }\n const modelIdPropertyName = getModelIdPropertyName(modelInfo.class);\n if (modelIdPropertyName) {\n const id = sn[modelIdPropertyName];\n if (obj[modelIdKey] !== id) {\n throw failure(`snapshot model id '${id}' does not match target model id '${obj[modelIdKey]}'`);\n }\n }\n return reconcile();\n }\n if (isPlainObject(sn)) {\n if (!isPlainObject(obj) && !isObservableObject(obj)) {\n throw failure(\"if the snapshot is an object the target must be an object too\");\n }\n return reconcile();\n }\n if (isMap(sn)) {\n throw failure(\"a snapshot must not contain maps\");\n }\n if (isSet(sn)) {\n throw failure(\"a snapshot must not contain sets\");\n }\n throw failure(`unsupported snapshot - ${sn}`);\n}\nconst wrappedInternalApplySnapshot = lazy(() => wrapInAction({\n nameOrNameFn: BuiltInAction.ApplySnapshot,\n fn: internalApplySnapshot,\n actionType: ActionContextActionType.Sync\n}));\nfunction onSnapshot(nodeOrFn, listener) {\n const nodeFn = typeof nodeOrFn === \"function\" ? nodeOrFn : () => nodeOrFn;\n const node = nodeFn();\n assertTweakedObject(node, \"node\");\n let currentSnapshot = getSnapshot(node);\n return reaction(() => getSnapshot(nodeFn()), (newSnapshot) => {\n const prevSn = currentSnapshot;\n currentSnapshot = newSnapshot;\n listener(newSnapshot, prevSn);\n });\n}\nfunction deepEquals(a, b) {\n if (a === b) {\n return true;\n }\n if (isTreeNode(a)) {\n a = getSnapshot(a);\n } else if (isObservable(a)) {\n a = toJS(a, toJSOptions);\n }\n if (isTreeNode(b)) {\n b = getSnapshot(b);\n } else if (isObservable(b)) {\n b = toJS(b, toJSOptions);\n }\n return fastDeepEqual(a, b);\n}\nconst toJSOptions = getMobxVersion() >= 6 ? void 0 : {\n exportMapsAsObjects: false,\n recurseEverything: false\n};\nfunction reconcileModelSnapshot(value, sn, modelPool, parent) {\n const type = sn[modelTypeKey];\n const modelInfo = getModelInfoForName(type);\n if (!modelInfo) {\n throw failure(`model with name \"${type}\" not found in the registry`);\n }\n const modelInPool = modelPool.findModelForSnapshot(sn);\n if (modelInPool) {\n value = modelInPool;\n }\n if (!isModel(value) || value[modelTypeKey] !== type) {\n return fromSnapshot(sn);\n }\n const modelClass2 = modelInfo.class;\n const modelProps = getInternalModelClassPropsInfo(modelClass2);\n const modelIdPropertyName = getModelIdPropertyName(modelClass2);\n if (modelIdPropertyName) {\n const id = sn[modelIdPropertyName];\n if (value[modelIdKey] !== id) {\n return fromSnapshot(sn);\n }\n } else if (isArray(parent)) {\n if (!deepEquals(value, sn)) {\n return fromSnapshot(sn);\n }\n }\n const modelObj = value;\n const snapshotBeforeChanges = getSnapshot(modelObj);\n withoutTypeChecking(() => {\n const modelClass22 = modelObj.constructor;\n const processedSn = modelClass22.fromSnapshotProcessor ? modelClass22.fromSnapshotProcessor(sn) : sn;\n const data = modelObj.$;\n const dataKeys = Object.keys(data);\n const dataKeysLen = dataKeys.length;\n for (let i = 0; i < dataKeysLen; i++) {\n const k = dataKeys[i];\n if (!(k in processedSn)) {\n const modelProp = modelProps[k];\n const defaultValue = modelProp ? getModelPropDefaultValue(modelProp) : noDefaultValue;\n if (defaultValue === noDefaultValue) {\n remove(data, k);\n } else {\n setIfDifferent(data, k, defaultValue);\n }\n }\n }\n const processedSnKeys = Object.keys(processedSn);\n const processedSnKeysLen = processedSnKeys.length;\n for (let i = 0; i < processedSnKeysLen; i++) {\n const k = processedSnKeys[i];\n if (!isReservedModelKey(k)) {\n const v = processedSn[k];\n const oldValue = data[k];\n let newValue = reconcileSnapshot(oldValue, v, modelPool, modelObj);\n if (newValue == null) {\n const modelProp = modelProps[k];\n const defaultValue = modelProp ? getModelPropDefaultValue(modelProp) : noDefaultValue;\n if (defaultValue !== noDefaultValue) {\n newValue = defaultValue;\n }\n }\n detachIfNeeded(newValue, oldValue, modelPool);\n setIfDifferent(data, k, newValue);\n }\n }\n });\n runTypeCheckingAfterChange(modelObj, void 0, snapshotBeforeChanges);\n return modelObj;\n}\nfunction registerModelSnapshotReconciler() {\n registerReconciler(SnapshotterAndReconcilerPriority.Model, (value, sn, modelPool, parent) => {\n if (isModelSnapshot(sn)) {\n return reconcileModelSnapshot(value, sn, modelPool, parent);\n }\n return void 0;\n });\n}\nfunction reconcilePlainObjectSnapshot(value, sn, modelPool) {\n if (!isPlainObject(value) && !isObservableObject(value)) {\n return fromSnapshot(sn);\n }\n const plainObj = value;\n const snapshotBeforeChanges = getSnapshot(plainObj);\n withoutTypeChecking(() => {\n const plainObjKeys = Object.keys(plainObj);\n const plainObjKeysLen = plainObjKeys.length;\n for (let i = 0; i < plainObjKeysLen; i++) {\n const k = plainObjKeys[i];\n if (!(k in sn)) {\n remove(plainObj, k);\n }\n }\n const snKeys = Object.keys(sn);\n const snKeysLen = snKeys.length;\n for (let i = 0; i < snKeysLen; i++) {\n const k = snKeys[i];\n const v = sn[k];\n const oldValue = plainObj[k];\n const newValue = reconcileSnapshot(oldValue, v, modelPool, plainObj);\n detachIfNeeded(newValue, oldValue, modelPool);\n setIfDifferent(plainObj, k, newValue);\n }\n });\n runTypeCheckingAfterChange(plainObj, void 0, snapshotBeforeChanges);\n return plainObj;\n}\nfunction registerPlainObjectSnapshotReconciler() {\n registerReconciler(SnapshotterAndReconcilerPriority.PlainObject, (value, sn, modelPool) => {\n if (isPlainObject(sn)) {\n return reconcilePlainObjectSnapshot(value, sn, modelPool);\n }\n return void 0;\n });\n}\nlet defaultReconcilersRegistered = false;\nfunction registerDefaultReconcilers() {\n if (defaultReconcilersRegistered) {\n return;\n }\n defaultReconcilersRegistered = true;\n registerArraySnapshotReconciler();\n registerFrozenSnapshotReconciler();\n registerModelSnapshotReconciler();\n registerPlainObjectSnapshotReconciler();\n}\nconst reconcilers = [];\nfunction registerReconciler(priority, reconciler) {\n reconcilers.push({ priority, reconciler });\n reconcilers.sort((a, b) => a.priority - b.priority);\n}\nfunction reconcileSnapshot(value, sn, modelPool, parent) {\n if (isPrimitive(sn)) {\n return sn;\n }\n if (getSnapshot(value) === sn) {\n return value;\n }\n registerDefaultReconcilers();\n const reconcilersLen = reconcilers.length;\n for (let i = 0; i < reconcilersLen; i++) {\n const { reconciler } = reconcilers[i];\n const ret = reconciler(value, sn, modelPool, parent);\n if (ret !== void 0) {\n return ret;\n }\n }\n if (isMap(sn)) {\n throw failure(\"a snapshot must not contain maps\");\n }\n if (isSet(sn)) {\n throw failure(\"a snapshot must not contain sets\");\n }\n throw failure(`unsupported snapshot - ${sn}`);\n}\nfunction detachIfNeeded(newValue, oldValue, modelPool) {\n if (newValue === oldValue) {\n return;\n }\n if (isModel(newValue) && modelPool.findModelByTypeAndId(newValue[modelTypeKey], newValue[modelIdKey])) {\n const parentPath = fastGetParentPathIncludingDataObjects(newValue);\n if (parentPath) {\n set(parentPath.parent, parentPath.path, null);\n }\n }\n}\nfunction applyPatches(node, patches, reverse = false) {\n assertTweakedObject(node, \"node\");\n if (patches.length <= 0) {\n return;\n }\n wrappedInternalApplyPatches().call(node, patches, reverse);\n}\nfunction internalApplyPatches(patches, reverse = false) {\n const obj = this;\n const modelPool = new ModelPool(obj);\n if (reverse) {\n let i = patches.length;\n while (i--) {\n const p = patches[i];\n if (!isArray(p)) {\n applySinglePatch(obj, p, modelPool);\n } else {\n let j = p.length;\n while (j--) {\n applySinglePatch(obj, p[j], modelPool);\n }\n }\n }\n } else {\n const len = patches.length;\n for (let i = 0; i < len; i++) {\n const p = patches[i];\n if (!isArray(p)) {\n applySinglePatch(obj, p, modelPool);\n } else {\n const len2 = p.length;\n for (let j = 0; j < len2; j++) {\n applySinglePatch(obj, p[j], modelPool);\n }\n }\n }\n }\n}\nconst wrappedInternalApplyPatches = lazy(() => wrapInAction({\n nameOrNameFn: BuiltInAction.ApplyPatches,\n fn: internalApplyPatches,\n actionType: ActionContextActionType.Sync\n}));\nfunction applySinglePatch(obj, patch, modelPool) {\n const { target, prop: prop2 } = pathArrayToObjectAndProp(obj, patch.path);\n if (isArray(target)) {\n switch (patch.op) {\n case \"add\": {\n const index = +prop2;\n const newValue = reconcileSnapshot(void 0, patch.value, modelPool, target);\n if (index < 0) {\n target.push(newValue);\n } else {\n target.splice(index, 0, newValue);\n }\n break;\n }\n case \"remove\": {\n const index = +prop2;\n target.splice(index, 1);\n break;\n }\n case \"replace\": {\n if (prop2 === \"length\") {\n target.length = patch.value;\n } else {\n const index = +prop2;\n const newValue = reconcileSnapshot(target[index], patch.value, modelPool, target);\n setIfDifferent(target, index, newValue);\n }\n break;\n }\n default:\n throw failure(`unsupported patch operation: ${patch.op}`);\n }\n } else {\n switch (patch.op) {\n case \"add\": {\n const newValue = reconcileSnapshot(void 0, patch.value, modelPool, target);\n setIfDifferent(target, prop2, newValue);\n break;\n }\n case \"remove\": {\n remove(target, prop2);\n break;\n }\n case \"replace\": {\n const newValue = reconcileSnapshot(target[prop2], patch.value, modelPool, target);\n setIfDifferent(target, prop2, newValue);\n break;\n }\n default:\n throw failure(`unsupported patch operation: ${patch.op}`);\n }\n }\n}\nfunction pathArrayToObjectAndProp(obj, path) {\n if (inDevMode) {\n if (!isArray(path)) {\n throw failure(`invalid path: ${path}`);\n }\n }\n let target = modelToDataNode(obj);\n if (path.length === 0) {\n return {\n target\n };\n }\n for (let i = 0; i <= path.length - 2; i++) {\n target = modelToDataNode(target[path[i]]);\n }\n return {\n target,\n prop: path[path.length - 1]\n };\n}\nfunction runTypeCheckingAfterChange(obj, patchRecorder2, snapshotBeforeChanges) {\n if (!isTypeCheckingAllowed()) {\n return;\n }\n invalidateCachedTypeCheckerResult(obj);\n if (isModelAutoTypeCheckingEnabled()) {\n const parentModelWithTypeChecker = findNearestParentModelWithTypeChecker(obj);\n if (parentModelWithTypeChecker) {\n const err = parentModelWithTypeChecker.typeCheck();\n if (err) {\n runWithoutSnapshotOrPatches(() => {\n if (patchRecorder2) {\n internalApplyPatches.call(obj, patchRecorder2.invPatches, true);\n } else if (snapshotBeforeChanges) {\n internalApplySnapshot.call(obj, snapshotBeforeChanges);\n }\n });\n err.throw();\n }\n }\n }\n}\nfunction findNearestParentModelWithTypeChecker(child) {\n const actualChild = dataToModelNode(child);\n if (child !== actualChild) {\n child = actualChild;\n if (isModel(child) && !!getModelMetadata(child).dataType) {\n return child;\n }\n }\n return findParent(child, (parent) => {\n return isModel(parent) && !!getModelMetadata(parent).dataType;\n });\n}\nfunction tweakArray(value, parentPath, doNotTweakChildren) {\n const originalArr = value;\n const arrLn = originalArr.length;\n const tweakedArr = isObservableArray(originalArr) ? originalArr : observable.array(void 0, observableOptions$2);\n if (tweakedArr !== originalArr) {\n tweakedArr.length = originalArr.length;\n }\n let interceptDisposer;\n let observeDisposer;\n const untweak = () => {\n interceptDisposer();\n observeDisposer();\n };\n tweakedObjects.set(tweakedArr, untweak);\n setParent({\n value: tweakedArr,\n parentPath,\n indexChangeAllowed: false,\n isDataObject: false,\n // arrays shouldn't be cloned anyway\n cloneIfApplicable: false\n });\n const untransformedSn = [];\n untransformedSn.length = arrLn;\n for (let i = 0; i < arrLn; i++) {\n const v = originalArr[i];\n if (isPrimitive(v)) {\n if (!doNotTweakChildren) {\n setIfDifferent(tweakedArr, i, v);\n }\n untransformedSn[i] = v;\n } else {\n const path = { parent: tweakedArr, path: i };\n let tweakedValue;\n if (doNotTweakChildren) {\n tweakedValue = v;\n setParent({\n value: tweakedValue,\n parentPath: path,\n indexChangeAllowed: false,\n isDataObject: false,\n // the value is already a new value (the result of a fromSnapshot)\n cloneIfApplicable: false\n });\n } else {\n tweakedValue = tweak(v, path);\n setIfDifferent(tweakedArr, i, tweakedValue);\n }\n const valueSn = getInternalSnapshot(tweakedValue);\n untransformedSn[i] = valueSn.transformed;\n }\n }\n setNewInternalSnapshot(tweakedArr, untransformedSn, void 0);\n interceptDisposer = intercept(tweakedArr, interceptArrayMutation.bind(void 0, tweakedArr));\n observeDisposer = observe(tweakedArr, arrayDidChange);\n return tweakedArr;\n}\nfunction mutateSet$1(k, v, sn) {\n sn[k] = v;\n}\nfunction mutateSplice(index, removedCount, addedItems, sn) {\n sn.splice(index, removedCount, ...addedItems);\n}\nconst patchRecorder$2 = new InternalPatchRecorder();\nfunction arrayDidChange(change) {\n const arr = change.object;\n let oldSnapshot = getInternalSnapshot(arr).untransformed;\n patchRecorder$2.reset();\n let mutate;\n switch (change.type) {\n case \"splice\":\n mutate = arrayDidChangeSplice(change, oldSnapshot);\n break;\n case \"update\":\n mutate = arrayDidChangeUpdate(change, oldSnapshot);\n break;\n }\n runTypeCheckingAfterChange(arr, patchRecorder$2);\n if (!runningWithoutSnapshotOrPatches && mutate) {\n updateInternalSnapshot(arr, mutate);\n patchRecorder$2.emit(arr);\n }\n}\nconst undefinedInsideArrayErrorMsg = \"undefined is not supported inside arrays since it is not serializable in JSON, consider using null instead\";\nfunction arrayDidChangeUpdate(change, oldSnapshot) {\n const k = change.index;\n const val = change.newValue;\n const oldVal = oldSnapshot[k];\n let newVal;\n if (isPrimitive(val)) {\n newVal = val;\n } else {\n const valueSn = getInternalSnapshot(val);\n newVal = valueSn.transformed;\n }\n const mutate = mutateSet$1.bind(void 0, k, newVal);\n const path = [k];\n patchRecorder$2.record([\n {\n op: \"replace\",\n path,\n value: freezeInternalSnapshot(newVal)\n }\n ], [\n {\n op: \"replace\",\n path,\n value: freezeInternalSnapshot(oldVal)\n }\n ]);\n return mutate;\n}\nfunction arrayDidChangeSplice(change, oldSnapshot) {\n const index = change.index;\n const addedCount = change.addedCount;\n const removedCount = change.removedCount;\n let addedItems = [];\n addedItems.length = addedCount;\n for (let i = 0; i < addedCount; i++) {\n const v = change.added[i];\n if (isPrimitive(v)) {\n addedItems[i] = v;\n } else {\n addedItems[i] = getInternalSnapshot(v).transformed;\n }\n }\n const oldLen = oldSnapshot.length;\n const mutate = mutateSplice.bind(void 0, index, removedCount, addedItems);\n const patches = [];\n const invPatches = [];\n if (addedCount === removedCount) {\n const readdPatches = [];\n const readdInvPatches = [];\n let removed = 0;\n for (let i = 0; i < addedCount; i++) {\n const realIndex = index + i;\n const newVal = getValueAfterSplice(oldSnapshot, realIndex, index, removedCount, addedItems);\n const oldVal = oldSnapshot[realIndex];\n if (newVal !== oldVal) {\n const removePath = [realIndex - removed];\n patches.push({\n op: \"remove\",\n path: removePath\n });\n invPatches.push({\n op: \"remove\",\n path: removePath\n });\n removed++;\n const readdPath = [realIndex];\n readdPatches.push({\n op: \"add\",\n path: readdPath,\n value: freezeInternalSnapshot(newVal)\n });\n readdInvPatches.push({\n op: \"add\",\n path: readdPath,\n value: freezeInternalSnapshot(oldVal)\n });\n }\n }\n patches.push(...readdPatches);\n invPatches.push(...readdInvPatches);\n invPatches.reverse();\n } else {\n const interimLen = oldLen - removedCount;\n if (removedCount > 0) {\n const removeUsingSetLength = index >= interimLen;\n if (removeUsingSetLength) {\n patches.push({\n op: \"replace\",\n path: [\"length\"],\n value: interimLen\n });\n }\n for (let i = removedCount - 1; i >= 0; i--) {\n const realIndex = index + i;\n const path = [realIndex];\n if (!removeUsingSetLength) {\n patches.push({\n op: \"remove\",\n path\n });\n }\n invPatches.push({\n op: \"add\",\n path,\n value: freezeInternalSnapshot(oldSnapshot[realIndex])\n });\n }\n }\n if (addedCount > 0) {\n const restoreUsingSetLength = index >= interimLen;\n if (restoreUsingSetLength) {\n invPatches.push({\n op: \"replace\",\n path: [\"length\"],\n value: interimLen\n });\n }\n for (let i = 0; i < addedCount; i++) {\n const realIndex = index + i;\n const path = [realIndex];\n patches.push({\n op: \"add\",\n path,\n value: freezeInternalSnapshot(getValueAfterSplice(oldSnapshot, realIndex, index, removedCount, addedItems))\n });\n if (!restoreUsingSetLength) {\n invPatches.push({\n op: \"remove\",\n path\n });\n }\n }\n }\n }\n patchRecorder$2.record(patches, invPatches);\n return mutate;\n}\nfunction interceptArrayMutation(array, change) {\n assertCanWrite();\n switch (change.type) {\n case \"splice\":\n interceptArrayMutationSplice(change);\n break;\n case \"update\":\n interceptArrayMutationUpdate(change, array);\n break;\n }\n return change;\n}\nfunction interceptArrayMutationUpdate(change, array) {\n if (inDevMode && !getGlobalConfig().allowUndefinedArrayElements && change.newValue === void 0) {\n throw failure(undefinedInsideArrayErrorMsg);\n }\n const oldVal = array[change.index];\n tweak(oldVal, void 0);\n change.newValue = tweak(change.newValue, { parent: array, path: change.index });\n}\nfunction interceptArrayMutationSplice(change) {\n if (inDevMode && !getGlobalConfig().allowUndefinedArrayElements) {\n const len = change.added.length;\n for (let i = 0; i < len; i++) {\n const v = change.added[i];\n if (v === void 0) {\n throw failure(undefinedInsideArrayErrorMsg);\n }\n }\n }\n for (let i = 0; i < change.removedCount; i++) {\n const removedValue = change.object[change.index + i];\n tweak(removedValue, void 0);\n }\n for (let i = 0; i < change.added.length; i++) {\n change.added[i] = tweak(change.added[i], {\n parent: change.object,\n path: change.index + i\n });\n }\n const oldNextIndex = change.index + change.removedCount;\n const newNextIndex = change.index + change.added.length;\n if (oldNextIndex !== newNextIndex) {\n for (let i = oldNextIndex, j = newNextIndex; i < change.object.length; i++, j++) {\n setParent({\n value: change.object[i],\n parentPath: {\n parent: change.object,\n path: j\n },\n indexChangeAllowed: true,\n isDataObject: false,\n // just re-indexing\n cloneIfApplicable: false\n });\n }\n }\n}\nfunction registerArrayTweaker() {\n registerTweaker(TweakerPriority.Array, (value, parentPath) => {\n if (isArray(value)) {\n return tweakArray(value, parentPath, false);\n }\n return void 0;\n });\n}\nconst observableOptions$2 = {\n deep: false\n};\nfunction getValueAfterSplice(array, i, index, remove2, addedItems) {\n const base = i - index;\n if (base < 0) {\n return array[i];\n }\n if (base < addedItems.length) {\n return addedItems[base];\n }\n return array[i - addedItems.length + remove2];\n}\nfunction fromArraySnapshot(sn, ctx) {\n const arr = observable.array([], observableOptions);\n const ln = sn.length;\n for (let i = 0; i < ln; i++) {\n arr.push(internalFromSnapshot(sn[i], ctx));\n }\n return tweakArray(arr, void 0, true);\n}\nfunction registerFromArraySnapshotter() {\n registerSnapshotter(SnapshotterAndReconcilerPriority.Array, (sn, ctx) => {\n if (isArray(sn)) {\n return fromArraySnapshot(sn, ctx);\n }\n return void 0;\n });\n}\nfunction registerFromFrozenSnapshotter() {\n registerSnapshotter(SnapshotterAndReconcilerPriority.Frozen, (sn) => {\n if (isFrozenSnapshot(sn)) {\n return frozen(sn.data);\n }\n return void 0;\n });\n}\nfunction fromModelSnapshot(sn, ctx) {\n const type = sn[modelTypeKey];\n if (!type) {\n throw failure(`a model snapshot must contain a type key (${modelTypeKey}), but none was found`);\n }\n const modelInfo = getModelInfoForName(type);\n if (!modelInfo) {\n throw failure(`model with name \"${type}\" not found in the registry`);\n }\n const modelIdPropertyName = getModelIdPropertyName(modelInfo.class);\n if (modelIdPropertyName && sn[modelIdPropertyName] === void 0) {\n throw failure(`a model snapshot of type '${type}' must contain an id key (${modelIdPropertyName}), but none was found`);\n }\n return new modelInfo.class(void 0, {\n snapshotInitialData: {\n unprocessedSnapshot: sn,\n unprocessedModelType: typeof ctx.untypedSnapshot === \"object\" && ctx.untypedSnapshot && modelTypeKey in ctx.untypedSnapshot ? ctx.untypedSnapshot[modelTypeKey] : void 0,\n snapshotToInitialData: ctx.snapshotToInitialData\n },\n generateNewIds: ctx.options.generateNewIds\n });\n}\nfunction registerFromModelSnapshotter() {\n registerSnapshotter(SnapshotterAndReconcilerPriority.Model, (sn, ctx) => {\n if (isModelSnapshot(sn)) {\n return fromModelSnapshot(sn, ctx);\n }\n return void 0;\n });\n}\nfunction tweakPlainObject(value, parentPath, snapshotModelType, doNotTweakChildren, isDataObject) {\n const originalObj = value;\n const tweakedObj = isObservableObject(originalObj) ? originalObj : observable.object({}, void 0, observableOptions$1);\n let interceptDisposer;\n let observeDisposer;\n const untweak = () => {\n interceptDisposer();\n observeDisposer();\n };\n tweakedObjects.set(tweakedObj, untweak);\n setParent({\n value: tweakedObj,\n parentPath,\n indexChangeAllowed: false,\n isDataObject,\n // an object shouldn't be cloned\n cloneIfApplicable: false\n });\n let untransformedSn = {};\n const originalObjKeys = Object.keys(originalObj);\n const originalObjKeysLen = originalObjKeys.length;\n for (let i = 0; i < originalObjKeysLen; i++) {\n const k = originalObjKeys[i];\n const v = originalObj[k];\n if (isPrimitive(v)) {\n if (!doNotTweakChildren) {\n setIfDifferent(tweakedObj, k, v);\n }\n untransformedSn[k] = v;\n } else {\n const path = { parent: tweakedObj, path: k };\n let tweakedValue;\n if (doNotTweakChildren) {\n tweakedValue = v;\n setParent({\n value: tweakedValue,\n parentPath: path,\n indexChangeAllowed: false,\n isDataObject: false,\n // the value is already a new value (the result of a fromSnapshot)\n cloneIfApplicable: false\n });\n } else {\n tweakedValue = tweak(v, path);\n setIfDifferent(tweakedObj, k, tweakedValue);\n }\n const valueSn = getInternalSnapshot(tweakedValue);\n untransformedSn[k] = valueSn.transformed;\n }\n }\n let transformFn;\n if (snapshotModelType) {\n untransformedSn[modelTypeKey] = snapshotModelType;\n const modelInfo = getModelInfoForName(snapshotModelType);\n if (!modelInfo) {\n throw failure(`model with name \"${snapshotModelType}\" not found in the registry`);\n }\n const originalTransformFn = modelInfo.class.toSnapshotProcessor;\n if (originalTransformFn) {\n transformFn = (sn) => originalTransformFn(sn, dataToModelNode(tweakedObj));\n }\n }\n setNewInternalSnapshot(isDataObject ? dataToModelNode(tweakedObj) : tweakedObj, untransformedSn, transformFn);\n interceptDisposer = intercept(tweakedObj, interceptObjectMutation);\n observeDisposer = observe(tweakedObj, objectDidChange);\n return tweakedObj;\n}\nconst observableOptions$1 = {\n deep: false\n};\nfunction mutateSet(k, v, sn) {\n sn[k] = v;\n}\nfunction mutateDelete(k, sn) {\n delete sn[k];\n}\nconst patchRecorder$1 = new InternalPatchRecorder();\nfunction objectDidChange(change) {\n const obj = change.object;\n const actualNode = dataToModelNode(obj);\n let oldUntransformedSn = getInternalSnapshot(actualNode).untransformed;\n patchRecorder$1.reset();\n let mutate;\n switch (change.type) {\n case \"add\":\n case \"update\":\n mutate = objectDidChangeAddOrUpdate(change, oldUntransformedSn);\n break;\n case \"remove\":\n mutate = objectDidChangeRemove(change, oldUntransformedSn);\n break;\n }\n runTypeCheckingAfterChange(obj, patchRecorder$1);\n if (!runningWithoutSnapshotOrPatches && mutate) {\n updateInternalSnapshot(actualNode, mutate);\n patchRecorder$1.emit(actualNode);\n }\n}\nfunction objectDidChangeRemove(change, oldUntransformedSn) {\n const k = change.name;\n const oldVal = oldUntransformedSn[k];\n const mutate = mutateDelete.bind(void 0, k);\n const path = [k];\n patchRecorder$1.record([\n {\n op: \"remove\",\n path\n }\n ], [\n {\n op: \"add\",\n path,\n value: freezeInternalSnapshot(oldVal)\n }\n ]);\n return mutate;\n}\nfunction objectDidChangeAddOrUpdate(change, oldUntransformedSn) {\n const k = change.name;\n const val = change.newValue;\n const oldVal = oldUntransformedSn[k];\n let newVal;\n if (isPrimitive(val)) {\n newVal = val;\n } else {\n const valueSn = getInternalSnapshot(val);\n newVal = valueSn.transformed;\n }\n const mutate = mutateSet.bind(void 0, k, newVal);\n const path = [k];\n if (change.type === \"add\") {\n patchRecorder$1.record([\n {\n op: \"add\",\n path,\n value: freezeInternalSnapshot(newVal)\n }\n ], [\n {\n op: \"remove\",\n path\n }\n ]);\n } else {\n patchRecorder$1.record([\n {\n op: \"replace\",\n path,\n value: freezeInternalSnapshot(newVal)\n }\n ], [\n {\n op: \"replace\",\n path,\n value: freezeInternalSnapshot(oldVal)\n }\n ]);\n }\n return mutate;\n}\nfunction interceptObjectMutation(change) {\n assertCanWrite();\n if (typeof change.name === \"symbol\") {\n throw failure(\"symbol properties are not supported\");\n }\n switch (change.type) {\n case \"add\":\n change.newValue = tweak(change.newValue, {\n parent: change.object,\n path: \"\" + change.name\n });\n break;\n case \"remove\": {\n const oldVal = change.object[change.name];\n tweak(oldVal, void 0);\n break;\n }\n case \"update\": {\n const oldVal = change.object[change.name];\n const newVal = change.newValue;\n if (newVal !== oldVal) {\n tweak(oldVal, void 0);\n change.newValue = tweak(change.newValue, {\n parent: change.object,\n path: \"\" + change.name\n });\n }\n break;\n }\n }\n return change;\n}\nfunction registerPlainObjectTweaker() {\n registerTweaker(TweakerPriority.PlainObject, (value, parentPath) => {\n if (isObservableObject(value) || isPlainObject(value)) {\n return tweakPlainObject(value, parentPath, void 0, false, false);\n }\n return void 0;\n });\n}\nfunction fromPlainObjectSnapshot(sn, ctx) {\n const plainObj = observable.object({}, void 0, observableOptions);\n const snKeys = Object.keys(sn);\n const snKeysLen = snKeys.length;\n for (let i = 0; i < snKeysLen; i++) {\n const k = snKeys[i];\n const v = sn[k];\n set(plainObj, k, internalFromSnapshot(v, ctx));\n }\n return tweakPlainObject(plainObj, void 0, void 0, true, false);\n}\nfunction registerFromPlainObjectSnapshotter() {\n registerSnapshotter(SnapshotterAndReconcilerPriority.PlainObject, (sn, ctx) => {\n if (isPlainObject(sn)) {\n return fromPlainObjectSnapshot(sn, ctx);\n }\n return void 0;\n });\n}\nlet defaultSnapshottersRegistered = false;\nfunction registerDefaultSnapshotters() {\n if (defaultSnapshottersRegistered) {\n return;\n }\n defaultSnapshottersRegistered = true;\n registerFromArraySnapshotter();\n registerFromFrozenSnapshotter();\n registerFromModelSnapshotter();\n registerFromPlainObjectSnapshotter();\n}\nconst snapshotters = [];\nfunction registerSnapshotter(priority, snapshotter) {\n snapshotters.push({ priority, snapshotter });\n snapshotters.sort((a, b) => a.priority - b.priority);\n}\nfunction fromSnapshot(arg1, arg2, arg3) {\n let snapshot;\n let unprocessedSnapshot;\n let options;\n if (isLateTypeChecker(arg1) || arg1 instanceof TypeChecker || isModelClass(arg1)) {\n const typeChecker = resolveTypeChecker(arg1);\n unprocessedSnapshot = arg2;\n snapshot = typeChecker.fromSnapshotProcessor ? typeChecker.fromSnapshotProcessor(unprocessedSnapshot) : unprocessedSnapshot;\n options = arg3;\n } else {\n snapshot = arg1;\n unprocessedSnapshot = snapshot;\n options = arg2;\n }\n return fromSnapshotAction(snapshot, unprocessedSnapshot, options);\n}\nconst fromSnapshotAction = action(\"fromSnapshot\", (snapshot, unprocessedSnapshot, options) => {\n const opts = {\n generateNewIds: false,\n overrideRootModelId: void 0,\n ...options\n };\n const ctx = {\n options: opts,\n untypedSnapshot: unprocessedSnapshot\n };\n ctx.snapshotToInitialData = snapshotToInitialData.bind(void 0, ctx);\n return internalFromSnapshot(snapshot, ctx);\n});\nfunction internalFromSnapshot(sn, ctx) {\n if (isPrimitive(sn)) {\n return sn;\n }\n registerDefaultSnapshotters();\n const snapshotterLen = snapshotters.length;\n for (let i = 0; i < snapshotterLen; i++) {\n const { snapshotter } = snapshotters[i];\n const ret = snapshotter(sn, ctx);\n if (ret !== void 0) {\n return ret;\n }\n }\n if (isMap(sn)) {\n throw failure(\"a snapshot must not contain maps\");\n }\n if (isSet(sn)) {\n throw failure(\"a snapshot must not contain sets\");\n }\n throw failure(`unsupported snapshot - ${sn}`);\n}\nfunction snapshotToInitialData(ctx, processedSn) {\n const initialData = observable.object({}, void 0, observableOptions);\n const processedSnKeys = Object.keys(processedSn);\n const processedSnKeysLen = processedSnKeys.length;\n for (let i = 0; i < processedSnKeysLen; i++) {\n const k = processedSnKeys[i];\n if (!isReservedModelKey(k)) {\n const v = processedSn[k];\n set(initialData, k, internalFromSnapshot(v, ctx));\n }\n }\n return initialData;\n}\nconst observableOptions = {\n deep: false\n};\nfunction clone(node, options) {\n assertTweakedObject(node, \"node\");\n const opts = {\n generateNewIds: true,\n ...options\n };\n const sn = getSnapshot(node);\n return fromSnapshot(sn, opts);\n}\nconst setParent = action(\"setParent\", ({ value, parentPath, indexChangeAllowed, isDataObject, cloneIfApplicable }) => {\n if (isPrimitive(value)) {\n return value;\n }\n if (inDevMode) {\n if (indexChangeAllowed && cloneIfApplicable) {\n throw failure(\"assertion failed: 'indexChangeAllowed' and 'cloneIfApplicable' cannot be set at the same time\");\n }\n if (typeof value === \"function\" || typeof value === \"symbol\") {\n throw failure(`assertion failed: value cannot be a function or a symbol`);\n }\n if (!isTweakedObject(value, true)) {\n throw failure(`assertion failed: value is not ready to take a parent`);\n }\n if (parentPath && !isTweakedObject(parentPath.parent, true)) {\n throw failure(`assertion failed: parent is not ready to take children`);\n }\n }\n let oldParentPath = fastGetParentPath(value);\n if (parentPathEquals(oldParentPath, parentPath)) {\n return value;\n }\n if (fastIsRootStore(value)) {\n throw failure(\"root stores cannot be attached to any parents\");\n }\n if (isDataObject) {\n dataObjectParent.set(value, parentPath.parent);\n return value;\n }\n if (parentPath) {\n const actualParent = dataToModelNode(parentPath.parent);\n if (parentPath.parent !== actualParent) {\n parentPath = {\n parent: actualParent,\n path: parentPath.path\n };\n }\n }\n if (cloneIfApplicable && (parentPath == null ? void 0 : parentPath.parent) && (oldParentPath == null ? void 0 : oldParentPath.parent) && isModel(value) && getModelMetadata(value).valueType) {\n value = clone(value, { generateNewIds: true });\n oldParentPath = fastGetParentPath(value);\n }\n if (oldParentPath && parentPath) {\n if (oldParentPath.parent === parentPath.parent && indexChangeAllowed) {\n objectParents.set(value, parentPath);\n reportParentPathChanged(value);\n return value;\n } else {\n throw failure(\"an object cannot be assigned a new parent when it already has one\");\n }\n }\n let postUntweaker;\n if (!parentPath) {\n postUntweaker = tryUntweak(value);\n }\n const attachToNewParent = () => {\n if (oldParentPath == null ? void 0 : oldParentPath.parent) {\n removeObjectChild(oldParentPath.parent, value);\n }\n objectParents.set(value, parentPath);\n if (parentPath == null ? void 0 : parentPath.parent) {\n addObjectChild(parentPath.parent, value);\n }\n reportParentPathChanged(value);\n };\n if (value instanceof BaseModel) {\n const oldRoot = fastGetRoot(value);\n const oldRootStore = fastIsRootStore(oldRoot) ? oldRoot : void 0;\n attachToNewParent();\n const newRoot = fastGetRoot(value);\n const newRootStore = fastIsRootStore(newRoot) ? newRoot : void 0;\n if (oldRootStore !== newRootStore && (oldRootStore || newRootStore)) {\n enqueuePendingAction(() => {\n if (oldRootStore) {\n detachFromRootStore(value);\n }\n if (newRootStore) {\n attachToRootStore(newRootStore, value);\n }\n });\n }\n } else {\n attachToNewParent();\n }\n postUntweaker == null ? void 0 : postUntweaker();\n return value;\n});\nfunction typeCheck(type, value) {\n const typeChecker = resolveTypeChecker(type);\n if (typeChecker.unchecked) {\n return null;\n } else {\n return typeChecker.check(value, [], value);\n }\n}\nfunction tweakFrozen(frozenObj, parentPath) {\n tweakedObjects.set(frozenObj, void 0);\n setParent({\n value: frozenObj,\n parentPath,\n indexChangeAllowed: false,\n isDataObject: false,\n // a frozen is not a value-type\n cloneIfApplicable: false\n });\n setNewInternalSnapshot(frozenObj, { [frozenKey]: true, data: frozenObj.data }, void 0, true);\n return frozenObj;\n}\nfunction registerFrozenTweaker() {\n registerTweaker(TweakerPriority.Frozen, (value, parentPath) => {\n if (value instanceof Frozen) {\n return tweakFrozen(value, parentPath);\n }\n return void 0;\n });\n}\nfunction tweakModel(value, parentPath) {\n tweakedObjects.set(value, void 0);\n setParent({\n value,\n parentPath,\n indexChangeAllowed: false,\n isDataObject: false,\n cloneIfApplicable: true\n });\n return value;\n}\nfunction registerModelTweaker() {\n registerTweaker(TweakerPriority.Model, (value, parentPath) => {\n if (isModel(value)) {\n return tweakModel(value, parentPath);\n }\n return void 0;\n });\n}\nlet defaultTweakersRegistered = false;\nfunction registerDefaultTweakers() {\n if (defaultTweakersRegistered) {\n return;\n }\n defaultTweakersRegistered = true;\n registerArrayTweaker();\n registerFrozenTweaker();\n registerModelTweaker();\n registerPlainObjectTweaker();\n}\nfunction toTreeNode(arg1, arg2) {\n let value, type;\n let hasType;\n if (arguments.length === 1) {\n hasType = false;\n value = arg1;\n } else {\n type = arg1;\n hasType = true;\n value = arg2;\n }\n if (!isObject(value)) {\n throw failure(\"only objects can be turned into tree nodes\");\n }\n if (hasType && isModelAutoTypeCheckingEnabled()) {\n const errors = typeCheck(type, value);\n if (errors) {\n errors.throw();\n }\n }\n if (!isTweakedObject(value, true)) {\n return tweak(value, void 0);\n }\n return value;\n}\nconst tweakers = [];\nfunction registerTweaker(priority, tweaker) {\n tweakers.push({ priority, tweaker });\n tweakers.sort((a, b) => a.priority - b.priority);\n}\nfunction internalTweak(value, parentPath) {\n if (isPrimitive(value)) {\n return value;\n }\n if (isTweakedObject(value, true)) {\n value = setParent({\n value,\n parentPath,\n indexChangeAllowed: false,\n isDataObject: false,\n cloneIfApplicable: true\n });\n return value;\n }\n if (isDataModel(value)) {\n throw failure(\"data models are not directly supported. you may insert the data in the tree instead ('$' property).\");\n }\n registerDefaultTweakers();\n const tweakersLen = tweakers.length;\n for (let i = 0; i < tweakersLen; i++) {\n const { tweaker } = tweakers[i];\n const tweakedVal = tweaker(value, parentPath);\n if (tweakedVal !== void 0) {\n return tweakedVal;\n }\n }\n if (isMap(value)) {\n throw failure(\"maps are not directly supported. consider using 'ObjectMap' / 'asMap' instead.\");\n }\n if (isSet(value)) {\n throw failure(\"sets are not directly supported. consider using 'ArraySet' / 'asSet' instead.\");\n }\n throw failure(`tweak can only work over models, observable objects/arrays, or primitives, but got ${value} instead`);\n}\nconst tweak = action(\"tweak\", internalTweak);\nfunction tryUntweak(value) {\n if (isPrimitive(value)) {\n return void 0;\n }\n if (inDevMode) {\n if (!fastGetParent(value)) {\n throw failure(\"assertion failed: object cannot be untweaked if it does not have a parent\");\n }\n }\n const untweaker = tweakedObjects.get(value);\n if (!untweaker) {\n return void 0;\n }\n const children = Array.from(getObjectChildren(value).values());\n for (let i = 0; i < children.length; i++) {\n setParent({\n value: children[i],\n parentPath: void 0,\n indexChangeAllowed: false,\n isDataObject: false,\n // no need to clone if unsetting the parent\n cloneIfApplicable: false\n });\n }\n return () => {\n untweaker();\n tweakedObjects.delete(value);\n unsetInternalSnapshot(value);\n };\n}\nconst modelInitializersSymbol = Symbol(\"modelInitializers\");\nfunction addModelClassInitializer(modelClass2, init) {\n let initializers = modelClass2[modelInitializersSymbol];\n if (!initializers) {\n initializers = [];\n modelClass2[modelInitializersSymbol] = initializers;\n }\n initializers.push(init);\n}\nfunction getModelClassInitializers(modelClass2) {\n return modelClass2[modelInitializersSymbol];\n}\nfunction applyModelInitializers(modelClass2, modelObj) {\n const initializers = getModelClassInitializers(modelClass2);\n if (initializers) {\n const len = initializers.length;\n for (let i = 0; i < len; i++) {\n initializers[i](modelObj);\n }\n }\n}\nconst internalNewDataModel = action(\"newModel\", (origModelObj, tweakedData, options) => {\n const { modelClass: _modelClass } = options;\n const modelClass2 = _modelClass;\n if (inDevMode) {\n assertIsDataModelClass(modelClass2, \"modelClass\");\n }\n const modelObj = origModelObj;\n const modelInfo = modelInfoByClass.get(modelClass2);\n if (!modelInfo) {\n throw failure(`no model info for class ${modelClass2.name} could be found - did you forget to add the @model decorator?`);\n }\n modelObj.$ = tweakedData;\n if (inDevMode) {\n makePropReadonly(modelObj, \"$\", true);\n }\n applyModelInitializers(modelClass2, modelObj);\n if (isModelAutoTypeCheckingEnabled() && getDataModelMetadata(modelClass2).dataType) {\n const err = modelObj.typeCheck();\n if (err) {\n err.throw();\n }\n }\n return modelObj;\n});\nconst dataModelInstanceCache = /* @__PURE__ */ new WeakMap();\nclass BaseDataModel {\n /**\n * Creates an instance of a data model.\n */\n constructor(data) {\n // just to make typing work properly\n __publicField(this, _a);\n /**\n * Data part of the model, which is observable and will be serialized in snapshots.\n * Use it if one of the data properties matches one of the model properties/functions.\n * This also allows access to the backed values of transformed properties.\n */\n __publicField(this, \"$\");\n if (!isObject(data)) {\n throw failure(\"data models can only work over data objects\");\n }\n const { modelClass: _modelClass } = arguments[1];\n const modelClass2 = _modelClass;\n let tweakedData;\n if (isTreeNode(data)) {\n tweakedData = data;\n } else {\n const modelInfo = modelInfoByClass.get(modelClass2);\n if (!modelInfo) {\n throw failure(`no model info for class ${modelClass2.name} could be found - did you forget to add the @model decorator?`);\n }\n const modelProps = getInternalModelClassPropsInfo(modelClass2);\n const initialData = Object.assign({}, data);\n const modelPropsKeys = Object.keys(modelProps);\n for (let i = 0; i < modelPropsKeys.length; i++) {\n const k = modelPropsKeys[i];\n const propData = modelProps[k];\n let newValue = initialData[k];\n let changed = false;\n if (propData._transform) {\n changed = true;\n newValue = propData._transform.untransform(newValue, this, k);\n }\n if (newValue == null) {\n if (propData._defaultFn !== noDefaultValue) {\n changed = true;\n newValue = propData._defaultFn();\n } else if (propData._defaultValue !== noDefaultValue) {\n changed = true;\n newValue = propData._defaultValue;\n }\n }\n if (changed) {\n initialData[k] = newValue;\n }\n }\n tweakedData = toTreeNode(initialData);\n }\n const instancesForModelClass = getOrCreate(dataModelInstanceCache, modelClass2, () => /* @__PURE__ */ new WeakMap());\n const instance = instancesForModelClass.get(tweakedData);\n if (instance) {\n return instance;\n }\n instancesForModelClass.set(tweakedData, this);\n Object.setPrototypeOf(this, modelClass2.prototype);\n const self = this;\n delete self[propsTypeSymbol];\n internalNewDataModel(this, tweakedData, {\n modelClass: modelClass2\n });\n }\n /**\n * Performs a type check over the model instance.\n * For this to work a data type has to be declared as part of the model properties.\n *\n * @returns A `TypeCheckError` or `null` if there is no error.\n */\n typeCheck() {\n const type = typesDataModelData(this.constructor);\n return typeCheck(type, this.$);\n }\n toString(options) {\n const finalOptions = {\n withData: true,\n ...options\n };\n const modelInfo = modelInfoByClass.get(this.constructor);\n const firstPart = `${this.constructor.name}#${modelInfo.name}`;\n return finalOptions.withData ? `[${firstPart} ${JSON.stringify(getSnapshot(this))}]` : `[${firstPart}]`;\n }\n}\n_a = propsTypeSymbol;\nconst baseDataModelPropNames = /* @__PURE__ */ new Set([\"onLazyInit\", \"$\", \"typeCheck\"]);\nfunction isDataModel(model2) {\n return model2 instanceof BaseDataModel;\n}\nfunction assertIsDataModel(model2, argName, customErrMsg = \"must be a data model instance\") {\n if (!isDataModel(model2)) {\n throw failure(`${argName} ${customErrMsg}`);\n }\n}\nfunction isDataModelClass(modelClass2) {\n if (typeof modelClass2 !== \"function\") {\n return false;\n }\n if (modelClass2 !== BaseDataModel && !(modelClass2.prototype instanceof BaseDataModel)) {\n return false;\n }\n return true;\n}\nfunction assertIsDataModelClass(modelClass2, argName) {\n if (typeof modelClass2 !== \"function\") {\n throw failure(`${argName} must be a class`);\n }\n if (modelClass2 !== BaseDataModel && !(modelClass2.prototype instanceof BaseDataModel)) {\n throw failure(`${argName} must extend DataModel`);\n }\n}\nfunction getDataModelMetadata(modelClassOrInstance) {\n if (isDataModel(modelClassOrInstance)) {\n return modelClassOrInstance.constructor[modelMetadataSymbol];\n } else if (isDataModelClass(modelClassOrInstance)) {\n return modelClassOrInstance[modelMetadataSymbol];\n } else {\n throw failure(`modelClassOrInstance must be a model class or instance`);\n }\n}\nfunction getTypeInfo(type) {\n const stdType = resolveStandardType(type);\n const typeInfo = stdType.typeInfo;\n if (!typeInfo) {\n throw failure(`type info not found for ${type}`);\n }\n return typeInfo;\n}\nconst cachedDataModelTypeChecker = /* @__PURE__ */ new WeakMap();\nfunction typesDataModelData(modelClass2) {\n if (!isDataModelClass(modelClass2) && typeof modelClass2 === \"function\") {\n const modelClassFn = modelClass2;\n const typeInfoGen = (t) => new DataModelDataTypeInfo(t, modelClassFn());\n return lateTypeChecker(() => typesDataModelData(modelClassFn()), typeInfoGen);\n } else {\n const modelClazz = modelClass2;\n const cachedTypeChecker = cachedDataModelTypeChecker.get(modelClazz);\n if (cachedTypeChecker) {\n return cachedTypeChecker;\n }\n const typeInfoGen = (t) => new DataModelDataTypeInfo(t, modelClazz);\n const tc = lateTypeChecker(() => {\n const modelInfo = modelInfoByClass.get(modelClazz);\n const typeName = `DataModelData(${modelInfo.name})`;\n const dataTypeChecker = getDataModelMetadata(modelClazz).dataType;\n if (!dataTypeChecker) {\n throw failure(`type checking cannot be performed over data model data of type '${modelInfo.name}' since that model type has no data type declared, consider adding a data type or using types.unchecked() instead`);\n }\n const resolvedDataTypeChecker = resolveTypeChecker(dataTypeChecker);\n const thisTc = new TypeChecker(TypeCheckerBaseType.Object, (value, path, typeCheckedValue) => {\n return resolvedDataTypeChecker.check(value, path, typeCheckedValue);\n }, () => typeName, typeInfoGen, (value) => {\n return resolvedDataTypeChecker.snapshotType(value) ? thisTc : null;\n }, (sn) => {\n return resolvedDataTypeChecker.fromSnapshotProcessor(sn);\n }, (sn) => {\n return resolvedDataTypeChecker.toSnapshotProcessor(sn);\n });\n return thisTc;\n }, typeInfoGen);\n cachedDataModelTypeChecker.set(modelClazz, tc);\n return tc;\n }\n}\nclass DataModelDataTypeInfo extends TypeInfo {\n constructor(thisType, modelClass2) {\n super(thisType);\n __publicField(this, \"modelClass\");\n __publicField(this, \"_props\", lazy(() => {\n const objSchema = getInternalModelClassPropsInfo(this.modelClass);\n const propTypes = {};\n Object.keys(objSchema).forEach((propName) => {\n const propData = objSchema[propName];\n const type = propData._typeChecker;\n let typeInfo;\n if (type) {\n typeInfo = getTypeInfo(type);\n }\n let hasDefault = false;\n let defaultValue;\n if (propData._defaultFn !== noDefaultValue) {\n defaultValue = propData._defaultFn;\n hasDefault = true;\n } else if (propData._defaultValue !== noDefaultValue) {\n defaultValue = propData._defaultValue;\n hasDefault = true;\n }\n propTypes[propName] = {\n type,\n typeInfo,\n hasDefault,\n default: defaultValue\n };\n });\n return propTypes;\n }));\n this.modelClass = modelClass2;\n }\n get props() {\n return this._props();\n }\n get modelType() {\n const modelInfo = modelInfoByClass.get(this.modelClass);\n return modelInfo.name;\n }\n}\nfunction registerDataModelDataStandardTypeResolver() {\n registerStandardTypeResolver((v) => isDataModelClass(v) ? typesDataModelData(v) : void 0);\n}\nconst cachedModelTypeChecker = /* @__PURE__ */ new WeakMap();\nfunction typesModel(modelClass2) {\n if (!isModelClass(modelClass2) && typeof modelClass2 === \"function\") {\n const modelClassFn = modelClass2;\n const typeInfoGen = (t) => new ModelTypeInfo(t, modelClassFn());\n return lateTypeChecker(() => typesModel(modelClassFn()), typeInfoGen);\n } else {\n const modelClazz = modelClass2;\n const cachedTypeChecker = cachedModelTypeChecker.get(modelClazz);\n if (cachedTypeChecker) {\n return cachedTypeChecker;\n }\n const typeInfoGen = (t) => new ModelTypeInfo(t, modelClazz);\n const tc = lateTypeChecker(() => {\n const modelInfo = modelInfoByClass.get(modelClazz);\n const typeName = `Model(${modelInfo.name})`;\n const dataTypeChecker = getModelMetadata(modelClazz).dataType;\n const resolvedDataTypeChecker = dataTypeChecker ? resolveTypeChecker(dataTypeChecker) : void 0;\n const thisTc = new TypeChecker(TypeCheckerBaseType.Object, (value, path, typeCheckedValue) => {\n if (!(value instanceof modelClazz)) {\n return new TypeCheckError(path, typeName, value, typeCheckedValue);\n }\n if (resolvedDataTypeChecker) {\n return resolvedDataTypeChecker.check(value.$, path, typeCheckedValue);\n }\n return null;\n }, () => typeName, typeInfoGen, (value) => {\n if (!isObject(value)) {\n return null;\n }\n if (value[modelTypeKey] !== void 0) {\n return value[modelTypeKey] === modelInfo.name ? thisTc : null;\n }\n if (resolvedDataTypeChecker) {\n return resolvedDataTypeChecker.snapshotType(value) ? thisTc : null;\n }\n return null;\n }, (sn) => {\n if (sn[modelTypeKey]) {\n return sn;\n } else {\n return {\n ...sn,\n [modelTypeKey]: modelInfo.name\n };\n }\n }, (sn) => sn);\n return thisTc;\n }, typeInfoGen);\n cachedModelTypeChecker.set(modelClazz, tc);\n return tc;\n }\n}\nclass ModelTypeInfo extends TypeInfo {\n constructor(thisType, modelClass2) {\n super(thisType);\n __publicField(this, \"modelClass\");\n __publicField(this, \"_props\", lazy(() => {\n const objSchema = getInternalModelClassPropsInfo(this.modelClass);\n const propTypes = {};\n Object.keys(objSchema).forEach((propName) => {\n const propData = objSchema[propName];\n const type = propData._typeChecker;\n let typeInfo;\n if (type) {\n typeInfo = getTypeInfo(type);\n }\n let hasDefault = false;\n let defaultValue;\n if (propData._defaultFn !== noDefaultValue) {\n defaultValue = propData._defaultFn;\n hasDefault = true;\n } else if (propData._defaultValue !== noDefaultValue) {\n defaultValue = propData._defaultValue;\n hasDefault = true;\n }\n propTypes[propName] = {\n type,\n typeInfo,\n hasDefault,\n default: defaultValue\n };\n });\n return propTypes;\n }));\n this.modelClass = modelClass2;\n }\n get props() {\n return this._props();\n }\n get modelType() {\n const modelInfo = modelInfoByClass.get(this.modelClass);\n return modelInfo.name;\n }\n}\nfunction registerModelStandardTypeResolver() {\n registerStandardTypeResolver((v) => isModelClass(v) ? typesModel(v) : void 0);\n}\nconst standardTypeResolvers$1 = [];\nfunction typesLiteral(literal) {\n assertIsPrimitive(literal, \"literal\");\n let typeName;\n switch (literal) {\n case void 0:\n typeName = \"undefined\";\n break;\n case null:\n typeName = \"null\";\n break;\n default:\n typeName = JSON.stringify(literal);\n break;\n }\n const typeInfoGen = (t) => new LiteralTypeInfo(t, literal);\n const thisTc = new TypeChecker(TypeCheckerBaseType.Primitive, (value, path, typeCheckedValue) => value === literal ? null : new TypeCheckError(path, typeName, value, typeCheckedValue), () => typeName, typeInfoGen, (value) => value === literal ? thisTc : null, identityFn, identityFn);\n return thisTc;\n}\nclass LiteralTypeInfo extends TypeInfo {\n constructor(thisType, literal) {\n super(thisType);\n __publicField(this, \"literal\");\n this.literal = literal;\n }\n}\nconst typesUndefined = typesLiteral(void 0);\nstandardTypeResolvers$1.push((v) => v === void 0 ? typesUndefined : void 0);\nconst typesNull = typesLiteral(null);\nstandardTypeResolvers$1.push((v) => v === null ? typesNull : void 0);\nconst typesBoolean = new TypeChecker(TypeCheckerBaseType.Primitive, (value, path, typeCheckedValue) => typeof value === \"boolean\" ? null : new TypeCheckError(path, \"boolean\", value, typeCheckedValue), () => \"boolean\", (t) => new BooleanTypeInfo(t), (value) => typeof value === \"boolean\" ? typesBoolean : null, identityFn, identityFn);\nstandardTypeResolvers$1.push((v) => v === Boolean ? typesBoolean : void 0);\nclass BooleanTypeInfo extends TypeInfo {\n}\nconst typesNumber = new TypeChecker(TypeCheckerBaseType.Primitive, (value, path, typeCheckedValue) => typeof value === \"number\" ? null : new TypeCheckError(path, \"number\", value, typeCheckedValue), () => \"number\", (t) => new NumberTypeInfo(t), (value) => typeof value === \"number\" ? typesNumber : null, identityFn, identityFn);\nstandardTypeResolvers$1.push((v) => v === Number ? typesNumber : void 0);\nclass NumberTypeInfo extends TypeInfo {\n}\nconst typesString = new TypeChecker(TypeCheckerBaseType.Primitive, (value, path, typeCheckedValue) => typeof value === \"string\" ? null : new TypeCheckError(path, \"string\", value, typeCheckedValue), () => \"string\", (t) => new StringTypeInfo(t), (value) => typeof value === \"string\" ? typesString : null, identityFn, identityFn);\nstandardTypeResolvers$1.push((v) => v === String ? typesString : void 0);\nclass StringTypeInfo extends TypeInfo {\n}\nfunction registerPrimitiveStandardTypeResolvers() {\n standardTypeResolvers$1.forEach((str) => {\n registerStandardTypeResolver(str);\n });\n}\nlet defaultStandardTypeResolversRegistered = false;\nfunction registerDefaultStandardTypeResolvers() {\n if (defaultStandardTypeResolversRegistered) {\n return;\n }\n defaultStandardTypeResolversRegistered = true;\n registerModelStandardTypeResolver();\n registerDataModelDataStandardTypeResolver();\n registerPrimitiveStandardTypeResolvers();\n}\nconst standardTypeResolvers = [];\nfunction registerStandardTypeResolver(resolverFn) {\n standardTypeResolvers.push(resolverFn);\n}\nfunction findStandardType(value) {\n registerDefaultStandardTypeResolvers();\n for (const resolverFn of standardTypeResolvers) {\n const tc = resolverFn(value);\n if (tc)\n return tc;\n }\n return void 0;\n}\nfunction resolveTypeChecker(v) {\n let next = v;\n while (true) {\n if (next instanceof TypeChecker) {\n return next;\n } else if (isLateTypeChecker(next)) {\n next = next();\n } else {\n const tc = findStandardType(v);\n if (tc) {\n return resolveTypeChecker(tc);\n }\n throw failure(\"type checker could not be resolved\");\n }\n }\n}\nfunction resolveStandardTypeNoThrow(v) {\n if (v instanceof TypeChecker || isLateTypeChecker(v)) {\n return v;\n } else {\n const tc = findStandardType(v);\n if (tc) {\n return tc;\n }\n return void 0;\n }\n}\nfunction resolveStandardType(v) {\n const tc = resolveStandardTypeNoThrow(v);\n if (tc) {\n return tc;\n }\n throw failure(\"standard type could not be resolved\");\n}\nfunction getSnapshot(arg1, arg2) {\n let toSnapshotProcessor = identityFn;\n let nodeOrPrimitive;\n if (arguments.length >= 2) {\n toSnapshotProcessor = resolveTypeChecker(arg1).toSnapshotProcessor;\n nodeOrPrimitive = arg2;\n } else {\n nodeOrPrimitive = arg1;\n }\n if (isPrimitive(nodeOrPrimitive)) {\n return toSnapshotProcessor(nodeOrPrimitive);\n }\n assertTweakedObject(nodeOrPrimitive, \"nodeOrPrimitive\");\n const snapshot = getInternalSnapshot(nodeOrPrimitive);\n if (!snapshot) {\n throw failure(\"getSnapshot is not supported for this kind of object\");\n }\n freezeInternalSnapshot(snapshot.transformed);\n reportInternalSnapshotObserved(snapshot);\n return toSnapshotProcessor(snapshot.transformed);\n}\nconst internalNewModel = action(\"newModel\", (origModelObj, initialData, options) => {\n const mode = initialData ? \"new\" : \"fromSnapshot\";\n const { modelClass: _modelClass, snapshotInitialData, generateNewIds } = options;\n const modelClass2 = _modelClass;\n if (inDevMode) {\n assertIsModelClass(modelClass2, \"modelClass\");\n }\n const modelObj = origModelObj;\n const modelInfo = modelInfoByClass.get(modelClass2);\n if (!modelInfo) {\n throw failure(`no model info for class ${modelClass2.name} could be found - did you forget to add the @model decorator?`);\n }\n const modelIdPropertyName = getModelIdPropertyName(modelClass2);\n const modelProps = getInternalModelClassPropsInfo(modelClass2);\n const modelIdPropData = modelIdPropertyName ? modelProps[modelIdPropertyName] : void 0;\n let id;\n if (snapshotInitialData) {\n let sn = snapshotInitialData.unprocessedSnapshot;\n if (modelIdPropData && modelIdPropertyName) {\n if (generateNewIds) {\n id = modelIdPropData._defaultFn();\n } else {\n id = sn[modelIdPropertyName];\n }\n }\n if (modelClass2.fromSnapshotProcessor) {\n sn = modelClass2.fromSnapshotProcessor(sn);\n }\n initialData = snapshotInitialData.snapshotToInitialData(sn);\n } else {\n if (modelIdPropData && modelIdPropertyName) {\n if (initialData[modelIdPropertyName]) {\n id = initialData[modelIdPropertyName];\n } else {\n id = modelIdPropData._defaultFn();\n }\n }\n }\n modelObj[modelTypeKey] = modelInfo.name;\n const patches = [];\n const inversePatches = [];\n const modelPropsKeys = Object.keys(modelProps);\n for (let i = 0; i < modelPropsKeys.length; i++) {\n const k = modelPropsKeys[i];\n if (k === modelIdPropertyName) {\n continue;\n }\n const propData = modelProps[k];\n const initialValue = initialData[k];\n let newValue = initialValue;\n let changed = false;\n if (mode === \"new\" && propData._transform) {\n changed = true;\n newValue = propData._transform.untransform(newValue, modelObj, k);\n }\n if (newValue == null) {\n const defaultValue = getModelPropDefaultValue(propData);\n if (defaultValue !== noDefaultValue) {\n changed = true;\n newValue = defaultValue;\n } else if (!(k in initialData)) {\n changed = true;\n }\n }\n if (changed) {\n set(initialData, k, newValue);\n if (mode === \"fromSnapshot\" && newValue !== initialValue) {\n const propPath = [k];\n patches.push(createPatchForObjectValueChange(propPath, initialValue, newValue));\n inversePatches.push(createPatchForObjectValueChange(propPath, newValue, initialValue));\n }\n }\n }\n if (modelIdPropertyName) {\n const initialValue = initialData[modelIdPropertyName];\n const valueChanged = setIfDifferent(initialData, modelIdPropertyName, id);\n if (valueChanged && mode === \"fromSnapshot\") {\n const modelIdPath = [modelIdPropertyName];\n patches.push(createPatchForObjectValueChange(modelIdPath, initialValue, id));\n inversePatches.push(createPatchForObjectValueChange(modelIdPath, id, initialValue));\n }\n }\n if (mode === \"fromSnapshot\") {\n const initialModelType = snapshotInitialData == null ? void 0 : snapshotInitialData.unprocessedModelType;\n const newModelType = modelInfo.name;\n if (initialModelType !== newModelType) {\n const modelTypePath = [modelTypeKey];\n patches.push(createPatchForObjectValueChange(modelTypePath, initialModelType, newModelType));\n inversePatches.push(createPatchForObjectValueChange(modelTypePath, newModelType, initialModelType));\n }\n }\n tweakModel(modelObj, void 0);\n modelObj.$ = tweakPlainObject(initialData, { parent: modelObj, path: \"$\" }, modelObj[modelTypeKey], false, true);\n if (inDevMode) {\n makePropReadonly(modelObj, \"$\", true);\n }\n applyModelInitializers(modelClass2, modelObj);\n emitPatches(modelObj, patches, inversePatches);\n if (isModelAutoTypeCheckingEnabled() && getModelMetadata(modelClass2).dataType) {\n const err = modelObj.typeCheck();\n if (err) {\n err.throw();\n }\n }\n return modelObj;\n});\nconst modelIdPropertyNameSymbol = Symbol(\"modelIdPropertyName\");\nclass BaseModel {\n /**\n * Creates an instance of a model.\n */\n constructor(data) {\n // just to make typing work properly\n __publicField(this, _b);\n __publicField(this, _c);\n __publicField(this, _d);\n __publicField(this, _e);\n /**\n * Model type name.\n */\n __publicField(this, _f);\n /**\n * Data part of the model, which is observable and will be serialized in snapshots.\n * Use it if one of the data properties matches one of the model properties/functions.\n */\n __publicField(this, \"$\");\n let initialData = data;\n const { snapshotInitialData, modelClass: modelClass2, generateNewIds } = arguments[1];\n Object.setPrototypeOf(this, modelClass2.prototype);\n const self = this;\n delete self[propsTypeSymbol];\n delete self[fromSnapshotOverrideTypeSymbol];\n delete self[toSnapshotOverrideTypeSymbol];\n delete self[modelIdPropertyNameSymbol];\n if (!snapshotInitialData) {\n assertIsObject(initialData, \"initialData\");\n internalNewModel(this, observable.object(initialData, void 0, { deep: false }), {\n modelClass: modelClass2,\n generateNewIds: true\n });\n } else {\n internalNewModel(this, void 0, { modelClass: modelClass2, snapshotInitialData, generateNewIds });\n }\n }\n /**\n * Model internal id. Can be modified inside a model action.\n * It will return `undefined` if there's no id prop set.\n */\n get [(_b = propsTypeSymbol, _c = fromSnapshotOverrideTypeSymbol, _d = toSnapshotOverrideTypeSymbol, _e = modelIdPropertyNameSymbol, _f = modelTypeKey, modelIdKey)]() {\n const idProp2 = getModelIdPropertyName(this.constructor);\n return idProp2 ? this.$[idProp2] : void 0;\n }\n set [modelIdKey](newId) {\n const idProp2 = getModelIdPropertyName(this.constructor);\n if (!idProp2) {\n throw failure(\"$modelId cannot be set when there is no idProp set in the model\");\n }\n this.$[idProp2] = newId;\n }\n /**\n * Can be overridden to offer a reference id to be used in reference resolution.\n * By default it will use the `idProp` if available or return `undefined` otherwise.\n */\n getRefId() {\n return this[modelIdKey];\n }\n /**\n * Performs a type check over the model instance.\n * For this to work a data type has to be declared as part of the model properties.\n *\n * @returns A `TypeCheckError` or `null` if there is no error.\n */\n typeCheck() {\n const type = typesModel(this.constructor);\n return typeCheck(type, this);\n }\n toString(options) {\n const finalOptions = {\n withData: true,\n ...options\n };\n const firstPart = `${this.constructor.name}#${this[modelTypeKey]}`;\n return finalOptions.withData ? `[${firstPart} ${JSON.stringify(getSnapshot(this))}]` : `[${firstPart}]`;\n }\n}\nconst baseModelPropNames = /* @__PURE__ */ new Set([\n modelTypeKey,\n modelIdKey,\n \"onInit\",\n \"$\",\n \"getRefId\",\n \"onAttachedToRootStore\",\n \"typeCheck\"\n]);\nfunction abstractModelClass(type) {\n return type;\n}\nfunction modelSnapshotInWithMetadata(modelClass2, snapshot) {\n assertIsModelClass(modelClass2, \"modelClass\");\n assertIsObject(snapshot, \"initialData\");\n const modelInfo = modelInfoByClass.get(modelClass2);\n return {\n ...snapshot,\n [modelTypeKey]: modelInfo.name\n };\n}\nfunction modelSnapshotOutWithMetadata(modelClass2, snapshot) {\n assertIsModelClass(modelClass2, \"modelClass\");\n assertIsObject(snapshot, \"initialData\");\n const modelInfo = modelInfoByClass.get(modelClass2);\n return {\n ...snapshot,\n [modelTypeKey]: modelInfo.name\n };\n}\nfunction isModel(model2) {\n return model2 instanceof BaseModel;\n}\nfunction assertIsModel(model2, argName, customErrMsg = \"must be a model instance\") {\n if (!isModel(model2)) {\n throw failure(`${argName} ${customErrMsg}`);\n }\n}\nfunction isModelClass(modelClass2) {\n if (typeof modelClass2 !== \"function\") {\n return false;\n }\n if (modelClass2 !== BaseModel && !(modelClass2.prototype instanceof BaseModel)) {\n return false;\n }\n return true;\n}\nfunction assertIsModelClass(modelClass2, argName) {\n if (typeof modelClass2 !== \"function\") {\n throw failure(`${argName} must be a class`);\n }\n if (modelClass2 !== BaseModel && !(modelClass2.prototype instanceof BaseModel)) {\n throw failure(`${argName} must extend Model`);\n }\n}\nfunction isModelSnapshot(sn) {\n return isPlainObject(sn) && modelTypeKey in sn;\n}\nfunction getParentPath(value) {\n assertTweakedObject(value, \"value\");\n return fastGetParentPath(value);\n}\nfunction fastGetParentPath(value) {\n reportParentPathObserved(value);\n return objectParents.get(value);\n}\nfunction fastGetParentPathIncludingDataObjects(value) {\n const parentModel = dataObjectParent.get(value);\n if (parentModel) {\n return { parent: parentModel, path: \"$\" };\n }\n const parentPath = fastGetParentPath(value);\n if (parentPath && isModel(parentPath.parent)) {\n return { parent: parentPath.parent.$, path: parentPath.path };\n }\n return parentPath;\n}\nfunction getParent(value) {\n assertTweakedObject(value, \"value\");\n return fastGetParent(value);\n}\nfunction fastGetParent(value) {\n var _a2;\n return (_a2 = fastGetParentPath(value)) == null ? void 0 : _a2.parent;\n}\nfunction fastGetParentIncludingDataObjects(value) {\n var _a2;\n return (_a2 = fastGetParentPathIncludingDataObjects(value)) == null ? void 0 : _a2.parent;\n}\nfunction isModelDataObject(value) {\n assertTweakedObject(value, \"value\", true);\n return fastIsModelDataObject(value);\n}\nfunction fastIsModelDataObject(value) {\n return dataObjectParent.has(value);\n}\nfunction getRootPath(value) {\n assertTweakedObject(value, \"value\");\n return fastGetRootPath(value);\n}\nfunction fastGetRootPath(value) {\n let root = value;\n let path = [];\n let pathObjects = [value];\n let parentPath;\n while (parentPath = fastGetParentPath(root)) {\n root = parentPath.parent;\n path.unshift(parentPath.path);\n pathObjects.unshift(parentPath.parent);\n }\n return { root, path, pathObjects };\n}\nfunction getRoot(value) {\n assertTweakedObject(value, \"value\");\n return fastGetRoot(value);\n}\nfunction fastGetRoot(value) {\n let root = value;\n let parentPath;\n while (parentPath = fastGetParentPath(root)) {\n root = parentPath.parent;\n }\n return root;\n}\nfunction isRoot(value) {\n assertTweakedObject(value, \"value\");\n return !fastGetParent(value);\n}\nconst unresolved = { resolved: false };\nfunction resolvePath(pathRootObject, path) {\n let current = pathRootObject;\n let len = path.length;\n for (let i = 0; i < len; i++) {\n if (!isObject(current)) {\n return unresolved;\n }\n const p = path[i];\n if (isArray(current) && +p >= current.length) {\n return unresolved;\n }\n if (isModel(current)) {\n const dataNode = modelToDataNode(current);\n if (p in dataNode) {\n current = dataNode;\n } else if (!(p in current)) {\n return unresolved;\n }\n }\n current = current[p];\n }\n return { resolved: true, value: current };\n}\nconst skipIdChecking = Symbol(\"skipIdChecking\");\nfunction resolvePathCheckingIds(pathRootObject, path, pathIds) {\n var _a2;\n let current = modelToDataNode(pathRootObject);\n let len = path.length;\n for (let i = 0; i < len; i++) {\n if (!isObject(current)) {\n return { resolved: false };\n }\n const p = path[i];\n if (isArray(current) && +p >= current.length) {\n return { resolved: false };\n }\n const currentMaybeModel = current[p];\n current = modelToDataNode(currentMaybeModel);\n const expectedId = pathIds[i];\n if (expectedId !== skipIdChecking) {\n const currentId = isModel(currentMaybeModel) ? (_a2 = currentMaybeModel[modelIdKey]) != null ? _a2 : null : null;\n if (expectedId !== currentId) {\n return { resolved: false };\n }\n }\n }\n return { resolved: true, value: dataToModelNode(current) };\n}\nfunction getParentToChildPath(fromParent, toChild) {\n assertTweakedObject(fromParent, \"fromParent\");\n assertTweakedObject(toChild, \"toChild\");\n if (fromParent === toChild) {\n return [];\n }\n const path = [];\n let current = toChild;\n let parentPath;\n while (parentPath = fastGetParentPath(current)) {\n path.unshift(parentPath.path);\n current = parentPath.parent;\n if (current === fromParent) {\n return path;\n }\n }\n return void 0;\n}\nconst perObjectActionMiddlewares = /* @__PURE__ */ new WeakMap();\nconst perObjectActionMiddlewaresIterator = /* @__PURE__ */ new WeakMap();\nfunction getActionMiddlewares(obj) {\n let iterable = perObjectActionMiddlewaresIterator.get(obj);\n if (!iterable) {\n iterable = {\n [Symbol.iterator]() {\n let current = obj;\n function getCurrentIterator() {\n const objMwares = current ? perObjectActionMiddlewares.get(current) : void 0;\n if (!objMwares || objMwares.length <= 0) {\n return void 0;\n }\n return objMwares[Symbol.iterator]();\n }\n function findNextIterator() {\n let nextIter;\n while (current && !nextIter) {\n current = fastGetParent(current);\n nextIter = getCurrentIterator();\n }\n return nextIter;\n }\n let iter = getCurrentIterator();\n if (!iter) {\n iter = findNextIterator();\n }\n const iterator = {\n next() {\n if (!iter) {\n return { value: void 0, done: true };\n }\n let result = iter.next();\n if (!result.done) {\n return result;\n }\n iter = findNextIterator();\n return this.next();\n }\n };\n return iterator;\n }\n };\n perObjectActionMiddlewaresIterator.set(obj, iterable);\n }\n return iterable;\n}\nfunction addActionMiddleware(mware) {\n assertIsObject(mware, \"middleware\");\n let { middleware, filter, subtreeRoot } = mware;\n assertTweakedObject(subtreeRoot, \"middleware.subtreeRoot\");\n assertIsFunction(middleware, \"middleware.middleware\");\n if (filter && typeof filter !== \"function\") {\n throw failure(\"middleware.filter must be a function or undefined\");\n }\n if (subtreeRoot) {\n const targetFilter = (ctx) => ctx.target === subtreeRoot || isChildOfParent(ctx.target, subtreeRoot);\n if (!filter) {\n filter = targetFilter;\n } else {\n const customFilter = filter;\n filter = (ctx) => {\n return targetFilter(ctx) && customFilter(ctx);\n };\n }\n }\n const actualMware = { middleware, filter };\n let objMwares = perObjectActionMiddlewares.get(subtreeRoot);\n if (!objMwares) {\n objMwares = [actualMware];\n perObjectActionMiddlewares.set(subtreeRoot, objMwares);\n } else {\n objMwares.push(actualMware);\n }\n return () => {\n deleteFromArray(objMwares, actualMware);\n };\n}\nfunction wrapInAction({ nameOrNameFn, fn, actionType, overrideContext, isFlowFinisher = false }) {\n let fnInAction = false;\n const wrappedAction = function() {\n const name = typeof nameOrNameFn === \"function\" ? nameOrNameFn() : nameOrNameFn;\n if (!fnInAction) {\n fnInAction = true;\n fn = action(name, fn);\n }\n const target = this;\n const parentContext = getCurrentActionContext();\n const context = {\n actionName: name,\n type: actionType,\n target,\n args: Array.from(arguments),\n parentContext,\n data: {},\n rootContext: void 0\n // will be set after the override\n };\n if (overrideContext) {\n overrideContext(context, this);\n }\n if (!context.rootContext) {\n if (context.previousAsyncStepContext) {\n context.rootContext = context.previousAsyncStepContext.rootContext;\n } else if (context.parentContext) {\n context.rootContext = context.parentContext.rootContext;\n } else {\n context.rootContext = context;\n }\n }\n setCurrentActionContext(context);\n let mwareFn = fn.bind(target, ...arguments);\n const mwareIter = getActionMiddlewares(context.target)[Symbol.iterator]();\n let mwareCur = mwareIter.next();\n while (!mwareCur.done) {\n const mware = mwareCur.value;\n const filterPassed = mware.filter ? mware.filter(context) : true;\n if (filterPassed) {\n mwareFn = mware.middleware.bind(void 0, context, mwareFn);\n }\n mwareCur = mwareIter.next();\n }\n try {\n const ret = mwareFn();\n if (isFlowFinisher) {\n const flowFinisher = ret;\n const value = flowFinisher.value;\n if (flowFinisher.resolution === \"accept\") {\n flowFinisher.accepter(value);\n } else {\n flowFinisher.rejecter(value);\n }\n return value;\n } else {\n return ret;\n }\n } finally {\n setCurrentActionContext(context.parentContext);\n tryRunPendingActions();\n }\n };\n wrappedAction[modelActionSymbol] = true;\n return wrappedAction;\n}\nfunction wrapModelMethodInActionIfNeeded(model2, propertyKey, name) {\n const fn = model2[propertyKey];\n if (isModelAction(fn)) {\n return;\n }\n const wrappedFn = wrapInAction({\n nameOrNameFn: name,\n fn,\n actionType: ActionContextActionType.Sync\n });\n const proto = Object.getPrototypeOf(model2);\n const protoFn = proto[propertyKey];\n if (protoFn === fn) {\n proto[propertyKey] = wrappedFn;\n } else {\n model2[propertyKey] = wrappedFn;\n }\n}\nfunction detach(node) {\n assertTweakedObject(node, \"node\");\n wrappedInternalDetach().call(node);\n}\nconst wrappedInternalDetach = lazy(() => wrapInAction({\n nameOrNameFn: BuiltInAction.Detach,\n fn: internalDetach,\n actionType: ActionContextActionType.Sync\n}));\nfunction internalDetach() {\n const node = this;\n const parentPath = fastGetParentPathIncludingDataObjects(node);\n if (!parentPath)\n return;\n const { parent, path } = parentPath;\n if (isObservableArray(parent)) {\n parent.splice(+path, 1);\n } else if (isObservableObject(parent)) {\n remove(parent, \"\" + path);\n } else {\n throw failure(\"parent must be an observable object or an observable array\");\n }\n}\nconst unboundMethodSymbol = Symbol(\"unboundMethod\");\nconst bindMethod = (method, instance) => {\n const unboundMethod = unboundMethodSymbol in method ? method[unboundMethodSymbol] : method;\n const boundMethod = unboundMethod.bind(instance);\n Object.getOwnPropertySymbols(unboundMethod).forEach((s) => {\n boundMethod[s] = unboundMethod[s];\n });\n boundMethod[unboundMethodSymbol] = unboundMethod;\n return boundMethod;\n};\nfunction decorateWrapMethodOrField(decoratorName, args, wrap) {\n if (typeof args[1] !== \"object\") {\n const target = args[0];\n const propertyKey = args[1];\n const baseDescriptor = args[2];\n checkModelDecoratorTaget(decoratorName, target);\n checkDecoratorContext(\"transaction\", propertyKey, false);\n const data = getActionNameAndContextOverride(target, propertyKey, true);\n const addFieldDecorator = () => {\n addLateInitializationFunction(target, runAfterNewSymbol, (instance) => {\n const method = wrap(data, instance[propertyKey]);\n instance[propertyKey] = bindMethod(method, instance);\n });\n };\n if (baseDescriptor) {\n if (baseDescriptor.get !== void 0) {\n throw failure(`@${decoratorName} cannot be used with getters`);\n }\n if (baseDescriptor.value) {\n return {\n enumerable: false,\n writable: true,\n configurable: true,\n value: wrap(data, baseDescriptor.value)\n };\n } else {\n addFieldDecorator();\n }\n } else {\n addFieldDecorator();\n }\n } else {\n const ctx = args[1];\n checkDecoratorContext(decoratorName, ctx.name, ctx.static);\n if (ctx.kind !== \"method\" && ctx.kind !== \"field\") {\n throw failure(`@${decoratorName} can only be used on fields or methods}`);\n }\n if (ctx.kind === \"method\") {\n const value = args[0];\n const propertyKey = ctx.name;\n let inited = false;\n ctx.addInitializer(function() {\n if (inited) {\n return;\n }\n inited = true;\n const target = this;\n checkModelDecoratorTaget(decoratorName, target);\n let proto = this;\n let nextProto = Object.getPrototypeOf(proto);\n while (nextProto && nextProto[propertyKey] === value) {\n proto = nextProto;\n nextProto = Object.getPrototypeOf(proto);\n }\n proto[propertyKey] = wrap(getActionNameAndContextOverride(target, propertyKey, false), proto[propertyKey]);\n });\n } else if (ctx.kind === \"field\") {\n const propertyKey = ctx.name;\n let data;\n return function(value) {\n const instance = this;\n if (!data) {\n checkModelDecoratorTaget(decoratorName, instance);\n data = getActionNameAndContextOverride(instance, propertyKey, false);\n }\n const method = wrap(data, value);\n return bindMethod(method, instance);\n };\n }\n }\n}\nfunction checkDecoratorContext(decoratorName, propertyKey, isStatic) {\n if (!inDevMode) {\n return;\n }\n if (typeof propertyKey !== \"string\") {\n throw failure(`@${decoratorName} cannot decorate symbol properties`);\n }\n if (isStatic) {\n throw failure(`@${decoratorName} cannot be used with static fields or methods`);\n }\n}\nconst dataModelOverrideContext = (ctx, self) => {\n ctx.target = self.$;\n};\nfunction getActionNameAndContextOverride(target, propertyKey, runLate) {\n if (isDataModelClass(target) || isDataModel(target)) {\n const modelClass2 = isDataModelClass(target) ? target : target.constructor;\n let fullActionName;\n const lateInit = (finalClass) => {\n const modelInfo = modelInfoByClass.get(finalClass);\n fullActionName = `fn::${modelInfo.name}::${propertyKey}`;\n setDataModelAction(fullActionName, modelInfo.class, propertyKey);\n };\n if (runLate) {\n addLateInitializationFunction(modelClass2, runAfterModelDecoratorSymbol, lateInit);\n } else {\n lateInit(modelClass2);\n }\n return {\n actionName: () => fullActionName,\n overrideContext: dataModelOverrideContext\n };\n } else {\n return { actionName: propertyKey, overrideContext: void 0 };\n }\n}\nfunction checkModelDecoratorTaget(decoratorName, target) {\n if (!inDevMode) {\n return;\n }\n const errMessage2 = `@${decoratorName} must be used over model classes or instances`;\n if (!target) {\n throw failure(errMessage2);\n }\n const isModel2 = target instanceof BaseModel || target === BaseModel || target.prototype instanceof BaseModel;\n if (isModel2)\n return;\n const isDataModel2 = target instanceof BaseDataModel || target === BaseDataModel || target.prototype instanceof BaseDataModel;\n if (isDataModel2)\n return;\n throw failure(errMessage2);\n}\nconst modelFlowSymbol = Symbol(\"modelFlow\");\nfunction flow({ nameOrNameFn, generator, overrideContext }) {\n const flowFn = function(...args) {\n const name = typeof nameOrNameFn === \"function\" ? nameOrNameFn() : nameOrNameFn;\n const target = this;\n let previousAsyncStepContext;\n const ctxOverride = (stepType) => {\n return (ctx, self) => {\n if (overrideContext) {\n overrideContext(ctx, self);\n }\n ctx.previousAsyncStepContext = previousAsyncStepContext;\n ctx.spawnAsyncStepContext = previousAsyncStepContext ? previousAsyncStepContext.spawnAsyncStepContext : ctx;\n ctx.asyncStepType = stepType;\n ctx.args = args;\n previousAsyncStepContext = ctx;\n };\n };\n let generatorRun = false;\n const gen = wrapInAction({\n nameOrNameFn: name,\n fn: () => {\n generatorRun = true;\n return generator.apply(target, args);\n },\n actionType: ActionContextActionType.Async,\n overrideContext: ctxOverride(ActionContextAsyncStepType.Spawn)\n }).apply(target);\n if (!generatorRun) {\n return gen instanceof Promise ? gen : Promise.resolve(gen);\n }\n const genNext = gen.next.bind(gen);\n const genThrow = gen.throw.bind(gen);\n const promise = new Promise(function(resolve, reject) {\n function onFulfilled(res) {\n let ret;\n try {\n ret = wrapInAction({\n nameOrNameFn: name,\n fn: genNext,\n actionType: ActionContextActionType.Async,\n overrideContext: ctxOverride(ActionContextAsyncStepType.Resume)\n }).call(target, res);\n } catch (e) {\n wrapInAction({\n nameOrNameFn: name,\n fn: (err) => {\n return {\n value: err,\n resolution: \"reject\",\n accepter: resolve,\n rejecter: reject\n };\n },\n actionType: ActionContextActionType.Async,\n overrideContext: ctxOverride(ActionContextAsyncStepType.Throw),\n isFlowFinisher: true\n }).call(target, e);\n return;\n }\n next(ret);\n }\n function onRejected(err) {\n let ret;\n try {\n ret = wrapInAction({\n nameOrNameFn: name,\n fn: genThrow,\n actionType: ActionContextActionType.Async,\n overrideContext: ctxOverride(ActionContextAsyncStepType.ResumeError)\n }).call(target, err);\n } catch (e) {\n wrapInAction({\n nameOrNameFn: name,\n fn: (err2) => {\n return {\n value: err2,\n resolution: \"reject\",\n accepter: resolve,\n rejecter: reject\n };\n },\n actionType: ActionContextActionType.Async,\n overrideContext: ctxOverride(ActionContextAsyncStepType.Throw),\n isFlowFinisher: true\n }).call(target, e);\n return;\n }\n next(ret);\n }\n function next(ret) {\n if (ret && typeof ret.then === \"function\") {\n ret.then(next, reject);\n } else if (ret.done) {\n wrapInAction({\n nameOrNameFn: name,\n fn: (val) => {\n return {\n value: val,\n resolution: \"accept\",\n accepter: resolve,\n rejecter: reject\n };\n },\n actionType: ActionContextActionType.Async,\n overrideContext: ctxOverride(ActionContextAsyncStepType.Return),\n isFlowFinisher: true\n }).call(target, ret.value);\n } else {\n Promise.resolve(ret.value).then(onFulfilled, onRejected);\n }\n }\n onFulfilled(void 0);\n });\n return promise;\n };\n flowFn[modelFlowSymbol] = true;\n return flowFn;\n}\nfunction isModelFlow(fn) {\n return typeof fn === \"function\" && modelFlowSymbol in fn;\n}\nfunction modelFlow(...args) {\n return decorateWrapMethodOrField(\"modelFlow\", args, (data, fn) => {\n if (isModelFlow(fn)) {\n return fn;\n } else {\n if (typeof fn !== \"function\") {\n throw failure(\"modelFlow has to be used over functions\");\n }\n return flow({\n nameOrNameFn: data.actionName,\n generator: fn,\n overrideContext: data.overrideContext\n });\n }\n });\n}\nfunction _async(fn) {\n return fn;\n}\nfunction _await(promise) {\n return promiseGenerator.call(promise);\n}\nconst __generator = function(thisArg, body) {\n let _ = {\n label: 0,\n sent: function() {\n if (t[0] & 1)\n throw t[1];\n return t[1];\n },\n trys: [],\n ops: []\n }, f, y, t, g;\n return g = { next: verb(0), throw: verb(1), return: verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() {\n return this;\n }), g;\n function verb(n) {\n return function(v) {\n return step([n, v]);\n };\n }\n function step(op) {\n if (f)\n throw new TypeError(\"Generator is already executing.\");\n while (_)\n try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)\n return t;\n if (y = 0, t)\n op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0:\n case 1:\n t = op;\n break;\n case 4:\n _.label++;\n return { value: op[1], done: false };\n case 5:\n _.label++;\n y = op[1];\n op = [0];\n continue;\n case 7:\n op = _.ops.pop();\n _.trys.pop();\n continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {\n _ = 0;\n continue;\n }\n if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {\n _.label = op[1];\n break;\n }\n if (op[0] === 6 && _.label < t[1]) {\n _.label = t[1];\n t = op;\n break;\n }\n if (t && _.label < t[2]) {\n _.label = t[2];\n _.ops.push(op);\n break;\n }\n if (t[2])\n _.ops.pop();\n _.trys.pop();\n continue;\n }\n op = body.call(thisArg, _);\n } catch (e) {\n op = [6, e];\n y = 0;\n } finally {\n f = t = 0;\n }\n if (op[0] & 5)\n throw op[1];\n return { value: op[0] ? op[1] : void 0, done: true };\n }\n};\nfunction promiseGenerator() {\n let ret;\n return __generator(this, function(_a2) {\n switch (_a2.label) {\n case 0:\n return [4, this];\n case 1:\n ret = _a2.sent();\n return [2, ret];\n default:\n return;\n }\n });\n}\nconst standaloneActionRegistry = /* @__PURE__ */ new Map();\nfunction getStandaloneAction(actionName) {\n return standaloneActionRegistry.get(actionName);\n}\nfunction addStandaloneAction(fullActionName, fn, isFlow) {\n assertIsFunction(fn, fullActionName);\n if (standaloneActionRegistry.has(fullActionName)) {\n logWarning(\"warn\", `an standalone action with name \"${fullActionName}\" already exists (if you are using hot-reloading you may safely ignore this warning)`, `duplicateActionName - ${fullActionName}`);\n }\n if (isModelAction(fn)) {\n throw failure(\"the standalone action must not be previously marked as an action\");\n }\n if (isModelFlow(fn)) {\n throw failure(\"the standalone action must not be previously marked as a flow action\");\n }\n const wrappedAction = isFlow ? flow({ nameOrNameFn: fullActionName, generator: fn }) : wrapInAction({\n nameOrNameFn: fullActionName,\n fn,\n actionType: ActionContextActionType.Sync\n });\n const finalAction = (target, ...args) => {\n assertIsTreeNode(target, \"target\");\n return wrappedAction.call(target, target, ...args);\n };\n standaloneActionRegistry.set(fullActionName, finalAction);\n return finalAction;\n}\nfunction applyDelete(node, fieldName) {\n assertTweakedObject(node, \"node\", true);\n wrappedInternalApplyDelete().call(node, fieldName);\n}\nfunction internalApplyDelete(fieldName) {\n remove(this, \"\" + fieldName);\n}\nconst wrappedInternalApplyDelete = lazy(() => wrapInAction({\n nameOrNameFn: BuiltInAction.ApplyDelete,\n fn: internalApplyDelete,\n actionType: ActionContextActionType.Sync\n}));\nfunction applyMethodCall(node, methodName, ...args) {\n assertTweakedObject(node, \"node\");\n return wrappedInternalApplyMethodCall().call(node, methodName, args);\n}\nfunction internalApplyMethodCall(methodName, args) {\n return this[methodName](...args);\n}\nconst wrappedInternalApplyMethodCall = lazy(() => wrapInAction({\n nameOrNameFn: BuiltInAction.ApplyMethodCall,\n fn: internalApplyMethodCall,\n actionType: ActionContextActionType.Sync\n}));\nfunction applySet(node, fieldName, value) {\n assertTweakedObject(node, \"node\", true);\n wrappedInternalApplySet().call(node, fieldName, value);\n}\nfunction internalApplySet(fieldName, value) {\n if (!isModel(this) && isObservable(this)) {\n setIfDifferent(this, fieldName, value);\n } else {\n this[fieldName] = value;\n }\n}\nconst wrappedInternalApplySet = lazy(() => wrapInAction({\n nameOrNameFn: BuiltInAction.ApplySet,\n fn: internalApplySet,\n actionType: ActionContextActionType.Sync\n}));\nconst builtInActionToFunction = {\n [BuiltInAction.ApplySnapshot]: applySnapshot,\n [BuiltInAction.ApplyPatches]: applyPatches,\n [BuiltInAction.Detach]: detach,\n [BuiltInAction.ApplySet]: applySet,\n [BuiltInAction.ApplyDelete]: applyDelete,\n [BuiltInAction.ApplyMethodCall]: applyMethodCall\n};\nfunction applyAction(subtreeRoot, call) {\n if (call.serialized) {\n throw failure(\"cannot apply a serialized action call, use one of the 'applySerializedAction' methods instead\");\n }\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n const { value: current, resolved } = resolvePathCheckingIds(subtreeRoot, call.targetPath, call.targetPathIds);\n if (!resolved) {\n throw failure(`object at path ${JSON.stringify(call.targetPath)} with ids ${JSON.stringify(call.targetPathIds)} could not be resolved`);\n }\n assertTweakedObject(current, `resolved ${current}`, true);\n if (isBuiltInAction(call.actionName)) {\n const fnToCall = builtInActionToFunction[call.actionName];\n if (!fnToCall) {\n throw failure(`assertion failed: unknown built-in action - ${call.actionName}`);\n }\n return fnToCall.apply(current, [current, ...call.args]);\n }\n if (isHookAction(call.actionName)) {\n throw failure(`calls to hooks (${call.actionName}) cannot be applied`);\n }\n const dataModelAction = getDataModelAction(call.actionName);\n if (dataModelAction) {\n const instance = new dataModelAction.modelClass(current);\n return instance[dataModelAction.fnName].apply(instance, call.args);\n }\n const standaloneAction2 = getStandaloneAction(call.actionName);\n if (standaloneAction2) {\n return standaloneAction2.apply(current, call.args);\n }\n return current[call.actionName].apply(current, call.args);\n}\nfunction modelAction(...args) {\n return decorateWrapMethodOrField(\"modelAction\", args, (data, fn) => {\n if (isModelAction(fn)) {\n return fn;\n } else {\n if (typeof fn !== \"function\") {\n throw failure(\"modelAction has to be used over functions\");\n }\n return wrapInAction({\n nameOrNameFn: data.actionName,\n fn,\n actionType: ActionContextActionType.Sync,\n overrideContext: data.overrideContext\n });\n }\n });\n}\nfunction runUnprotected(arg1, arg2) {\n const name = typeof arg1 === \"string\" ? arg1 : void 0;\n const fn = typeof arg1 === \"string\" ? arg2 : arg1;\n const innerAction = () => {\n const oldActionProtection = getActionProtection();\n setActionProtection(false);\n try {\n return fn();\n } finally {\n setActionProtection(oldActionProtection);\n tryRunPendingActions();\n }\n };\n if (name) {\n return action(name, innerAction)();\n } else {\n return action(innerAction)();\n }\n}\nconst cannotSerialize = Symbol(\"cannotSerialize\");\nconst arraySerializer = {\n id: `${namespace$2}/array`,\n serialize(value, serialize) {\n if (!isArray(value))\n return cannotSerialize;\n return value.map(serialize);\n },\n deserialize(arr, deserialize) {\n return arr.map(deserialize);\n }\n};\nconst dateSerializer = {\n id: `${namespace$2}/dateAsTimestamp`,\n serialize(date) {\n if (!(date instanceof Date))\n return cannotSerialize;\n return +date;\n },\n deserialize(timestamp) {\n return new Date(timestamp);\n }\n};\nconst mapSerializer = {\n id: `${namespace$2}/mapAsArray`,\n serialize(map, serialize) {\n if (!(map instanceof Map) && !isObservableMap(map))\n return cannotSerialize;\n const arr = [];\n const iter = map.keys();\n let cur = iter.next();\n while (!cur.done) {\n const k = cur.value;\n const v = map.get(k);\n arr.push([serialize(k), serialize(v)]);\n cur = iter.next();\n }\n return arr;\n },\n deserialize(arr, deserialize) {\n const map = /* @__PURE__ */ new Map();\n const len = arr.length;\n for (let i = 0; i < len; i++) {\n const k = arr[i][0];\n const v = arr[i][1];\n map.set(deserialize(k), deserialize(v));\n }\n return map;\n }\n};\nfunction rootPathToTargetPathIds(rootPath) {\n var _a2;\n const targetPathIds = [];\n for (let i = 0; i < rootPath.path.length; i++) {\n const targetObj = rootPath.pathObjects[i + 1];\n const targetObjId = isModel(targetObj) ? (_a2 = targetObj[modelIdKey]) != null ? _a2 : null : null;\n targetPathIds.push(targetObjId);\n }\n return targetPathIds;\n}\nfunction pathToTargetPathIds(root, path) {\n var _a2;\n const targetPathIds = [];\n let current = root;\n for (let i = 0; i < path.length; i++) {\n current = current[path[i]];\n const targetObjId = isModel(current) ? (_a2 = current[modelIdKey]) != null ? _a2 : null : null;\n targetPathIds.push(targetObjId);\n }\n return targetPathIds;\n}\nconst objectPathSerializer = {\n id: `${namespace$2}/objectPath`,\n serialize(value, _, targetRoot) {\n if (typeof value !== \"object\" || value === null || !isTweakedObject(value, false))\n return cannotSerialize;\n if (targetRoot) {\n const rootPath = fastGetRootPath(value);\n if (rootPath.root === targetRoot) {\n return {\n targetPath: rootPath.path,\n targetPathIds: rootPathToTargetPathIds(rootPath)\n };\n }\n }\n return cannotSerialize;\n },\n deserialize(ref, _, targetRoot) {\n if (targetRoot) {\n const result = resolvePathCheckingIds(targetRoot, ref.targetPath, ref.targetPathIds);\n if (result.resolved) {\n return result.value;\n }\n }\n throw failure(`object at path ${JSON.stringify(ref.targetPath)} with ids ${JSON.stringify(ref.targetPathIds)} could not be resolved`);\n }\n};\nconst objectSnapshotSerializer = {\n id: `${namespace$2}/objectSnapshot`,\n serialize(value) {\n if (typeof value !== \"object\" || value === null || !isTweakedObject(value, false))\n return cannotSerialize;\n return getSnapshot(value);\n },\n deserialize(snapshot) {\n return fromSnapshot(snapshot);\n }\n};\nconst plainObjectSerializer = {\n id: `${namespace$2}/plainObject`,\n serialize(value, serialize) {\n if (!isPlainObject(value) && !isObservableObject(value))\n return cannotSerialize;\n return mapObjectFields(value, serialize);\n },\n deserialize(obj, serialize) {\n return mapObjectFields(obj, serialize);\n }\n};\nfunction mapObjectFields(originalObj, mapFn) {\n const obj = {};\n const keys2 = Object.keys(originalObj);\n const len = keys2.length;\n for (let i = 0; i < len; i++) {\n const k = keys2[i];\n const v = originalObj[k];\n obj[k] = mapFn(v);\n }\n return obj;\n}\nconst primitiveSerializer = {\n id: `${namespace$2}/primitiveAsString`,\n serialize(value) {\n if (Number.isNaN(value)) {\n return \"nan\";\n }\n switch (value) {\n case Infinity:\n return \"+inf\";\n case -Infinity:\n return \"-inf\";\n }\n if (typeof value === \"bigint\") {\n return value.toString();\n }\n if (value === void 0) {\n return \"undefined\";\n }\n return cannotSerialize;\n },\n deserialize(str) {\n switch (str) {\n case \"nan\":\n return NaN;\n case \"+inf\":\n return Infinity;\n case \"-inf\":\n return -Infinity;\n case \"undefined\":\n return void 0;\n default:\n return BigInt(str);\n }\n }\n};\nconst setSerializer = {\n id: `${namespace$2}/setAsArray`,\n serialize(set2, serialize) {\n if (!(set2 instanceof Set))\n return cannotSerialize;\n const arr = [];\n const iter = set2.keys();\n let cur = iter.next();\n while (!cur.done) {\n const k = cur.value;\n arr.push(serialize(k));\n cur = iter.next();\n }\n return arr;\n },\n deserialize(arr, deserialize) {\n const set2 = /* @__PURE__ */ new Set();\n const len = arr.length;\n for (let i = 0; i < len; i++) {\n const k = arr[i];\n set2.add(deserialize(k));\n }\n return set2;\n }\n};\nconst serializersArray = [];\nconst serializersMap = /* @__PURE__ */ new Map();\nfunction registerActionCallArgumentSerializer(serializer) {\n registerDefaultActionCallArgumentSerializers();\n if (serializersArray.includes(serializer)) {\n throw failure(\"action call argument serializer already registered\");\n }\n if (serializersMap.has(serializer.id)) {\n throw failure(`action call argument serializer with id '${serializer.id}' already registered`);\n }\n serializersArray.unshift(serializer);\n serializersMap.set(serializer.id, serializer);\n return () => {\n const index = serializersArray.indexOf(serializer);\n if (index >= 0) {\n serializersArray.splice(index, 1);\n }\n serializersMap.delete(serializer.id);\n };\n}\nfunction serializeActionCallArgument(argValue, targetRoot) {\n registerDefaultActionCallArgumentSerializers();\n if (isJSONPrimitive(argValue)) {\n return argValue;\n }\n const origValue = argValue;\n const serialize = (v) => serializeActionCallArgument(v, targetRoot);\n for (let i = 0; i < serializersArray.length; i++) {\n const serializer = serializersArray[i];\n const serializedValue = serializer.serialize(argValue, serialize, targetRoot);\n if (serializedValue !== cannotSerialize) {\n return {\n $mobxKeystoneSerializer: serializer.id,\n value: serializedValue\n };\n }\n }\n throw failure(`serializeActionCallArgument could not serialize the given value: ${origValue}`);\n}\nfunction serializeActionCall(actionCall, targetRoot) {\n if (actionCall.serialized) {\n throw failure(\"cannot serialize an already serialized action call\");\n }\n if (targetRoot !== void 0) {\n assertTweakedObject(targetRoot, \"targetRoot\");\n }\n const serialize = (v) => serializeActionCallArgument(v, targetRoot);\n return {\n ...actionCall,\n serialized: true,\n args: actionCall.args.map(serialize)\n };\n}\nfunction deserializeActionCallArgument(argValue, targetRoot) {\n registerDefaultActionCallArgumentSerializers();\n if (isJSONPrimitive(argValue)) {\n return argValue;\n }\n if (!isPlainObject(argValue) || typeof argValue.$mobxKeystoneSerializer !== \"string\") {\n throw failure(\"invalid serialized action call argument\");\n }\n const serializerId = argValue.$mobxKeystoneSerializer;\n const serializer = serializersMap.get(serializerId);\n if (!serializer) {\n throw failure(`a serializer with id '${serializerId}' could not be found`);\n }\n const serializedValue = argValue;\n const deserialize = (v) => deserializeActionCallArgument(v, targetRoot);\n return serializer.deserialize(serializedValue.value, deserialize, targetRoot);\n}\nfunction deserializeActionCall(actionCall, targetRoot) {\n if (!actionCall.serialized) {\n throw failure(\"cannot deserialize a non-serialized action call\");\n }\n if (targetRoot !== void 0) {\n assertTweakedObject(targetRoot, \"targetRoot\");\n }\n const deserialize = (v) => deserializeActionCallArgument(v, targetRoot);\n const deserializedActionCall = {\n ...actionCall,\n serialized: void 0,\n args: actionCall.args.map(deserialize)\n };\n delete deserializedActionCall.serialized;\n return deserializedActionCall;\n}\nlet defaultActionCallArgumentSerializersRegistered = false;\nfunction registerDefaultActionCallArgumentSerializers() {\n if (defaultActionCallArgumentSerializersRegistered) {\n return;\n }\n defaultActionCallArgumentSerializersRegistered = true;\n registerActionCallArgumentSerializer(primitiveSerializer);\n registerActionCallArgumentSerializer(plainObjectSerializer);\n registerActionCallArgumentSerializer(setSerializer);\n registerActionCallArgumentSerializer(mapSerializer);\n registerActionCallArgumentSerializer(dateSerializer);\n registerActionCallArgumentSerializer(arraySerializer);\n registerActionCallArgumentSerializer(objectSnapshotSerializer);\n registerActionCallArgumentSerializer(objectPathSerializer);\n}\nfunction applySerializedActionAndTrackNewModelIds(subtreeRoot, call) {\n if (!call.serialized) {\n throw failure(\"cannot apply a non-serialized action call, use 'applyAction' instead\");\n }\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n const deserializedCall = deserializeActionCall(call, subtreeRoot);\n const modelIdOverrides = [];\n const patchDisposer = onPatches(subtreeRoot, (patches) => {\n scanPatchesForModelIdChanges(subtreeRoot, modelIdOverrides, patches);\n });\n try {\n const returnValue = applyAction(subtreeRoot, deserializedCall);\n return {\n returnValue,\n serializedActionCall: {\n ...call,\n modelIdOverrides\n }\n };\n } finally {\n patchDisposer();\n }\n}\nfunction scanPatchesForModelIdChanges(root, modelIdOverrides, patches) {\n const len = patches.length;\n for (let i = 0; i < len; i++) {\n const patch = patches[i];\n if (patch.op === \"replace\" || patch.op === \"add\") {\n deepScanValueForModelIdChanges(root, modelIdOverrides, patch.value, patch.path);\n }\n }\n}\nfunction deepScanValueForModelIdChanges(root, modelIdOverrides, value, path) {\n if (path.length >= 1 && typeof value === \"string\") {\n const parent = resolvePath(root, path.slice(0, path.length - 1)).value;\n if (isModel(parent)) {\n const propertyName = path[path.length - 1];\n if (propertyName === getModelIdPropertyName(parent.constructor)) {\n modelIdOverrides.push({\n op: \"replace\",\n path: path.slice(),\n value\n });\n }\n }\n } else if (Array.isArray(value)) {\n const len = value.length;\n for (let i = 0; i < len; i++) {\n path.push(i);\n deepScanValueForModelIdChanges(root, modelIdOverrides, value[i], path);\n path.pop();\n }\n } else if (isObject(value)) {\n if (!value[frozenKey]) {\n const keys2 = Object.keys(value);\n const len = keys2.length;\n for (let i = 0; i < len; i++) {\n const propName = keys2[i];\n const propValue = value[propName];\n path.push(propName);\n deepScanValueForModelIdChanges(root, modelIdOverrides, propValue, path);\n path.pop();\n }\n }\n }\n}\nfunction applySerializedActionAndSyncNewModelIds(subtreeRoot, call) {\n if (!call.serialized) {\n throw failure(\"cannot apply a non-serialized action call, use 'applyAction' instead\");\n }\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n const deserializedCall = deserializeActionCall(call, subtreeRoot);\n let returnValue;\n runInAction(() => {\n returnValue = applyAction(subtreeRoot, deserializedCall);\n applyPatches(subtreeRoot, call.modelIdOverrides);\n });\n return returnValue;\n}\nvar ActionTrackingResult;\n(function(ActionTrackingResult2) {\n ActionTrackingResult2[\"Return\"] = \"return\";\n ActionTrackingResult2[\"Throw\"] = \"throw\";\n})(ActionTrackingResult || (ActionTrackingResult = {}));\nfunction actionTrackingMiddleware(subtreeRoot, hooks) {\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n const dataSymbol = Symbol(\"actionTrackingMiddlewareData\");\n let State;\n (function(State2) {\n State2[\"Idle\"] = \"idle\";\n State2[\"Started\"] = \"started\";\n State2[\"RealResumed\"] = \"realResumed\";\n State2[\"FakeResumed\"] = \"fakeResumed\";\n State2[\"Suspended\"] = \"suspended\";\n State2[\"Finished\"] = \"finished\";\n })(State || (State = {}));\n function getCtxData(ctx) {\n return ctx.data[dataSymbol];\n }\n function setCtxData(ctx, partialData) {\n let currentData = ctx.data[dataSymbol];\n if (!currentData) {\n ctx.data[dataSymbol] = partialData;\n } else {\n Object.assign(currentData, partialData);\n }\n }\n const userFilter = (ctx) => {\n if (hooks.filter) {\n return hooks.filter(simplifyActionContext(ctx));\n }\n return true;\n };\n const resumeSuspendSupport = !!hooks.onResume || !!hooks.onSuspend;\n const filter = (ctx) => {\n if (ctx.type === ActionContextActionType.Sync) {\n const accepted = userFilter(ctx);\n if (accepted) {\n setCtxData(ctx, {\n startAccepted: true,\n state: State.Idle\n });\n }\n return accepted;\n } else {\n switch (ctx.asyncStepType) {\n case ActionContextAsyncStepType.Spawn:\n const accepted = userFilter(ctx);\n if (accepted) {\n setCtxData(ctx, {\n startAccepted: true,\n state: State.Idle\n });\n }\n return accepted;\n case ActionContextAsyncStepType.Return:\n case ActionContextAsyncStepType.Throw:\n const data = getCtxData(ctx.spawnAsyncStepContext);\n return data ? data.startAccepted : false;\n case ActionContextAsyncStepType.Resume:\n case ActionContextAsyncStepType.ResumeError:\n if (!resumeSuspendSupport) {\n return false;\n } else {\n const data2 = getCtxData(ctx.spawnAsyncStepContext);\n return data2 ? data2.startAccepted : false;\n }\n default:\n return false;\n }\n }\n };\n const start = (simpleCtx) => {\n setCtxData(simpleCtx, {\n state: State.Started\n });\n if (hooks.onStart) {\n return hooks.onStart(simpleCtx) || void 0;\n }\n return void 0;\n };\n const finish = (simpleCtx, ret) => {\n const parentCtx = simpleCtx.parentContext;\n let parentResumed = false;\n if (parentCtx) {\n const parentData = getCtxData(parentCtx);\n if (parentData && parentData.startAccepted && parentData.state === State.Suspended) {\n parentResumed = true;\n resume(parentCtx, false);\n }\n }\n setCtxData(simpleCtx, {\n state: State.Finished\n });\n if (hooks.onFinish) {\n ret = hooks.onFinish(simpleCtx, ret) || ret;\n }\n if (parentResumed) {\n suspend(parentCtx);\n }\n return ret;\n };\n const resume = (simpleCtx, real) => {\n const parentCtx = simpleCtx.parentContext;\n if (parentCtx) {\n const parentData = getCtxData(parentCtx);\n if (parentData && parentData.startAccepted && parentData.state === State.Suspended) {\n resume(parentCtx, false);\n }\n }\n setCtxData(simpleCtx, {\n state: real ? State.RealResumed : State.FakeResumed\n });\n if (hooks.onResume) {\n hooks.onResume(simpleCtx);\n }\n };\n const suspend = (simpleCtx) => {\n setCtxData(simpleCtx, {\n state: State.Suspended\n });\n if (hooks.onSuspend) {\n hooks.onSuspend(simpleCtx);\n }\n const parentCtx = simpleCtx.parentContext;\n if (parentCtx) {\n const parentData = getCtxData(parentCtx);\n if (parentData && parentData.startAccepted && parentData.state === State.FakeResumed) {\n suspend(parentCtx);\n }\n }\n };\n const mware = (ctx, next) => {\n const simpleCtx = simplifyActionContext(ctx);\n const origNext = next;\n next = () => {\n resume(simpleCtx, true);\n try {\n return origNext();\n } finally {\n suspend(simpleCtx);\n }\n };\n if (ctx.type === ActionContextActionType.Sync) {\n let retObj = start(simpleCtx);\n if (retObj) {\n resume(simpleCtx, true);\n suspend(simpleCtx);\n retObj = finish(simpleCtx, retObj);\n } else {\n try {\n retObj = finish(simpleCtx, { result: ActionTrackingResult.Return, value: next() });\n } catch (err) {\n retObj = finish(simpleCtx, { result: ActionTrackingResult.Throw, value: err });\n }\n }\n return returnOrThrowActionTrackingReturn(retObj);\n } else {\n switch (ctx.asyncStepType) {\n case ActionContextAsyncStepType.Spawn: {\n let retObj = start(simpleCtx);\n if (retObj) {\n resume(simpleCtx, true);\n suspend(simpleCtx);\n retObj = finish(simpleCtx, retObj);\n return returnOrThrowActionTrackingReturn(retObj);\n } else {\n return next();\n }\n }\n case ActionContextAsyncStepType.Return: {\n const flowFinisher = next();\n const retObj = finish(simpleCtx, {\n result: ActionTrackingResult.Return,\n value: flowFinisher.value\n });\n flowFinisher.resolution = retObj.result === ActionTrackingResult.Return ? \"accept\" : \"reject\";\n flowFinisher.value = retObj.value;\n return flowFinisher;\n }\n case ActionContextAsyncStepType.Throw: {\n const flowFinisher = next();\n const retObj = finish(simpleCtx, {\n result: ActionTrackingResult.Throw,\n value: flowFinisher.value\n });\n flowFinisher.resolution = retObj.result === ActionTrackingResult.Return ? \"accept\" : \"reject\";\n flowFinisher.value = retObj.value;\n return flowFinisher;\n }\n case ActionContextAsyncStepType.Resume:\n case ActionContextAsyncStepType.ResumeError:\n if (resumeSuspendSupport) {\n return next();\n } else {\n throw failure(`assertion error: async step should have been filtered out - ${ctx.asyncStepType}`);\n }\n default:\n throw failure(`assertion error: async step should have been filtered out - ${ctx.asyncStepType}`);\n }\n }\n };\n return addActionMiddleware({ middleware: mware, filter, subtreeRoot });\n}\nfunction returnOrThrowActionTrackingReturn(retObj) {\n if (retObj.result === ActionTrackingResult.Return) {\n return retObj.value;\n } else {\n throw retObj.value;\n }\n}\nconst simpleDataContextSymbol = Symbol(\"simpleDataContext\");\nfunction simplifyActionContext(ctx) {\n while (ctx.previousAsyncStepContext) {\n ctx = ctx.previousAsyncStepContext;\n }\n let simpleCtx = ctx.data[simpleDataContextSymbol];\n if (!simpleCtx) {\n const parentContext = ctx.parentContext ? simplifyActionContext(ctx.parentContext) : void 0;\n simpleCtx = {\n actionName: ctx.actionName,\n type: ctx.type,\n target: ctx.target,\n args: ctx.args,\n data: ctx.data,\n parentContext\n };\n simpleCtx.rootContext = parentContext ? parentContext.rootContext : simpleCtx;\n ctx.data[simpleDataContextSymbol] = simpleCtx;\n }\n return simpleCtx;\n}\nfunction onActionMiddleware(subtreeRoot, listeners) {\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n assertIsObject(listeners, \"listeners\");\n return actionTrackingMiddleware(subtreeRoot, {\n filter(ctx) {\n if (ctx.parentContext) {\n return false;\n }\n if (isHookAction(ctx.actionName)) {\n return false;\n }\n return true;\n },\n onStart(ctx) {\n if (listeners.onStart) {\n const actionCall = actionContextToActionCall(ctx);\n return listeners.onStart(actionCall, ctx);\n }\n },\n onFinish(ctx, ret) {\n if (listeners.onFinish) {\n const actionCall = actionContextToActionCall(ctx);\n return listeners.onFinish(actionCall, ctx, ret);\n }\n }\n });\n}\nfunction actionContextToActionCall(ctx) {\n const rootPath = fastGetRootPath(ctx.target);\n return {\n actionName: ctx.actionName,\n args: ctx.args,\n targetPath: rootPath.path,\n targetPathIds: rootPathToTargetPathIds(rootPath)\n };\n}\nfunction readonlyMiddleware(subtreeRoot) {\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n let writable = false;\n const writableSymbol = Symbol(\"writable\");\n const disposer = actionTrackingMiddleware(subtreeRoot, {\n filter(ctx) {\n if (isHookAction(ctx.actionName)) {\n return false;\n }\n let currentlyWritable = writable;\n if (!currentlyWritable) {\n let currentCtx = ctx;\n while (currentCtx && !currentlyWritable) {\n currentlyWritable = !!currentCtx.data[writableSymbol];\n currentCtx = currentCtx.parentContext;\n }\n }\n if (currentlyWritable) {\n ctx.data[writableSymbol] = true;\n return false;\n }\n return true;\n },\n onStart(ctx) {\n return {\n result: ActionTrackingResult.Throw,\n value: failure(`tried to invoke action '${ctx.actionName}' over a readonly node`)\n };\n }\n });\n return {\n dispose: disposer,\n allowWrite(fn) {\n const oldWritable = writable;\n writable = true;\n try {\n return fn();\n } finally {\n writable = oldWritable;\n }\n }\n };\n}\nfunction escapePathComponent(path) {\n if (typeof path === \"number\") {\n return \"\" + path;\n }\n if (path.indexOf(\"/\") === -1 && path.indexOf(\"~\") === -1) {\n return path;\n }\n return path.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\nfunction unescapePathComponent(path) {\n return path.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\nfunction pathToJsonPointer(path) {\n if (path.length <= 0) {\n return \"\";\n }\n return \"/\" + path.map(escapePathComponent).join(\"/\");\n}\nfunction jsonPointerToPath(jsonPointer) {\n if (jsonPointer === \"\") {\n return [];\n }\n if (!jsonPointer.startsWith(\"/\")) {\n throw failure(\"a JSON pointer must start with '/' or be empty\");\n }\n jsonPointer = jsonPointer.slice(1);\n return jsonPointer.split(\"/\").map(unescapePathComponent);\n}\nfunction patchToJsonPatch(patch) {\n return {\n ...patch,\n path: pathToJsonPointer(patch.path)\n };\n}\nfunction jsonPatchToPatch(jsonPatch) {\n return {\n ...jsonPatch,\n path: jsonPointerToPath(jsonPatch.path)\n };\n}\nfunction patchRecorder(subtreeRoot, opts) {\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n return internalPatchRecorder(subtreeRoot, opts);\n}\nfunction internalPatchRecorder(subtreeRoot, opts) {\n let { recording, filter } = {\n recording: true,\n filter: alwaysAcceptFilter,\n ...opts\n };\n const events = observable.array([], {\n deep: false\n });\n let onPatchesDisposer;\n if (subtreeRoot) {\n onPatchesDisposer = onPatches(subtreeRoot, (p, invP) => {\n var _a2;\n if (recording && filter(p, invP)) {\n events.push({\n target: subtreeRoot,\n patches: p,\n inversePatches: invP\n });\n (_a2 = opts == null ? void 0 : opts.onPatches) == null ? void 0 : _a2.call(opts, p, invP);\n }\n });\n } else {\n onPatchesDisposer = onGlobalPatches((target, p, invP) => {\n var _a2;\n if (recording && filter(p, invP)) {\n events.push({\n target,\n patches: p,\n inversePatches: invP\n });\n (_a2 = opts == null ? void 0 : opts.onPatches) == null ? void 0 : _a2.call(opts, p, invP);\n }\n });\n }\n return {\n get recording() {\n return recording;\n },\n set recording(enabled) {\n recording = enabled;\n },\n get events() {\n return events;\n },\n dispose() {\n onPatchesDisposer();\n }\n };\n}\nconst alwaysAcceptFilter = () => true;\nfunction transactionMiddleware(target) {\n assertIsObject(target, \"target\");\n const { model: model2, actionName } = target;\n assertIsModel(model2, \"target.model\");\n if (typeof actionName !== \"string\") {\n throw failure(\"target.actionName must be a string\");\n }\n const patchRecorderSymbol = Symbol(\"patchRecorder\");\n function initPatchRecorder(ctx) {\n ctx.rootContext.data[patchRecorderSymbol] = internalPatchRecorder(void 0, {\n recording: false\n });\n }\n function getPatchRecorder(ctx) {\n return ctx.rootContext.data[patchRecorderSymbol];\n }\n return actionTrackingMiddleware(model2, {\n filter(ctx) {\n const rootContext = ctx.rootContext;\n return rootContext.target === model2 && rootContext.actionName === actionName;\n },\n onStart(ctx) {\n if (ctx === ctx.rootContext) {\n initPatchRecorder(ctx);\n }\n },\n onResume(ctx) {\n getPatchRecorder(ctx).recording = true;\n },\n onSuspend(ctx) {\n getPatchRecorder(ctx).recording = false;\n },\n onFinish(ctx, ret) {\n if (ctx === ctx.rootContext) {\n const patchRecorder2 = getPatchRecorder(ctx);\n try {\n if (ret.result === ActionTrackingResult.Throw) {\n const { events } = patchRecorder2;\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i];\n applyPatches(event.target, event.inversePatches, true);\n }\n }\n } finally {\n patchRecorder2.dispose();\n }\n }\n }\n });\n}\nfunction transaction(...args) {\n if (typeof args[1] === \"object\") {\n const ctx = args[1];\n checkDecoratorContext(\"transaction\", ctx.name, ctx.static);\n if (ctx.kind !== \"method\" && ctx.kind !== \"field\") {\n throw failure(`@transaction can only be used on fields or methods}`);\n }\n ctx.addInitializer(function() {\n const modelInstance = this;\n transactionMiddleware({\n model: modelInstance,\n actionName: ctx.name\n });\n });\n } else {\n const target = args[0];\n const propertyKey = args[1];\n checkDecoratorContext(\"transaction\", propertyKey, false);\n addModelClassInitializer(target.constructor, (modelInstance) => {\n transactionMiddleware({\n model: modelInstance,\n actionName: propertyKey\n });\n });\n }\n}\nfunction __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\")\n r = Reflect.decorate(decorators, target, key, desc);\n else\n for (var i = decorators.length - 1; i >= 0; i--)\n if (d = decorators[i])\n r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\ntypeof SuppressedError === \"function\" ? SuppressedError : function(error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\nfunction typesObjectHelper(objFn, frozen2, typeInfoGen) {\n assertIsFunction(objFn, \"objFn\");\n return lateTypeChecker(() => {\n const objectSchema = objFn();\n assertIsObject(objectSchema, \"objectSchema\");\n const schemaEntries = Object.entries(objectSchema);\n const getTypeName = (...recursiveTypeCheckers) => {\n const propsMsg = [];\n for (const [k, unresolvedTc] of schemaEntries) {\n const tc = resolveTypeChecker(unresolvedTc);\n let propTypename = \"...\";\n if (!recursiveTypeCheckers.includes(tc)) {\n propTypename = tc.getTypeName(...recursiveTypeCheckers, tc);\n }\n propsMsg.push(`${k}: ${propTypename};`);\n }\n return `{ ${propsMsg.join(\" \")} }`;\n };\n const applySnapshotProcessor = (obj, mode) => {\n const newObj = {};\n const keys2 = Object.keys(obj);\n for (let i = 0; i < keys2.length; i++) {\n const k = keys2[i];\n const unresolvedTc = objectSchema[k];\n if (unresolvedTc) {\n const tc = resolveTypeChecker(unresolvedTc);\n newObj[k] = mode === \"from\" ? tc.fromSnapshotProcessor(obj[k]) : tc.toSnapshotProcessor(obj[k]);\n } else {\n newObj[k] = obj[k];\n }\n }\n return newObj;\n };\n const thisTc = new TypeChecker(TypeCheckerBaseType.Object, (obj, path, typeCheckedValue) => {\n if (!isObject(obj) || frozen2 && !(obj instanceof Frozen)) {\n return new TypeCheckError(path, getTypeName(thisTc), obj, typeCheckedValue);\n }\n for (const [k, unresolvedTc] of schemaEntries) {\n const tc = resolveTypeChecker(unresolvedTc);\n const objVal = obj[k];\n const valueError = tc.check(objVal, [...path, k], typeCheckedValue);\n if (valueError) {\n return valueError;\n }\n }\n return null;\n }, getTypeName, typeInfoGen, (obj) => {\n if (!isObject(obj)) {\n return null;\n }\n for (const [k, unresolvedTc] of schemaEntries) {\n const tc = resolveTypeChecker(unresolvedTc);\n const objVal = obj[k];\n const valueActualChecker = tc.snapshotType(objVal);\n if (!valueActualChecker) {\n return null;\n }\n }\n return thisTc;\n }, (obj) => {\n return applySnapshotProcessor(obj, \"from\");\n }, (obj) => {\n return applySnapshotProcessor(obj, \"to\");\n });\n return thisTc;\n }, typeInfoGen);\n}\nfunction typesObject(objectFunction) {\n const typeInfoGen = (t) => new ObjectTypeInfo(t, objectFunction);\n return typesObjectHelper(objectFunction, false, typeInfoGen);\n}\nclass ObjectTypeInfo extends TypeInfo {\n constructor(thisType, _objTypeFn) {\n super(thisType);\n __publicField(this, \"_objTypeFn\");\n // memoize to always return the same object\n __publicField(this, \"_props\", lazy(() => {\n const objSchema = this._objTypeFn();\n const propTypes = {};\n Object.keys(objSchema).forEach((propName) => {\n const type = resolveStandardType(objSchema[propName]);\n propTypes[propName] = { type, typeInfo: getTypeInfo(type) };\n });\n return propTypes;\n }));\n this._objTypeFn = _objTypeFn;\n }\n get props() {\n return this._props();\n }\n}\nfunction typesFrozen(dataType) {\n return typesObjectHelper(() => ({\n data: dataType\n }), true, (t) => new FrozenTypeInfo(t, resolveStandardType(dataType)));\n}\nclass FrozenTypeInfo extends TypeInfo {\n constructor(thisType, dataType) {\n super(thisType);\n __publicField(this, \"dataType\");\n this.dataType = dataType;\n }\n get dataTypeInfo() {\n return getTypeInfo(this.dataType);\n }\n}\nconst unchecked = new TypeChecker(TypeCheckerBaseType.Any, null, () => \"any\", (t) => new UncheckedTypeInfo(t), () => unchecked, identityFn, identityFn);\nfunction typesUnchecked() {\n return unchecked;\n}\nclass UncheckedTypeInfo extends TypeInfo {\n}\nfunction typesOr(dispatcherOrType, ...moreOrTypes) {\n const orTypes = moreOrTypes.slice();\n let finalDispatcher;\n const firstTypeChecker = resolveStandardTypeNoThrow(dispatcherOrType);\n if (firstTypeChecker) {\n orTypes.unshift(firstTypeChecker);\n } else {\n const dispatcher = dispatcherOrType;\n finalDispatcher = (sn) => {\n const type = dispatcher(sn);\n const typeChecker = resolveTypeChecker(type);\n return typeChecker;\n };\n }\n if (orTypes.length <= 0) {\n throw failure(\"or type must have at least 1 possible type\");\n }\n const typeInfoGen = (t) => new OrTypeInfo(t, orTypes.map(resolveStandardType));\n return lateTypeChecker(() => {\n const checkers = orTypes.map(resolveTypeChecker);\n if (checkers.some((tc) => tc.unchecked)) {\n return typesUnchecked();\n }\n const getTypeName = (...recursiveTypeCheckers) => {\n const typeNames = checkers.map((tc) => {\n if (recursiveTypeCheckers.includes(tc)) {\n return \"...\";\n }\n return tc.getTypeName(...recursiveTypeCheckers, tc);\n });\n return typeNames.join(\" | \");\n };\n let thisTcBaseType;\n if (checkers.some((c) => c.baseType !== checkers[0].baseType)) {\n thisTcBaseType = TypeCheckerBaseType.Any;\n } else {\n thisTcBaseType = checkers[0].baseType;\n }\n const thisTc = new TypeChecker(thisTcBaseType, (value, path, typeCheckedValue) => {\n const someMatchingType = checkers.some((tc) => !tc.check(value, path, typeCheckedValue));\n if (someMatchingType) {\n return null;\n } else {\n return new TypeCheckError(path, getTypeName(thisTc), value, typeCheckedValue);\n }\n }, getTypeName, typeInfoGen, (value) => {\n const valueBaseType = getTypeCheckerBaseTypeFromValue(value);\n const checkerForBaseType = checkers.filter((c) => c.baseType === valueBaseType || c.baseType === TypeCheckerBaseType.Any);\n if (checkerForBaseType.length === 1 && checkerForBaseType[0].baseType === valueBaseType) {\n return checkerForBaseType[0];\n }\n for (let i = 0; i < checkerForBaseType.length; i++) {\n const matchingType = checkerForBaseType[i].snapshotType(value);\n if (matchingType) {\n return matchingType;\n }\n }\n return null;\n }, (sn) => {\n const type = finalDispatcher ? finalDispatcher(sn) : thisTc.snapshotType(sn);\n if (!type) {\n throw failure(`snapshot '${JSON.stringify(sn)}' does not match the following type: ${getTypeName(thisTc)}`);\n }\n return type.fromSnapshotProcessor(sn);\n }, (sn) => {\n const type = finalDispatcher ? finalDispatcher(sn) : thisTc.snapshotType(sn);\n if (!type) {\n throw failure(`snapshot '${JSON.stringify(sn)}' does not match the following type: ${getTypeName(thisTc)}`);\n }\n return type.toSnapshotProcessor(sn);\n });\n return thisTc;\n }, typeInfoGen);\n}\nclass OrTypeInfo extends TypeInfo {\n constructor(thisType, orTypes) {\n super(thisType);\n __publicField(this, \"orTypes\");\n // memoize to always return the same array on the getter\n __publicField(this, \"_orTypeInfos\", lazy(() => this.orTypes.map(getTypeInfo)));\n this.orTypes = orTypes;\n }\n get orTypeInfos() {\n return this._orTypeInfos();\n }\n}\nconst noDefaultValueSymbol = Symbol(\"noDefaultValue\");\nconst tPropCache = /* @__PURE__ */ new WeakMap();\nfunction getOrCreateTProp(type, defKey, createTProp) {\n let defValueCache = tPropCache.get(type);\n if (!defValueCache) {\n defValueCache = /* @__PURE__ */ new Map();\n tPropCache.set(type, defValueCache);\n }\n let prop2 = defValueCache.get(defKey);\n if (!prop2) {\n prop2 = createTProp();\n defValueCache.set(defKey, prop2);\n }\n return prop2;\n}\nfunction tProp(typeOrDefaultValue, def) {\n switch (typeof typeOrDefaultValue) {\n case \"string\":\n return tProp(typesString, typeOrDefaultValue);\n case \"number\":\n return tProp(typesNumber, typeOrDefaultValue);\n case \"boolean\":\n return tProp(typesBoolean, typeOrDefaultValue);\n }\n const hasDefaultValue = arguments.length >= 2;\n const typeChecker = resolveStandardType(typeOrDefaultValue);\n return getOrCreateTProp(typeChecker, hasDefaultValue ? def : noDefaultValueSymbol, () => {\n const fromSnapshotTypeChecker = hasDefaultValue ? typesOr(typeChecker, typesUndefined, typesNull) : typeChecker;\n const newProp = Object.create(hasDefaultValue ? prop(def) : prop());\n Object.assign(newProp, {\n _typeChecker: typeChecker,\n _fromSnapshotProcessor: tPropFromSnapshotProcessor.bind(void 0, fromSnapshotTypeChecker),\n _toSnapshotProcessor: tPropToSnapshotProcessor.bind(void 0, typeChecker)\n });\n return newProp;\n });\n}\nfunction tPropFromSnapshotProcessor(fromSnapshotTypeChecker, sn) {\n const fsnp = resolveTypeChecker(fromSnapshotTypeChecker).fromSnapshotProcessor;\n return fsnp ? fsnp(sn) : sn;\n}\nfunction tPropToSnapshotProcessor(typeChecker, sn) {\n const tsnp = resolveTypeChecker(typeChecker).toSnapshotProcessor;\n return tsnp ? tsnp(sn) : sn;\n}\nfunction chainFns(...fns) {\n const definedFns = fns.filter((fn) => !!fn);\n if (definedFns.length <= 0)\n return void 0;\n const chainedFn = (v, ...args) => {\n let ret = v;\n for (let i = 0; i < definedFns.length; i++) {\n ret = definedFns[i](ret, ...args);\n }\n return ret;\n };\n return chainedFn;\n}\nfunction assertIsClassOrDataModelClass(model2, argName, customErrMsg = \"must be a class or data model class\") {\n if (!isModelClass(model2) && !isDataModelClass(model2)) {\n throw failure(`${argName} ${customErrMsg}`);\n }\n}\nfunction getModelInstanceDataField(model2, modelProp, modelPropName) {\n const value = model2.$[modelPropName];\n if (!modelProp._transform) {\n return value;\n }\n return modelProp._transform.transform(value, model2, modelPropName, (newValue) => {\n applySet(model2.$, modelPropName, newValue);\n });\n}\nfunction setModelInstanceDataField(model2, modelProp, modelPropName, value) {\n if (!(modelInitializedSymbol in model2)) {\n return;\n }\n if (modelProp._setter === \"assign\" && !getCurrentActionContext()) {\n applySet(model2, modelPropName, value);\n return;\n }\n let untransformedValue = modelProp._transform ? modelProp._transform.untransform(value, model2, modelPropName) : value;\n if (untransformedValue == null) {\n const defaultValue = getModelPropDefaultValue(modelProp);\n if (defaultValue !== noDefaultValue) {\n untransformedValue = defaultValue;\n }\n }\n model2.$[modelPropName] = untransformedValue;\n}\nconst idGenerator = () => getGlobalConfig().modelIdGenerator();\nconst tPropForId = tProp(typesString, idGenerator);\ntPropForId._isId = true;\nconst propForId = prop(idGenerator);\npropForId._isId = true;\nfunction sharedInternalModel({ modelProps, baseModel, type, valueType, fromSnapshotProcessor, toSnapshotProcessor }) {\n assertIsObject(modelProps, \"modelProps\");\n modelProps = Object.assign(/* @__PURE__ */ Object.create(null), modelProps);\n if (baseModel) {\n assertIsClassOrDataModelClass(baseModel, \"baseModel\");\n const unwrappedClass = baseModel[modelUnwrappedClassSymbol];\n if (unwrappedClass) {\n baseModel = unwrappedClass;\n assertIsClassOrDataModelClass(baseModel, \"baseModel\");\n }\n }\n const composedModelProps = modelProps;\n if (baseModel) {\n const oldModelProps = getInternalModelClassPropsInfo(baseModel);\n for (const oldModelPropKey of Object.keys(oldModelProps)) {\n if (!modelProps[oldModelPropKey]) {\n composedModelProps[oldModelPropKey] = oldModelProps[oldModelPropKey];\n }\n }\n }\n const idKeys = Object.keys(composedModelProps).filter((k) => {\n const p = composedModelProps[k];\n return p._isId;\n });\n if (type === \"class\") {\n if (idKeys.length > 1) {\n throw failure(`expected at most one idProp but got many: ${JSON.stringify(idKeys)}`);\n }\n } else {\n if (idKeys.length >= 1) {\n throw failure(`expected no idProp but got some: ${JSON.stringify(idKeys)}`);\n }\n }\n const needsTypeChecker = Object.values(composedModelProps).some((mp) => !!mp._typeChecker);\n let idKey;\n if (idKeys.length >= 1) {\n idKey = idKeys[0];\n const idProp2 = composedModelProps[idKey];\n let baseProp2 = needsTypeChecker ? tPropForId : propForId;\n switch (idProp2 == null ? void 0 : idProp2._setter) {\n case true:\n baseProp2 = baseProp2.withSetter();\n break;\n case \"assign\":\n baseProp2 = baseProp2.withSetter(\"assign\");\n break;\n }\n composedModelProps[idKey] = baseProp2;\n }\n let dataTypeChecker;\n if (needsTypeChecker) {\n const typeCheckerObj = {};\n for (const [k, mp] of Object.entries(composedModelProps)) {\n typeCheckerObj[k] = !mp._typeChecker ? typesUnchecked() : mp._typeChecker;\n }\n dataTypeChecker = typesObject(() => typeCheckerObj);\n }\n const base = baseModel != null ? baseModel : type === \"class\" ? BaseModel : BaseDataModel;\n const basePropNames = type === \"class\" ? baseModelPropNames : baseDataModelPropNames;\n let propsToDeleteFromBase;\n function ThisModel(initialData, constructorOptions) {\n var _a2;\n const modelClass2 = (_a2 = constructorOptions == null ? void 0 : constructorOptions.modelClass) != null ? _a2 : this.constructor;\n const baseModel2 = new base(initialData, {\n ...constructorOptions,\n modelClass: modelClass2\n });\n if (!propsToDeleteFromBase) {\n propsToDeleteFromBase = Object.keys(composedModelProps).filter((p) => !basePropNames.has(p) && Object.hasOwn(baseModel2, p));\n }\n propsToDeleteFromBase.forEach((prop2) => delete baseModel2[prop2]);\n return baseModel2;\n }\n Object.assign(ThisModel, base);\n const initializers = base[modelInitializersSymbol];\n if (initializers) {\n ThisModel[modelInitializersSymbol] = initializers.slice();\n }\n setInternalModelClassPropsInfo(ThisModel, composedModelProps);\n if (type === \"class\") {\n const metadata = {\n dataType: dataTypeChecker,\n modelIdProperty: idKey,\n valueType\n };\n ThisModel[modelMetadataSymbol] = metadata;\n } else {\n const metadata = {\n dataType: dataTypeChecker\n };\n ThisModel[modelMetadataSymbol] = metadata;\n }\n const newPrototype = Object.create(base.prototype);\n ThisModel.prototype = new Proxy(newPrototype, {\n get(target, p, receiver) {\n if (receiver === ThisModel.prototype) {\n return target[p];\n }\n const modelProp = !basePropNames.has(p) && composedModelProps[p];\n return modelProp ? getModelInstanceDataField(receiver, modelProp, p) : Reflect.get(target, p, receiver);\n },\n set(target, p, v, receiver) {\n if (receiver === ThisModel.prototype) {\n target[p] = v;\n return true;\n }\n const modelProp = !basePropNames.has(p) && composedModelProps[p];\n if (modelProp) {\n setModelInstanceDataField(receiver, modelProp, p, v);\n return true;\n }\n return Reflect.set(target, p, v, receiver);\n },\n has(target, p) {\n const modelProp = !basePropNames.has(p) && composedModelProps[p];\n return !!modelProp || Reflect.has(target, p);\n }\n });\n newPrototype.constructor = ThisModel;\n for (const [propName, propData] of Object.entries(modelProps)) {\n if (propData._setter === true) {\n const setterName = propNameToSetterName(propName);\n const newPropDescriptor = modelAction(newPrototype, setterName, {\n value: function(value) {\n this[propName] = value;\n },\n writable: true,\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(newPrototype, setterName, newPropDescriptor);\n }\n }\n const modelPropsFromSnapshotProcessor = getModelPropsFromSnapshotProcessor(composedModelProps);\n const modelPropsToSnapshotProcessor = getModelPropsToSnapshotProcessor(composedModelProps);\n if (fromSnapshotProcessor) {\n const fn = fromSnapshotProcessor;\n fromSnapshotProcessor = (sn) => {\n return {\n ...fn(sn),\n [modelTypeKey]: sn[modelTypeKey]\n };\n };\n }\n if (toSnapshotProcessor) {\n const fn = toSnapshotProcessor;\n toSnapshotProcessor = (sn, modelInstance) => {\n return {\n ...fn(sn, modelInstance),\n [modelTypeKey]: sn[modelTypeKey]\n };\n };\n }\n ThisModel.fromSnapshotProcessor = chainFns(fromSnapshotProcessor, modelPropsFromSnapshotProcessor);\n ThisModel.toSnapshotProcessor = chainFns(modelPropsToSnapshotProcessor, toSnapshotProcessor);\n return ThisModel;\n}\nfunction getModelPropsFromSnapshotProcessor(composedModelProps) {\n const propsWithFromSnapshotProcessor = Object.entries(composedModelProps).filter(([_propName, propData]) => propData._fromSnapshotProcessor);\n if (propsWithFromSnapshotProcessor.length <= 0) {\n return void 0;\n }\n return (sn) => {\n const newSn = { ...sn };\n for (const [propName, propData] of propsWithFromSnapshotProcessor) {\n if (propData._fromSnapshotProcessor) {\n newSn[propName] = propData._fromSnapshotProcessor(sn[propName]);\n }\n }\n return newSn;\n };\n}\nfunction getModelPropsToSnapshotProcessor(composedModelProps) {\n const propsWithToSnapshotProcessor = Object.entries(composedModelProps).filter(([_propName, propData]) => propData._toSnapshotProcessor);\n if (propsWithToSnapshotProcessor.length <= 0) {\n return void 0;\n }\n return (sn) => {\n const newSn = { ...sn };\n for (const [propName, propData] of propsWithToSnapshotProcessor) {\n if (propData._toSnapshotProcessor) {\n newSn[propName] = propData._toSnapshotProcessor(sn[propName]);\n }\n }\n return newSn;\n };\n}\nfunction ExtendedModel(...args) {\n let baseModel;\n let modelProps;\n let modelOptions;\n if (isModelClass(args[0])) {\n baseModel = args[0];\n modelProps = args[1];\n modelOptions = args[2];\n } else {\n const gen = args[0]();\n baseModel = gen.baseModel;\n modelProps = gen.props;\n modelOptions = args[1];\n }\n assertIsModelClass(baseModel, \"baseModel\");\n return internalModel$1(modelProps, baseModel, modelOptions);\n}\nfunction Model(fnModelPropsOrModelProps, modelOptions) {\n const modelProps = typeof fnModelPropsOrModelProps === \"function\" ? fnModelPropsOrModelProps() : fnModelPropsOrModelProps;\n return internalModel$1(modelProps, void 0, modelOptions);\n}\nfunction internalModel$1(modelProps, baseModel, modelOptions) {\n var _a2;\n return sharedInternalModel({\n modelProps,\n baseModel,\n type: \"class\",\n valueType: (_a2 = modelOptions == null ? void 0 : modelOptions.valueType) != null ? _a2 : false,\n fromSnapshotProcessor: modelOptions == null ? void 0 : modelOptions.fromSnapshotProcessor,\n toSnapshotProcessor: modelOptions == null ? void 0 : modelOptions.toSnapshotProcessor\n });\n}\nconst model = (name) => (clazz, ...args) => {\n const ctx = typeof args[1] === \"object\" ? args[1] : void 0;\n return internalModel(name, clazz, ctx == null ? void 0 : ctx.addInitializer);\n};\nconst afterClassInitializationData = /* @__PURE__ */ new WeakMap();\nconst runAfterClassInitialization = (target, instance) => {\n runLateInitializationFunctions(instance, runAfterNewSymbol);\n const tag2 = afterClassInitializationData.get(target);\n if (!tag2.makeObservableFailed && getMobxVersion() >= 6) {\n try {\n mobx6.makeObservable(instance);\n } catch (e) {\n tag2.makeObservableFailed = true;\n const err = e;\n if (err.message !== \"[MobX] No annotations were passed to makeObservable, but no decorator members have been found either\" && err.message !== \"[MobX] No annotations were passed to makeObservable, but no decorated members have been found either\") {\n throw err;\n }\n }\n }\n addHiddenProp(instance, modelInitializedSymbol, true, false);\n runLateInitializationFunctions(instance, runBeforeOnInitSymbol);\n if (tag2.type === \"class\" && instance.onInit) {\n wrapModelMethodInActionIfNeeded(instance, \"onInit\", HookAction.OnInit);\n instance.onInit();\n }\n if (tag2.type === \"data\" && instance.onLazyInit) {\n wrapModelMethodInActionIfNeeded(instance, \"onLazyInit\", HookAction.OnLazyInit);\n instance.onLazyInit();\n }\n};\nconst proxyClassHandler = {\n construct(clazz, args) {\n const instance = new clazz(...args);\n runAfterClassInitialization(clazz, instance);\n return instance;\n }\n};\nconst internalModel = (name, clazz, addInitializer) => {\n const type = isModelClass(clazz) ? \"class\" : isDataModelClass(clazz) ? \"data\" : void 0;\n if (!type) {\n throw failure(`clazz must be a class that extends from Model/DataModel`);\n }\n if (modelInfoByName[name]) {\n if (getGlobalConfig().showDuplicateModelNameWarnings) {\n logWarning(\"warn\", `a model with name \"${name}\" already exists (if you are using hot-reloading you may safely ignore this warning)`, `duplicateModelName - ${name}`);\n }\n }\n if (modelUnwrappedClassSymbol in clazz && clazz[modelUnwrappedClassSymbol] === clazz) {\n throw failure(\"a class already decorated with `@model` cannot be re-decorated\");\n }\n clazz.toString = () => `class ${clazz.name}#${name}`;\n if (type === \"class\") {\n clazz[modelTypeKey] = name;\n }\n afterClassInitializationData.set(clazz, { makeObservableFailed: false, type });\n if (addInitializer) {\n addInitializer(function() {\n runAfterClassInitialization(clazz, this);\n });\n const modelInfo = {\n name,\n class: clazz\n };\n modelInfoByName[name] = modelInfo;\n modelInfoByClass.set(clazz, modelInfo);\n runLateInitializationFunctions(clazz, runAfterModelDecoratorSymbol);\n return void 0;\n } else {\n const proxyClass = new Proxy(clazz, proxyClassHandler);\n proxyClass.prototype.constructor = proxyClass;\n proxyClass[modelUnwrappedClassSymbol] = clazz;\n const modelInfo = {\n name,\n class: proxyClass\n };\n modelInfoByName[name] = modelInfo;\n modelInfoByClass.set(proxyClass, modelInfo);\n modelInfoByClass.set(clazz, modelInfo);\n runLateInitializationFunctions(clazz, runAfterModelDecoratorSymbol);\n return proxyClass;\n }\n};\nfunction tsDecorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\")\n r = Reflect.decorate(decorators, target, key, desc);\n else\n for (var i = decorators.length - 1; i >= 0; i--)\n if (d = decorators[i])\n r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\nfunction decoratedModel(name, clazz, decorators) {\n for (const [k, decorator] of Object.entries(decorators)) {\n const prototypeValueDesc = Object.getOwnPropertyDescriptor(clazz.prototype, k);\n tsDecorate(Array.isArray(decorator) ? decorator : [decorator], clazz.prototype, k, prototypeValueDesc ? prototypeValueDesc : void 0);\n }\n return name ? model(name)(clazz) : clazz;\n}\nfunction typesArray(itemType) {\n const typeInfoGen = (t) => new ArrayTypeInfo(t, resolveStandardType(itemType));\n return lateTypeChecker(() => {\n const itemChecker = resolveTypeChecker(itemType);\n const getTypeName = (...recursiveTypeCheckers) => `Array<${itemChecker.getTypeName(...recursiveTypeCheckers, itemChecker)}>`;\n const thisTc = new TypeChecker(TypeCheckerBaseType.Array, (array, path, typeCheckedValue) => {\n if (!isArray(array)) {\n return new TypeCheckError(path, getTypeName(thisTc), array, typeCheckedValue);\n }\n if (!itemChecker.unchecked) {\n for (let i = 0; i < array.length; i++) {\n const itemError = itemChecker.check(array[i], [...path, i], typeCheckedValue);\n if (itemError) {\n return itemError;\n }\n }\n }\n return null;\n }, getTypeName, typeInfoGen, (array) => {\n if (!isArray(array)) {\n return null;\n }\n if (!itemChecker.unchecked) {\n for (let i = 0; i < array.length; i++) {\n const itemActualChecker = itemChecker.snapshotType(array[i]);\n if (!itemActualChecker) {\n return null;\n }\n }\n }\n return thisTc;\n }, (sn) => {\n if (itemChecker.unchecked) {\n return sn;\n }\n return sn.map((item) => itemChecker.fromSnapshotProcessor(item));\n }, (sn) => {\n if (itemChecker.unchecked) {\n return sn;\n }\n return sn.map((item) => itemChecker.toSnapshotProcessor(item));\n });\n return thisTc;\n }, typeInfoGen);\n}\nclass ArrayTypeInfo extends TypeInfo {\n constructor(thisType, itemType) {\n super(thisType);\n __publicField(this, \"itemType\");\n this.itemType = itemType;\n }\n get itemTypeInfo() {\n return getTypeInfo(this.itemType);\n }\n}\nvar UndoEventType;\n(function(UndoEventType2) {\n UndoEventType2[\"Single\"] = \"single\";\n UndoEventType2[\"Group\"] = \"group\";\n})(UndoEventType || (UndoEventType = {}));\nfunction toSingleEvents(event, reverse) {\n if (event.type === UndoEventType.Single)\n return [event];\n else {\n const array = [];\n for (const e of event.events) {\n if (reverse) {\n array.unshift(...toSingleEvents(e, true));\n } else {\n array.push(...toSingleEvents(e, false));\n }\n }\n return array;\n }\n}\nlet UndoStore = class UndoStore2 extends Model({\n // TODO: add proper type checking to undo store\n undoEvents: tProp(typesArray(typesUnchecked()), () => []),\n redoEvents: tProp(typesArray(typesUnchecked()), () => [])\n}) {\n constructor() {\n super(...arguments);\n __publicField(this, \"_groupStack\", []);\n }\n /**\n * @ignore\n */\n _clearUndo() {\n withoutUndo(() => {\n this.undoEvents.length = 0;\n });\n }\n /**\n * @ignore\n */\n _clearRedo() {\n withoutUndo(() => {\n this.redoEvents.length = 0;\n });\n }\n /**\n * @ignore\n */\n enforceMaxLevels({ maxUndoLevels, maxRedoLevels }) {\n if (maxUndoLevels !== void 0) {\n while (this.undoEvents.length > maxUndoLevels) {\n this.undoEvents.shift();\n }\n }\n if (maxRedoLevels !== void 0) {\n while (this.redoEvents.length > maxRedoLevels) {\n this.redoEvents.shift();\n }\n }\n }\n /**\n * @ignore\n */\n _undo({ maxRedoLevels }) {\n withoutUndo(() => {\n const event = this.undoEvents.pop();\n this.redoEvents.push(event);\n this.enforceMaxLevels({ maxRedoLevels });\n });\n }\n /**\n * @ignore\n */\n _redo({ maxUndoLevels }) {\n withoutUndo(() => {\n const event = this.redoEvents.pop();\n this.undoEvents.push(event);\n this.enforceMaxLevels({ maxUndoLevels });\n });\n }\n /**\n * @ignore\n */\n _addUndo({ event, maxUndoLevels }) {\n withoutUndo(() => {\n this.undoEvents.push(event);\n this.redoEvents.length = 0;\n this.enforceMaxLevels({ maxUndoLevels });\n });\n }\n /**\n * @ignore\n */\n _addUndoToParentGroup(parentGroup, event) {\n parentGroup.events.push(event);\n }\n /**\n * @ignore\n */\n get _currentGroup() {\n return this._groupStack[this._groupStack.length - 1];\n }\n /**\n * @ignore\n */\n _startGroup(groupName, startRunning, options) {\n var _a2;\n let running = false;\n let ended = false;\n const parentGroup = this._currentGroup;\n const group = {\n type: UndoEventType.Group,\n groupName,\n events: []\n };\n const attachedStateBeforeEvent = parentGroup ? void 0 : (_a2 = options == null ? void 0 : options.attachedState) == null ? void 0 : _a2.save();\n const api = {\n pause: () => {\n if (ended) {\n throw failure(\"cannot pause a group when it is already ended\");\n }\n if (!running) {\n throw failure(\"cannot pause a group when it is not running\");\n }\n if (this._currentGroup !== group) {\n throw failure(\"group out of order\");\n }\n this._groupStack.pop();\n running = false;\n },\n resume: () => {\n if (ended) {\n throw failure(\"cannot resume a group when it is already ended\");\n }\n if (running) {\n throw failure(\"cannot resume a group when it is already running\");\n }\n this._groupStack.push(group);\n running = true;\n },\n end: () => {\n var _a3;\n if (running) {\n api.pause();\n }\n ended = true;\n if (parentGroup) {\n this._addUndoToParentGroup(parentGroup, group);\n } else {\n this._addUndo({\n event: {\n ...group,\n attachedState: {\n beforeEvent: attachedStateBeforeEvent,\n afterEvent: (_a3 = options == null ? void 0 : options.attachedState) == null ? void 0 : _a3.save()\n }\n },\n maxUndoLevels: options == null ? void 0 : options.maxUndoLevels\n });\n }\n }\n };\n if (startRunning) {\n api.resume();\n }\n return api;\n }\n};\n__decorate([\n modelAction\n], UndoStore.prototype, \"_clearUndo\", null);\n__decorate([\n modelAction\n], UndoStore.prototype, \"_clearRedo\", null);\n__decorate([\n modelAction\n], UndoStore.prototype, \"_undo\", null);\n__decorate([\n modelAction\n], UndoStore.prototype, \"_redo\", null);\n__decorate([\n modelAction\n], UndoStore.prototype, \"_addUndo\", null);\nUndoStore = __decorate([\n model(`${namespace$2}/UndoStore`)\n], UndoStore);\nclass UndoManager {\n /**\n * Creates an instance of `UndoManager`.\n * Do not use directly, use `undoMiddleware` instead.\n *\n * @param disposer\n * @param subtreeRoot\n * @param [store]\n */\n constructor(disposer, subtreeRoot, store, options) {\n __publicField(this, \"disposer\");\n __publicField(this, \"subtreeRoot\");\n __publicField(this, \"options\");\n /**\n * The store currently being used to store undo/redo action events.\n */\n __publicField(this, \"store\");\n __publicField(this, \"_isUndoRecordingDisabled\", false);\n this.disposer = disposer;\n this.subtreeRoot = subtreeRoot;\n this.options = options;\n if (getMobxVersion() >= 6) {\n mobx6.makeObservable(this);\n }\n this.store = store != null ? store : new UndoStore({});\n }\n /**\n * The undo stack, where the first operation to undo will be the last of the array.\n * Do not manipulate this array directly.\n */\n get undoQueue() {\n return this.store.undoEvents;\n }\n /**\n * The redo stack, where the first operation to redo will be the last of the array.\n * Do not manipulate this array directly.\n */\n get redoQueue() {\n return this.store.redoEvents;\n }\n /**\n * The number of undo actions available.\n */\n get undoLevels() {\n return this.undoQueue.length;\n }\n /**\n * If undo can be performed (if there is at least one undo action available).\n */\n get canUndo() {\n return this.undoLevels > 0;\n }\n /**\n * Clears the undo queue.\n */\n clearUndo() {\n this.store._clearUndo();\n }\n /**\n * The number of redo actions available.\n */\n get redoLevels() {\n return this.redoQueue.length;\n }\n /**\n * If redo can be performed (if there is at least one redo action available)\n */\n get canRedo() {\n return this.redoLevels > 0;\n }\n /**\n * Clears the redo queue.\n */\n clearRedo() {\n this.store._clearRedo();\n }\n /**\n * Undoes the last action.\n * Will throw if there is no action to undo.\n */\n undo() {\n var _a2;\n if (!this.canUndo) {\n throw failure(\"nothing to undo\");\n }\n const event = this.undoQueue[this.undoQueue.length - 1];\n withoutUndo(() => {\n var _a3, _b2, _c2;\n toSingleEvents(event, true).forEach((e) => {\n applyPatches(this.subtreeRoot, e.inversePatches, true);\n });\n if ((_a3 = event.attachedState) == null ? void 0 : _a3.beforeEvent) {\n (_c2 = (_b2 = this.options) == null ? void 0 : _b2.attachedState) == null ? void 0 : _c2.restore(event.attachedState.beforeEvent);\n }\n });\n this.store._undo({ maxRedoLevels: (_a2 = this.options) == null ? void 0 : _a2.maxRedoLevels });\n }\n /**\n * Redoes the previous action.\n * Will throw if there is no action to redo.\n */\n redo() {\n var _a2;\n if (!this.canRedo) {\n throw failure(\"nothing to redo\");\n }\n const event = this.redoQueue[this.redoQueue.length - 1];\n withoutUndo(() => {\n var _a3, _b2, _c2;\n toSingleEvents(event, false).forEach((e) => {\n applyPatches(this.subtreeRoot, e.patches);\n });\n if ((_a3 = event.attachedState) == null ? void 0 : _a3.afterEvent) {\n (_c2 = (_b2 = this.options) == null ? void 0 : _b2.attachedState) == null ? void 0 : _c2.restore(event.attachedState.afterEvent);\n }\n });\n this.store._redo({ maxUndoLevels: (_a2 = this.options) == null ? void 0 : _a2.maxUndoLevels });\n }\n /**\n * Disposes the undo middleware.\n */\n dispose() {\n this.disposer();\n }\n /**\n * Returns if undo recording is currently disabled or not for this particular `UndoManager`.\n */\n get isUndoRecordingDisabled() {\n return this._isUndoRecordingDisabled;\n }\n /**\n * Skips the undo recording mechanism for the code block that gets run synchronously inside.\n *\n * @typeparam T Code block return type.\n * @param fn Code block to run.\n * @returns The value returned by the code block.\n */\n withoutUndo(fn) {\n const savedUndoDisabled = this._isUndoRecordingDisabled;\n this._isUndoRecordingDisabled = true;\n try {\n return fn();\n } finally {\n this._isUndoRecordingDisabled = savedUndoDisabled;\n }\n }\n /**\n * Creates a custom group that can be continued multiple times and then ended.\n * @param groupName Optional group name.\n * @returns An API to continue/end the group.\n */\n createGroup(groupName) {\n const group = this.store._startGroup(groupName, false, this.options);\n return {\n continue(fn) {\n group.resume();\n try {\n return fn();\n } finally {\n group.pause();\n }\n },\n end() {\n group.end();\n }\n };\n }\n withGroup(arg1, arg2) {\n let groupName;\n let fn;\n if (typeof arg1 === \"string\") {\n groupName = arg1;\n fn = arg2;\n } else {\n fn = arg1;\n }\n const group = this.store._startGroup(groupName, true, this.options);\n try {\n return fn();\n } finally {\n group.end();\n }\n }\n withGroupFlow(arg1, arg2) {\n let groupName;\n let fn;\n if (typeof arg1 === \"string\") {\n groupName = arg1;\n fn = arg2;\n } else {\n fn = arg1;\n }\n const gen = fn();\n const group = this.store._startGroup(groupName, false, this.options);\n const genNext = gen.next.bind(gen);\n const genThrow = gen.throw.bind(gen);\n const promise = new Promise(function(resolve, reject) {\n function onFulfilled(res) {\n group.resume();\n let ret;\n try {\n ret = genNext(res);\n } catch (e) {\n group.end();\n reject(e);\n return;\n }\n group.pause();\n next(ret);\n }\n function onRejected(err) {\n group.resume();\n let ret;\n try {\n ret = genThrow(err);\n } catch (e) {\n group.end();\n reject(e);\n return;\n }\n group.pause();\n next(ret);\n }\n function next(ret) {\n if (ret && typeof ret.then === \"function\") {\n ret.then(next, reject);\n } else if (ret.done) {\n group.end();\n resolve(ret.value);\n } else {\n Promise.resolve(ret.value).then(onFulfilled, onRejected);\n }\n }\n onFulfilled(void 0);\n });\n return promise;\n }\n}\n__decorate([\n computed\n], UndoManager.prototype, \"undoQueue\", null);\n__decorate([\n computed\n], UndoManager.prototype, \"redoQueue\", null);\n__decorate([\n computed\n], UndoManager.prototype, \"undoLevels\", null);\n__decorate([\n computed\n], UndoManager.prototype, \"canUndo\", null);\n__decorate([\n action\n], UndoManager.prototype, \"clearUndo\", null);\n__decorate([\n computed\n], UndoManager.prototype, \"redoLevels\", null);\n__decorate([\n computed\n], UndoManager.prototype, \"canRedo\", null);\n__decorate([\n action\n], UndoManager.prototype, \"clearRedo\", null);\n__decorate([\n action\n], UndoManager.prototype, \"undo\", null);\n__decorate([\n action\n], UndoManager.prototype, \"redo\", null);\nfunction undoMiddleware(subtreeRoot, store, options) {\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n let manager;\n const patchRecorderSymbol = Symbol(\"patchRecorder\");\n function initPatchRecorder(ctx) {\n var _a2;\n const group = manager.store._currentGroup;\n const patchRecorderData = {\n recorder: patchRecorder(subtreeRoot, {\n recording: false,\n filter: () => {\n return !_isGlobalUndoRecordingDisabled && !manager.isUndoRecordingDisabled;\n }\n }),\n recorderStack: 0,\n undoRootContext: ctx,\n group,\n attachedStateBeforeEvent: (_a2 = options == null ? void 0 : options.attachedState) == null ? void 0 : _a2.save()\n };\n ctx.rootContext.data[patchRecorderSymbol] = patchRecorderData;\n }\n function getPatchRecorderData(ctx) {\n return ctx.rootContext.data[patchRecorderSymbol];\n }\n const middlewareDisposer = actionTrackingMiddleware(subtreeRoot, {\n onStart(ctx) {\n if (!getPatchRecorderData(ctx)) {\n initPatchRecorder(ctx);\n }\n },\n onResume(ctx) {\n const patchRecorderData = getPatchRecorderData(ctx);\n patchRecorderData.recorderStack++;\n patchRecorderData.recorder.recording = patchRecorderData.recorderStack > 0;\n },\n onSuspend(ctx) {\n const patchRecorderData = getPatchRecorderData(ctx);\n patchRecorderData.recorderStack--;\n patchRecorderData.recorder.recording = patchRecorderData.recorderStack > 0;\n },\n onFinish(ctx) {\n var _a2;\n const patchRecorderData = getPatchRecorderData(ctx);\n if (patchRecorderData && patchRecorderData.undoRootContext === ctx) {\n const patchRecorder2 = patchRecorderData.recorder;\n if (patchRecorder2.events.length > 0) {\n const patches = [];\n const inversePatches = [];\n for (const event2 of patchRecorder2.events) {\n patches.push(...event2.patches);\n inversePatches.push(...event2.inversePatches);\n }\n const event = {\n type: UndoEventType.Single,\n targetPath: fastGetRootPath(ctx.target).path,\n actionName: ctx.actionName,\n patches,\n inversePatches\n };\n const parentGroup = patchRecorderData.group;\n if (parentGroup) {\n manager.store._addUndoToParentGroup(parentGroup, event);\n } else {\n manager.store._addUndo({\n event: {\n ...event,\n attachedState: {\n beforeEvent: patchRecorderData.attachedStateBeforeEvent,\n afterEvent: (_a2 = options == null ? void 0 : options.attachedState) == null ? void 0 : _a2.save()\n }\n },\n maxUndoLevels: options == null ? void 0 : options.maxUndoLevels\n });\n }\n }\n patchRecorder2.dispose();\n }\n }\n });\n manager = new UndoManager(middlewareDisposer, subtreeRoot, store, options);\n return manager;\n}\nlet _isGlobalUndoRecordingDisabled = false;\nfunction isGlobalUndoRecordingDisabled() {\n return _isGlobalUndoRecordingDisabled;\n}\nfunction withoutUndo(fn) {\n const savedUndoDisabled = _isGlobalUndoRecordingDisabled;\n _isGlobalUndoRecordingDisabled = true;\n try {\n return fn();\n } finally {\n _isGlobalUndoRecordingDisabled = savedUndoDisabled;\n }\n}\nfunction resolveContextValue(contextValue) {\n if (contextValue.type === \"value\") {\n return contextValue.value;\n } else {\n return contextValue.value.get();\n }\n}\nconst createContextValueAtom = () => createAtom(\"contextValue\");\nclass ContextClass {\n constructor(defaultValue) {\n __publicField(this, \"defaultContextValue\", observable.box(void 0, { deep: false }));\n __publicField(this, \"overrideContextValue\", observable.box(void 0, {\n deep: false\n }));\n __publicField(this, \"nodeContextValue\", /* @__PURE__ */ new WeakMap());\n __publicField(this, \"nodeAtom\", /* @__PURE__ */ new WeakMap());\n __publicField(this, \"setDefault\", action((value) => {\n this.defaultContextValue.set({\n type: \"value\",\n value\n });\n }));\n __publicField(this, \"setDefaultComputed\", action((valueFn) => {\n this.defaultContextValue.set({\n type: \"computed\",\n value: computed(valueFn)\n });\n }));\n __publicField(this, \"set\", action((node, value) => {\n assertTweakedObject(node, \"node\");\n this.nodeContextValue.set(node, {\n type: \"value\",\n value\n });\n this.getNodeAtom(node).reportChanged();\n }));\n __publicField(this, \"setComputed\", action((node, valueFn) => {\n this._setComputed(node, computed(valueFn));\n }));\n __publicField(this, \"unset\", action((node) => {\n assertTweakedObject(node, \"node\");\n this.nodeContextValue.delete(node);\n this.getNodeAtom(node).reportChanged();\n }));\n __publicField(this, \"apply\", action((fn, value) => {\n const old = this.overrideContextValue.get();\n this.overrideContextValue.set({\n type: \"value\",\n value\n });\n try {\n const ret = fn();\n if (isTweakedObject(ret, true)) {\n this.set(ret, value);\n }\n return ret;\n } finally {\n this.overrideContextValue.set(old);\n }\n }));\n __publicField(this, \"applyComputed\", action((fn, valueFn) => {\n const computedValueFn = computed(valueFn);\n const old = this.overrideContextValue.get();\n this.overrideContextValue.set({\n type: \"computed\",\n value: computedValueFn\n });\n try {\n const ret = fn();\n if (isTweakedObject(ret, true)) {\n this._setComputed(ret, computedValueFn);\n }\n return ret;\n } finally {\n this.overrideContextValue.set(old);\n }\n }));\n this.setDefault(defaultValue);\n }\n getNodeAtom(node) {\n return getOrCreate(this.nodeAtom, node, createContextValueAtom);\n }\n fastGet(node) {\n this.getNodeAtom(node).reportObserved();\n const obsForNode = this.nodeContextValue.get(node);\n if (obsForNode) {\n return resolveContextValue(obsForNode);\n }\n const parent = fastGetParent(node);\n if (!parent) {\n const overrideValue = this.overrideContextValue.get();\n if (overrideValue) {\n return resolveContextValue(overrideValue);\n }\n return this.getDefault();\n }\n return this.fastGet(parent);\n }\n get(node) {\n assertTweakedObject(node, \"node\");\n return this.fastGet(node);\n }\n fastGetProviderNode(node) {\n this.getNodeAtom(node).reportObserved();\n const obsForNode = this.nodeContextValue.get(node);\n if (obsForNode) {\n return node;\n }\n const parent = fastGetParent(node);\n if (!parent) {\n return void 0;\n }\n return this.fastGetProviderNode(parent);\n }\n getProviderNode(node) {\n assertTweakedObject(node, \"node\");\n return this.fastGetProviderNode(node);\n }\n getDefault() {\n return resolveContextValue(this.defaultContextValue.get());\n }\n _setComputed(node, computedValueFn) {\n assertTweakedObject(node, \"node\");\n this.nodeContextValue.set(node, { type: \"computed\", value: computedValueFn });\n this.getNodeAtom(node).reportChanged();\n }\n}\nfunction createContext(defaultValue) {\n return new ContextClass(defaultValue);\n}\nconst computedTreeContext = createContext(false);\nfunction isComputedTreeNode(node) {\n return computedTreeContext.get(node);\n}\nconst tweakedComputedTreeNodes = /* @__PURE__ */ new WeakSet();\nfunction tweakComputedTreeNode(newValue, parent, path) {\n const tweakedValue = tweak(newValue, { parent, path });\n if (isTreeNode(tweakedValue) && !tweakedComputedTreeNodes.has(tweakedValue)) {\n tweakedComputedTreeNodes.add(tweakedValue);\n readonlyMiddleware(tweakedValue);\n computedTreeContext.set(tweakedValue, true);\n }\n return tweakedValue;\n}\nconst computedTreeNodeInfo = /* @__PURE__ */ new WeakMap();\nfunction getOrCreateComputedTreeNodeInfo(instance) {\n return getOrCreate(computedTreeNodeInfo, instance, () => /* @__PURE__ */ new Map());\n}\nfunction computedTree(...args) {\n const createGetter = (propertyKey) => function() {\n const entry = getOrCreateComputedTreeNodeInfo(this).get(propertyKey);\n const oldValue = entry.value;\n const newValue = entry.computed.get();\n if (oldValue === newValue) {\n return entry.tweakedValue;\n }\n const oldTweakedValue = entry.tweakedValue;\n tweak(oldTweakedValue, void 0);\n const tweakedValue = tweakComputedTreeNode(newValue, this, propertyKey);\n entry.value = newValue;\n entry.tweakedValue = tweakedValue;\n return tweakedValue;\n };\n const runLateInit = (instance, original, propertyKey) => {\n const c = computed(() => original.call(instance), { keepAlive: true });\n const newValue = c.get();\n const tweakedValue = tweakComputedTreeNode(newValue, instance, propertyKey);\n getOrCreateComputedTreeNodeInfo(instance).set(propertyKey, {\n computed: c,\n value: newValue,\n tweakedValue\n });\n };\n const checkInstanceClass = (instance) => {\n const instanceClass = instance.constructor;\n if (!isModelClass(instanceClass) && !isDataModelClass(instanceClass)) {\n throw failure(\"@computedTree can only decorate 'get' accessors of class or data models\");\n }\n };\n if (typeof args[1] === \"object\") {\n const value = args[0];\n const ctx = args[1];\n if (ctx.kind !== \"getter\") {\n throw failure(\"@computedTree requires a 'get' accessor\");\n }\n checkDecoratorContext(\"computedTree\", ctx.name, ctx.static);\n const propertyKey = ctx.name;\n const original = value;\n let classChecked = false;\n ctx.addInitializer(function() {\n const instance = this;\n if (!classChecked) {\n checkInstanceClass(instance);\n classChecked = true;\n }\n runLateInit(instance, original, propertyKey);\n });\n return createGetter(propertyKey);\n } else {\n const instance = args[0];\n const propertyKey = args[1];\n const descriptor = args[2];\n if (!descriptor.get) {\n throw failure(\"@computedTree requires a 'get' accessor\");\n }\n checkDecoratorContext(\"computedTree\", propertyKey, false);\n checkInstanceClass(instance);\n const original = descriptor.get;\n descriptor.get = createGetter(propertyKey);\n addLateInitializationFunction(instance, runBeforeOnInitSymbol, (instance2) => {\n runLateInit(instance2, original, propertyKey);\n });\n }\n}\nfunction ExtendedDataModel(...args) {\n let baseModel;\n let modelProps;\n if (isDataModelClass(args[0])) {\n baseModel = args[0];\n modelProps = args[1];\n } else {\n const gen = args[0]();\n baseModel = gen.baseModel;\n modelProps = gen.props;\n }\n assertIsDataModelClass(baseModel, \"baseModel\");\n return internalDataModel(modelProps, baseModel);\n}\nfunction DataModel(fnModelPropsOrModelProps) {\n const modelProps = typeof fnModelPropsOrModelProps === \"function\" ? fnModelPropsOrModelProps() : fnModelPropsOrModelProps;\n return internalDataModel(modelProps, void 0);\n}\nfunction internalDataModel(modelProps, baseModel) {\n return sharedInternalModel({\n modelProps,\n baseModel,\n type: \"data\",\n valueType: false,\n fromSnapshotProcessor: void 0,\n toSnapshotProcessor: void 0\n });\n}\nfunction connectReduxDevTools(remotedevPackage, remotedevConnection, target, options) {\n assertTweakedObject(target, \"target\");\n const opts = {\n logArgsNearName: true,\n ...options\n };\n let handlingMonitorAction = 0;\n remotedevConnection.subscribe((message) => {\n if (message.type === \"DISPATCH\") {\n handleMonitorActions(remotedevConnection, target, message);\n }\n });\n const initialState = getSnapshot(target);\n remotedevConnection.init(initialState);\n let currentActionId = 0;\n const actionIdSymbol = Symbol(\"actionId\");\n actionTrackingMiddleware(target, {\n onStart(ctx) {\n ctx.data[actionIdSymbol] = currentActionId++;\n },\n onResume(ctx) {\n if (ctx.parentContext) {\n log(ctx.parentContext, void 0);\n }\n log(ctx, void 0);\n },\n onSuspend(ctx) {\n log(ctx, void 0);\n },\n onFinish(ctx, ret) {\n log(ctx, ret.result);\n }\n });\n function handleMonitorActions(remotedev2, target2, message) {\n try {\n handlingMonitorAction++;\n switch (message.payload.type) {\n case \"RESET\":\n applySnapshot(target2, initialState);\n return remotedev2.init(initialState);\n case \"COMMIT\":\n return remotedev2.init(getSnapshot(target2));\n case \"ROLLBACK\":\n return remotedev2.init(remotedevPackage.extractState(message));\n case \"JUMP_TO_STATE\":\n case \"JUMP_TO_ACTION\":\n applySnapshot(target2, remotedevPackage.extractState(message));\n return;\n case \"IMPORT_STATE\":\n const nextLiftedState = message.payload.nextLiftedState;\n const computedStates = nextLiftedState.computedStates;\n applySnapshot(target2, computedStates[computedStates.length - 1].state);\n remotedev2.send(null, nextLiftedState);\n return;\n default:\n }\n } finally {\n handlingMonitorAction--;\n }\n }\n let lastLoggedSnapshot = initialState;\n function log(ctx, result) {\n if (handlingMonitorAction) {\n return;\n }\n const sn = getSnapshot(target);\n if (sn === lastLoggedSnapshot && result !== ActionTrackingResult.Throw) {\n return;\n }\n lastLoggedSnapshot = sn;\n const rootPath = fastGetRootPath(ctx.target);\n const name = getActionContextNameAndTypePath(ctx, rootPath, result);\n const copy = {\n type: name,\n path: rootPath.path,\n args: ctx.args\n };\n remotedevConnection.send(copy, sn);\n }\n function getActionContextNameAndTypePath(ctx, rootPath, result) {\n const pathStr = \"[/\" + rootPath.path.join(\"/\") + \"] \";\n let name = pathStr + ctx.actionName;\n if (opts.logArgsNearName) {\n let args = ctx.args.map((a) => {\n try {\n return JSON.stringify(a);\n } catch {\n return \"**unserializable**\";\n }\n }).join(\", \");\n if (args.length > 64) {\n args = args.slice(0, 64) + \"...\";\n }\n name += `(${args})`;\n }\n const actionId = ctx.data[actionIdSymbol];\n name += ` (id ${actionId !== void 0 ? actionId : \"?\"}`;\n if (ctx.type === ActionContextActionType.Async) {\n name += \", async\";\n }\n name += \")\";\n if (result === ActionTrackingResult.Throw) {\n name += \" -error thrown-\";\n }\n if (ctx.parentContext) {\n const parentName = getActionContextNameAndTypePath(ctx.parentContext, fastGetRootPath(ctx.parentContext.target), void 0);\n if (parentName) {\n name = `${parentName} >>> ${name}`;\n }\n }\n return name;\n }\n}\nconst reduxActionType = \"applyAction\";\nfunction actionCallToReduxAction(actionCall) {\n return {\n type: reduxActionType,\n payload: actionCall\n };\n}\nfunction asReduxStore(target, ...middlewares) {\n assertTweakedObject(target, \"target\");\n const defaultDispatch = (action2) => {\n if (action2.type !== reduxActionType) {\n throw failure(`action type was expected to be '${reduxActionType}', but it was '${action2.type}'`);\n }\n applyAction(target, action2.payload);\n return action2;\n };\n let store = {\n getState() {\n return getSnapshot(target);\n },\n dispatch(action2) {\n return runMiddlewares(action2, runners, defaultDispatch);\n },\n subscribe(listener) {\n return onSnapshot(target, listener);\n }\n };\n const runners = middlewares.map((mw) => mw(store));\n return store;\n}\nfunction runMiddlewares(initialAction, runners, next) {\n let i = 0;\n function runNextMiddleware(action2) {\n const runner = runners[i];\n i++;\n if (runner) {\n return runner(runNextMiddleware)(action2);\n } else {\n return next(action2);\n }\n }\n return runNextMiddleware(initialAction);\n}\nclass Ref extends Model({\n /**\n * Reference id.\n */\n id: tProp(typesString)\n}) {\n /**\n * The object this reference points to, or `undefined` if the reference is currently invalid.\n */\n get maybeCurrent() {\n return this.resolve();\n }\n /**\n * If the reference is currently valid.\n */\n get isValid() {\n return !!this.maybeCurrent;\n }\n /**\n * The object this reference points to, or throws if invalid.\n */\n get current() {\n const current = this.maybeCurrent;\n if (!current) {\n throw failure(`a reference of type '${this[modelTypeKey]}' could not resolve an object with id '${this.id}'`);\n }\n return current;\n }\n}\n__decorate([\n computed\n], Ref.prototype, \"maybeCurrent\", null);\n__decorate([\n computed\n], Ref.prototype, \"isValid\", null);\n__decorate([\n computed\n], Ref.prototype, \"current\", null);\nfunction isRefOfType(ref, refType) {\n return ref instanceof refType.refClass;\n}\nconst objectBackRefs = /* @__PURE__ */ new WeakMap();\nfunction internalCustomRef(modelTypeId, resolverGen, getId, onResolvedValueChange) {\n let CustomRef = class CustomRef extends Ref {\n constructor() {\n super(...arguments);\n __publicField(this, \"resolver\");\n __publicField(this, \"savedOldTarget\");\n }\n resolve() {\n if (!this.resolver) {\n this.resolver = resolverGen(this);\n }\n return this.resolver(this);\n }\n internalForceUpdateBackRefs(newTarget) {\n const oldTarget = this.savedOldTarget;\n this.savedOldTarget = newTarget;\n updateBackRefs(this, thisRefConstructor, newTarget, oldTarget);\n }\n forceUpdateBackRefs() {\n this.internalForceUpdateBackRefs(this.maybeCurrent);\n }\n onInit() {\n let savedOldTarget;\n let savedFirstTime = true;\n reaction(() => this.maybeCurrent, (newTarget) => {\n this.internalForceUpdateBackRefs(newTarget);\n const oldTarget = savedOldTarget;\n const firstTime = savedFirstTime;\n savedOldTarget = newTarget;\n savedFirstTime = false;\n if (!firstTime && onResolvedValueChange && newTarget !== oldTarget) {\n onResolvedValueChange(this, newTarget, oldTarget);\n }\n }, { fireImmediately: true });\n }\n };\n __decorate([\n action\n ], CustomRef.prototype, \"forceUpdateBackRefs\", null);\n CustomRef = __decorate([\n model(modelTypeId)\n ], CustomRef);\n const fn = (target) => {\n let id;\n if (typeof target === \"string\") {\n id = target;\n } else {\n assertIsObject(target, \"target\");\n id = getId(target);\n }\n if (typeof id !== \"string\") {\n throw failure(\"ref target object must have an id of string type\");\n }\n const ref = new CustomRef({\n id\n });\n return ref;\n };\n fn.refClass = CustomRef;\n const thisRefConstructor = fn;\n return thisRefConstructor;\n}\nfunction getModelRefId(target) {\n if (isModel(target) && target.getRefId) {\n const id = target.getRefId();\n if (id !== void 0 && typeof id !== \"string\") {\n throw failure(\"'getRefId()' must return a string or undefined when present\");\n }\n return id;\n }\n return void 0;\n}\nconst computedIdTrees = /* @__PURE__ */ new WeakMap();\nfunction resolveId(root, id, getId = getModelRefId) {\n const computedIdTree = getOrCreate(computedIdTrees, getId, () => computedWalkTreeAggregate((node) => getId(node)));\n const idMap = computedIdTree.walk(root);\n return idMap ? idMap.get(id) : void 0;\n}\nfunction getBackRefs(target, refType) {\n let backRefs = objectBackRefs.get(target);\n if (!backRefs) {\n backRefs = {\n all: observable.set(void 0, { deep: false }),\n byType: /* @__PURE__ */ new WeakMap()\n };\n objectBackRefs.set(target, backRefs);\n }\n if (!refType) {\n return backRefs.all;\n } else {\n let byType = backRefs.byType.get(refType);\n if (!byType) {\n byType = observable.set(void 0, { deep: false });\n backRefs.byType.set(refType, byType);\n }\n return byType;\n }\n}\nfunction getRefsResolvingTo(target, refType, options) {\n assertTweakedObject(target, \"target\");\n if ((options == null ? void 0 : options.updateAllRefsIfNeeded) && isReactionDelayed()) {\n const refsChecked = /* @__PURE__ */ new Set();\n const updateRef = (ref) => {\n if (!refsChecked.has(ref)) {\n if (!refType || ref instanceof refType.refClass) {\n ref.forceUpdateBackRefs();\n }\n refsChecked.add(ref);\n }\n };\n const oldBackRefs = getBackRefs(target, refType);\n oldBackRefs.forEach(updateRef);\n const refsChildrenOfRoot = getDeepChildrenRefs(getDeepObjectChildren(fastGetRoot(target)));\n let refs;\n if (refType) {\n refs = refsChildrenOfRoot.byType.get(refType.refClass);\n } else {\n refs = refsChildrenOfRoot.all;\n }\n refs == null ? void 0 : refs.forEach(updateRef);\n }\n return getBackRefs(target, refType);\n}\nconst updateBackRefs = action(\"updateBackRefs\", (ref, refClass, newTarget, oldTarget) => {\n if (newTarget === oldTarget) {\n return;\n }\n if (oldTarget) {\n getBackRefs(oldTarget).delete(ref);\n getBackRefs(oldTarget, refClass).delete(ref);\n }\n if (newTarget) {\n getBackRefs(newTarget).add(ref);\n getBackRefs(newTarget, refClass).add(ref);\n }\n});\nfunction isReactionDelayed() {\n let reactionDelayed = true;\n const dispose = when(() => true, () => {\n reactionDelayed = false;\n });\n dispose();\n return reactionDelayed;\n}\nconst getDeepChildrenRefs = registerDeepObjectChildrenExtension({\n initData() {\n return {\n all: /* @__PURE__ */ new Set(),\n byType: /* @__PURE__ */ new WeakMap()\n };\n },\n addNode(node, data) {\n if (node instanceof Ref) {\n data.all.add(node);\n const refsByThisType = getOrCreate(data.byType, node.constructor, () => /* @__PURE__ */ new Set());\n refsByThisType.add(node);\n }\n }\n});\nconst customRef = action(\"customRef\", (modelTypeId, options) => {\n var _a2;\n const getId = (_a2 = options.getId) != null ? _a2 : getModelRefId;\n return internalCustomRef(modelTypeId, () => options.resolve, getId, options.onResolvedValueChange);\n});\nconst rootRef = action(\"rootRef\", (modelTypeId, options) => {\n var _a2;\n const getId = (_a2 = options == null ? void 0 : options.getId) != null ? _a2 : getModelRefId;\n const onResolvedValueChange = options == null ? void 0 : options.onResolvedValueChange;\n const resolverGen = (ref) => {\n let cachedTarget;\n return () => {\n const refRoot = fastGetRoot(ref);\n if (isRefRootCachedTargetOk(ref, refRoot, cachedTarget, getId)) {\n return cachedTarget;\n }\n const newTarget = resolveId(refRoot, ref.id, getId);\n if (newTarget) {\n cachedTarget = newTarget;\n }\n return newTarget;\n };\n };\n return internalCustomRef(modelTypeId, resolverGen, getId, onResolvedValueChange);\n});\nfunction isRefRootCachedTargetOk(ref, refRoot, cachedTarget, getId) {\n if (!cachedTarget)\n return false;\n if (ref.id !== getId(cachedTarget))\n return false;\n if (refRoot !== fastGetRoot(cachedTarget))\n return false;\n return true;\n}\nfunction standaloneAction(actionName, fn) {\n return addStandaloneAction(actionName, fn, false);\n}\nfunction standaloneFlow(actionName, fn) {\n return addStandaloneAction(actionName, fn, true);\n}\nfunction _splice(array, ...args) {\n return array.splice(...args);\n}\nconst namespace$1 = `${namespace$2}/arrayActions`;\nconst arrayActions = {\n set: standaloneAction(`${namespace$1}::set`, (array, index, value) => {\n setIfDifferent(array, index, value);\n }),\n delete: standaloneAction(`${namespace$1}::delete`, (array, index) => {\n return remove(array, \"\" + index);\n }),\n setLength: standaloneAction(`${namespace$1}::setLength`, (array, length) => {\n array.length = length;\n }),\n concat: standaloneAction(`${namespace$1}::concat`, (array, ...items) => {\n return array.concat(...items);\n }),\n copyWithin: standaloneAction(`${namespace$1}::copyWithin`, (array, target, start, end) => {\n return array.copyWithin(target, start, end);\n }),\n fill: standaloneAction(`${namespace$1}::fill`, (array, value, start, end) => {\n return array.fill(value, start, end);\n }),\n pop: standaloneAction(`${namespace$1}::pop`, (array) => {\n return array.pop();\n }),\n push: standaloneAction(`${namespace$1}::push`, (array, ...items) => {\n return array.push(...items);\n }),\n reverse: standaloneAction(`${namespace$1}::reverse`, (array) => {\n return array.reverse();\n }),\n shift: standaloneAction(`${namespace$1}::shift`, (array) => {\n return array.shift();\n }),\n slice: standaloneAction(`${namespace$1}::slice`, (array, start, end) => {\n return array.slice(start, end);\n }),\n sort: standaloneAction(`${namespace$1}::sort`, (array, compareFn) => {\n return array.sort(compareFn);\n }),\n splice: standaloneAction(`${namespace$1}::splice`, _splice),\n unshift: standaloneAction(`${namespace$1}::unshift`, (array, ...items) => {\n return array.unshift(...items);\n }),\n swap: standaloneAction(`${namespace$1}::swap`, (array, index1, index2) => {\n if (index1 < 0 || index2 < 0 || index1 >= array.length || index2 >= array.length) {\n return false;\n }\n if (index2 < index1) {\n [index1, index2] = [index2, index1];\n }\n const [v1] = array.splice(index1, 1);\n const [v2] = array.splice(index2 - 1, 1);\n array.splice(index1, 0, v2);\n array.splice(index2, 0, v1);\n return true;\n }),\n create: (data) => toTreeNode(data)\n};\nconst namespace = `${namespace$2}/objectActions`;\nconst objectActions = {\n set: standaloneAction(`${namespace}::set`, (target, key, value) => {\n if (isObservable(target)) {\n setIfDifferent(target, key, value);\n } else {\n target[key] = value;\n }\n }),\n assign: standaloneAction(`${namespace}::assign`, (target, partialObject) => {\n assertIsObject(partialObject, \"partialObject\");\n const keys2 = Object.keys(partialObject);\n if (isObservable(target)) {\n for (const key of keys2) {\n const newValue = partialObject[key];\n setIfDifferent(target, key, newValue);\n }\n } else {\n for (const key of keys2) {\n target[key] = partialObject[key];\n }\n }\n }),\n delete: standaloneAction(`${namespace}::delete`, (target, key) => {\n return remove(target, key);\n }),\n call: standaloneAction(`${namespace}::call`, (target, methodName, ...args) => {\n return target[methodName](...args);\n }),\n create: (data) => toTreeNode(data)\n};\nfunction tag(tagDataConstructor) {\n const map = /* @__PURE__ */ new WeakMap();\n return {\n for(target) {\n if (!map.has(target)) {\n const data = tagDataConstructor(target);\n map.set(target, data);\n return data;\n } else {\n return map.get(target);\n }\n }\n };\n}\nconst observableMapBackedByObservableObject = action((obj) => {\n if (inDevMode) {\n if (!isObservableObject(obj)) {\n throw failure(\"assertion failed: expected an observable object\");\n }\n }\n const map = observable.map();\n map.dataObject = obj;\n const keys2 = Object.keys(obj);\n for (let i = 0; i < keys2.length; i++) {\n const k = keys2[i];\n map.set(k, obj[k]);\n }\n let mapAlreadyChanged = false;\n let objectAlreadyChanged = false;\n observe(obj, action((change) => {\n if (mapAlreadyChanged) {\n return;\n }\n objectAlreadyChanged = true;\n try {\n switch (change.type) {\n case \"add\":\n case \"update\": {\n map.set(change.name, change.newValue);\n break;\n }\n case \"remove\": {\n map.delete(change.name);\n break;\n }\n }\n } finally {\n objectAlreadyChanged = false;\n }\n }));\n intercept(map, action((change) => {\n if (mapAlreadyChanged) {\n return null;\n }\n if (objectAlreadyChanged) {\n return change;\n }\n mapAlreadyChanged = true;\n try {\n switch (change.type) {\n case \"add\":\n case \"update\": {\n setIfDifferent(obj, change.name, change.newValue);\n break;\n }\n case \"delete\": {\n remove(obj, change.name);\n break;\n }\n }\n return change;\n } finally {\n mapAlreadyChanged = false;\n }\n }));\n return map;\n});\nconst observableMapBackedByObservableArray = action((array) => {\n if (inDevMode) {\n if (!isObservableArray(array)) {\n throw failure(\"assertion failed: expected an observable array\");\n }\n }\n let map;\n if (getMobxVersion() >= 6) {\n map = observable.map(array);\n } else {\n map = observable.map();\n array.forEach(([k, v]) => {\n map.set(k, v);\n });\n }\n map.dataObject = array;\n if (map.size !== array.length) {\n throw failure(\"arrays backing a map cannot contain duplicate keys\");\n }\n let mapAlreadyChanged = false;\n let arrayAlreadyChanged = false;\n observe(array, action((change) => {\n if (mapAlreadyChanged) {\n return;\n }\n arrayAlreadyChanged = true;\n try {\n switch (change.type) {\n case \"splice\": {\n {\n const removed = change.removed;\n for (let i = 0; i < removed.length; i++) {\n map.delete(removed[i][0]);\n }\n }\n {\n const added = change.added;\n for (let i = 0; i < added.length; i++) {\n map.set(added[i][0], added[i][1]);\n }\n }\n break;\n }\n case \"update\": {\n map.delete(change.oldValue[0]);\n map.set(change.newValue[0], change.newValue[1]);\n break;\n }\n }\n } finally {\n arrayAlreadyChanged = false;\n }\n }));\n intercept(map, action((change) => {\n if (mapAlreadyChanged) {\n return null;\n }\n if (arrayAlreadyChanged) {\n return change;\n }\n mapAlreadyChanged = true;\n try {\n switch (change.type) {\n case \"update\": {\n const i = array.findIndex((i2) => i2[0] === change.name);\n array[i] = [change.name, change.newValue];\n break;\n }\n case \"add\": {\n array.push([change.name, change.newValue]);\n break;\n }\n case \"delete\": {\n const i = array.findIndex((i2) => i2[0] === change.name);\n if (i >= 0) {\n array.splice(i, 1);\n }\n break;\n }\n }\n return change;\n } finally {\n mapAlreadyChanged = false;\n }\n }));\n return map;\n});\nconst asMapTag = tag((objOrArray) => {\n if (isArray(objOrArray)) {\n assertIsObservableArray(objOrArray, \"objOrArray\");\n return observableMapBackedByObservableArray(objOrArray);\n } else {\n assertIsObservableObject(objOrArray, \"objOrArray\");\n return observableMapBackedByObservableObject(objOrArray);\n }\n});\nfunction asMap(objOrArray) {\n return asMapTag.for(objOrArray);\n}\nfunction mapToObject(map) {\n assertIsMap(map, \"map\");\n const dataObject = map.dataObject;\n if (dataObject && !isArray(dataObject)) {\n return dataObject;\n }\n const obj = {};\n for (const k of map.keys()) {\n obj[k] = map.get(k);\n }\n return obj;\n}\nfunction mapToArray(map) {\n assertIsMap(map, \"map\");\n const dataObject = map.dataObject;\n if (dataObject && isArray(dataObject)) {\n return dataObject;\n }\n const arr = [];\n for (const k of map.keys()) {\n arr.push([k, map.get(k)]);\n }\n return arr;\n}\nconst _objectToMapTransform = {\n transform({ originalValue: obj, cachedTransformedValue: cachedMap }) {\n return cachedMap != null ? cachedMap : asMap(obj);\n },\n untransform({ transformedValue: map }) {\n const obj = {};\n for (const k of map.keys()) {\n obj[k] = map.get(k);\n }\n return obj;\n }\n};\nconst objectToMapTransform = () => _objectToMapTransform;\nconst _arrayToMapTransform = {\n transform({ originalValue: arr, cachedTransformedValue: cachedMap }) {\n return cachedMap != null ? cachedMap : asMap(arr);\n },\n untransform({ transformedValue: map }) {\n const arr = [];\n for (const k of map.keys()) {\n arr.push([k, map.get(k)]);\n }\n return arr;\n }\n};\nconst arrayToMapTransform = () => _arrayToMapTransform;\nconst observableSetBackedByObservableArray = action((array) => {\n if (inDevMode) {\n if (!isObservableArray(array)) {\n throw failure(\"assertion failed: expected an observable array\");\n }\n }\n let set2;\n if (getMobxVersion() >= 6) {\n set2 = observable.set(array);\n } else {\n set2 = observable.set();\n array.forEach((item) => {\n set2.add(item);\n });\n }\n set2.dataObject = array;\n if (set2.size !== array.length) {\n throw failure(\"arrays backing a set cannot contain duplicate values\");\n }\n let setAlreadyChanged = false;\n let arrayAlreadyChanged = false;\n observe(array, action((change) => {\n if (setAlreadyChanged) {\n return;\n }\n arrayAlreadyChanged = true;\n try {\n switch (change.type) {\n case \"splice\": {\n {\n const removed = change.removed;\n for (let i = 0; i < removed.length; i++) {\n set2.delete(removed[i]);\n }\n }\n {\n const added = change.added;\n for (let i = 0; i < added.length; i++) {\n set2.add(added[i]);\n }\n }\n break;\n }\n case \"update\": {\n set2.delete(change.oldValue);\n set2.add(change.newValue);\n break;\n }\n }\n } finally {\n arrayAlreadyChanged = false;\n }\n }));\n intercept(set2, action((change) => {\n if (setAlreadyChanged) {\n return null;\n }\n if (arrayAlreadyChanged) {\n return change;\n }\n setAlreadyChanged = true;\n try {\n switch (change.type) {\n case \"add\": {\n array.push(change.newValue);\n break;\n }\n case \"delete\": {\n const i = array.indexOf(change.oldValue);\n if (i >= 0) {\n array.splice(i, 1);\n }\n break;\n }\n }\n return change;\n } finally {\n setAlreadyChanged = false;\n }\n }));\n return set2;\n});\nconst asSetTag = tag((array) => {\n assertIsObservableArray(array, \"array\");\n return observableSetBackedByObservableArray(array);\n});\nfunction asSet(array) {\n return asSetTag.for(array);\n}\nfunction setToArray(set2) {\n assertIsSet(set2, \"set\");\n const dataObject = set2.dataObject;\n if (dataObject) {\n return dataObject;\n }\n return Array.from(set2.values());\n}\nconst _arrayToSetTransform = {\n transform({ originalValue: arr, cachedTransformedValue: cachedSet }) {\n return cachedSet != null ? cachedSet : asSet(arr);\n },\n untransform({ transformedValue: set2 }) {\n return Array.from(set2.values());\n }\n};\nconst arrayToSetTransform = () => _arrayToSetTransform;\nconst _stringToBigIntTransform = {\n transform({ originalValue, cachedTransformedValue }) {\n return cachedTransformedValue != null ? cachedTransformedValue : BigInt(originalValue);\n },\n untransform({ transformedValue, cacheTransformedValue }) {\n if (typeof transformedValue === \"bigint\") {\n cacheTransformedValue();\n }\n return transformedValue.toString();\n }\n};\nconst stringToBigIntTransform = () => _stringToBigIntTransform;\nconst errMessage = \"this Date object is immutable\";\nclass ImmutableDate extends Date {\n // disable mutable methods\n setTime() {\n throw failure(errMessage);\n }\n setMilliseconds() {\n throw failure(errMessage);\n }\n setUTCMilliseconds() {\n throw failure(errMessage);\n }\n setSeconds() {\n throw failure(errMessage);\n }\n setUTCSeconds() {\n throw failure(errMessage);\n }\n setMinutes() {\n throw failure(errMessage);\n }\n setUTCMinutes() {\n throw failure(errMessage);\n }\n setHours() {\n throw failure(errMessage);\n }\n setUTCHours() {\n throw failure(errMessage);\n }\n setDate() {\n throw failure(errMessage);\n }\n setUTCDate() {\n throw failure(errMessage);\n }\n setMonth() {\n throw failure(errMessage);\n }\n setUTCMonth() {\n throw failure(errMessage);\n }\n setFullYear() {\n throw failure(errMessage);\n }\n setUTCFullYear() {\n throw failure(errMessage);\n }\n}\nconst _timestampToDateTransform = {\n transform({ originalValue, cachedTransformedValue }) {\n return cachedTransformedValue != null ? cachedTransformedValue : new ImmutableDate(originalValue);\n },\n untransform({ transformedValue, cacheTransformedValue }) {\n if (transformedValue instanceof ImmutableDate) {\n cacheTransformedValue();\n }\n return +transformedValue;\n }\n};\nconst timestampToDateTransform = () => _timestampToDateTransform;\nconst _isoStringToDateTransform = {\n transform({ originalValue, cachedTransformedValue }) {\n return cachedTransformedValue != null ? cachedTransformedValue : new ImmutableDate(originalValue);\n },\n untransform({ transformedValue, cacheTransformedValue }) {\n if (transformedValue instanceof ImmutableDate) {\n cacheTransformedValue();\n }\n return transformedValue.toISOString();\n }\n};\nconst isoStringToDateTransform = () => _isoStringToDateTransform;\nclass Draft {\n /**\n * Creates an instance of Draft.\n * Do not use directly, use `draft` instead.\n *\n * @param original\n */\n constructor(original) {\n /**\n * Draft data object.\n */\n __publicField(this, \"data\");\n /**\n * Original data object.\n */\n __publicField(this, \"originalData\");\n assertTweakedObject(original, \"original\");\n this.originalData = original;\n this.data = fromSnapshot(this.originalSnapshot, { generateNewIds: false });\n }\n /**\n * Commits current draft changes to the original object.\n */\n commit() {\n applySnapshot(this.originalData, getSnapshot(this.data));\n }\n /**\n * Partially commits current draft changes to the original object.\n * If the path cannot be resolved in either the draft or the original object it will throw.\n * Note that model IDs are checked to be the same when resolving the paths.\n *\n * @param path Path to commit.\n */\n commitByPath(path) {\n const draftTarget = resolvePath(this.data, path);\n if (!draftTarget.resolved) {\n throw failure(`path ${JSON.stringify(path)} could not be resolved in draft object`);\n }\n const draftPathIds = pathToTargetPathIdsIgnoringLast(this.data, path);\n const originalTarget = resolvePathCheckingIds(this.originalData, path, draftPathIds);\n if (!originalTarget.resolved) {\n throw failure(`path ${JSON.stringify(path)} could not be resolved in original object`);\n }\n applyPatches(this.originalData, [\n {\n path,\n op: \"replace\",\n value: getSnapshot(draftTarget.value)\n }\n ]);\n }\n /**\n * Resets the draft to be an exact copy of the current state of the original object.\n */\n reset() {\n applySnapshot(this.data, this.originalSnapshot);\n }\n /**\n * Partially resets current draft changes to be the same as the original object.\n * If the path cannot be resolved in either the draft or the original object it will throw.\n * Note that model IDs are checked to be the same when resolving the paths.\n *\n * @param path Path to reset.\n */\n resetByPath(path) {\n const originalTarget = resolvePath(this.originalData, path);\n if (!originalTarget.resolved) {\n throw failure(`path ${JSON.stringify(path)} could not be resolved in original object`);\n }\n const originalPathIds = pathToTargetPathIdsIgnoringLast(this.originalData, path);\n const draftTarget = resolvePathCheckingIds(this.data, path, originalPathIds);\n if (!draftTarget.resolved) {\n throw failure(`path ${JSON.stringify(path)} could not be resolved in draft object`);\n }\n applyPatches(this.data, [\n {\n path,\n op: \"replace\",\n value: getSnapshot(originalTarget.value)\n }\n ]);\n }\n /**\n * Returns `true` if the draft has changed compared to the original object, `false` otherwise.\n */\n get isDirty() {\n return !deepEquals(getSnapshot(this.data), this.originalSnapshot);\n }\n /**\n * Returns `true` if the value at the given path of the draft has changed compared to the original object.\n * If the path cannot be resolved in the draft it will throw.\n * If the path cannot be resolved in the original object it will return `true`.\n * Note that model IDs are checked to be the same when resolving the paths.\n *\n * @param path Path to check.\n */\n isDirtyByPath(path) {\n const draftTarget = resolvePath(this.data, path);\n if (!draftTarget.resolved) {\n throw failure(`path ${JSON.stringify(path)} could not be resolved in draft object`);\n }\n const draftPathIds = pathToTargetPathIdsIgnoringLast(this.data, path);\n const originalTarget = resolvePathCheckingIds(this.originalData, path, draftPathIds);\n if (!originalTarget.resolved) {\n return true;\n }\n return !deepEquals(draftTarget.value, originalTarget.value);\n }\n get originalSnapshot() {\n return getSnapshot(this.originalData);\n }\n}\n__decorate([\n action\n], Draft.prototype, \"commit\", null);\n__decorate([\n action\n], Draft.prototype, \"commitByPath\", null);\n__decorate([\n action\n], Draft.prototype, \"reset\", null);\n__decorate([\n action\n], Draft.prototype, \"resetByPath\", null);\n__decorate([\n computed\n], Draft.prototype, \"isDirty\", null);\n__decorate([\n computed\n], Draft.prototype, \"originalSnapshot\", null);\nfunction draft(original) {\n return new Draft(original);\n}\nfunction pathToTargetPathIdsIgnoringLast(root, path) {\n const pathIds = pathToTargetPathIds(root, path);\n if (pathIds.length >= 1) {\n pathIds[pathIds.length - 1] = skipIdChecking;\n }\n return pathIds;\n}\nconst sandboxManagerContext = createContext();\nfunction getNodeSandboxManager(node) {\n return sandboxManagerContext.get(node);\n}\nfunction isSandboxedNode(node) {\n return !!getNodeSandboxManager(node);\n}\nclass SandboxManager {\n /**\n * Creates an instance of `SandboxManager`.\n * Do not use directly, use `sandbox` instead.\n *\n * @param subtreeRoot Subtree root target object.\n */\n constructor(subtreeRoot) {\n __publicField(this, \"subtreeRoot\");\n /**\n * The sandbox copy of the original subtree.\n */\n __publicField(this, \"subtreeRootClone\");\n /**\n * The internal disposer.\n */\n __publicField(this, \"disposer\");\n /**\n * The internal `withSandbox` patch recorder. If `undefined`, no `withSandbox` call is being\n * executed.\n */\n __publicField(this, \"withSandboxPatchRecorder\");\n /**\n * Function from `readonlyMiddleware` that will allow actions to be started inside the provided\n * code block on a readonly node.\n */\n __publicField(this, \"allowWrite\");\n /**\n * Whether changes made in the sandbox are currently being committed to the original subtree.\n */\n __publicField(this, \"isCommitting\", false);\n this.subtreeRoot = subtreeRoot;\n assertTweakedObject(subtreeRoot, \"subtreeRoot\");\n let previousContextDefault = sandboxManagerContext.getDefault();\n sandboxManagerContext.setDefault(this);\n try {\n this.subtreeRootClone = clone(subtreeRoot, { generateNewIds: false });\n sandboxManagerContext.set(this.subtreeRootClone, this);\n } catch (err) {\n throw err;\n } finally {\n sandboxManagerContext.setDefault(previousContextDefault);\n }\n let wasRS = false;\n const disposeReactionRS = reaction(() => fastIsRootStore(subtreeRoot), (isRS) => {\n if (isRS !== wasRS) {\n wasRS = isRS;\n if (isRS) {\n registerRootStore(this.subtreeRootClone);\n } else {\n unregisterRootStore(this.subtreeRootClone);\n }\n }\n }, { fireImmediately: true });\n const disposeOnPatches = onPatches(subtreeRoot, (patches) => {\n if (this.withSandboxPatchRecorder) {\n throw failure(\"original subtree must not change while 'withSandbox' executes\");\n }\n if (!this.isCommitting) {\n this.allowWrite(() => {\n applyPatches(this.subtreeRootClone, patches);\n });\n }\n });\n const { allowWrite, dispose: disposeReadonlyMW } = readonlyMiddleware(this.subtreeRootClone);\n this.allowWrite = allowWrite;\n this.disposer = () => {\n disposeReactionRS();\n disposeOnPatches();\n disposeReadonlyMW();\n if (fastIsRootStore(this.subtreeRootClone)) {\n unregisterRootStore(this.subtreeRootClone);\n }\n this.disposer = () => {\n };\n };\n }\n /**\n * Executes `fn` with sandbox copies of the elements of `nodes`. The changes made to the sandbox\n * in `fn` can be accepted, i.e. applied to the original subtree, or rejected.\n *\n * @typeparam T Object type.\n * @typeparam R Return type.\n * @param nodes Tuple of objects for which to obtain sandbox copies.\n * @param fn Function that is called with sandbox copies of the elements of `nodes`. Any changes\n * made to the sandbox are applied to the original subtree when `fn` returns `true` or\n * `{ commit: true, ... }`. When `fn` returns `false` or `{ commit: false, ... }` the changes made\n * to the sandbox are rejected.\n * @returns Value of type `R` when `fn` returns an object of type `{ commit: boolean; return: R }`\n * or `void` when `fn` returns a boolean.\n */\n withSandbox(nodes, fn) {\n for (let i = 0; i < nodes.length; i++) {\n assertTweakedObject(nodes[i], `nodes[${i}]`);\n }\n assertIsFunction(fn, \"fn\");\n const { sandboxNodes, applyRecorderChanges } = this.prepareSandboxChanges(nodes);\n let commit = false;\n try {\n const returnValue = this.allowWrite(() => fn(...sandboxNodes));\n if (typeof returnValue === \"boolean\") {\n commit = returnValue;\n return void 0;\n } else {\n commit = returnValue.commit;\n return returnValue.return;\n }\n } finally {\n applyRecorderChanges(commit);\n }\n }\n /**\n * Disposes of the sandbox.\n */\n dispose() {\n this.disposer();\n }\n prepareSandboxChanges(nodes) {\n const isNestedWithSandboxCall = !!this.withSandboxPatchRecorder;\n const sandboxNodes = nodes.map((node) => {\n const path = getParentToChildPath(isNestedWithSandboxCall ? this.subtreeRootClone : this.subtreeRoot, node);\n if (!path) {\n throw failure(`node is not a child of subtreeRoot${isNestedWithSandboxCall ? \"Clone\" : \"\"}`);\n }\n const sandboxNode = resolvePath(this.subtreeRootClone, path).value;\n if (!sandboxNode) {\n throw failure(\"path could not be resolved - sandbox may be out of sync with original tree\");\n }\n return sandboxNode;\n });\n if (!this.withSandboxPatchRecorder) {\n this.withSandboxPatchRecorder = patchRecorder(this.subtreeRootClone);\n }\n const recorder = this.withSandboxPatchRecorder;\n const numRecorderEvents = recorder.events.length;\n const applyRecorderChanges = (commit) => {\n if (!isNestedWithSandboxCall) {\n recorder.dispose();\n this.withSandboxPatchRecorder = void 0;\n }\n if (commit) {\n if (!isNestedWithSandboxCall) {\n const patches = [];\n const len = recorder.events.length;\n for (let i = 0; i < len; i++) {\n patches.push(...recorder.events[i].patches);\n }\n const isCommitting = this.isCommitting;\n this.isCommitting = true;\n try {\n applyPatches(this.subtreeRoot, patches);\n } finally {\n this.isCommitting = isCommitting;\n }\n }\n } else {\n this.allowWrite(() => {\n runInAction(() => {\n let i = recorder.events.length;\n while (i-- > numRecorderEvents) {\n applyPatches(this.subtreeRootClone, recorder.events[i].inversePatches, true);\n }\n });\n });\n }\n };\n return { sandboxNodes, applyRecorderChanges };\n }\n}\nfunction sandbox(subtreeRoot) {\n return new SandboxManager(subtreeRoot);\n}\nfunction typesTuple(...itemTypes) {\n const typeInfoGen = (t) => new TupleTypeInfo(t, itemTypes.map(resolveStandardType));\n return lateTypeChecker(() => {\n const checkers = itemTypes.map(resolveTypeChecker);\n const getTypeName = (...recursiveTypeCheckers) => {\n const typeNames = checkers.map((tc) => {\n if (recursiveTypeCheckers.includes(tc)) {\n return \"...\";\n }\n return tc.getTypeName(...recursiveTypeCheckers, tc);\n });\n return \"[\" + typeNames.join(\", \") + \"]\";\n };\n const thisTc = new TypeChecker(TypeCheckerBaseType.Array, (array, path, typeCheckedValue) => {\n if (!isArray(array) || array.length !== itemTypes.length) {\n return new TypeCheckError(path, getTypeName(thisTc), array, typeCheckedValue);\n }\n for (let i = 0; i < array.length; i++) {\n const itemError = checkers[i].check(array[i], [...path, i], typeCheckedValue);\n if (itemError) {\n return itemError;\n }\n }\n return null;\n }, getTypeName, typeInfoGen, (array) => {\n if (!isArray(array) || array.length !== itemTypes.length) {\n return null;\n }\n for (let i = 0; i < array.length; i++) {\n const itemActualChecker = checkers[i].snapshotType(array[i]);\n if (!itemActualChecker) {\n return null;\n }\n }\n return thisTc;\n }, (array) => {\n return array.map((item, i) => {\n return checkers[i].fromSnapshotProcessor(item);\n });\n }, (array) => {\n return array.map((item, i) => {\n return checkers[i].toSnapshotProcessor(item);\n });\n });\n return thisTc;\n }, typeInfoGen);\n}\nclass TupleTypeInfo extends TypeInfo {\n constructor(thisType, itemTypes) {\n super(thisType);\n __publicField(this, \"itemTypes\");\n // memoize to always return the same array on the getter\n __publicField(this, \"_itemTypeInfos\", lazy(() => this.itemTypes.map(getTypeInfo)));\n this.itemTypes = itemTypes;\n }\n get itemTypeInfos() {\n return this._itemTypeInfos();\n }\n}\nlet ArraySet = class ArraySet2 extends Model({\n [modelIdKey]: idProp,\n items: tProp(typesArray(typesUnchecked()), () => [])\n // will be properly checked by types.arraySet(subType)\n}) {\n add(value) {\n const items = this.items;\n if (!items.includes(value)) {\n items.push(value);\n }\n return this;\n }\n clear() {\n this.items.length = 0;\n }\n delete(value) {\n const items = this.items;\n const index = items.findIndex((t) => t === value);\n if (index >= 0) {\n items.splice(index, 1);\n return true;\n } else {\n return false;\n }\n }\n forEach(callbackfn, thisArg) {\n const items = this.items;\n const len = items.length;\n for (let i = 0; i < len; i++) {\n const k = items[i];\n callbackfn.call(thisArg, k, k, this);\n }\n }\n has(value) {\n return this.items.includes(value);\n }\n get size() {\n return this.items.length;\n }\n keys() {\n return this.values();\n }\n values() {\n const items = this.items;\n return values(items)[Symbol.iterator]();\n }\n entries() {\n const items = this.items;\n return items.map((v) => [v, v]).values();\n }\n [Symbol.iterator]() {\n return this.values();\n }\n get [Symbol.toStringTag]() {\n return \"ArraySet\";\n }\n};\n__decorate([\n modelAction\n], ArraySet.prototype, \"add\", null);\n__decorate([\n modelAction\n], ArraySet.prototype, \"clear\", null);\n__decorate([\n modelAction\n], ArraySet.prototype, \"delete\", null);\nArraySet = __decorate([\n model(`${namespace$2}/ArraySet`)\n], ArraySet);\nfunction arraySet(values2) {\n const initialArr = values2 ? values2.slice() : [];\n return new ArraySet({ items: initialArr });\n}\nfunction typesArraySet(valueType) {\n const typeInfoGen = (t) => new ArraySetTypeInfo(t, resolveStandardType(valueType));\n return lateTypeChecker(() => {\n const modelInfo = modelInfoByClass.get(ArraySet);\n const valueChecker = resolveTypeChecker(valueType);\n const getTypeName = (...recursiveTypeCheckers) => `ArraySet<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`;\n const dataTypeChecker = typesObject(() => ({\n items: typesArray(valueChecker)\n }));\n const thisTc = new TypeChecker(\n TypeCheckerBaseType.Object,\n // because it is really a model\n (obj, path, typeCheckedValue) => {\n if (!(obj instanceof ArraySet)) {\n return new TypeCheckError(path, getTypeName(thisTc), obj, typeCheckedValue);\n }\n const resolvedTc = resolveTypeChecker(dataTypeChecker);\n return resolvedTc.check(obj.$, path, typeCheckedValue);\n },\n getTypeName,\n typeInfoGen,\n (obj) => {\n if (!isObject(obj)) {\n return null;\n }\n if (obj[modelTypeKey] !== void 0) {\n return obj[modelTypeKey] === modelInfo.name ? thisTc : null;\n }\n const resolvedTc = resolveTypeChecker(dataTypeChecker);\n return resolvedTc.snapshotType(obj) ? thisTc : null;\n },\n (sn) => {\n return {\n ...sn,\n [modelTypeKey]: modelInfo.name,\n items: sn.items.map((v) => valueChecker.fromSnapshotProcessor(v))\n };\n },\n (sn) => {\n const snCopy = {\n ...sn,\n items: sn.items.map((v) => valueChecker.toSnapshotProcessor(v))\n };\n return snCopy;\n }\n );\n return thisTc;\n }, typeInfoGen);\n}\nclass ArraySetTypeInfo extends TypeInfo {\n constructor(originalType, valueType) {\n super(originalType);\n __publicField(this, \"valueType\");\n this.valueType = valueType;\n }\n get valueTypeInfo() {\n return getTypeInfo(this.valueType);\n }\n}\nfunction typesRecord(valueType) {\n const typeInfoGen = (tc) => new RecordTypeInfo(tc, resolveStandardType(valueType));\n return lateTypeChecker(() => {\n const valueChecker = resolveTypeChecker(valueType);\n const getTypeName = (...recursiveTypeCheckers) => `Record<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`;\n const applySnapshotProcessor = (obj, mode) => {\n if (valueChecker.unchecked) {\n return obj;\n }\n const newObj = {};\n const keys2 = Object.keys(obj);\n for (let i = 0; i < keys2.length; i++) {\n const k = keys2[i];\n const v = mode === \"from\" ? valueChecker.fromSnapshotProcessor(obj[k]) : valueChecker.toSnapshotProcessor(obj[k]);\n newObj[k] = v;\n }\n return newObj;\n };\n const thisTc = new TypeChecker(TypeCheckerBaseType.Object, (obj, path, typeCheckedValue) => {\n if (!isObject(obj)) {\n return new TypeCheckError(path, getTypeName(thisTc), obj, typeCheckedValue);\n }\n if (!valueChecker.unchecked) {\n const keys2 = Object.keys(obj);\n for (let i = 0; i < keys2.length; i++) {\n const k = keys2[i];\n const v = obj[k];\n const valueError = valueChecker.check(v, [...path, k], typeCheckedValue);\n if (valueError) {\n return valueError;\n }\n }\n }\n return null;\n }, getTypeName, typeInfoGen, (obj) => {\n if (!isObject(obj))\n return null;\n if (!valueChecker.unchecked) {\n const keys2 = Object.keys(obj);\n for (let i = 0; i < keys2.length; i++) {\n const k = keys2[i];\n const v = obj[k];\n const valueActualChecker = valueChecker.snapshotType(v);\n if (!valueActualChecker) {\n return null;\n }\n }\n }\n return thisTc;\n }, (obj) => {\n return applySnapshotProcessor(obj, \"from\");\n }, (obj) => {\n return applySnapshotProcessor(obj, \"to\");\n });\n return thisTc;\n }, typeInfoGen);\n}\nclass RecordTypeInfo extends TypeInfo {\n constructor(thisType, valueType) {\n super(thisType);\n __publicField(this, \"valueType\");\n this.valueType = valueType;\n }\n get valueTypeInfo() {\n return getTypeInfo(this.valueType);\n }\n}\nlet ObjectMap = class ObjectMap2 extends Model({\n [modelIdKey]: idProp,\n items: tProp(typesRecord(typesUnchecked()), () => ({}))\n // will be properly checked by types.objectMap(subType)\n}) {\n clear() {\n const items = this.items;\n const keys2 = Object.keys(items);\n const len = keys2.length;\n for (let i = 0; i < len; i++) {\n const k = keys2[i];\n remove(items, k);\n }\n }\n delete(key) {\n const hasKey = this.has(key);\n if (hasKey) {\n remove(this.items, key);\n return true;\n } else {\n return false;\n }\n }\n forEach(callbackfn, thisArg) {\n const items = this.items;\n const keys2 = Object.keys(items);\n const len = keys2.length;\n for (let i = 0; i < len; i++) {\n const k = keys2[i];\n callbackfn.call(thisArg, items[k], k, this);\n }\n }\n get(key) {\n return get(this.items, key);\n }\n has(key) {\n return has(this.items, key);\n }\n set(key, value) {\n setIfDifferent(this.items, key, value);\n return this;\n }\n get size() {\n return keys(this.items).length;\n }\n keys() {\n return keys(this.items)[Symbol.iterator]();\n }\n values() {\n return values(this.items)[Symbol.iterator]();\n }\n entries() {\n return entries(this.items)[Symbol.iterator]();\n }\n [Symbol.iterator]() {\n return this.entries();\n }\n get [Symbol.toStringTag]() {\n return \"ObjectMap\";\n }\n};\n__decorate([\n modelAction\n], ObjectMap.prototype, \"clear\", null);\n__decorate([\n modelAction\n], ObjectMap.prototype, \"delete\", null);\n__decorate([\n modelAction\n], ObjectMap.prototype, \"set\", null);\nObjectMap = __decorate([\n model(`${namespace$2}/ObjectMap`)\n], ObjectMap);\nfunction objectMap(entries2) {\n const initialObj = {};\n if (entries2) {\n let len = entries2.length;\n for (let i = 0; i < len; i++) {\n const entry = entries2[i];\n initialObj[entry[0]] = entry[1];\n }\n }\n return new ObjectMap({ items: initialObj });\n}\nfunction typesObjectMap(valueType) {\n const typeInfoGen = (t) => new ObjectMapTypeInfo(t, resolveStandardType(valueType));\n return lateTypeChecker(() => {\n const modelInfo = modelInfoByClass.get(ObjectMap);\n const valueChecker = resolveTypeChecker(valueType);\n const getTypeName = (...recursiveTypeCheckers) => `ObjectMap<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`;\n const dataTypeChecker = typesObject(() => ({\n items: typesRecord(valueChecker)\n }));\n const resolvedDataTypeChecker = resolveTypeChecker(dataTypeChecker);\n const thisTc = new TypeChecker(TypeCheckerBaseType.Object, (obj, path, typeCheckedValue) => {\n if (!(obj instanceof ObjectMap)) {\n return new TypeCheckError(path, getTypeName(thisTc), obj, typeCheckedValue);\n }\n return resolvedDataTypeChecker.check(obj.$, path, typeCheckedValue);\n }, getTypeName, typeInfoGen, (obj) => {\n if (!isObject(obj)) {\n return null;\n }\n if (obj[modelTypeKey] !== void 0) {\n return obj[modelTypeKey] === modelInfo.name ? thisTc : null;\n }\n return resolvedDataTypeChecker.snapshotType(obj) ? thisTc : null;\n }, (sn) => {\n const newItems = {};\n for (const k of Object.keys(sn.items)) {\n newItems[k] = valueChecker.fromSnapshotProcessor(sn.items[k]);\n }\n return {\n ...sn,\n [modelTypeKey]: modelInfo.name,\n items: newItems\n };\n }, (sn) => {\n const newItems = {};\n for (const k of Object.keys(sn.items)) {\n newItems[k] = valueChecker.toSnapshotProcessor(sn.items[k]);\n }\n const snCopy = {\n ...sn,\n items: newItems\n };\n return snCopy;\n });\n return thisTc;\n }, typeInfoGen);\n}\nclass ObjectMapTypeInfo extends TypeInfo {\n constructor(thisType, valueType) {\n super(thisType);\n __publicField(this, \"valueType\");\n this.valueType = valueType;\n }\n get valueTypeInfo() {\n return getTypeInfo(this.valueType);\n }\n}\nfunction typesRef(refConstructor) {\n const typeName = \"Ref\";\n const modelInfo = modelInfoByClass.get(refConstructor.refClass);\n const refDataTypeChecker = resolveTypeChecker(typesObject(() => ({\n id: typesString\n })));\n const thisTc = new TypeChecker(TypeCheckerBaseType.Object, (value, path, typeCheckedValue) => {\n if (!(value instanceof Ref)) {\n return new TypeCheckError(path, typeName, value, typeCheckedValue);\n }\n return refDataTypeChecker.check(value.$, path, typeCheckedValue);\n }, () => typeName, (t) => new RefTypeInfo(t), (obj) => {\n if (!isObject(obj)) {\n return null;\n }\n if (obj[modelTypeKey] !== void 0) {\n return obj[modelTypeKey] === modelInfo.name ? thisTc : null;\n }\n return refDataTypeChecker.snapshotType(obj) ? thisTc : null;\n }, (sn) => {\n if (sn[modelTypeKey]) {\n return sn;\n } else {\n return {\n ...sn,\n [modelTypeKey]: modelInfo.name\n };\n }\n }, (sn) => sn);\n return thisTc;\n}\nclass RefTypeInfo extends TypeInfo {\n}\nfunction enumValues(e) {\n const vals = [];\n for (const k of Object.keys(e)) {\n const v = e[k];\n if (!vals.includes(v) && (typeof v !== \"string\" && v !== +k || e[v] !== +k)) {\n vals.push(v);\n }\n }\n return vals;\n}\nfunction typesEnum(enumObject) {\n assertIsObject(enumObject, \"enumObject\");\n const literals = enumValues(enumObject).map((e) => typesLiteral(e));\n return typesOr(...literals);\n}\nfunction typesRefinement(baseType, checkFn, typeName) {\n const typeInfoGen = (t) => new RefinementTypeInfo(t, resolveStandardType(baseType), checkFn, typeName);\n return lateTypeChecker(() => {\n const baseChecker = resolveTypeChecker(baseType);\n const getTypeName = (...recursiveTypeCheckers) => {\n const baseTypeName = baseChecker.getTypeName(...recursiveTypeCheckers, baseChecker);\n const refinementName = typeName || \"refinementOf\";\n return `${refinementName}<${baseTypeName}>`;\n };\n const thisTc = new TypeChecker(\n baseChecker.baseType,\n (data, path, typeCheckedValue) => {\n const baseErr = baseChecker.check(data, path, typeCheckedValue);\n if (baseErr) {\n return baseErr;\n }\n const refinementErr = checkFn(data);\n if (refinementErr === true || refinementErr == null) {\n return null;\n } else if (refinementErr === false) {\n return new TypeCheckError(path, getTypeName(thisTc), data, typeCheckedValue);\n } else {\n return new TypeCheckError(refinementErr.path, refinementErr.expectedTypeName, refinementErr.actualValue, typeCheckedValue);\n }\n },\n getTypeName,\n typeInfoGen,\n // we cannot check refinement here since it checks data instances, not snapshots\n (sn) => baseChecker.snapshotType(sn),\n (sn) => baseChecker.fromSnapshotProcessor(sn),\n (sn) => baseChecker.toSnapshotProcessor(sn)\n );\n return thisTc;\n }, typeInfoGen);\n}\nclass RefinementTypeInfo extends TypeInfo {\n constructor(thisType, baseType, checkFunction, typeName) {\n super(thisType);\n __publicField(this, \"baseType\");\n __publicField(this, \"checkFunction\");\n __publicField(this, \"typeName\");\n this.baseType = baseType;\n this.checkFunction = checkFunction;\n this.typeName = typeName;\n }\n get baseTypeInfo() {\n return getTypeInfo(this.baseType);\n }\n}\nconst typesInteger = typesRefinement(typesNumber, (n) => Number.isInteger(n), \"integer\");\nconst typesNonEmptyString = typesRefinement(typesString, (s) => s !== \"\", \"nonEmpty\");\nfunction typesMaybe(baseType) {\n return typesOr(baseType, typesUndefined);\n}\nfunction typesMaybeNull(type) {\n return typesOr(type, typesNull);\n}\nfunction typesTag(baseType, tag2, typeName) {\n const typeInfoGen = (t) => new TagTypeInfo(t, resolveStandardType(baseType), tag2, typeName);\n return lateTypeChecker(() => {\n const baseChecker = resolveTypeChecker(baseType);\n const getTypeName = (...recursiveTypeCheckers) => {\n const baseTypeName = baseChecker.getTypeName(...recursiveTypeCheckers, baseChecker);\n const taggedName = typeName || \"tagged\";\n return `${taggedName}<${baseTypeName}>`;\n };\n const thisTc = new TypeChecker(baseChecker.baseType, (data, path, typeCheckedValue) => baseChecker.check(data, path, typeCheckedValue), getTypeName, typeInfoGen, (sn) => baseChecker.snapshotType(sn), (sn) => baseChecker.fromSnapshotProcessor(sn), (sn) => baseChecker.toSnapshotProcessor(sn));\n return thisTc;\n }, typeInfoGen);\n}\nclass TagTypeInfo extends TypeInfo {\n constructor(thisType, baseType, tag2, typeName) {\n super(thisType);\n __publicField(this, \"baseType\");\n __publicField(this, \"tag\");\n __publicField(this, \"typeName\");\n this.baseType = baseType;\n this.tag = tag2;\n this.typeName = typeName;\n }\n get baseTypeInfo() {\n return getTypeInfo(this.baseType);\n }\n}\nconst types = {\n literal: typesLiteral,\n undefined: typesUndefined,\n null: typesNull,\n boolean: typesBoolean,\n number: typesNumber,\n string: typesString,\n or: typesOr,\n maybe: typesMaybe,\n maybeNull: typesMaybeNull,\n array: typesArray,\n record: typesRecord,\n unchecked: typesUnchecked,\n model: typesModel,\n dataModelData: typesDataModelData,\n object: typesObject,\n ref: typesRef,\n frozen: typesFrozen,\n enum: typesEnum,\n tag: typesTag,\n refinement: typesRefinement,\n integer: typesInteger,\n nonEmptyString: typesNonEmptyString,\n objectMap: typesObjectMap,\n arraySet: typesArraySet,\n tuple: typesTuple,\n mapArray(valueType) {\n return typesArray(typesTuple(typesString, valueType));\n },\n setArray(valueType) {\n return typesArray(valueType);\n },\n mapObject(valueType) {\n return typesRecord(valueType);\n },\n dateString: typesNonEmptyString,\n dateTimestamp: typesInteger\n};\nexport {\n ActionContextActionType,\n ActionContextAsyncStepType,\n ActionTrackingResult,\n ArraySet,\n ArraySetTypeInfo,\n ArrayTypeInfo,\n BaseDataModel,\n BaseModel,\n BooleanTypeInfo,\n BuiltInAction,\n DataModel,\n Draft,\n ExtendedDataModel,\n ExtendedModel,\n Frozen,\n FrozenCheckMode,\n FrozenTypeInfo,\n HookAction,\n InternalPatchRecorder,\n LiteralTypeInfo,\n MobxKeystoneError,\n Model,\n ModelAutoTypeCheckingMode,\n ModelTypeInfo,\n NumberTypeInfo,\n ObjectMap,\n ObjectMapTypeInfo,\n ObjectTypeInfo,\n OrTypeInfo,\n RecordTypeInfo,\n Ref,\n RefTypeInfo,\n RefinementTypeInfo,\n SandboxManager,\n StringTypeInfo,\n TagTypeInfo,\n TupleTypeInfo,\n TypeCheckError,\n TypeInfo,\n UncheckedTypeInfo,\n UndoEventType,\n UndoManager,\n UndoStore,\n WalkTreeMode,\n _async,\n _await,\n abstractModelClass,\n actionCallToReduxAction,\n actionTrackingMiddleware,\n addActionMiddleware,\n addHiddenProp,\n addLateInitializationFunction,\n applyAction,\n applyDelete,\n applyMethodCall,\n applyPatches,\n applySerializedActionAndSyncNewModelIds,\n applySerializedActionAndTrackNewModelIds,\n applySet,\n applySnapshot,\n arrayActions,\n arraySet,\n arrayToMapTransform,\n arrayToSetTransform,\n asMap,\n asReduxStore,\n asSet,\n assertIsDataModel,\n assertIsDataModelClass,\n assertIsFunction,\n assertIsMap,\n assertIsModel,\n assertIsModelClass,\n assertIsObject,\n assertIsObservableArray,\n assertIsObservableObject,\n assertIsPlainObject,\n assertIsPrimitive,\n assertIsSet,\n assertIsString,\n assertIsTreeNode,\n assertTweakedObject,\n baseDataModelPropNames,\n baseModelPropNames,\n cannotSerialize,\n clone,\n computedTree,\n computedWalkTreeAggregate,\n connectReduxDevTools,\n createContext,\n createPatchForObjectValueChange,\n customRef,\n decoratedModel,\n deepEquals,\n deleteFromArray,\n deserializeActionCall,\n deserializeActionCallArgument,\n detach,\n draft,\n emitPatches,\n failure,\n fastGetParent,\n fastGetParentIncludingDataObjects,\n fastGetParentPath,\n fastGetParentPathIncludingDataObjects,\n fastGetRoot,\n fastGetRootPath,\n fastGetRootStore,\n fastIsModelDataObject,\n fastIsRootStore,\n findChildren,\n findParent,\n findParentPath,\n flow,\n fromSnapshot,\n fromSnapshotOverrideTypeSymbol,\n frozen,\n frozenKey,\n getActionMiddlewares,\n getChildrenObjects,\n getCurrentActionContext,\n getDataModelMetadata,\n getGlobalConfig,\n getMobxVersion,\n getModelIdPropertyName,\n getModelMetadata,\n getModelPropDefaultValue,\n getModelRefId,\n getNodeSandboxManager,\n getParent,\n getParentPath,\n getParentToChildPath,\n getRefsResolvingTo,\n getRoot,\n getRootPath,\n getRootStore,\n getSnapshot,\n getTypeInfo,\n idProp,\n identityFn,\n inDevMode,\n internalApplyDelete,\n internalApplyMethodCall,\n internalApplyPatches,\n internalApplySnapshot,\n internalCustomRef,\n internalFromSnapshot,\n internalPatchRecorder,\n isArray,\n isBuiltInAction,\n isChildOfParent,\n isComputedTreeNode,\n isDataModel,\n isDataModelClass,\n isFrozenSnapshot,\n isGlobalUndoRecordingDisabled,\n isHookAction,\n isJSONPrimitive,\n isMap,\n isModel,\n isModelAction,\n isModelAutoTypeCheckingEnabled,\n isModelClass,\n isModelDataObject,\n isModelFlow,\n isModelSnapshot,\n isObject,\n isParentOfChild,\n isPlainObject,\n isPrimitive,\n isRefOfType,\n isReservedModelKey,\n isRoot,\n isRootStore,\n isSandboxedNode,\n isSet,\n isTreeNode,\n isTweakedObject,\n isoStringToDateTransform,\n jsonPatchToPatch,\n jsonPointerToPath,\n lazy,\n logWarning,\n makePropReadonly,\n mapToArray,\n mapToObject,\n mobx6,\n model,\n modelAction,\n modelActionSymbol,\n modelClass,\n modelFlow,\n modelIdKey,\n modelIdPropertyNameSymbol,\n modelInitializedSymbol,\n modelSnapshotInWithMetadata,\n modelSnapshotOutWithMetadata,\n modelTypeKey,\n namespace$2 as namespace,\n noDefaultValue,\n objectActions,\n objectMap,\n objectToMapTransform,\n observableOptions,\n onActionMiddleware,\n onChildAttachedTo,\n onGlobalPatches,\n onPatches,\n onSnapshot,\n patchRecorder,\n patchToJsonPatch,\n pathToJsonPointer,\n prop,\n propNameToSetterName,\n propsTypeSymbol,\n readonlyMiddleware,\n reduxActionType,\n registerActionCallArgumentSerializer,\n registerRootStore,\n registerSnapshotter,\n registerTweaker,\n resolveId,\n resolvePath,\n resolvePathCheckingIds,\n rootRef,\n runAfterNewSymbol,\n runBeforeOnInitSymbol,\n runLateInitializationFunctions,\n runUnprotected,\n runWithoutSnapshotOrPatches,\n runningWithoutSnapshotOrPatches,\n sandbox,\n serializeActionCall,\n serializeActionCallArgument,\n setCurrentActionContext,\n setGlobalConfig,\n setToArray,\n simplifyActionContext,\n skipIdChecking,\n standaloneAction,\n standaloneFlow,\n stringToBigIntTransform,\n tProp,\n tag,\n timestampToDateTransform,\n toSnapshotOverrideTypeSymbol,\n toTreeNode,\n transaction,\n transactionMiddleware,\n tryUntweak,\n tweak,\n tweakedObjects,\n typeCheck,\n types,\n undoMiddleware,\n unregisterRootStore,\n walkTree,\n withoutUndo\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9ieC1rZXlzdG9uZS5lc20ubWpzIiwic291cmNlcyI6WyIuLi9zcmMvZGF0YU1vZGVsL2FjdGlvbnMudHMiLCIuLi9zcmMvYWN0aW9uL2J1aWx0SW5BY3Rpb25zLnRzIiwiLi4vc3JjL2FjdGlvbi9jb250ZXh0LnRzIiwiLi4vc3JjL2FjdGlvbi9pc01vZGVsQWN0aW9uLnRzIiwiLi4vc3JjL21vZGVsL21ldGFkYXRhLnRzIiwiLi4vc3JjL3V0aWxzL2luZGV4LnRzIiwiLi4vc3JjL21vZGVsU2hhcmVkL0Jhc2VNb2RlbFNoYXJlZC50cyIsIi4uL3NyYy9tb2RlbFNoYXJlZC9tb2RlbEluZm8udHMiLCIuLi9zcmMvdXRpbHMvbWFwVXRpbHMudHMiLCIuLi9zcmMvcGFyZW50L2NvcmUudHMiLCIuLi9zcmMvdHdlYWtlci9jb3JlLnRzIiwiLi4vc3JjL21vZGVsU2hhcmVkL21vZGVsU3ltYm9scy50cyIsIi4uL3NyYy9tb2RlbFNoYXJlZC9tb2RlbFByb3BzSW5mby50cyIsIi4uL3NyYy9tb2RlbFNoYXJlZC9wcm9wLnRzIiwiLi4vbm9kZV9tb2R1bGVzL25hbm9pZC9ub24tc2VjdXJlL2luZGV4LmpzIiwiLi4vc3JjL2dsb2JhbENvbmZpZy9nbG9iYWxDb25maWcudHMiLCIuLi9zcmMvcGFyZW50L2NvcmVPYmplY3RDaGlsZHJlbi50cyIsIi4uL3NyYy9hY3Rpb24vcHJvdGVjdGlvbi50cyIsIi4uL3NyYy9hY3Rpb24vcGVuZGluZ0FjdGlvbnMudHMiLCIuLi9zcmMvbW9kZWwvZ2V0TW9kZWxNZXRhZGF0YS50cyIsIi4uL3NyYy9hY3Rpb24vaG9va0FjdGlvbnMudHMiLCIuLi9zcmMvcGFyZW50L3dhbGtUcmVlLnRzIiwiLi4vc3JjL3Jvb3RTdG9yZS9hdHRhY2hEZXRhY2gudHMiLCIuLi9zcmMvcm9vdFN0b3JlL3Jvb3RTdG9yZS50cyIsIi4uL3NyYy90eXBlcy9UeXBlQ2hlY2tFcnJvci50cyIsIi4uL3NyYy90eXBlcy9UeXBlQ2hlY2tlci50cyIsIi4uL3NyYy9zbmFwc2hvdC9pbnRlcm5hbC50cyIsIi4uL3NyYy9wYXRjaC9lbWl0UGF0Y2gudHMiLCIuLi9zcmMvdXRpbHMvc2V0SWZEaWZmZXJlbnQudHMiLCIuLi9zcmMvdHdlYWtlci9Ud2Vha2VyUHJpb3JpdHkudHMiLCIuLi9zcmMvcGFyZW50L2ZpbmRQYXJlbnQudHMiLCIuLi9zcmMvcGFyZW50L2dldENoaWxkcmVuT2JqZWN0cy50cyIsIi4uL3NyYy9wYXJlbnQvZmluZENoaWxkcmVuLnRzIiwiLi4vc3JjL3BhcmVudC9vbkNoaWxkQXR0YWNoZWRUby50cyIsIi4uL3NyYy9wYXJlbnQvcGF0aDIudHMiLCIuLi9zcmMvdHdlYWtlci93aXRob3V0VHlwZUNoZWNraW5nLnRzIiwiLi4vc3JjL3NuYXBzaG90L1NuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5LnRzIiwiLi4vc3JjL3NuYXBzaG90L3JlY29uY2lsZUFycmF5U25hcHNob3QudHMiLCIuLi9zcmMvZnJvemVuL0Zyb3plbi50cyIsIi4uL3NyYy9zbmFwc2hvdC9yZWNvbmNpbGVGcm96ZW5TbmFwc2hvdC50cyIsIi4uL25vZGVfbW9kdWxlcy9mYXN0LWRlZXAtZXF1YWwvZXM2L2luZGV4LmpzIiwiLi4vc3JjL3V0aWxzL01vZGVsUG9vbC50cyIsIi4uL3NyYy9zbmFwc2hvdC9hcHBseVNuYXBzaG90LnRzIiwiLi4vc3JjL3NuYXBzaG90L29uU25hcHNob3QudHMiLCIuLi9zcmMvdHJlZVV0aWxzL2RlZXBFcXVhbHMudHMiLCIuLi9zcmMvc25hcHNob3QvcmVjb25jaWxlTW9kZWxTbmFwc2hvdC50cyIsIi4uL3NyYy9zbmFwc2hvdC9yZWNvbmNpbGVQbGFpbk9iamVjdFNuYXBzaG90LnRzIiwiLi4vc3JjL3NuYXBzaG90L3JlZ2lzdGVyRGVmYXVsdFJlY29uY2lsZXJzLnRzIiwiLi4vc3JjL3NuYXBzaG90L3JlY29uY2lsZVNuYXBzaG90LnRzIiwiLi4vc3JjL3BhdGNoL2FwcGx5UGF0Y2hlcy50cyIsIi4uL3NyYy90d2Vha2VyL3R5cGVDaGVja2luZy50cyIsIi4uL3NyYy90d2Vha2VyL3R3ZWFrQXJyYXkudHMiLCIuLi9zcmMvc25hcHNob3QvZnJvbUFycmF5U25hcHNob3QudHMiLCIuLi9zcmMvc25hcHNob3QvZnJvbUZyb3plblNuYXBzaG90LnRzIiwiLi4vc3JjL3NuYXBzaG90L2Zyb21Nb2RlbFNuYXBzaG90LnRzIiwiLi4vc3JjL3R3ZWFrZXIvdHdlYWtQbGFpbk9iamVjdC50cyIsIi4uL3NyYy9zbmFwc2hvdC9mcm9tUGxhaW5PYmplY3RTbmFwc2hvdC50cyIsIi4uL3NyYy9zbmFwc2hvdC9yZWdpc3RlckRlZmF1bHRTbmFwc2hvdHRlcnMudHMiLCIuLi9zcmMvc25hcHNob3QvZnJvbVNuYXBzaG90LnRzIiwiLi4vc3JjL3NuYXBzaG90L2Nsb25lLnRzIiwiLi4vc3JjL3BhcmVudC9zZXRQYXJlbnQudHMiLCIuLi9zcmMvdHlwZXMvdHlwZUNoZWNrLnRzIiwiLi4vc3JjL3R3ZWFrZXIvdHdlYWtGcm96ZW4udHMiLCIuLi9zcmMvdHdlYWtlci90d2Vha01vZGVsLnRzIiwiLi4vc3JjL3R3ZWFrZXIvcmVnaXN0ZXJEZWZhdWx0VHdlYWtlcnMudHMiLCIuLi9zcmMvdHdlYWtlci90d2Vhay50cyIsIi4uL3NyYy9tb2RlbFNoYXJlZC9tb2RlbENsYXNzSW5pdGlhbGl6ZXIudHMiLCIuLi9zcmMvbW9kZWxTaGFyZWQvbmV3TW9kZWwudHMiLCIuLi9zcmMvZGF0YU1vZGVsL25ld0RhdGFNb2RlbC50cyIsIi4uL3NyYy9kYXRhTW9kZWwvQmFzZURhdGFNb2RlbC50cyIsIi4uL3NyYy9kYXRhTW9kZWwvdXRpbHMudHMiLCIuLi9zcmMvZGF0YU1vZGVsL2dldERhdGFNb2RlbE1ldGFkYXRhLnRzIiwiLi4vc3JjL3R5cGVzL2dldFR5cGVJbmZvLnRzIiwiLi4vc3JjL3R5cGVzL29iamVjdEJhc2VkL3R5cGVzRGF0YU1vZGVsRGF0YS50cyIsIi4uL3NyYy90eXBlcy9vYmplY3RCYXNlZC90eXBlc01vZGVsLnRzIiwiLi4vc3JjL3R5cGVzL3ByaW1pdGl2ZUJhc2VkL3R5cGVzUHJpbWl0aXZlLnRzIiwiLi4vc3JjL3R5cGVzL3JlZ2lzdGVyRGVmYXVsdFN0YW5kYXJkVHlwZVJlc29sdmVycy50cyIsIi4uL3NyYy90eXBlcy9yZXNvbHZlVHlwZUNoZWNrZXIudHMiLCIuLi9zcmMvc25hcHNob3QvZ2V0U25hcHNob3QudHMiLCIuLi9zcmMvbW9kZWwvbmV3TW9kZWwudHMiLCIuLi9zcmMvbW9kZWwvQmFzZU1vZGVsLnRzIiwiLi4vc3JjL21vZGVsL3V0aWxzLnRzIiwiLi4vc3JjL3BhcmVudC9wYXRoLnRzIiwiLi4vc3JjL2FjdGlvbi9taWRkbGV3YXJlLnRzIiwiLi4vc3JjL2FjdGlvbi93cmFwSW5BY3Rpb24udHMiLCIuLi9zcmMvcGFyZW50L2RldGFjaC50cyIsIi4uL3NyYy91dGlscy9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL2FjdGlvbi9tb2RlbEZsb3cudHMiLCIuLi9zcmMvc3RhbmRhcmRBY3Rpb25zL2FjdGlvbnMudHMiLCIuLi9zcmMvYWN0aW9uL2FwcGx5RGVsZXRlLnRzIiwiLi4vc3JjL2FjdGlvbi9hcHBseU1ldGhvZENhbGwudHMiLCIuLi9zcmMvYWN0aW9uL2FwcGx5U2V0LnRzIiwiLi4vc3JjL2FjdGlvbi9hcHBseUFjdGlvbi50cyIsIi4uL3NyYy9hY3Rpb24vbW9kZWxBY3Rpb24udHMiLCIuLi9zcmMvYWN0aW9uL3J1blVucHJvdGVjdGVkLnRzIiwiLi4vc3JjL2FjdGlvbk1pZGRsZXdhcmVzL2FjdGlvblNlcmlhbGl6YXRpb24vY29yZS50cyIsIi4uL3NyYy9hY3Rpb25NaWRkbGV3YXJlcy9hY3Rpb25TZXJpYWxpemF0aW9uL2FycmF5U2VyaWFsaXplci50cyIsIi4uL3NyYy9hY3Rpb25NaWRkbGV3YXJlcy9hY3Rpb25TZXJpYWxpemF0aW9uL2RhdGVTZXJpYWxpemVyLnRzIiwiLi4vc3JjL2FjdGlvbk1pZGRsZXdhcmVzL2FjdGlvblNlcmlhbGl6YXRpb24vbWFwU2VyaWFsaXplci50cyIsIi4uL3NyYy9hY3Rpb25NaWRkbGV3YXJlcy91dGlscy50cyIsIi4uL3NyYy9hY3Rpb25NaWRkbGV3YXJlcy9hY3Rpb25TZXJpYWxpemF0aW9uL29iamVjdFBhdGhTZXJpYWxpemVyLnRzIiwiLi4vc3JjL2FjdGlvbk1pZGRsZXdhcmVzL2FjdGlvblNlcmlhbGl6YXRpb24vb2JqZWN0U25hcHNob3RTZXJpYWxpemVyLnRzIiwiLi4vc3JjL2FjdGlvbk1pZGRsZXdhcmVzL2FjdGlvblNlcmlhbGl6YXRpb24vcGxhaW5PYmplY3RTZXJpYWxpemVyLnRzIiwiLi4vc3JjL2FjdGlvbk1pZGRsZXdhcmVzL2FjdGlvblNlcmlhbGl6YXRpb24vcHJpbWl0aXZlU2VyaWFsaXplci50cyIsIi4uL3NyYy9hY3Rpb25NaWRkbGV3YXJlcy9hY3Rpb25TZXJpYWxpemF0aW9uL3NldFNlcmlhbGl6ZXIudHMiLCIuLi9zcmMvYWN0aW9uTWlkZGxld2FyZXMvYWN0aW9uU2VyaWFsaXphdGlvbi9hY3Rpb25TZXJpYWxpemF0aW9uLnRzIiwiLi4vc3JjL2FjdGlvbk1pZGRsZXdhcmVzL2FjdGlvblNlcmlhbGl6YXRpb24vYXBwbHlTZXJpYWxpemVkQWN0aW9uLnRzIiwiLi4vc3JjL2FjdGlvbk1pZGRsZXdhcmVzL2FjdGlvblRyYWNraW5nTWlkZGxld2FyZS50cyIsIi4uL3NyYy9hY3Rpb25NaWRkbGV3YXJlcy9vbkFjdGlvbk1pZGRsZXdhcmUudHMiLCIuLi9zcmMvYWN0aW9uTWlkZGxld2FyZXMvcmVhZG9ubHlNaWRkbGV3YXJlLnRzIiwiLi4vc3JjL3BhdGNoL2pzb25QYXRjaC50cyIsIi4uL3NyYy9wYXRjaC9wYXRjaFJlY29yZGVyLnRzIiwiLi4vc3JjL2FjdGlvbk1pZGRsZXdhcmVzL3RyYW5zYWN0aW9uTWlkZGxld2FyZS50cyIsIi4uL3NyYy90eXBlcy9vYmplY3RCYXNlZC90eXBlc09iamVjdC50cyIsIi4uL3NyYy90eXBlcy91dGlsaXR5L3R5cGVzVW5jaGVja2VkLnRzIiwiLi4vc3JjL3R5cGVzL3V0aWxpdHkvdHlwZXNPci50cyIsIi4uL3NyYy90eXBlcy90UHJvcC50cyIsIi4uL3NyYy91dGlscy9jaGFpbkZucy50cyIsIi4uL3NyYy9tb2RlbFNoYXJlZC91dGlscy50cyIsIi4uL3NyYy9tb2RlbFNoYXJlZC9zaGFyZWRJbnRlcm5hbE1vZGVsLnRzIiwiLi4vc3JjL21vZGVsL01vZGVsLnRzIiwiLi4vc3JjL21vZGVsU2hhcmVkL21vZGVsRGVjb3JhdG9yLnRzIiwiLi4vc3JjL3R5cGVzL2FycmF5QmFzZWQvdHlwZXNBcnJheS50cyIsIi4uL3NyYy9hY3Rpb25NaWRkbGV3YXJlcy91bmRvTWlkZGxld2FyZS50cyIsIi4uL3NyYy9jb250ZXh0L2NvbnRleHQudHMiLCIuLi9zcmMvY29tcHV0ZWRUcmVlL2NvbXB1dGVkVHJlZS50cyIsIi4uL3NyYy9kYXRhTW9kZWwvRGF0YU1vZGVsLnRzIiwiLi4vc3JjL3JlZHV4L2Nvbm5lY3RSZWR1eERldlRvb2xzLnRzIiwiLi4vc3JjL3JlZHV4L3JlZHV4LnRzIiwiLi4vc3JjL3JlZi9SZWYudHMiLCIuLi9zcmMvcmVmL2NvcmUudHMiLCIuLi9zcmMvcmVmL2N1c3RvbVJlZi50cyIsIi4uL3NyYy9yZWYvcm9vdFJlZi50cyIsIi4uL3NyYy9zdGFuZGFyZEFjdGlvbnMvc3RhbmRhbG9uZUFjdGlvbnMudHMiLCIuLi9zcmMvc3RhbmRhcmRBY3Rpb25zL2FycmF5QWN0aW9ucy50cyIsIi4uL3NyYy9zdGFuZGFyZEFjdGlvbnMvb2JqZWN0QWN0aW9ucy50cyIsIi4uL3NyYy91dGlscy90YWcudHMiLCIuLi9zcmMvd3JhcHBlcnMvYXNNYXAudHMiLCIuLi9zcmMvdHJhbnNmb3Jtcy9hc01hcC50cyIsIi4uL3NyYy93cmFwcGVycy9hc1NldC50cyIsIi4uL3NyYy90cmFuc2Zvcm1zL2FzU2V0LnRzIiwiLi4vc3JjL3RyYW5zZm9ybXMvYmlnaW50LnRzIiwiLi4vc3JjL3RyYW5zZm9ybXMvSW1tdXRhYmxlRGF0ZS50cyIsIi4uL3NyYy90cmFuc2Zvcm1zL2RhdGUudHMiLCIuLi9zcmMvdHJlZVV0aWxzL2RyYWZ0LnRzIiwiLi4vc3JjL3RyZWVVdGlscy9zYW5kYm94LnRzIiwiLi4vc3JjL3R5cGVzL2FycmF5QmFzZWQvdHlwZXNUdXBsZS50cyIsIi4uL3NyYy93cmFwcGVycy9BcnJheVNldC50cyIsIi4uL3NyYy90eXBlcy9vYmplY3RCYXNlZC90eXBlc0FycmF5U2V0LnRzIiwiLi4vc3JjL3R5cGVzL29iamVjdEJhc2VkL3R5cGVzUmVjb3JkLnRzIiwiLi4vc3JjL3dyYXBwZXJzL09iamVjdE1hcC50cyIsIi4uL3NyYy90eXBlcy9vYmplY3RCYXNlZC90eXBlc09iamVjdE1hcC50cyIsIi4uL3NyYy90eXBlcy9vYmplY3RCYXNlZC90eXBlc1JlZi50cyIsIi4uL3NyYy90eXBlcy9wcmltaXRpdmVCYXNlZC90eXBlc0VudW0udHMiLCIuLi9zcmMvdHlwZXMvdXRpbGl0eS90eXBlc1JlZmluZW1lbnQudHMiLCIuLi9zcmMvdHlwZXMvcHJpbWl0aXZlQmFzZWQvdHlwZXNSZWZpbmVkUHJpbWl0aXZlLnRzIiwiLi4vc3JjL3R5cGVzL3V0aWxpdHkvdHlwZXNNYXliZS50cyIsIi4uL3NyYy90eXBlcy91dGlsaXR5L3R5cGVzVGFnLnRzIiwiLi4vc3JjL3R5cGVzL3R5cGVzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcbmltcG9ydCB0eXBlIHsgQW55RGF0YU1vZGVsIH0gZnJvbSBcIi4vQmFzZURhdGFNb2RlbFwiXG5cbmNvbnN0IGRhdGFNb2RlbEFjdGlvblJlZ2lzdHJ5ID0gbmV3IE1hcDxcbiAgc3RyaW5nLFxuICB7XG4gICAgbW9kZWxDbGFzczogTW9kZWxDbGFzczxBbnlEYXRhTW9kZWw+XG4gICAgZm5OYW1lOiBzdHJpbmdcbiAgfVxuPigpXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXRhTW9kZWxBY3Rpb24oZnVsbEFjdGlvbk5hbWU6IHN0cmluZykge1xuICByZXR1cm4gZGF0YU1vZGVsQWN0aW9uUmVnaXN0cnkuZ2V0KGZ1bGxBY3Rpb25OYW1lKVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0RGF0YU1vZGVsQWN0aW9uKFxuICBmdWxsQWN0aW9uTmFtZTogc3RyaW5nLFxuICBtb2RlbENsYXNzOiBNb2RlbENsYXNzPEFueURhdGFNb2RlbD4sXG4gIGZuTmFtZTogc3RyaW5nXG4pIHtcbiAgZGF0YU1vZGVsQWN0aW9uUmVnaXN0cnkuc2V0KGZ1bGxBY3Rpb25OYW1lLCB7XG4gICAgbW9kZWxDbGFzcyxcbiAgICBmbk5hbWUsXG4gIH0pXG59XG4iLCIvKipcbiAqIEEgYnVpbHQtaW4gYWN0aW9uLlxuICovXG5leHBvcnQgZW51bSBCdWlsdEluQWN0aW9uIHtcbiAgLyoqXG4gICAqIGFwcGx5UGF0Y2hlc1xuICAgKi9cbiAgQXBwbHlQYXRjaGVzID0gXCIkJGFwcGx5UGF0Y2hlc1wiLFxuICAvKipcbiAgICogYXBwbHlTbmFwc2hvdFxuICAgKi9cbiAgQXBwbHlTbmFwc2hvdCA9IFwiJCRhcHBseVNuYXBzaG90XCIsXG4gIC8qKlxuICAgKiBkZXRhY2hcbiAgICovXG4gIERldGFjaCA9IFwiJCRkZXRhY2hcIixcbiAgLyoqXG4gICAqIGFwcGx5U2V0XG4gICAqL1xuICBBcHBseVNldCA9IFwiJCRhcHBseVNldFwiLFxuICAvKipcbiAgICogYXBwbHlEZWxldGVcbiAgICovXG4gIEFwcGx5RGVsZXRlID0gXCIkJGFwcGx5RGVsZXRlXCIsXG4gIC8qKlxuICAgKiBhcHBseU1ldGhvZENhbGxcbiAgICovXG4gIEFwcGx5TWV0aG9kQ2FsbCA9IFwiJCRhcHBseU1ldGhvZENhbGxcIixcbn1cblxuY29uc3QgYnVpbHRJbkFjdGlvblZhbHVlczogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoT2JqZWN0LnZhbHVlcyhCdWlsdEluQWN0aW9uKSlcblxuLyoqXG4gKiBSZXR1cm5zIGlmIGEgZ2l2ZW4gYWN0aW9uIG5hbWUgaXMgYSBidWlsdC1pbiBhY3Rpb24sIHRoaXMgaXMsIG9uZSBvZjpcbiAqIC0gYXBwbHlQYXRjaGVzKClcbiAqIC0gYXBwbHlTbmFwc2hvdCgpXG4gKiAtIGRldGFjaCgpXG4gKlxuICogQHBhcmFtIGFjdGlvbk5hbWUgQWN0aW9uIG5hbWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB0cnVlIGlmIGl0IGlzIGEgYnVpbHQtaW4gYWN0aW9uLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0J1aWx0SW5BY3Rpb24oYWN0aW9uTmFtZTogc3RyaW5nKTogYWN0aW9uTmFtZSBpcyBCdWlsdEluQWN0aW9uIHtcbiAgcmV0dXJuIGJ1aWx0SW5BY3Rpb25WYWx1ZXMuaGFzKGFjdGlvbk5hbWUpXG59XG4iLCJpbXBvcnQgdHlwZSB7IEFueU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Jhc2VNb2RlbFwiXG5cbi8qKlxuICogTG93IGxldmVsIGFjdGlvbiBjb250ZXh0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFjdGlvbkNvbnRleHQge1xuICAvKipcbiAgICogQWN0aW9uIG5hbWVcbiAgICovXG4gIHJlYWRvbmx5IGFjdGlvbk5hbWU6IHN0cmluZ1xuICAvKipcbiAgICogQWN0aW9uIHR5cGUsIHN5bmMgb3IgYXN5bmMuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZVxuICAvKipcbiAgICogQWN0aW9uIHRhcmdldCBvYmplY3QuXG4gICAqL1xuICByZWFkb25seSB0YXJnZXQ6IEFueU1vZGVsXG4gIC8qKlxuICAgKiBBcnJheSBvZiBhY3Rpb24gYXJndW1lbnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgYXJnczogUmVhZG9ubHlBcnJheTxhbnk+XG4gIC8qKlxuICAgKiBQYXJlbnQgYWN0aW9uIGNvbnRleHQsIGlmIGFueS5cbiAgICovXG4gIHJlYWRvbmx5IHBhcmVudENvbnRleHQ/OiBBY3Rpb25Db250ZXh0XG4gIC8qKlxuICAgKiBSb290IGFjdGlvbiBjb250ZXh0LCBvciBpdHNlbGYgaWYgdGhlIHJvb3QuXG4gICAqL1xuICByZWFkb25seSByb290Q29udGV4dDogQWN0aW9uQ29udGV4dFxuICAvKipcbiAgICogUHJldmlvdXMgYXN5bmMgc3RlcCBjb250ZXh0LCB1bmRlZmluZWQgZm9yIHN5bmMgYWN0aW9ucyBvciB0aGUgZmlyc3QgYWN0aW9uIG9mIGEgZmxvdy5cbiAgICovXG4gIHJlYWRvbmx5IHByZXZpb3VzQXN5bmNTdGVwQ29udGV4dD86IEFjdGlvbkNvbnRleHRcbiAgLyoqXG4gICAqIFNwYXduIGFzeW5jIHN0ZXAgY29udGV4dCwgdW5kZWZpbmVkIGZvciBzeW5jIGFjdGlvbnMuXG4gICAqL1xuICByZWFkb25seSBzcGF3bkFzeW5jU3RlcENvbnRleHQ/OiBBY3Rpb25Db250ZXh0XG4gIC8qKlxuICAgKiBBc3luYyBzdGVwIHR5cGUsIG9yIHVuZGVmaW5lZCBmb3Igc3luYyBhY3Rpb25zLlxuICAgKi9cbiAgcmVhZG9ubHkgYXN5bmNTdGVwVHlwZT86IEFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlXG4gIC8qKlxuICAgKiBDdXN0b20gZGF0YSBmb3IgdGhlIGFjdGlvbiBjb250ZXh0IHRvIGJlIHNldCBieSBtaWRkbGV3YXJlcywgYW4gb2JqZWN0LlxuICAgKiBTeW1ib2xzIG11c3QgYmUgdXNlZCBhcyBrZXlzIHRvIGF2b2lkIG5hbWUgY2xhc2hpbmcgYmV0d2VlbiBtaWRkbGV3YXJlcy5cbiAgICovXG4gIHJlYWRvbmx5IGRhdGE6IFJlY29yZDxzeW1ib2wsIGFueT5cbn1cblxuLyoqXG4gKiBBY3Rpb24gdHlwZSwgc3luYyBvciBhc3luYy5cbiAqL1xuZXhwb3J0IGVudW0gQWN0aW9uQ29udGV4dEFjdGlvblR5cGUge1xuICBTeW5jID0gXCJzeW5jXCIsXG4gIEFzeW5jID0gXCJhc3luY1wiLFxufVxuXG4vKipcbiAqIEFuIGFzeW5jIHN0ZXAgdHlwZS5cbiAqL1xuZXhwb3J0IGVudW0gQWN0aW9uQ29udGV4dEFzeW5jU3RlcFR5cGUge1xuICAvKipcbiAgICogVGhlIGZsb3cgaXMgYWJvdXQgdG8gc3RhcnQuXG4gICAqL1xuICBTcGF3biA9IFwic3Bhd25cIixcbiAgLyoqXG4gICAqIFRoZSBmbG93IGlzIGFib3V0IHRvIHJldHVybiAoZmluaXNoKS5cbiAgICovXG4gIFJldHVybiA9IFwicmV0dXJuXCIsXG4gIC8qKlxuICAgKiBUaGUgZmxvdyBpcyBhYm91dCB0byBjb250aW51ZS5cbiAgICovXG4gIFJlc3VtZSA9IFwicmVzdW1lXCIsXG4gIC8qKlxuICAgKiBUaGUgZmxvdyB5aWVsZCBqdXN0IHRocmV3LCB3aGljaCBtaWdodCBiZSByZWNvdmVyZWQgKGNhdWdodCkgb3Igbm90LlxuICAgKi9cbiAgUmVzdW1lRXJyb3IgPSBcInJlc3VtZUVycm9yXCIsXG4gIC8qKlxuICAgKiBUaGUgZmxvdyBpcyBhYm91dCB0byB0aHJvdyBhbiBlcnJvciB0byB0aGUgZmxvdyBjYWxsZXIuXG4gICAqL1xuICBUaHJvdyA9IFwidGhyb3dcIixcbn1cblxubGV0IGN1cnJlbnRBY3Rpb25Db250ZXh0OiBBY3Rpb25Db250ZXh0IHwgdW5kZWZpbmVkXG5cbi8qKlxuICogR2V0cyB0aGUgY3VycmVudGx5IHJ1bm5pbmcgYWN0aW9uIGNvbnRleHQsIG9yIHVuZGVmaW5lZCBpZiBub25lLlxuICpcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDdXJyZW50QWN0aW9uQ29udGV4dCgpOiBBY3Rpb25Db250ZXh0IHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIGN1cnJlbnRBY3Rpb25Db250ZXh0XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKlxuICogU2V0cyB0aGUgY3VycmVudCBhY3Rpb24gY29udGV4dC5cbiAqXG4gKiBAcGFyYW0gY3R4IEN1cnJlbnQgYWN0aW9uIGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRDdXJyZW50QWN0aW9uQ29udGV4dChjdHg6IEFjdGlvbkNvbnRleHQgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgY3VycmVudEFjdGlvbkNvbnRleHQgPSBjdHhcbn1cbiIsIi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjb25zdCBtb2RlbEFjdGlvblN5bWJvbCA9IFN5bWJvbChcIm1vZGVsQWN0aW9uXCIpXG5cbi8qKlxuICogUmV0dXJucyBpZiB0aGUgZ2l2ZW4gZnVuY3Rpb24gaXMgYSBtb2RlbCBhY3Rpb24gb3Igbm90LlxuICpcbiAqIEBwYXJhbSBmbiBGdW5jdGlvbiB0byBjaGVjay5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc01vZGVsQWN0aW9uKGZuOiAoLi4uYXJnczogYW55W10pID0+IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZW9mIGZuID09PSBcImZ1bmN0aW9uXCIgJiYgbW9kZWxBY3Rpb25TeW1ib2wgaW4gZm5cbn1cbiIsIi8qKlxuICogS2V5IHdoZXJlIG1vZGVsIHNuYXBzaG90cyB3aWxsIHN0b3JlIG1vZGVsIHR5cGUgbWV0YWRhdGEuXG4gKi9cbmV4cG9ydCBjb25zdCBtb2RlbFR5cGVLZXkgPSBcIiRtb2RlbFR5cGVcIlxuXG4vKipcbiAqIEtleSB0aGF0IHNlcnZlcyBhcyBwcm94eSB0byB0aGUgbW9kZWwgcHJvcGVydHkgZGVzaWduZWQgYXMgJ2lkUHJvcCcgKGlmIGFueSkuXG4gKi9cbmV4cG9ydCBjb25zdCBtb2RlbElkS2V5ID0gXCIkbW9kZWxJZFwiXG5cbi8qKlxuICogQGludGVybmFsXG4gKiBSZXR1cm5zIGlmIGEgZ2l2ZW4ga2V5IGlzIGEgcmVzZXJ2ZWQga2V5IGluIG1vZGVsIHNuYXBzaG90cy5cbiAqXG4gKiBAcGFyYW0ga2V5XG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZXNlcnZlZE1vZGVsS2V5KGtleTogc3RyaW5nKSB7XG4gIC8vIG5vdGUgJG1vZGVsSWQgaXMgTk9UIGEgcmVzZXJ2ZWQga2V5LCBzaW5jZSBpdCB3aWxsIGV2ZW50dWFsbHkgZW5kIHVwIGluIHRoZSBkYXRhXG4gIC8vIGFuZCBjYW4gYWN0dWFsbHkgYmUgY2hhbmdlZFxuICByZXR1cm4ga2V5ID09PSBtb2RlbFR5cGVLZXlcbn1cbiIsImltcG9ydCAqIGFzIG1vYnggZnJvbSBcIm1vYnhcIlxyXG5pbXBvcnQge1xyXG4gIElPYnNlcnZhYmxlQXJyYXksXHJcbiAgaXNPYnNlcnZhYmxlQXJyYXksXHJcbiAgaXNPYnNlcnZhYmxlTWFwLFxyXG4gIGlzT2JzZXJ2YWJsZU9iamVjdCxcclxuICBpc09ic2VydmFibGVTZXQsXHJcbiAgT2JzZXJ2YWJsZU1hcCxcclxuICBPYnNlcnZhYmxlU2V0LFxyXG59IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHsgSlNPTlByaW1pdGl2ZVZhbHVlLCBQcmltaXRpdmVWYWx1ZSB9IGZyb20gXCIuL3R5cGVzXCJcclxuXHJcbi8qKlxyXG4gKiBBIG1vYngta2V5c3RvbmUgZXJyb3IuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgTW9ieEtleXN0b25lRXJyb3IgZXh0ZW5kcyBFcnJvciB7XHJcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcpIHtcclxuICAgIHN1cGVyKG1zZylcclxuXHJcbiAgICAvLyBTZXQgdGhlIHByb3RvdHlwZSBleHBsaWNpdGx5LlxyXG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIE1vYnhLZXlzdG9uZUVycm9yLnByb3RvdHlwZSlcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmYWlsdXJlKG1zZzogc3RyaW5nKSB7XHJcbiAgcmV0dXJuIG5ldyBNb2J4S2V5c3RvbmVFcnJvcihtc2cpXHJcbn1cclxuXHJcbmNvbnN0IHdyaXRhYmxlSGlkZGVuUHJvcERlc2NyaXB0b3I6IFByb3BlcnR5RGVzY3JpcHRvciA9IHtcclxuICBlbnVtZXJhYmxlOiBmYWxzZSxcclxuICB3cml0YWJsZTogdHJ1ZSxcclxuICBjb25maWd1cmFibGU6IGZhbHNlLFxyXG4gIHZhbHVlOiB1bmRlZmluZWQsXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhZGRIaWRkZW5Qcm9wKG9iamVjdDogYW55LCBwcm9wTmFtZTogUHJvcGVydHlLZXksIHZhbHVlOiBhbnksIHdyaXRhYmxlID0gdHJ1ZSkge1xyXG4gIGlmICh3cml0YWJsZSkge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcE5hbWUsIHdyaXRhYmxlSGlkZGVuUHJvcERlc2NyaXB0b3IpXHJcbiAgICBvYmplY3RbcHJvcE5hbWVdID0gdmFsdWVcclxuICB9IGVsc2Uge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcE5hbWUsIHtcclxuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXHJcbiAgICAgIHdyaXRhYmxlLFxyXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXHJcbiAgICAgIHZhbHVlLFxyXG4gICAgfSlcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBtYWtlUHJvcFJlYWRvbmx5PFQ+KG9iamVjdDogVCwgcHJvcE5hbWU6IGtleW9mIFQsIGVudW1lcmFibGU6IGJvb2xlYW4pIHtcclxuICBjb25zdCBwcm9wRGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wTmFtZSlcclxuICBpZiAocHJvcERlc2MpIHtcclxuICAgIHByb3BEZXNjLmVudW1lcmFibGUgPSBlbnVtZXJhYmxlXHJcbiAgICBpZiAocHJvcERlc2MuZ2V0KSB7XHJcbiAgICAgIGRlbGV0ZSBwcm9wRGVzYy5zZXRcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHByb3BEZXNjLndyaXRhYmxlID0gZmFsc2VcclxuICAgIH1cclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmplY3QsIHByb3BOYW1lLCBwcm9wRGVzYylcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1BsYWluT2JqZWN0KHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgUmVjb3JkPFByb3BlcnR5S2V5LCB1bmtub3duPiB7XHJcbiAgaWYgKCFpc09iamVjdCh2YWx1ZSkpIHJldHVybiBmYWxzZVxyXG4gIGNvbnN0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKVxyXG4gIHJldHVybiBwcm90byA9PT0gT2JqZWN0LnByb3RvdHlwZSB8fCBwcm90byA9PT0gbnVsbFxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaXNPYmplY3QodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBSZWNvcmQ8UHJvcGVydHlLZXksIHVua25vd24+IHtcclxuICByZXR1cm4gdmFsdWUgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1ByaW1pdGl2ZSh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFByaW1pdGl2ZVZhbHVlIHtcclxuICBzd2l0Y2ggKHR5cGVvZiB2YWx1ZSkge1xyXG4gICAgY2FzZSBcIm51bWJlclwiOlxyXG4gICAgY2FzZSBcInN0cmluZ1wiOlxyXG4gICAgY2FzZSBcImJvb2xlYW5cIjpcclxuICAgIGNhc2UgXCJ1bmRlZmluZWRcIjpcclxuICAgIGNhc2UgXCJiaWdpbnRcIjpcclxuICAgICAgcmV0dXJuIHRydWVcclxuICB9XHJcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc0pTT05QcmltaXRpdmUodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBKU09OUHJpbWl0aXZlVmFsdWUge1xyXG4gIHN3aXRjaCAodHlwZW9mIHZhbHVlKSB7XHJcbiAgICBjYXNlIFwibnVtYmVyXCI6XHJcbiAgICAgIHJldHVybiBpc0Zpbml0ZSh2YWx1ZSlcclxuICAgIGNhc2UgXCJzdHJpbmdcIjpcclxuICAgIGNhc2UgXCJib29sZWFuXCI6XHJcbiAgICAgIHJldHVybiB0cnVlXHJcbiAgfVxyXG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbFxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZGVsZXRlRnJvbUFycmF5PFQ+KGFycmF5OiBUW10sIHZhbHVlOiBUKTogYm9vbGVhbiB7XHJcbiAgbGV0IGluZGV4ID0gYXJyYXkuaW5kZXhPZih2YWx1ZSlcclxuICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgYXJyYXkuc3BsaWNlKGluZGV4LCAxKVxyXG4gICAgcmV0dXJuIHRydWVcclxuICB9XHJcbiAgcmV0dXJuIGZhbHNlXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc01hcCh2YWw6IHVua25vd24pOiB2YWwgaXMgTWFwPGFueSwgYW55PiB8IE9ic2VydmFibGVNYXAge1xyXG4gIHJldHVybiB2YWwgaW5zdGFuY2VvZiBNYXAgfHwgaXNPYnNlcnZhYmxlTWFwKHZhbClcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzU2V0KHZhbDogdW5rbm93bik6IHZhbCBpcyBTZXQ8YW55PiB8IE9ic2VydmFibGVTZXQge1xyXG4gIHJldHVybiB2YWwgaW5zdGFuY2VvZiBTZXQgfHwgaXNPYnNlcnZhYmxlU2V0KHZhbClcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzQXJyYXkodmFsOiB1bmtub3duKTogdmFsIGlzIGFueVtdIHwgSU9ic2VydmFibGVBcnJheSB7XHJcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsKSB8fCBpc09ic2VydmFibGVBcnJheSh2YWwpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBjb25zdCBpbkRldk1vZGUgPSBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gXCJwcm9kdWN0aW9uXCJcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRJc09iamVjdCh2YWx1ZTogdW5rbm93biwgYXJnTmFtZTogc3RyaW5nKTogYXNzZXJ0cyB2YWx1ZSBpcyBvYmplY3Qge1xyXG4gIGlmICghaXNPYmplY3QodmFsdWUpKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKGAke2FyZ05hbWV9IG11c3QgYmUgYW4gb2JqZWN0YClcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRJc1BsYWluT2JqZWN0KHZhbHVlOiB1bmtub3duLCBhcmdOYW1lOiBzdHJpbmcpOiBhc3NlcnRzIHZhbHVlIGlzIG9iamVjdCB7XHJcbiAgaWYgKCFpc1BsYWluT2JqZWN0KHZhbHVlKSkge1xyXG4gICAgdGhyb3cgZmFpbHVyZShgJHthcmdOYW1lfSBtdXN0IGJlIGEgcGxhaW4gb2JqZWN0YClcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRJc09ic2VydmFibGVPYmplY3QodmFsdWU6IHVua25vd24sIGFyZ05hbWU6IHN0cmluZyk6IGFzc2VydHMgdmFsdWUgaXMgb2JqZWN0IHtcclxuICBpZiAoIWlzT2JzZXJ2YWJsZU9iamVjdCh2YWx1ZSkpIHtcclxuICAgIHRocm93IGZhaWx1cmUoYCR7YXJnTmFtZX0gbXVzdCBiZSBhbiBvYnNlcnZhYmxlIG9iamVjdGApXHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0SXNPYnNlcnZhYmxlQXJyYXkoXHJcbiAgdmFsdWU6IHVua25vd24sXHJcbiAgYXJnTmFtZTogc3RyaW5nXHJcbik6IGFzc2VydHMgdmFsdWUgaXMgSU9ic2VydmFibGVBcnJheSB7XHJcbiAgaWYgKCFpc09ic2VydmFibGVBcnJheSh2YWx1ZSkpIHtcclxuICAgIHRocm93IGZhaWx1cmUoYCR7YXJnTmFtZX0gbXVzdCBiZSBhbiBvYnNlcnZhYmxlIGFycmF5YClcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRJc01hcCh2YWx1ZTogdW5rbm93biwgYXJnTmFtZTogc3RyaW5nKTogYXNzZXJ0cyB2YWx1ZSBpcyBNYXA8YW55LCBhbnk+IHtcclxuICBpZiAoIWlzTWFwKHZhbHVlKSkge1xyXG4gICAgdGhyb3cgZmFpbHVyZShgJHthcmdOYW1lfSBtdXN0IGJlIGEgbWFwYClcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRJc1NldCh2YWx1ZTogdW5rbm93biwgYXJnTmFtZTogc3RyaW5nKTogYXNzZXJ0cyB2YWx1ZSBpcyBTZXQ8YW55PiB7XHJcbiAgaWYgKCFpc1NldCh2YWx1ZSkpIHtcclxuICAgIHRocm93IGZhaWx1cmUoYCR7YXJnTmFtZX0gbXVzdCBiZSBhIHNldGApXHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0SXNGdW5jdGlvbih2YWx1ZTogdW5rbm93biwgYXJnTmFtZTogc3RyaW5nKTogYXNzZXJ0cyB2YWx1ZSBpcyBGdW5jdGlvbiB7XHJcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJmdW5jdGlvblwiKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKGAke2FyZ05hbWV9IG11c3QgYmUgYSBmdW5jdGlvbmApXHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0SXNQcmltaXRpdmUoXHJcbiAgdmFsdWU6IHVua25vd24sXHJcbiAgYXJnTmFtZTogc3RyaW5nXHJcbik6IGFzc2VydHMgdmFsdWUgaXMgUHJpbWl0aXZlVmFsdWUge1xyXG4gIGlmICghaXNQcmltaXRpdmUodmFsdWUpKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKGAke2FyZ05hbWV9IG11c3QgYmUgYSBwcmltaXRpdmVgKVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydElzU3RyaW5nKHZhbHVlOiB1bmtub3duLCBhcmdOYW1lOiBzdHJpbmcpOiBhc3NlcnRzIHZhbHVlIGlzIHN0cmluZyB7XHJcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJzdHJpbmdcIikge1xyXG4gICAgdGhyb3cgZmFpbHVyZShgJHthcmdOYW1lfSBtdXN0IGJlIGEgc3RyaW5nYClcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBjb25zdCBydW5BZnRlck5ld1N5bWJvbCA9IFN5bWJvbChcInJ1bkFmdGVyTmV3XCIpXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgcnVuQmVmb3JlT25Jbml0U3ltYm9sID0gU3ltYm9sKFwicnVuQmVmb3JlT25Jbml0XCIpXHJcblxyXG50eXBlIExhdGVJbml0aWFsaXphdGlvbkZ1bmN0aW9uc0FycmF5ID0gKChpbnN0YW5jZTogYW55KSA9PiB2b2lkKVtdXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYWRkTGF0ZUluaXRpYWxpemF0aW9uRnVuY3Rpb24oXHJcbiAgdGFyZ2V0OiBhbnksXHJcbiAgc3ltYm9sOiBzeW1ib2wsXHJcbiAgZm46IChpbnN0YW5jZTogYW55KSA9PiB2b2lkXHJcbikge1xyXG4gIGxldCBhcnJheTogTGF0ZUluaXRpYWxpemF0aW9uRnVuY3Rpb25zQXJyYXkgPSB0YXJnZXRbc3ltYm9sXVxyXG4gIGlmICghYXJyYXkgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0YXJnZXQsIHN5bWJvbCkpIHtcclxuICAgIC8vIGxlYXZlIGJhc2UgYXJyYXkgdW5tb2RpZmllZCwgY3JlYXRlIG5ldyBhcnJheSBpbiB0aGUgZGVyaXZlZCBjbGFzc1xyXG4gICAgYXJyYXkgPSBhcnJheSA/IGFycmF5LnNsaWNlKCkgOiBbXVxyXG4gICAgYWRkSGlkZGVuUHJvcCh0YXJnZXQsIHN5bWJvbCwgYXJyYXkpXHJcbiAgfVxyXG4gIGFycmF5LnB1c2goZm4pXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBydW5MYXRlSW5pdGlhbGl6YXRpb25GdW5jdGlvbnModGFyZ2V0OiBhbnksIHN5bWJvbDogc3ltYm9sKTogdm9pZCB7XHJcbiAgY29uc3QgZm5zOiBMYXRlSW5pdGlhbGl6YXRpb25GdW5jdGlvbnNBcnJheSB8IHVuZGVmaW5lZCA9IHRhcmdldFtzeW1ib2xdXHJcbiAgaWYgKGZucykge1xyXG4gICAgZm9yIChjb25zdCBmbiBvZiBmbnMpIHtcclxuICAgICAgZm4odGFyZ2V0KVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuY29uc3Qgd2FybmluZ3NBbHJlYWR5RGlzcGxheWVkID0gbmV3IFNldDxzdHJpbmc+KClcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBsb2dXYXJuaW5nKHR5cGU6IFwid2FyblwiIHwgXCJlcnJvclwiLCBtc2c6IHN0cmluZywgdW5pcXVlS2V5Pzogc3RyaW5nKTogdm9pZCB7XHJcbiAgaWYgKHVuaXF1ZUtleSkge1xyXG4gICAgaWYgKHdhcm5pbmdzQWxyZWFkeURpc3BsYXllZC5oYXModW5pcXVlS2V5KSkge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuICAgIHdhcm5pbmdzQWxyZWFkeURpc3BsYXllZC5hZGQodW5pcXVlS2V5KVxyXG4gIH1cclxuXHJcbiAgbXNnID0gXCJbbW9ieC1rZXlzdG9uZV0gXCIgKyBtc2dcclxuICBzd2l0Y2ggKHR5cGUpIHtcclxuICAgIGNhc2UgXCJ3YXJuXCI6XHJcbiAgICAgIGNvbnNvbGUud2Fybihtc2cpXHJcbiAgICAgIGJyZWFrXHJcbiAgICBjYXNlIFwiZXJyb3JcIjpcclxuICAgICAgY29uc29sZS5lcnJvcihtc2cpXHJcbiAgICAgIGJyZWFrXHJcbiAgICBkZWZhdWx0OlxyXG4gICAgICB0aHJvdyBmYWlsdXJlKGB1bmtub3duIGxvZyB0eXBlIC0gJHt0eXBlfWApXHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gbGF6eTxBIGV4dGVuZHMgdW5rbm93bltdLCBSPihnZXR0ZXI6ICguLi5hcmdzOiBBKSA9PiBSKTogdHlwZW9mIGdldHRlciB7XHJcbiAgbGV0IG1lbW9pemVkVmFsdWU6IFJcclxuICBsZXQgbWVtb2l6ZWQgPSBmYWxzZVxyXG5cclxuICByZXR1cm4gKC4uLmFyZ3M6IEEpOiBSID0+IHtcclxuICAgIGlmICghbWVtb2l6ZWQpIHtcclxuICAgICAgbWVtb2l6ZWRWYWx1ZSA9IGdldHRlciguLi5hcmdzKVxyXG4gICAgICBtZW1vaXplZCA9IHRydWVcclxuICAgIH1cclxuICAgIHJldHVybiBtZW1vaXplZFZhbHVlXHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgaWRlbnRpdHlGbiA9IDxUPih4OiBUKTogVCA9PiB4XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgbW9ieDYgPSB7XHJcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY29uY2F0XHJcbiAgbWFrZU9ic2VydmFibGU6IChtb2J4IGFzIGFueSlbXHJcbiAgICAvLyBqdXN0IHRvIGVuc3VyZSBpbXBvcnQgKiBpcyBrZXB0IHByb3Blcmx5XHJcbiAgICBTdHJpbmcuZnJvbUNoYXJDb2RlKFwibFwiLmNoYXJDb2RlQXQoMCkgKyAxKSArIFwiYWtlT2JzZXJ2YWJsZVwiXHJcbiAgXSxcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHByb3BOYW1lVG9TZXR0ZXJOYW1lKHByb3BOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gIHJldHVybiBgc2V0JHtwcm9wTmFtZVswXS50b1VwcGVyQ2FzZSgpfSR7cHJvcE5hbWUuc2xpY2UoMSl9YFxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2V0TW9ieFZlcnNpb24oKTogbnVtYmVyIHtcclxuICBpZiAobW9ieDYubWFrZU9ic2VydmFibGUhKSB7XHJcbiAgICByZXR1cm4gNlxyXG4gIH0gZWxzZSB7XHJcbiAgICByZXR1cm4gNVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IG5hbWVzcGFjZSA9IFwibW9ieC1rZXlzdG9uZVwiXHJcbiIsImltcG9ydCB0eXBlIHsgQW55RGF0YU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9CYXNlRGF0YU1vZGVsXCJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcbmltcG9ydCB0eXBlIHsgbW9kZWxUeXBlS2V5IH0gZnJvbSBcIi4uL21vZGVsL21ldGFkYXRhXCJcbmltcG9ydCB0eXBlIHsgRmxhdHRlbiwgSXNOZXZlclR5cGUgfSBmcm9tIFwiLi4vdXRpbHMvdHlwZXNcIlxuaW1wb3J0IHR5cGUge1xuICBNb2RlbFByb3BzLFxuICBNb2RlbFByb3BzVG9TbmFwc2hvdENyZWF0aW9uRGF0YSxcbiAgTW9kZWxQcm9wc1RvU25hcHNob3REYXRhLFxuICBNb2RlbFByb3BzVG9UcmFuc2Zvcm1lZENyZWF0aW9uRGF0YSxcbiAgTW9kZWxQcm9wc1RvVHJhbnNmb3JtZWREYXRhLFxuICBNb2RlbFByb3BzVG9VbnRyYW5zZm9ybWVkQ3JlYXRpb25EYXRhLFxufSBmcm9tIFwiLi9wcm9wXCJcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCBwcm9wc1R5cGVTeW1ib2wgPSBTeW1ib2woXCJwcm9wc1R5cGVcIilcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCBmcm9tU25hcHNob3RPdmVycmlkZVR5cGVTeW1ib2wgPSBTeW1ib2woXCJmcm9tU25hcHNob3RPdmVycmlkZVR5cGVcIilcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCB0b1NuYXBzaG90T3ZlcnJpZGVUeXBlU3ltYm9sID0gU3ltYm9sKFwidG9TbmFwc2hvdE92ZXJyaWRlVHlwZVwiKVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgbW9kZWxJbml0aWFsaXplZFN5bWJvbCA9IFN5bWJvbChcIm1vZGVsSW5pdGlhbGl6ZWRcIilcblxuLyoqXG4gKiBFeHRyYWN0cyB0aGUgaW5zdGFuY2UgdHlwZSBvZiBhIG1vZGVsIGNsYXNzLlxuICovXG5leHBvcnQgdHlwZSBNb2RlbENsYXNzPE0gZXh0ZW5kcyBBbnlNb2RlbCB8IEFueURhdGFNb2RlbD4gPSB7XG4gIG5ldyAoaW5pdGlhbERhdGE6IGFueSk6IE1cblxuICBmcm9tU25hcHNob3RQcm9jZXNzb3I/KHNuOiBhbnkpOiBhbnlcbiAgdG9TbmFwc2hvdFByb2Nlc3Nvcj8oc246IGFueSwgbW9kZWxJbnN0YW5jZTogYW55KTogYW55XG59XG5cbi8qKlxuICogRXh0cmFjdHMgdGhlIGluc3RhbmNlIHR5cGUgb2YgYW4gYWJzdHJhY3QgbW9kZWwgY2xhc3MuXG4gKi9cbmV4cG9ydCB0eXBlIEFic3RyYWN0TW9kZWxDbGFzczxNIGV4dGVuZHMgQW55TW9kZWwgfCBBbnlEYXRhTW9kZWw+ID0gYWJzdHJhY3QgbmV3IChcbiAgaW5pdGlhbERhdGE6IGFueVxuKSA9PiBNXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCB0eXBlIE1vZGVsV2l0aFByb3BzID0geyBbcHJvcHNUeXBlU3ltYm9sXTogTW9kZWxQcm9wcyB9XG5cbi8qKlxuICogVGhlIHByb3BzIG9mIGEgbW9kZWwuXG4gKi9cbmV4cG9ydCB0eXBlIE1vZGVsUHJvcHNPZjxNIGV4dGVuZHMgTW9kZWxXaXRoUHJvcHM+ID0gTVt0eXBlb2YgcHJvcHNUeXBlU3ltYm9sXVxuXG4vKipcbiAqIFRoZSBkYXRhIHR5cGUgb2YgYSBtb2RlbCwgd2l0aG91dCB0cmFuc2Zvcm1hdGlvbnMgYXBwbGllZC5cbiAqL1xuZXhwb3J0IHR5cGUgTW9kZWxVbnRyYW5zZm9ybWVkRGF0YTxNIGV4dGVuZHMgeyByZWFkb25seSAkOiBhbnkgfT4gPSBGbGF0dGVuPE1bXCIkXCJdPlxuXG4vKipcbiAqIFRoZSBjcmVhdGlvbiBkYXRhIHR5cGUgb2YgYSBtb2RlbCwgd2l0aG91dCB0cmFuc2Zvcm1hdGlvbnMgYXBwbGllZC5cbiAqL1xuZXhwb3J0IHR5cGUgTW9kZWxVbnRyYW5zZm9ybWVkQ3JlYXRpb25EYXRhPE0gZXh0ZW5kcyBNb2RlbFdpdGhQcm9wcz4gPVxuICBNb2RlbFByb3BzVG9VbnRyYW5zZm9ybWVkQ3JlYXRpb25EYXRhPE1vZGVsUHJvcHNPZjxNPj5cblxuLyoqXG4gKiBUaGUgZGF0YSB0eXBlIG9mIGEgbW9kZWwsIHdpdGggdHJhbnNmb3JtYXRpb25zIGFwcGxpZWQuXG4gKi9cbmV4cG9ydCB0eXBlIE1vZGVsRGF0YTxNIGV4dGVuZHMgTW9kZWxXaXRoUHJvcHM+ID0gTW9kZWxQcm9wc1RvVHJhbnNmb3JtZWREYXRhPE1vZGVsUHJvcHNPZjxNPj5cblxuLyoqXG4gKiBUaGUgY3JlYXRpb24gZGF0YSB0eXBlIG9mIGEgbW9kZWwsIHdpdGggdHJhbnNmb3JtYXRpb25zIGFwcGxpZWQuXG4gKi9cbmV4cG9ydCB0eXBlIE1vZGVsQ3JlYXRpb25EYXRhPE0gZXh0ZW5kcyBNb2RlbFdpdGhQcm9wcz4gPSBNb2RlbFByb3BzVG9UcmFuc2Zvcm1lZENyZWF0aW9uRGF0YTxcbiAgTW9kZWxQcm9wc09mPE0+XG4+XG5cbi8qKlxuICogVGhlIGZyb20gc25hcHNob3QgdHlwZSBvZiBhIG1vZGVsLlxuICpcbiAqIEBkZXByZWNhdGVkIFVzZSBTbmFwc2hvdEluT2Y8TW9kZWw+IGluc3RlYWQuXG4gKi9cbmV4cG9ydCB0eXBlIE1vZGVsRnJvbVNuYXBzaG90PFxuICBNIGV4dGVuZHMgTW9kZWxXaXRoUHJvcHMgJiB7IFtmcm9tU25hcHNob3RPdmVycmlkZVR5cGVTeW1ib2xdOiBhbnkgfVxuPiA9IElzTmV2ZXJUeXBlPFxuICBNW3R5cGVvZiBmcm9tU25hcHNob3RPdmVycmlkZVR5cGVTeW1ib2xdLFxuICBNb2RlbFByb3BzVG9TbmFwc2hvdENyZWF0aW9uRGF0YTxNb2RlbFByb3BzT2Y8TT4+LFxuICBNW3R5cGVvZiBmcm9tU25hcHNob3RPdmVycmlkZVR5cGVTeW1ib2xdXG4+ICYgeyBbbW9kZWxUeXBlS2V5XT86IHN0cmluZyB9XG5cbi8qKlxuICogVGhlIHRvIHNuYXBzaG90IHR5cGUgb2YgYSBtb2RlbC5cbiAqXG4gKiBAZGVwcmVjYXRlZCBVc2UgU25hcHNob3RPdXRPZjxNb2RlbD4gaW5zdGVhZC5cbiAqL1xuZXhwb3J0IHR5cGUgTW9kZWxUb1NuYXBzaG90PE0gZXh0ZW5kcyBNb2RlbFdpdGhQcm9wcyAmIHsgW3RvU25hcHNob3RPdmVycmlkZVR5cGVTeW1ib2xdOiBhbnkgfT4gPVxuICBJc05ldmVyVHlwZTxcbiAgICBNW3R5cGVvZiB0b1NuYXBzaG90T3ZlcnJpZGVUeXBlU3ltYm9sXSxcbiAgICBNb2RlbFByb3BzVG9TbmFwc2hvdERhdGE8TW9kZWxQcm9wc09mPE0+PixcbiAgICBNW3R5cGVvZiB0b1NuYXBzaG90T3ZlcnJpZGVUeXBlU3ltYm9sXVxuICA+ICYgeyBbbW9kZWxUeXBlS2V5XT86IHN0cmluZyB9XG5cbi8qKlxuICogVHJpY2tzIFR5cGVTY3JpcHQgaW50byBhY2NlcHRpbmcgYSBwYXJ0aWN1bGFyIGtpbmQgb2YgZ2VuZXJpYyBjbGFzcyBhcyBhIHBhcmFtZXRlciBmb3IgYEV4dGVuZGVkTW9kZWxgLlxuICogRG9lcyBub3RoaW5nIGluIHJ1bnRpbWUuXG4gKlxuICogQHR5cGVwYXJhbSBUIEdlbmVyaWMgbW9kZWwgY2xhc3MgdHlwZS5cbiAqIEBwYXJhbSB0eXBlIEdlbmVyaWMgbW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbW9kZWxDbGFzczxUIGV4dGVuZHMgQW55TW9kZWwgfCBBbnlEYXRhTW9kZWw+KHR5cGU6IHtcbiAgcHJvdG90eXBlOiBUXG59KTogTW9kZWxDbGFzczxUPiB7XG4gIHJldHVybiB0eXBlIGFzIGFueVxufVxuIiwiaW1wb3J0IHR5cGUgeyBBbnlEYXRhTW9kZWwgfSBmcm9tIFwiLi4vZGF0YU1vZGVsL0Jhc2VEYXRhTW9kZWxcIlxyXG5pbXBvcnQgdHlwZSB7IEFueU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Jhc2VNb2RlbFwiXHJcbmltcG9ydCB0eXBlIHsgTW9kZWxDbGFzcyB9IGZyb20gXCIuL0Jhc2VNb2RlbFNoYXJlZFwiXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIE1vZGVsSW5mbyB7XHJcbiAgbmFtZTogc3RyaW5nXHJcbiAgY2xhc3M6IE1vZGVsQ2xhc3M8QW55TW9kZWwgfCBBbnlEYXRhTW9kZWw+XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBjb25zdCBtb2RlbEluZm9CeU5hbWU6IHtcclxuICBbbmFtZTogc3RyaW5nXTogTW9kZWxJbmZvXHJcbn0gPSB7fVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IG1vZGVsSW5mb0J5Q2xhc3MgPSBuZXcgV2Vha01hcDxNb2RlbENsYXNzPEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPiwgTW9kZWxJbmZvPigpXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2V0TW9kZWxJbmZvRm9yTmFtZShuYW1lOiBzdHJpbmcpOiBNb2RlbEluZm8gfCB1bmRlZmluZWQge1xyXG4gIHJldHVybiBtb2RlbEluZm9CeU5hbWVbbmFtZV1cclxufVxyXG4iLCJ0eXBlIEFueU1hcDxWID0gYW55PiA9IE1hcDxhbnksIFY+IHwgV2Vha01hcDxhbnksIFY+XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRPckNyZWF0ZTxLLCBWLCBDID0gVj4obWFwOiBNYXA8SywgVj4sIGtleTogSywgY3JlYXRlOiAoKSA9PiBDKTogVlxuZXhwb3J0IGZ1bmN0aW9uIGdldE9yQ3JlYXRlPEsgZXh0ZW5kcyBvYmplY3QsIFYsIEMgPSBWPihcbiAgbWFwOiBXZWFrTWFwPEssIFY+LFxuICBrZXk6IEssXG4gIGNyZWF0ZTogKCkgPT4gQ1xuKTogVlxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0T3JDcmVhdGU8Vj4obWFwOiBBbnlNYXA8Vj4sIGtleTogYW55LCBjcmVhdGU6ICgpID0+IFYpIHtcbiAgbGV0IHZhbHVlID0gbWFwLmdldChrZXkpXG4gIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdmFsdWUgPSBjcmVhdGUoKVxuICAgIG1hcC5zZXQoa2V5LCB2YWx1ZSlcbiAgfVxuICByZXR1cm4gdmFsdWVcbn1cbiIsImltcG9ydCB7IGNyZWF0ZUF0b20sIElBdG9tIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgaXNNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXG5pbXBvcnQgeyBnZXRPckNyZWF0ZSB9IGZyb20gXCIuLi91dGlscy9tYXBVdGlsc1wiXG5pbXBvcnQgdHlwZSB7IFBhcmVudFBhdGggfSBmcm9tIFwiLi9wYXRoXCJcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IG9iamVjdFBhcmVudHMgPSBuZXcgV2Vha01hcDxvYmplY3QsIFBhcmVudFBhdGg8b2JqZWN0PiB8IHVuZGVmaW5lZD4oKVxuXG5jb25zdCBvYmplY3RQYXJlbnRzQXRvbXMgPSBuZXcgV2Vha01hcDxvYmplY3QsIElBdG9tPigpXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJlbnRQYXRoRXF1YWxzKFxuICBwYXJlbnRQYXRoMTogUGFyZW50UGF0aDxhbnk+IHwgdW5kZWZpbmVkLFxuICBwYXJlbnRQYXRoMjogUGFyZW50UGF0aDxhbnk+IHwgdW5kZWZpbmVkLFxuICBjb21wYXJlUGF0aCA9IHRydWVcbikge1xuICBpZiAoIXBhcmVudFBhdGgxICYmICFwYXJlbnRQYXRoMikgcmV0dXJuIHRydWVcbiAgaWYgKCFwYXJlbnRQYXRoMSB8fCAhcGFyZW50UGF0aDIpIHJldHVybiBmYWxzZVxuICBjb25zdCBwYXJlbnRFcXVhbHMgPSBwYXJlbnRQYXRoMS5wYXJlbnQgPT09IHBhcmVudFBhdGgyLnBhcmVudFxuICBpZiAoIXBhcmVudEVxdWFscykgcmV0dXJuIGZhbHNlXG4gIHJldHVybiBjb21wYXJlUGF0aCA/IHBhcmVudFBhdGgxLnBhdGggPT09IHBhcmVudFBhdGgyLnBhdGggOiB0cnVlXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVBhcmVudFBhdGhBdG9tKG9iajogb2JqZWN0KSB7XG4gIHJldHVybiBnZXRPckNyZWF0ZShvYmplY3RQYXJlbnRzQXRvbXMsIG9iaiwgKCkgPT4gY3JlYXRlQXRvbShcInBhcmVudEF0b21cIikpXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXBvcnRQYXJlbnRQYXRoT2JzZXJ2ZWQobm9kZTogb2JqZWN0KSB7XG4gIGNyZWF0ZVBhcmVudFBhdGhBdG9tKG5vZGUpLnJlcG9ydE9ic2VydmVkKClcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcG9ydFBhcmVudFBhdGhDaGFuZ2VkKG5vZGU6IG9iamVjdCkge1xuICBjcmVhdGVQYXJlbnRQYXRoQXRvbShub2RlKS5yZXBvcnRDaGFuZ2VkKClcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IGRhdGFPYmplY3RQYXJlbnQgPSBuZXcgV2Vha01hcDxvYmplY3QsIG9iamVjdD4oKVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0YVRvTW9kZWxOb2RlPFQgZXh0ZW5kcyBvYmplY3Q+KG5vZGU6IFQpOiBUIHtcbiAgY29uc3QgbW9kZWxOb2RlID0gZGF0YU9iamVjdFBhcmVudC5nZXQobm9kZSlcbiAgcmV0dXJuIChtb2RlbE5vZGUgYXMgVCkgPz8gbm9kZVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gbW9kZWxUb0RhdGFOb2RlPFQgZXh0ZW5kcyBvYmplY3Q+KG5vZGU6IFQpOiBUIHtcbiAgcmV0dXJuIGlzTW9kZWwobm9kZSkgPyBub2RlLiQgOiBub2RlXG59XG4iLCJpbXBvcnQgeyBydW5JbkFjdGlvbiB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHsgZGF0YU9iamVjdFBhcmVudCB9IGZyb20gXCIuLi9wYXJlbnQvY29yZVwiXHJcbmltcG9ydCB7IGZhaWx1cmUsIGlzUHJpbWl0aXZlIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBjb25zdCB0d2Vha2VkT2JqZWN0cyA9IG5ldyBXZWFrTWFwPG9iamVjdCwgdW5kZWZpbmVkIHwgKCgpID0+IHZvaWQpPigpXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaXNUd2Vha2VkT2JqZWN0KHZhbHVlOiB1bmtub3duLCBjYW5CZURhdGFPYmplY3Q6IGJvb2xlYW4pOiB2YWx1ZSBpcyBvYmplY3Qge1xyXG4gIGlmICghY2FuQmVEYXRhT2JqZWN0ICYmIGRhdGFPYmplY3RQYXJlbnQuaGFzKHZhbHVlIGFzIG9iamVjdCkpIHtcclxuICAgIHJldHVybiBmYWxzZVxyXG4gIH1cclxuICByZXR1cm4gdHdlYWtlZE9iamVjdHMuaGFzKHZhbHVlIGFzIG9iamVjdClcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiBhIGdpdmVuIG9iamVjdCBpcyBub3cgYSB0cmVlIG5vZGUuXHJcbiAqXHJcbiAqIEBwYXJhbSB2YWx1ZSBWYWx1ZSB0byBjaGVjay5cclxuICogQHJldHVybnMgdHJ1ZSBpZiBpdCBpcyBhIHRyZWUgbm9kZSwgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzVHJlZU5vZGUodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBvYmplY3Qge1xyXG4gIHJldHVybiAhaXNQcmltaXRpdmUodmFsdWUpICYmIGlzVHdlYWtlZE9iamVjdCh2YWx1ZSwgZmFsc2UpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRUd2Vha2VkT2JqZWN0KFxyXG4gIHRyZWVOb2RlOiB1bmtub3duLFxyXG4gIGFyZ05hbWU6IHN0cmluZyxcclxuICBjYW5CZURhdGFPYmplY3QgPSBmYWxzZVxyXG4pOiBhc3NlcnRzIHRyZWVOb2RlIGlzIG9iamVjdCB7XHJcbiAgaWYgKCFjYW5CZURhdGFPYmplY3QgJiYgZGF0YU9iamVjdFBhcmVudC5oYXModHJlZU5vZGUgYXMgb2JqZWN0KSkge1xyXG4gICAgdGhyb3cgZmFpbHVyZShgJHthcmdOYW1lfSBtdXN0IGJlIHRoZSBtb2RlbCBvYmplY3QgaW5zdGFuY2UgaW5zdGVhZCBvZiB0aGUgJyQnIHN1Yi1vYmplY3RgKVxyXG4gIH1cclxuICBpZiAoaXNQcmltaXRpdmUodHJlZU5vZGUpIHx8ICFpc1R3ZWFrZWRPYmplY3QodHJlZU5vZGUsIHRydWUpKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKFxyXG4gICAgICBgJHthcmdOYW1lfSBtdXN0IGJlIGEgdHJlZSBub2RlICh1c3VhbGx5IGEgbW9kZWwgb3IgYSBzaGFsbG93IC8gZGVlcCBjaGlsZCBwYXJ0IG9mIGEgbW9kZWwgJ2RhdGEnIG9iamVjdClgXHJcbiAgICApXHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogQXNzZXJ0cyBhIGdpdmVuIG9iamVjdCBpcyBub3cgYSB0cmVlIG5vZGUsIG9yIHRocm93cyBvdGhlcndpc2UuXHJcbiAqXHJcbiAqIEBwYXJhbSB2YWx1ZSBWYWx1ZSB0byBjaGVjay5cclxuICogQHBhcmFtIGFyZ05hbWUgQXJndW1lbnQgbmFtZSwgcGFydCBvZiB0aGUgdGhyb3duIGVycm9yIGRlc2NyaXB0aW9uLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydElzVHJlZU5vZGUoXHJcbiAgdmFsdWU6IHVua25vd24sXHJcbiAgYXJnTmFtZTogc3RyaW5nID0gXCJhcmd1bWVudFwiXHJcbik6IGFzc2VydHMgdmFsdWUgaXMgb2JqZWN0IHtcclxuICBhc3NlcnRUd2Vha2VkT2JqZWN0KHZhbHVlLCBhcmdOYW1lLCBmYWxzZSlcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGxldCBydW5uaW5nV2l0aG91dFNuYXBzaG90T3JQYXRjaGVzID0gZmFsc2VcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBydW5XaXRob3V0U25hcHNob3RPclBhdGNoZXMoZm46ICgpID0+IHZvaWQpIHtcclxuICBjb25zdCBvbGQgPSBydW5uaW5nV2l0aG91dFNuYXBzaG90T3JQYXRjaGVzXHJcbiAgcnVubmluZ1dpdGhvdXRTbmFwc2hvdE9yUGF0Y2hlcyA9IHRydWVcclxuICB0cnkge1xyXG4gICAgcnVuSW5BY3Rpb24oKCkgPT4ge1xyXG4gICAgICBmbigpXHJcbiAgICB9KVxyXG4gIH0gZmluYWxseSB7XHJcbiAgICBydW5uaW5nV2l0aG91dFNuYXBzaG90T3JQYXRjaGVzID0gb2xkXHJcbiAgfVxyXG59XHJcbiIsImV4cG9ydCBjb25zdCBtb2RlbE1ldGFkYXRhU3ltYm9sID0gU3ltYm9sKFwibW9kZWxNZXRhZGF0YVwiKVxyXG5leHBvcnQgY29uc3QgbW9kZWxVbndyYXBwZWRDbGFzc1N5bWJvbCA9IFN5bWJvbChcIm1vZGVsVW53cmFwcGVkQ2xhc3NcIilcclxuZXhwb3J0IGNvbnN0IHJ1bkFmdGVyTW9kZWxEZWNvcmF0b3JTeW1ib2wgPSBTeW1ib2woXCJydW5BZnRlck1vZGVsRGVjb3JhdG9yXCIpXHJcbiIsImltcG9ydCB0eXBlIHsgQW55RGF0YU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9CYXNlRGF0YU1vZGVsXCJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcbmltcG9ydCB0eXBlIHsgTW9kZWxDbGFzcyB9IGZyb20gXCIuL0Jhc2VNb2RlbFNoYXJlZFwiXG5pbXBvcnQgdHlwZSB7IE1vZGVsUHJvcHMgfSBmcm9tIFwiLi9wcm9wXCJcblxuY29uc3QgbW9kZWxQcm9wZXJ0aWVzU3ltYm9sID0gU3ltYm9sKFwibW9kZWxQcm9wZXJ0aWVzXCIpXG5cbi8qKlxuICogQGludGVybmFsXG4gKlxuICogR2V0cyB0aGUgaW5mbyByZWxhdGVkIHRvIGEgbW9kZWwgY2xhc3MgcHJvcGVydGllcy5cbiAqXG4gKiBAcGFyYW0gbW9kZWxDbGFzc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0SW50ZXJuYWxNb2RlbENsYXNzUHJvcHNJbmZvKFxuICBtb2RlbENsYXNzOiBNb2RlbENsYXNzPEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPlxuKTogTW9kZWxQcm9wcyB7XG4gIHJldHVybiAobW9kZWxDbGFzcyBhcyBhbnkpW21vZGVsUHJvcGVydGllc1N5bWJvbF1cbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqXG4gKiBTZXRzIHRoZSBpbmZvIHJlbGF0ZWQgdG8gYSBtb2RlbCBjbGFzcyBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSBtb2RlbENsYXNzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRJbnRlcm5hbE1vZGVsQ2xhc3NQcm9wc0luZm8oXG4gIG1vZGVsQ2xhc3M6IE1vZGVsQ2xhc3M8QW55TW9kZWwgfCBBbnlEYXRhTW9kZWw+LFxuICBwcm9wczogTW9kZWxQcm9wc1xuKTogdm9pZCB7XG4gIDsobW9kZWxDbGFzcyBhcyBhbnkpW21vZGVsUHJvcGVydGllc1N5bWJvbF0gPSBwcm9wc1xufVxuIiwiaW1wb3J0IHR5cGUgeyBTbmFwc2hvdEluT2YsIFNuYXBzaG90T3V0T2YgfSBmcm9tIFwiLi4vc25hcHNob3QvU25hcHNob3RPZlwiXG5pbXBvcnQgdHlwZSB7IExhdGVUeXBlQ2hlY2tlciwgVHlwZUNoZWNrZXIgfSBmcm9tIFwiLi4vdHlwZXMvVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHsgZ2V0T3JDcmVhdGUgfSBmcm9tIFwiLi4vdXRpbHMvbWFwVXRpbHNcIlxuaW1wb3J0IHR5cGUgeyBGbGF0dGVuLCBJc05ldmVyVHlwZSwgSXNPcHRpb25hbFZhbHVlIH0gZnJvbSBcIi4uL3V0aWxzL3R5cGVzXCJcblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBjb25zdCBub0RlZmF1bHRWYWx1ZSA9IFN5bWJvbChcIm5vRGVmYXVsdFZhbHVlXCIpXG5cbi8qKlxuICogQSBtb2RlbCBwcm9wZXJ0eS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNb2RlbFByb3A8XG4gIFRQcm9wVmFsdWUsXG4gIFRQcm9wQ3JlYXRpb25WYWx1ZSxcbiAgVFRyYW5zZm9ybWVkVmFsdWUsXG4gIFRUcmFuc2Zvcm1lZENyZWF0aW9uVmFsdWUsXG4gIFRJc1JlcXVpcmVkLFxuICBUSXNJZCBleHRlbmRzIGJvb2xlYW4gPSBmYWxzZSxcbiAgVEhhc1NldHRlciA9IG5ldmVyLFxuICBURnJvbVNuYXBzaG90T3ZlcnJpZGUgPSBuZXZlcixcbiAgVFRvU25hcHNob3RPdmVycmlkZSA9IG5ldmVyXG4+IHtcbiAgJHZhbHVlVHlwZTogVFByb3BWYWx1ZVxuICAkY3JlYXRpb25WYWx1ZVR5cGU6IFRQcm9wQ3JlYXRpb25WYWx1ZVxuICAkdHJhbnNmb3JtZWRWYWx1ZVR5cGU6IFRUcmFuc2Zvcm1lZFZhbHVlXG4gICR0cmFuc2Zvcm1lZENyZWF0aW9uVmFsdWVUeXBlOiBUVHJhbnNmb3JtZWRDcmVhdGlvblZhbHVlXG4gICRpc1JlcXVpcmVkOiBUSXNSZXF1aXJlZFxuICAkaXNJZDogVElzSWRcbiAgJGhhc1NldHRlcjogVEhhc1NldHRlclxuICAkZnJvbVNuYXBzaG90T3ZlcnJpZGU6IFRGcm9tU25hcHNob3RPdmVycmlkZVxuICAkdG9TbmFwc2hvdE92ZXJyaWRlOiBUVG9TbmFwc2hvdE92ZXJyaWRlXG5cbiAgX2RlZmF1bHRGbjogKCgpID0+IFRQcm9wVmFsdWUpIHwgdHlwZW9mIG5vRGVmYXVsdFZhbHVlXG4gIF9kZWZhdWx0VmFsdWU6IFRQcm9wVmFsdWUgfCB0eXBlb2Ygbm9EZWZhdWx0VmFsdWVcbiAgX3R5cGVDaGVja2VyOiBUeXBlQ2hlY2tlciB8IExhdGVUeXBlQ2hlY2tlciB8IHVuZGVmaW5lZFxuICBfc2V0dGVyOiBib29sZWFuIHwgXCJhc3NpZ25cIlxuICBfaXNJZDogYm9vbGVhblxuICBfdHJhbnNmb3JtOlxuICAgIHwge1xuICAgICAgICB0cmFuc2Zvcm0oXG4gICAgICAgICAgb3JpZ2luYWw6IHVua25vd24sXG4gICAgICAgICAgbW9kZWw6IG9iamVjdCxcbiAgICAgICAgICBwcm9wTmFtZTogUHJvcGVydHlLZXksXG4gICAgICAgICAgc2V0T3JpZ2luYWxWYWx1ZTogKG5ld09yaWdpbmFsVmFsdWU6IHVua25vd24pID0+IHZvaWRcbiAgICAgICAgKTogdW5rbm93blxuICAgICAgICB1bnRyYW5zZm9ybSh0cmFuc2Zvcm1lZDogdW5rbm93biwgbW9kZWw6IG9iamVjdCwgcHJvcE5hbWU6IFByb3BlcnR5S2V5KTogdW5rbm93blxuICAgICAgfVxuICAgIHwgdW5kZWZpbmVkXG4gIF9mcm9tU25hcHNob3RQcm9jZXNzb3I/KHNuOiB1bmtub3duKTogdW5rbm93blxuICBfdG9TbmFwc2hvdFByb2Nlc3Nvcj8oc246IHVua25vd24pOiB1bmtub3duXG5cbiAgd2l0aFNldHRlcigpOiBNb2RlbFByb3A8XG4gICAgVFByb3BWYWx1ZSxcbiAgICBUUHJvcENyZWF0aW9uVmFsdWUsXG4gICAgVFRyYW5zZm9ybWVkVmFsdWUsXG4gICAgVFRyYW5zZm9ybWVkQ3JlYXRpb25WYWx1ZSxcbiAgICBUSXNSZXF1aXJlZCxcbiAgICBUSXNJZCxcbiAgICBzdHJpbmcsXG4gICAgVEZyb21TbmFwc2hvdE92ZXJyaWRlLFxuICAgIFRUb1NuYXBzaG90T3ZlcnJpZGVcbiAgPlxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgU2V0dGVyIG1ldGhvZHMgYXJlIHByZWZlcnJlZC5cbiAgICovXG4gIHdpdGhTZXR0ZXIoXG4gICAgbW9kZTogXCJhc3NpZ25cIlxuICApOiBNb2RlbFByb3A8XG4gICAgVFByb3BWYWx1ZSxcbiAgICBUUHJvcENyZWF0aW9uVmFsdWUsXG4gICAgVFRyYW5zZm9ybWVkVmFsdWUsXG4gICAgVFRyYW5zZm9ybWVkQ3JlYXRpb25WYWx1ZSxcbiAgICBUSXNSZXF1aXJlZCxcbiAgICBUSXNJZCxcbiAgICBzdHJpbmcsXG4gICAgVEZyb21TbmFwc2hvdE92ZXJyaWRlLFxuICAgIFRUb1NuYXBzaG90T3ZlcnJpZGVcbiAgPlxuXG4gIC8qKlxuICAgKiBTZXRzIGEgdHJhbnNmb3JtIGZvciB0aGUgcHJvcGVydHkgaW5zdGFuY2UgdmFsdWUuXG4gICAqXG4gICAqIEB0eXBlcGFyYW0gVFRWIFRyYW5zZm9ybWVkIHZhbHVlIHR5cGUuXG4gICAqIEBwYXJhbSB0cmFuc2Zvcm0gVHJhbnNmb3JtIHRvIGJlIHVzZWQuXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICB3aXRoVHJhbnNmb3JtPFRUVj4oXG4gICAgdHJhbnNmb3JtOiBNb2RlbFByb3BUcmFuc2Zvcm08Tm9uTnVsbGFibGU8VFByb3BWYWx1ZT4sIFRUVj5cbiAgKTogTW9kZWxQcm9wPFxuICAgIFRQcm9wVmFsdWUsXG4gICAgVFByb3BDcmVhdGlvblZhbHVlLFxuICAgIFRUViB8IEV4dHJhY3Q8VFByb3BWYWx1ZSwgbnVsbCB8IHVuZGVmaW5lZD4sXG4gICAgVFRWIHwgRXh0cmFjdDxUUHJvcENyZWF0aW9uVmFsdWUsIG51bGwgfCB1bmRlZmluZWQ+LFxuICAgIFRJc1JlcXVpcmVkLFxuICAgIFRJc0lkLFxuICAgIFRIYXNTZXR0ZXIsXG4gICAgVEZyb21TbmFwc2hvdE92ZXJyaWRlLFxuICAgIFRUb1NuYXBzaG90T3ZlcnJpZGVcbiAgPlxuXG4gIHdpdGhTbmFwc2hvdFByb2Nlc3NvcjxcbiAgICBGUyA9IFRGcm9tU25hcHNob3RPdmVycmlkZSxcbiAgICBUUyA9IFRUb1NuYXBzaG90T3ZlcnJpZGUsXG4gICAgVGhpcyBleHRlbmRzIEFueU1vZGVsUHJvcCA9IHRoaXNcbiAgPihwcm9jZXNzb3I6IHtcbiAgICBmcm9tU25hcHNob3Q/KHNuOiBGUyk6IE1vZGVsUHJvcEZyb21TbmFwc2hvdDxUaGlzPlxuICAgIHRvU25hcHNob3Q/KHNuOiBNb2RlbFByb3BUb1NuYXBzaG90PFRoaXM+KTogVFNcbiAgfSk6IE1vZGVsUHJvcDxcbiAgICBUUHJvcFZhbHVlLFxuICAgIFRQcm9wQ3JlYXRpb25WYWx1ZSxcbiAgICBUVHJhbnNmb3JtZWRWYWx1ZSxcbiAgICBUVHJhbnNmb3JtZWRDcmVhdGlvblZhbHVlLFxuICAgIFRJc1JlcXVpcmVkLFxuICAgIFRJc0lkLFxuICAgIFRIYXNTZXR0ZXIsXG4gICAgRlMsXG4gICAgVFNcbiAgPlxufVxuXG4vKipcbiAqIFRoZSBzbmFwc2hvdCBpbiB0eXBlIG9mIGEgbW9kZWwgcHJvcGVydHkuXG4gKi9cbmV4cG9ydCB0eXBlIE1vZGVsUHJvcEZyb21TbmFwc2hvdDxNUCBleHRlbmRzIEFueU1vZGVsUHJvcD4gPSBJc05ldmVyVHlwZTxcbiAgTVBbXCIkZnJvbVNuYXBzaG90T3ZlcnJpZGVcIl0sXG4gIFNuYXBzaG90SW5PZjxNUFtcIiRjcmVhdGlvblZhbHVlVHlwZVwiXT4sXG4gIE1QW1wiJGZyb21TbmFwc2hvdE92ZXJyaWRlXCJdXG4+XG5cbi8qKlxuICogVGhlIHNuYXBzaG90IG91dCB0eXBlIG9mIGEgbW9kZWwgcHJvcGVydHkuXG4gKi9cbmV4cG9ydCB0eXBlIE1vZGVsUHJvcFRvU25hcHNob3Q8TVAgZXh0ZW5kcyBBbnlNb2RlbFByb3A+ID0gSXNOZXZlclR5cGU8XG4gIE1QW1wiJHRvU25hcHNob3RPdmVycmlkZVwiXSxcbiAgU25hcHNob3RPdXRPZjxNUFtcIiR2YWx1ZVR5cGVcIl0+LFxuICBNUFtcIiR0b1NuYXBzaG90T3ZlcnJpZGVcIl1cbj5cblxuLyoqXG4gKiBBIG1vZGVsIHByb3AgdHJhbnNmb3JtLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1vZGVsUHJvcFRyYW5zZm9ybTxUT3JpZ2luYWwsIFRUcmFuc2Zvcm1lZD4ge1xuICB0cmFuc2Zvcm0ocGFyYW1zOiB7XG4gICAgb3JpZ2luYWxWYWx1ZTogVE9yaWdpbmFsXG4gICAgY2FjaGVkVHJhbnNmb3JtZWRWYWx1ZTogVFRyYW5zZm9ybWVkIHwgdW5kZWZpbmVkXG4gICAgc2V0T3JpZ2luYWxWYWx1ZSh2YWx1ZTogVE9yaWdpbmFsKTogdm9pZFxuICB9KTogVFRyYW5zZm9ybWVkXG5cbiAgdW50cmFuc2Zvcm0ocGFyYW1zOiB7IHRyYW5zZm9ybWVkVmFsdWU6IFRUcmFuc2Zvcm1lZDsgY2FjaGVUcmFuc2Zvcm1lZFZhbHVlKCk6IHZvaWQgfSk6IFRPcmlnaW5hbFxufVxuXG4vKipcbiAqIEFueSBtb2RlbCBwcm9wZXJ0eS5cbiAqL1xuZXhwb3J0IHR5cGUgQW55TW9kZWxQcm9wID0gTW9kZWxQcm9wPGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnksIGFueSwgYW55LCBhbnk+XG5cbi8qKlxuICogTW9kZWwgcHJvcGVydGllcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNb2RlbFByb3BzIHtcbiAgW2s6IHN0cmluZ106IEFueU1vZGVsUHJvcFxufVxuXG5leHBvcnQgdHlwZSBSZXF1aXJlZE1vZGVsUHJvcHM8TVAgZXh0ZW5kcyBNb2RlbFByb3BzPiA9IHtcbiAgW0sgaW4ga2V5b2YgTVBdOiBNUFtLXVtcIiRpc1JlcXVpcmVkXCJdICYgS1xufVtrZXlvZiBNUF1cblxuZXhwb3J0IHR5cGUgTW9kZWxQcm9wc1RvVW50cmFuc2Zvcm1lZERhdGE8TVAgZXh0ZW5kcyBNb2RlbFByb3BzPiA9IEZsYXR0ZW48e1xuICBbayBpbiBrZXlvZiBNUF06IE1QW2tdW1wiJHZhbHVlVHlwZVwiXVxufT5cblxuZXhwb3J0IHR5cGUgTW9kZWxQcm9wc1RvU25hcHNob3REYXRhPE1QIGV4dGVuZHMgTW9kZWxQcm9wcz4gPSBGbGF0dGVuPHtcbiAgW2sgaW4ga2V5b2YgTVBdOiBNb2RlbFByb3BUb1NuYXBzaG90PE1QW2tdPiBleHRlbmRzIGluZmVyIFIgPyBSIDogbmV2ZXJcbn0+XG5cbi8vIHdlIGRvbid0IHVzZSBPLk9wdGlvbmFsIGFueW1vcmUgc2luY2UgaXQgZ2VuZXJhdGVzIHVuaW9ucyB0b28gaGVhdnlcbi8vIGFsc28gaWYgd2UgdXNlIFBpY2sgb3ZlciB0aGUgb3B0aW9uYWwgcHJvcHMgd2Ugd2lsbCBsb29zZSB0aGUgYWJpbGl0eSB0byBpbmZlciBnZW5lcmljc1xuLy8gd2UgYWxzbyBkb24ndCB1c2UgRmxhdHRlbiBiZWNhdXNlIGlmIHdlIGRvIHNvbWUgZ2VuZXJpY3Mgd29uJ3Qgd29ya1xuZXhwb3J0IHR5cGUgTW9kZWxQcm9wc1RvVW50cmFuc2Zvcm1lZENyZWF0aW9uRGF0YTxNUCBleHRlbmRzIE1vZGVsUHJvcHM+ID0ge1xuICBbayBpbiBrZXlvZiBNUF0/OiBNUFtrXVtcIiRjcmVhdGlvblZhbHVlVHlwZVwiXVxufSAmIHtcbiAgW2sgaW4gUmVxdWlyZWRNb2RlbFByb3BzPE1QPl06IE1QW2tdW1wiJGNyZWF0aW9uVmFsdWVUeXBlXCJdXG59XG5cbi8vIHdlIGRvbid0IHVzZSBPLk9wdGlvbmFsIGFueW1vcmUgc2luY2UgaXQgZ2VuZXJhdGVzIHVuaW9ucyB0b28gaGVhdnlcbi8vIGFsc28gaWYgd2UgdXNlIFBpY2sgb3ZlciB0aGUgb3B0aW9uYWwgcHJvcHMgd2Ugd2lsbCBsb29zZSB0aGUgYWJpbGl0eSB0byBpbmZlciBnZW5lcmljc1xuZXhwb3J0IHR5cGUgTW9kZWxQcm9wc1RvU25hcHNob3RDcmVhdGlvbkRhdGE8TVAgZXh0ZW5kcyBNb2RlbFByb3BzPiA9IEZsYXR0ZW48XG4gIHtcbiAgICBbayBpbiBrZXlvZiBNUF0/OiBNb2RlbFByb3BGcm9tU25hcHNob3Q8TVBba10+IGV4dGVuZHMgaW5mZXIgUiA/IFIgOiBuZXZlclxuICB9ICYge1xuICAgIFtrIGluIHtcbiAgICAgIFtLIGluIGtleW9mIE1QXTogSXNOZXZlclR5cGU8XG4gICAgICAgIE1QW0tdW1wiJGZyb21TbmFwc2hvdE92ZXJyaWRlXCJdLFxuICAgICAgICBNUFtLXVtcIiRpc1JlcXVpcmVkXCJdICYgSywgLy8gbm8gb3ZlcnJpZGVcbiAgICAgICAgSXNPcHRpb25hbFZhbHVlPE1QW0tdW1wiJGZyb21TbmFwc2hvdE92ZXJyaWRlXCJdLCBuZXZlciwgSz4gLy8gd2l0aCBvdmVycmlkZVxuICAgICAgPlxuICAgIH1ba2V5b2YgTVBdXTogTW9kZWxQcm9wRnJvbVNuYXBzaG90PE1QW2tdPiBleHRlbmRzIGluZmVyIFIgPyBSIDogbmV2ZXJcbiAgfVxuPlxuXG5leHBvcnQgdHlwZSBNb2RlbFByb3BzVG9UcmFuc2Zvcm1lZERhdGE8TVAgZXh0ZW5kcyBNb2RlbFByb3BzPiA9IEZsYXR0ZW48e1xuICBbayBpbiBrZXlvZiBNUF06IE1QW2tdW1wiJHRyYW5zZm9ybWVkVmFsdWVUeXBlXCJdXG59PlxuXG4vLyB3ZSBkb24ndCB1c2UgTy5PcHRpb25hbCBhbnltb3JlIHNpbmNlIGl0IGdlbmVyYXRlcyB1bmlvbnMgdG9vIGhlYXZ5XG4vLyBhbHNvIGlmIHdlIHVzZSBQaWNrIG92ZXIgdGhlIG9wdGlvbmFsIHByb3BzIHdlIHdpbGwgbG9vc2UgdGhlIGFiaWxpdHkgdG8gaW5mZXIgZ2VuZXJpY3Ncbi8vIHdlIGFsc28gZG9uJ3QgdXNlIEZsYXR0ZW4gYmVjYXVzZSBpZiB3ZSBkbyBzb21lIGdlbmVyaWNzIHdvbid0IHdvcmtcbi8vIHdlIGFsc28gZG9uJ3QgdXNlIE9taXQgYmVjYXVzZSBpZiB3ZSBkbyBzb21lIGdlbmVyaWNzIHdvbid0IHdvcmtcbmV4cG9ydCB0eXBlIE1vZGVsUHJvcHNUb1RyYW5zZm9ybWVkQ3JlYXRpb25EYXRhPE1QIGV4dGVuZHMgTW9kZWxQcm9wcz4gPSB7XG4gIFtrIGluIGtleW9mIE1QXT86IE1QW2tdW1wiJHRyYW5zZm9ybWVkQ3JlYXRpb25WYWx1ZVR5cGVcIl1cbn0gJiB7XG4gIFtrIGluIFJlcXVpcmVkTW9kZWxQcm9wczxNUD5dOiBNUFtrXVtcIiR0cmFuc2Zvcm1lZENyZWF0aW9uVmFsdWVUeXBlXCJdXG59XG5cbmV4cG9ydCB0eXBlIE1vZGVsUHJvcHNUb1NldHRlcjxNUCBleHRlbmRzIE1vZGVsUHJvcHM+ID0gRmxhdHRlbjx7XG4gIFtrIGluIGtleW9mIE1QIGFzIE1QW2tdW1wiJGhhc1NldHRlclwiXSAmIGBzZXQke0NhcGl0YWxpemU8ayAmIHN0cmluZz59YF06IChcbiAgICB2YWx1ZTogTVBba11bXCIkdHJhbnNmb3JtZWRWYWx1ZVR5cGVcIl1cbiAgKSA9PiB2b2lkXG59PlxuXG5leHBvcnQgdHlwZSBNb2RlbElkUHJvcDxUIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiA9IE1vZGVsUHJvcDxcbiAgVCxcbiAgVCB8IHVuZGVmaW5lZCxcbiAgVCxcbiAgVCB8IHVuZGVmaW5lZCxcbiAgbmV2ZXIsIC8vIG5vdCByZXF1aXJlZFxuICB0cnVlXG4+XG5cbi8qKlxuICogQSBwcm9wZXJ0eSB0aGF0IHdpbGwgYmUgdXNlZCBhcyBtb2RlbCBpZCwgYWNjZXNzaWJsZSB0aHJvdWdoICRtb2RlbElkLlxuICogQ2FuIG9ubHkgYmUgdXNlZCBpbiBtb2RlbHMgYW5kIHRoZXJlIGNhbiBiZSBvbmx5IG9uZSBwZXIgbW9kZWwuXG4gKi9cbmV4cG9ydCBjb25zdCBpZFByb3AgPSB7XG4gIF9zZXR0ZXI6IGZhbHNlLFxuICBfaXNJZDogdHJ1ZSxcblxuICB3aXRoU2V0dGVyKG1vZGU/OiBib29sZWFuIHwgXCJhc3NpZ25cIikge1xuICAgIGNvbnN0IG9iajogQW55TW9kZWxQcm9wID0gT2JqZWN0LmNyZWF0ZSh0aGlzKVxuICAgIG9iai5fc2V0dGVyID0gbW9kZSA/PyB0cnVlXG4gICAgcmV0dXJuIG9ialxuICB9LFxuXG4gIHR5cGVkQXMoKSB7XG4gICAgcmV0dXJuIGlkUHJvcFxuICB9LFxufSBhcyBhbnkgYXMgTW9kZWxJZFByb3AgJiB7XG4gIC8qKlxuICAgKiBTYW1lIGFzIGBpZFByb3BgLCBleGNlcHQgdGhhdCBpdCBtaWdodCBoYXZlIGFuIHNwZWNpZmljIFR5cGVTY3JpcHQgc3RyaW5nIHRlbXBsYXRlIGFzIHR5cGUuXG4gICAqIEUuZy4gYHR5cGVkSWRQcm9wPGBjdXN0b20tJHtzdHJpbmd9YD4oKWBcbiAgICovXG4gIHR5cGVkQXM8VCBleHRlbmRzIHN0cmluZz4oKTogTW9kZWxJZFByb3A8VD5cbn1cblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCB0eXBlIE9ubHlQcmltaXRpdmVzPFQ+ID0gRXhjbHVkZTxULCBvYmplY3Q+XG5cbi8qKlxuICogQSBtb2RlbCBwcm9wIHRoYXQgbWF5YmUgLyBtYXliZSBub3QgaXMgb3B0aW9uYWwsIGRlcGVuZGluZyBvbiBpZiB0aGUgdmFsdWUgY2FuIHRha2UgdW5kZWZpbmVkLlxuICovXG5leHBvcnQgdHlwZSBNYXliZU9wdGlvbmFsTW9kZWxQcm9wPFRQcm9wVmFsdWU+ID0gTW9kZWxQcm9wPFxuICBUUHJvcFZhbHVlLFxuICBUUHJvcFZhbHVlLFxuICBUUHJvcFZhbHVlLFxuICBUUHJvcFZhbHVlLFxuICBJc09wdGlvbmFsVmFsdWU8VFByb3BWYWx1ZSwgbmV2ZXIsIHN0cmluZz4gLy8gY2FsY3VsYXRlIGlmIHJlcXVpcmVkXG4+XG5cbi8qKlxuICogQSBtb2RlbCBwcm9wIHRoYXQgaXMgZGVmaW5pdGVseSBvcHRpb25hbC5cbiAqL1xuZXhwb3J0IHR5cGUgT3B0aW9uYWxNb2RlbFByb3A8VFByb3BWYWx1ZT4gPSBNb2RlbFByb3A8XG4gIFRQcm9wVmFsdWUsXG4gIFRQcm9wVmFsdWUgfCBudWxsIHwgdW5kZWZpbmVkLFxuICBUUHJvcFZhbHVlLFxuICBUUHJvcFZhbHVlIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgbmV2ZXIgLy8gbm90IHJlcXVpcmVkXG4+XG5cbmNvbnN0IGJhc2VQcm9wOiBBbnlNb2RlbFByb3AgPSB7XG4gIC4uLih7fSBhcyBQaWNrPFxuICAgIEFueU1vZGVsUHJvcCxcbiAgICB8IFwiJHZhbHVlVHlwZVwiXG4gICAgfCBcIiRjcmVhdGlvblZhbHVlVHlwZVwiXG4gICAgfCBcIiR0cmFuc2Zvcm1lZFZhbHVlVHlwZVwiXG4gICAgfCBcIiR0cmFuc2Zvcm1lZENyZWF0aW9uVmFsdWVUeXBlXCJcbiAgICB8IFwiJGlzUmVxdWlyZWRcIlxuICAgIHwgXCIkaXNJZFwiXG4gICAgfCBcIiRoYXNTZXR0ZXJcIlxuICAgIHwgXCIkZnJvbVNuYXBzaG90T3ZlcnJpZGVcIlxuICAgIHwgXCIkdG9TbmFwc2hvdE92ZXJyaWRlXCJcbiAgPiksXG5cbiAgX2RlZmF1bHRGbjogbm9EZWZhdWx0VmFsdWUsXG4gIF9kZWZhdWx0VmFsdWU6IG5vRGVmYXVsdFZhbHVlLFxuICBfdHlwZUNoZWNrZXI6IHVuZGVmaW5lZCxcbiAgX3NldHRlcjogZmFsc2UsXG4gIF9pc0lkOiBmYWxzZSxcbiAgX3RyYW5zZm9ybTogdW5kZWZpbmVkLFxuICBfZnJvbVNuYXBzaG90UHJvY2Vzc29yOiB1bmRlZmluZWQsXG4gIF90b1NuYXBzaG90UHJvY2Vzc29yOiB1bmRlZmluZWQsXG5cbiAgd2l0aFNldHRlcihtb2RlPzogYm9vbGVhbiB8IFwiYXNzaWduXCIpIHtcbiAgICBjb25zdCBvYmo6IEFueU1vZGVsUHJvcCA9IE9iamVjdC5jcmVhdGUodGhpcylcbiAgICBvYmouX3NldHRlciA9IG1vZGUgPz8gdHJ1ZVxuICAgIHJldHVybiBvYmpcbiAgfSxcblxuICB3aXRoVHJhbnNmb3JtKHRyYW5zZm9ybTogTW9kZWxQcm9wVHJhbnNmb3JtPHVua25vd24sIHVua25vd24+KSB7XG4gICAgY29uc3Qgb2JqOiBBbnlNb2RlbFByb3AgPSBPYmplY3QuY3JlYXRlKHRoaXMpXG4gICAgb2JqLl90cmFuc2Zvcm0gPSB0b0Z1bGxUcmFuc2Zvcm0odHJhbnNmb3JtKVxuICAgIHJldHVybiBvYmpcbiAgfSxcblxuICB3aXRoU25hcHNob3RQcm9jZXNzb3IoeyBmcm9tU25hcHNob3QsIHRvU25hcHNob3QgfSkge1xuICAgIGxldCBuZXdGcm9tU25hcHNob3RcblxuICAgIGlmICh0aGlzLl9mcm9tU25hcHNob3RQcm9jZXNzb3IgJiYgZnJvbVNuYXBzaG90KSB7XG4gICAgICBjb25zdCBvbGRGbiA9IHRoaXMuX2Zyb21TbmFwc2hvdFByb2Nlc3NvclxuICAgICAgY29uc3QgbmV3Rm4gPSBmcm9tU25hcHNob3RcbiAgICAgIG5ld0Zyb21TbmFwc2hvdCA9IChzbjogYW55KSA9PiBvbGRGbihuZXdGbihzbikpXG4gICAgfSBlbHNlIGlmIChmcm9tU25hcHNob3QpIHtcbiAgICAgIG5ld0Zyb21TbmFwc2hvdCA9IGZyb21TbmFwc2hvdFxuICAgIH0gZWxzZSB7XG4gICAgICBuZXdGcm9tU25hcHNob3QgPSB0aGlzLl9mcm9tU25hcHNob3RQcm9jZXNzb3JcbiAgICB9XG5cbiAgICBsZXQgbmV3VG9TbmFwc2hvdFxuXG4gICAgaWYgKHRoaXMuX3RvU25hcHNob3RQcm9jZXNzb3IgJiYgdG9TbmFwc2hvdCkge1xuICAgICAgY29uc3Qgb2xkRm46IGFueSA9IHRoaXMuX3RvU25hcHNob3RQcm9jZXNzb3JcbiAgICAgIGNvbnN0IG5ld0ZuID0gdG9TbmFwc2hvdFxuICAgICAgbmV3VG9TbmFwc2hvdCA9IChzbjogYW55KSA9PiBuZXdGbihvbGRGbihzbikpXG4gICAgfSBlbHNlIGlmICh0b1NuYXBzaG90KSB7XG4gICAgICBuZXdUb1NuYXBzaG90ID0gdG9TbmFwc2hvdFxuICAgIH0gZWxzZSB7XG4gICAgICBuZXdUb1NuYXBzaG90ID0gdGhpcy5fdG9TbmFwc2hvdFByb2Nlc3NvclxuICAgIH1cblxuICAgIGNvbnN0IG9iajogQW55TW9kZWxQcm9wID0gT2JqZWN0LmNyZWF0ZSh0aGlzKVxuICAgIG9iai5fZnJvbVNuYXBzaG90UHJvY2Vzc29yID0gbmV3RnJvbVNuYXBzaG90XG4gICAgb2JqLl90b1NuYXBzaG90UHJvY2Vzc29yID0gbmV3VG9TbmFwc2hvdFxuXG4gICAgcmV0dXJuIG9ialxuICB9LFxufVxuXG4vKipcbiAqIERlZmluZXMgYSBtb2RlbCBwcm9wZXJ0eSwgd2l0aCBhbiBvcHRpb25hbCBmdW5jdGlvbiB0byBnZW5lcmF0ZSBhIGRlZmF1bHQgdmFsdWVcbiAqIGlmIHRoZSBpbnB1dCBzbmFwc2hvdCAvIG1vZGVsIGNyZWF0aW9uIGRhdGEgaXMgYG51bGxgIG9yIGB1bmRlZmluZWRgLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogeDogcHJvcCgoKSA9PiAxMCkgLy8gYW4gb3B0aW9uYWwgbnVtYmVyLCB3aXRoIGEgZGVmYXVsdCB2YWx1ZSBvZiAxMFxuICogeDogcHJvcDxudW1iZXJbXT4oKCkgPT4gW10pIC8vIGFuIG9wdGlvbmFsIG51bWJlciBhcnJheSwgd2l0aCBhIGRlZmF1bHQgZW1wdHkgYXJyYXlcbiAqIGBgYFxuICpcbiAqIEB0eXBlcGFyYW0gVFZhbHVlIFZhbHVlIHR5cGUuXG4gKiBAcGFyYW0gZGVmYXVsdEZuIERlZmF1bHQgdmFsdWUgZ2VuZXJhdG9yIGZ1bmN0aW9uLlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3A8VFZhbHVlPihkZWZhdWx0Rm46ICgpID0+IFRWYWx1ZSk6IE9wdGlvbmFsTW9kZWxQcm9wPFRWYWx1ZT5cblxuLyoqXG4gKiBEZWZpbmVzIGEgbW9kZWwgcHJvcGVydHksIHdpdGggYW4gb3B0aW9uYWwgZGVmYXVsdCB2YWx1ZVxuICogaWYgdGhlIGlucHV0IHNuYXBzaG90IC8gbW9kZWwgY3JlYXRpb24gZGF0YSBpcyBgbnVsbGAgb3IgYHVuZGVmaW5lZGAuXG4gKiBZb3Ugc2hvdWxkIG9ubHkgdXNlIHRoaXMgd2l0aCBwcmltaXRpdmUgdmFsdWVzIGFuZCBuZXZlciB3aXRoIG9iamVjdCB2YWx1ZXNcbiAqIChhcnJheSwgbW9kZWwsIG9iamVjdCwgZXRjKS5cbiAqXG4gKiBFeGFtcGxlOlxuICogYGBgdHNcbiAqIHg6IHByb3AoMTApIC8vIGFuIG9wdGlvbmFsIG51bWJlciwgd2l0aCBhIGRlZmF1bHQgdmFsdWUgb2YgMTBcbiAqIGBgYFxuICpcbiAqIEB0eXBlcGFyYW0gVFZhbHVlIFZhbHVlIHR5cGUuXG4gKiBAcGFyYW0gZGVmYXVsdFZhbHVlIERlZmF1bHQgcHJpbWl0aXZlIHZhbHVlLlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3A8VFZhbHVlPihkZWZhdWx0VmFsdWU6IE9ubHlQcmltaXRpdmVzPFRWYWx1ZT4pOiBPcHRpb25hbE1vZGVsUHJvcDxUVmFsdWU+XG5cbi8qKlxuICogRGVmaW5lcyBhIG1vZGVsIHByb3BlcnR5IHdpdGggbm8gZGVmYXVsdCB2YWx1ZS5cbiAqXG4gKiBFeGFtcGxlOlxuICogYGBgdHNcbiAqIHg6IHByb3A8bnVtYmVyPigpIC8vIGEgcmVxdWlyZWQgbnVtYmVyXG4gKiB4OiBwcm9wPG51bWJlciB8IHVuZGVmaW5lZD4oKSAvLyBhbiBvcHRpb25hbCBudW1iZXIsIHdoaWNoIGRlZmF1bHRzIHRvIHVuZGVmaW5lZFxuICogYGBgXG4gKlxuICogQHR5cGVwYXJhbSBUVmFsdWUgVmFsdWUgdHlwZS5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm9wPFRWYWx1ZT4oKTogTWF5YmVPcHRpb25hbE1vZGVsUHJvcDxUVmFsdWU+XG5cbi8vIGJhc2VcbmV4cG9ydCBmdW5jdGlvbiBwcm9wKGRlZj86IGFueSk6IEFueU1vZGVsUHJvcCB7XG4gIGNvbnN0IGhhc0RlZmF1bHRWYWx1ZSA9IGFyZ3VtZW50cy5sZW5ndGggPj0gMVxuICBpZiAoIWhhc0RlZmF1bHRWYWx1ZSkge1xuICAgIHJldHVybiBiYXNlUHJvcFxuICB9XG5cbiAgbGV0IHAgPSBwcm9wQ2FjaGUuZ2V0KGRlZilcblxuICBpZiAoIXApIHtcbiAgICBwID0gT2JqZWN0LmNyZWF0ZShiYXNlUHJvcClcblxuICAgIGlmICh0eXBlb2YgZGVmID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHAhLl9kZWZhdWx0Rm4gPSBkZWZcbiAgICB9IGVsc2Uge1xuICAgICAgcCEuX2RlZmF1bHRWYWx1ZSA9IGRlZlxuICAgIH1cblxuICAgIHByb3BDYWNoZS5zZXQoZGVmLCBwISlcbiAgfVxuXG4gIHJldHVybiBwIVxufVxuXG5jb25zdCBwcm9wQ2FjaGUgPSBuZXcgTWFwPHVua25vd24sIEFueU1vZGVsUHJvcD4oKVxuXG5sZXQgY2FjaGVUcmFuc2Zvcm1SZXN1bHQgPSBmYWxzZVxuY29uc3QgY2FjaGVUcmFuc2Zvcm1lZFZhbHVlRm4gPSAoKSA9PiB7XG4gIGNhY2hlVHJhbnNmb3JtUmVzdWx0ID0gdHJ1ZVxufVxuXG5mdW5jdGlvbiB0b0Z1bGxUcmFuc2Zvcm0odHJhbnNmb3JtT2JqZWN0OiBNb2RlbFByb3BUcmFuc2Zvcm08dW5rbm93biwgdW5rbm93bj4pIHtcbiAgY29uc3QgY2FjaGUgPSBuZXcgV2Vha01hcDxcbiAgICBvYmplY3QsXG4gICAgTWFwPFByb3BlcnR5S2V5LCB7IG9yaWdpbmFsVmFsdWU6IHVua25vd247IHRyYW5zZm9ybWVkVmFsdWU6IHVua25vd24gfT5cbiAgPigpXG5cbiAgY29uc3QgdHJhbnNmb3JtID0gKHBhcmFtczoge1xuICAgIG9yaWdpbmFsVmFsdWU6IHVua25vd25cbiAgICBjYWNoZWRUcmFuc2Zvcm1lZFZhbHVlOiB1bmtub3duXG4gICAgc2V0T3JpZ2luYWxWYWx1ZShuZXdPcmlnaW5hbFZhbHVlOiB1bmtub3duKTogdm9pZFxuICB9KSA9PiAocGFyYW1zLm9yaWdpbmFsVmFsdWUgPT0gbnVsbCA/IHBhcmFtcy5vcmlnaW5hbFZhbHVlIDogdHJhbnNmb3JtT2JqZWN0LnRyYW5zZm9ybShwYXJhbXMpKVxuXG4gIGNvbnN0IHVudHJhbnNmb3JtID0gKHBhcmFtczogeyB0cmFuc2Zvcm1lZFZhbHVlOiB1bmtub3duOyBjYWNoZVRyYW5zZm9ybWVkVmFsdWUoKTogdm9pZCB9KSA9PlxuICAgIHBhcmFtcy50cmFuc2Zvcm1lZFZhbHVlID09IG51bGwgPyBwYXJhbXMudHJhbnNmb3JtZWRWYWx1ZSA6IHRyYW5zZm9ybU9iamVjdC51bnRyYW5zZm9ybShwYXJhbXMpXG5cbiAgcmV0dXJuIHtcbiAgICB0cmFuc2Zvcm0oXG4gICAgICBvcmlnaW5hbFZhbHVlOiB1bmtub3duLFxuICAgICAgbW9kZWw6IG9iamVjdCxcbiAgICAgIHByb3BOYW1lOiBQcm9wZXJ0eUtleSxcbiAgICAgIHNldE9yaWdpbmFsVmFsdWU6IChuZXdPcmlnaW5hbFZhbHVlOiB1bmtub3duKSA9PiB2b2lkXG4gICAgKSB7XG4gICAgICBjb25zdCBtb2RlbENhY2hlID0gZ2V0T3JDcmVhdGUoY2FjaGUsIG1vZGVsLCAoKSA9PiBuZXcgTWFwKCkpXG5cbiAgICAgIGxldCBwcm9wQ2FjaGUgPSBtb2RlbENhY2hlLmdldChwcm9wTmFtZSlcbiAgICAgIGlmIChwcm9wQ2FjaGU/Lm9yaWdpbmFsVmFsdWUgIT09IG9yaWdpbmFsVmFsdWUpIHtcbiAgICAgICAgLy8gb3JpZ2luYWwgY2hhbmdlZCwgaW52YWxpZGF0ZSBjYWNoZVxuICAgICAgICBtb2RlbENhY2hlLmRlbGV0ZShwcm9wTmFtZSlcbiAgICAgICAgcHJvcENhY2hlID0gdW5kZWZpbmVkXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSB0cmFuc2Zvcm0oe1xuICAgICAgICBvcmlnaW5hbFZhbHVlLFxuICAgICAgICBjYWNoZWRUcmFuc2Zvcm1lZFZhbHVlOiBwcm9wQ2FjaGU/LnRyYW5zZm9ybWVkVmFsdWUsXG4gICAgICAgIHNldE9yaWdpbmFsVmFsdWUsXG4gICAgICB9KVxuXG4gICAgICBtb2RlbENhY2hlLnNldChwcm9wTmFtZSwge1xuICAgICAgICBvcmlnaW5hbFZhbHVlLFxuICAgICAgICB0cmFuc2Zvcm1lZFZhbHVlLFxuICAgICAgfSlcblxuICAgICAgcmV0dXJuIHRyYW5zZm9ybWVkVmFsdWVcbiAgICB9LFxuXG4gICAgdW50cmFuc2Zvcm0odHJhbnNmb3JtZWRWYWx1ZTogdW5rbm93biwgbW9kZWw6IG9iamVjdCwgcHJvcE5hbWU6IFByb3BlcnR5S2V5KSB7XG4gICAgICBjb25zdCBtb2RlbENhY2hlID0gZ2V0T3JDcmVhdGUoY2FjaGUsIG1vZGVsLCAoKSA9PiBuZXcgTWFwKCkpXG5cbiAgICAgIGNhY2hlVHJhbnNmb3JtUmVzdWx0ID0gZmFsc2VcbiAgICAgIGNvbnN0IG9yaWdpbmFsVmFsdWUgPSB1bnRyYW5zZm9ybSh7XG4gICAgICAgIHRyYW5zZm9ybWVkVmFsdWUsXG4gICAgICAgIGNhY2hlVHJhbnNmb3JtZWRWYWx1ZTogY2FjaGVUcmFuc2Zvcm1lZFZhbHVlRm4sXG4gICAgICB9KVxuICAgICAgaWYgKGNhY2hlVHJhbnNmb3JtUmVzdWx0KSB7XG4gICAgICAgIG1vZGVsQ2FjaGUuc2V0KHByb3BOYW1lLCB7IG9yaWdpbmFsVmFsdWUsIHRyYW5zZm9ybWVkVmFsdWUgfSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1vZGVsQ2FjaGUuZGVsZXRlKHByb3BOYW1lKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gb3JpZ2luYWxWYWx1ZVxuICAgIH0sXG4gIH1cbn1cblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNb2RlbFByb3BEZWZhdWx0VmFsdWUocHJvcERhdGE6IEFueU1vZGVsUHJvcCk6IHVua25vd24gfCB0eXBlb2Ygbm9EZWZhdWx0VmFsdWUge1xuICBpZiAocHJvcERhdGEuX2RlZmF1bHRGbiAhPT0gbm9EZWZhdWx0VmFsdWUpIHtcbiAgICByZXR1cm4gcHJvcERhdGEuX2RlZmF1bHRGbigpXG4gIH1cblxuICBpZiAocHJvcERhdGEuX2RlZmF1bHRWYWx1ZSAhPT0gbm9EZWZhdWx0VmFsdWUpIHtcbiAgICByZXR1cm4gcHJvcERhdGEuX2RlZmF1bHRWYWx1ZVxuICB9XG5cbiAgcmV0dXJuIG5vRGVmYXVsdFZhbHVlXG59XG4iLCJsZXQgdXJsQWxwaGFiZXQgPVxuICAndXNlYW5kb20tMjZUMTk4MzQwUFg3NXB4SkFDS1ZFUllNSU5EQlVTSFdPTEZfR1FaYmZnaGprbHF2d3l6cmljdCdcbmxldCBjdXN0b21BbHBoYWJldCA9IChhbHBoYWJldCwgZGVmYXVsdFNpemUgPSAyMSkgPT4ge1xuICByZXR1cm4gKHNpemUgPSBkZWZhdWx0U2l6ZSkgPT4ge1xuICAgIGxldCBpZCA9ICcnXG4gICAgbGV0IGkgPSBzaXplXG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgaWQgKz0gYWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiBhbHBoYWJldC5sZW5ndGgpIHwgMF1cbiAgICB9XG4gICAgcmV0dXJuIGlkXG4gIH1cbn1cbmxldCBuYW5vaWQgPSAoc2l6ZSA9IDIxKSA9PiB7XG4gIGxldCBpZCA9ICcnXG4gIGxldCBpID0gc2l6ZVxuICB3aGlsZSAoaS0tKSB7XG4gICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICB9XG4gIHJldHVybiBpZFxufVxuZXhwb3J0IHsgbmFub2lkLCBjdXN0b21BbHBoYWJldCB9XG4iLCJpbXBvcnQgeyBuYW5vaWQgfSBmcm9tIFwibmFub2lkL25vbi1zZWN1cmVcIlxuaW1wb3J0IHsgZmFpbHVyZSwgaW5EZXZNb2RlIH0gZnJvbSBcIi4uL3V0aWxzXCJcblxuLyoqXG4gKiBNb2RlbCBhdXRvIHR5cGUtY2hlY2tpbmcgbW9kZS5cbiAqL1xuZXhwb3J0IGVudW0gTW9kZWxBdXRvVHlwZUNoZWNraW5nTW9kZSB7XG4gIC8qKlxuICAgKiBBdXRvIHR5cGUgY2hlY2sgbW9kZWxzIG9ubHkgaW4gZGV2IG1vZGVcbiAgICovXG4gIERldk1vZGVPbmx5ID0gXCJkZXZNb2RlT25seVwiLFxuICAvKipcbiAgICogQXV0byB0eXBlIGNoZWNrIG1vZGVscyBubyBtYXR0ZXIgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnRcbiAgICovXG4gIEFsd2F5c09uID0gXCJhbHdheXNPblwiLFxuICAvKipcbiAgICogRG8gbm90IGF1dG8gdHlwZSBjaGVjayBtb2RlbHMgbm8gbWF0dGVyIHRoZSBjdXJyZW50IGVudmlyb25tZW50XG4gICAqL1xuICBBbHdheXNPZmYgPSBcImFsd2F5c09mZlwiLFxufVxuXG4vKipcbiAqIEdsb2JhbCBjb25maWcgb2JqZWN0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdsb2JhbENvbmZpZyB7XG4gIC8qKlxuICAgKiBNb2RlbCBhdXRvIHR5cGUtY2hlY2tpbmcgbW9kZS5cbiAgICovXG4gIG1vZGVsQXV0b1R5cGVDaGVja2luZzogTW9kZWxBdXRvVHlwZUNoZWNraW5nTW9kZVxuXG4gIC8qKlxuICAgKiBJRCBnZW5lcmF0b3IgZnVuY3Rpb24gZm9yIG1vZGVsIGlkcy5cbiAgICovXG4gIG1vZGVsSWRHZW5lcmF0b3IoKTogc3RyaW5nXG5cbiAgLyoqXG4gICAqIEFsbG93IGFycmF5IGVsZW1lbnRzIHRvIGJlIGB1bmRlZmluZWRgLlxuICAgKi9cbiAgYWxsb3dVbmRlZmluZWRBcnJheUVsZW1lbnRzOiBib29sZWFuXG5cbiAgLyoqXG4gICAqIEVuYWJsZXMvZGlzYWJsZXMgd2FybmluZ3MgcmVsYXRlZCB0byBkdXBsaWNhdGVkIG1vZGVsIG5hbWVzIChkZWZhdWx0cyB0byBgdHJ1ZWApLlxuICAgKiBVc3VhbGx5IHNldCB0byBmYWxzZSBpbiB0ZXN0IGVudmlyb25tZW50cyAoZS5nLiBqZXN0KS5cbiAgICovXG4gIHNob3dEdXBsaWNhdGVNb2RlbE5hbWVXYXJuaW5nczogYm9vbGVhblxufVxuXG5sZXQgbG9jYWxJZCA9IDBcbmNvbnN0IGxvY2FsQmFzZUlkID0gbmFub2lkKClcblxuZnVuY3Rpb24gZGVmYXVsdE1vZGVsSWRHZW5lcmF0b3IoKTogc3RyaW5nIHtcbiAgLy8gd2UgdXNlIGJhc2UgMzYgZm9yIGxvY2FsIGlkIHNpbmNlIGl0IGlzIHNob3J0IGFuZCBmYXN0XG4gIGNvbnN0IGlkID0gbG9jYWxJZC50b1N0cmluZygzNikgKyBcIi1cIiArIGxvY2FsQmFzZUlkXG4gIGxvY2FsSWQrK1xuICByZXR1cm4gaWRcbn1cblxuLy8gZGVmYXVsdHNcbmxldCBnbG9iYWxDb25maWc6IEdsb2JhbENvbmZpZyA9IHtcbiAgbW9kZWxBdXRvVHlwZUNoZWNraW5nOiBNb2RlbEF1dG9UeXBlQ2hlY2tpbmdNb2RlLkRldk1vZGVPbmx5LFxuICBtb2RlbElkR2VuZXJhdG9yOiBkZWZhdWx0TW9kZWxJZEdlbmVyYXRvcixcbiAgYWxsb3dVbmRlZmluZWRBcnJheUVsZW1lbnRzOiBmYWxzZSxcbiAgc2hvd0R1cGxpY2F0ZU1vZGVsTmFtZVdhcm5pbmdzOiB0cnVlLFxufVxuXG4vKipcbiAqIFBhcnRpYWxseSBzZXRzIHRoZSBjdXJyZW50IGdsb2JhbCBjb25maWcuXG4gKlxuICogQHBhcmFtIGNvbmZpZyBQYXJ0aWFsIG9iamVjdCB3aXRoIHRoZSBuZXcgY29uZmlndXJhdGlvbnMuIE9wdGlvbnMgbm90IGluY2x1ZGVkIGluIHRoZSBvYmplY3Qgd29uJ3QgYmUgY2hhbmdlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldEdsb2JhbENvbmZpZyhjb25maWc6IFBhcnRpYWw8R2xvYmFsQ29uZmlnPikge1xuICBnbG9iYWxDb25maWcgPSBPYmplY3QuZnJlZXplKHtcbiAgICAuLi5nbG9iYWxDb25maWcsXG4gICAgLi4uY29uZmlnLFxuICB9KVxufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGN1cnJlbnQgZ2xvYmFsIGNvbmZpZyBvYmplY3QuXG4gKlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEdsb2JhbENvbmZpZygpOiBSZWFkb25seTxHbG9iYWxDb25maWc+IHtcbiAgcmV0dXJuIGdsb2JhbENvbmZpZ1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICpcbiAqIFJldHVybnMgaWYgdGhlIGF1dG8gdHlwZSBjaGVja2luZyBmb3IgbW9kZWxzIGlzIGVuYWJsZWQuXG4gKlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTW9kZWxBdXRvVHlwZUNoZWNraW5nRW5hYmxlZCgpIHtcbiAgc3dpdGNoIChnZXRHbG9iYWxDb25maWcoKS5tb2RlbEF1dG9UeXBlQ2hlY2tpbmcpIHtcbiAgICBjYXNlIE1vZGVsQXV0b1R5cGVDaGVja2luZ01vZGUuRGV2TW9kZU9ubHk6XG4gICAgICByZXR1cm4gaW5EZXZNb2RlXG4gICAgY2FzZSBNb2RlbEF1dG9UeXBlQ2hlY2tpbmdNb2RlLkFsd2F5c09mZjpcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIGNhc2UgTW9kZWxBdXRvVHlwZUNoZWNraW5nTW9kZS5BbHdheXNPbjpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IGZhaWx1cmUoXG4gICAgICAgIGBpbnZhbGlkICdtb2RlbEF1dG9UeXBlQ2hlY2tpbmcnIGNvbmZpZyB2YWx1ZSAtICR7Z2xvYmFsQ29uZmlnLm1vZGVsQXV0b1R5cGVDaGVja2luZ31gXG4gICAgICApXG4gIH1cbn1cbiIsImltcG9ydCB7IGFjdGlvbiwgY3JlYXRlQXRvbSwgSUF0b20gfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgeyBmYXN0R2V0UGFyZW50IH0gZnJvbSBcIi4vcGF0aFwiXG5cbmludGVyZmFjZSBEZWVwT2JqZWN0Q2hpbGRyZW4ge1xuICBkZWVwOiBTZXQ8b2JqZWN0PlxuXG4gIGV4dGVuc2lvbnNEYXRhOiBXZWFrTWFwPG9iamVjdCwgYW55PlxufVxuXG5pbnRlcmZhY2UgT2JqZWN0Q2hpbGRyZW5EYXRhIGV4dGVuZHMgRGVlcE9iamVjdENoaWxkcmVuIHtcbiAgc2hhbGxvdzogU2V0PG9iamVjdD5cbiAgc2hhbGxvd0F0b206IElBdG9tXG5cbiAgZGVlcERpcnR5OiBib29sZWFuXG4gIGRlZXBBdG9tOiBJQXRvbVxufVxuXG5jb25zdCBvYmplY3RDaGlsZHJlbiA9IG5ldyBXZWFrTWFwPG9iamVjdCwgT2JqZWN0Q2hpbGRyZW5EYXRhPigpXG5cbmZ1bmN0aW9uIGdldE9iamVjdENoaWxkcmVuT2JqZWN0KG5vZGU6IG9iamVjdCkge1xuICBsZXQgb2JqID0gb2JqZWN0Q2hpbGRyZW4uZ2V0KG5vZGUpXG5cbiAgaWYgKCFvYmopIHtcbiAgICBvYmogPSB7XG4gICAgICBzaGFsbG93OiBuZXcgU2V0KCksXG4gICAgICBzaGFsbG93QXRvbTogY3JlYXRlQXRvbShcInNoYWxsb3dDaGlsZHJlbkF0b21cIiksXG5cbiAgICAgIGRlZXA6IG5ldyBTZXQoKSxcbiAgICAgIGRlZXBEaXJ0eTogdHJ1ZSxcbiAgICAgIGRlZXBBdG9tOiBjcmVhdGVBdG9tKFwiZGVlcENoaWxkcmVuQXRvbVwiKSxcblxuICAgICAgZXh0ZW5zaW9uc0RhdGE6IGluaXRFeHRlbnNpb25zRGF0YSgpLFxuICAgIH1cbiAgICBvYmplY3RDaGlsZHJlbi5zZXQobm9kZSwgb2JqKVxuICB9XG5cbiAgcmV0dXJuIG9ialxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0T2JqZWN0Q2hpbGRyZW4obm9kZTogb2JqZWN0KTogT2JqZWN0Q2hpbGRyZW5EYXRhW1wic2hhbGxvd1wiXSB7XG4gIGNvbnN0IG9iaiA9IGdldE9iamVjdENoaWxkcmVuT2JqZWN0KG5vZGUpXG4gIG9iai5zaGFsbG93QXRvbS5yZXBvcnRPYnNlcnZlZCgpXG4gIHJldHVybiBvYmouc2hhbGxvd1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGVlcE9iamVjdENoaWxkcmVuKG5vZGU6IG9iamVjdCk6IERlZXBPYmplY3RDaGlsZHJlbiB7XG4gIGNvbnN0IG9iaiA9IGdldE9iamVjdENoaWxkcmVuT2JqZWN0KG5vZGUpXG5cbiAgaWYgKG9iai5kZWVwRGlydHkpIHtcbiAgICB1cGRhdGVEZWVwT2JqZWN0Q2hpbGRyZW4obm9kZSlcbiAgfVxuXG4gIG9iai5kZWVwQXRvbS5yZXBvcnRPYnNlcnZlZCgpXG5cbiAgcmV0dXJuIG9ialxufVxuXG5mdW5jdGlvbiBhZGROb2RlVG9EZWVwTGlzdHMobm9kZTogYW55LCBkYXRhOiBEZWVwT2JqZWN0Q2hpbGRyZW4pIHtcbiAgZGF0YS5kZWVwLmFkZChub2RlKVxuICBleHRlbnNpb25zLmZvckVhY2goKGV4dGVuc2lvbiwgZGF0YVN5bWJvbCkgPT4ge1xuICAgIGV4dGVuc2lvbi5hZGROb2RlKG5vZGUsIGRhdGEuZXh0ZW5zaW9uc0RhdGEuZ2V0KGRhdGFTeW1ib2wpKVxuICB9KVxufVxuXG5jb25zdCB1cGRhdGVEZWVwT2JqZWN0Q2hpbGRyZW4gPSBhY3Rpb24oKG5vZGU6IG9iamVjdCk6IERlZXBPYmplY3RDaGlsZHJlbiA9PiB7XG4gIGNvbnN0IG9iaiA9IGdldE9iamVjdENoaWxkcmVuT2JqZWN0KG5vZGUpIVxuICBpZiAoIW9iai5kZWVwRGlydHkpIHtcbiAgICByZXR1cm4gb2JqXG4gIH1cblxuICBvYmouZGVlcCA9IG5ldyBTZXQoKVxuICBvYmouZXh0ZW5zaW9uc0RhdGEgPSBpbml0RXh0ZW5zaW9uc0RhdGEoKVxuXG4gIGNvbnN0IGNoaWxkcmVuSXRlcmF0b3IgPSBvYmouc2hhbGxvdy52YWx1ZXMoKVxuICBsZXQgY2hpbGRyZW5JdGVyYXRvclJlc3VsdCA9IGNoaWxkcmVuSXRlcmF0b3IubmV4dCgpXG4gIHdoaWxlICghY2hpbGRyZW5JdGVyYXRvclJlc3VsdC5kb25lKSB7XG4gICAgYWRkTm9kZVRvRGVlcExpc3RzKGNoaWxkcmVuSXRlcmF0b3JSZXN1bHQudmFsdWUsIG9iailcblxuICAgIGNvbnN0IGNoaWxkRGVlcENoaWxkcmVuID0gdXBkYXRlRGVlcE9iamVjdENoaWxkcmVuKGNoaWxkcmVuSXRlcmF0b3JSZXN1bHQudmFsdWUpLmRlZXBcbiAgICBjb25zdCBjaGlsZERlZXBDaGlsZHJlbkl0ZXJhdG9yID0gY2hpbGREZWVwQ2hpbGRyZW4udmFsdWVzKClcbiAgICBsZXQgY2hpbGREZWVwQ2hpbGRyZW5JdGVyYXRvclJlc3VsdCA9IGNoaWxkRGVlcENoaWxkcmVuSXRlcmF0b3IubmV4dCgpXG4gICAgd2hpbGUgKCFjaGlsZERlZXBDaGlsZHJlbkl0ZXJhdG9yUmVzdWx0LmRvbmUpIHtcbiAgICAgIGFkZE5vZGVUb0RlZXBMaXN0cyhjaGlsZERlZXBDaGlsZHJlbkl0ZXJhdG9yUmVzdWx0LnZhbHVlLCBvYmopXG4gICAgICBjaGlsZERlZXBDaGlsZHJlbkl0ZXJhdG9yUmVzdWx0ID0gY2hpbGREZWVwQ2hpbGRyZW5JdGVyYXRvci5uZXh0KClcbiAgICB9XG5cbiAgICBjaGlsZHJlbkl0ZXJhdG9yUmVzdWx0ID0gY2hpbGRyZW5JdGVyYXRvci5uZXh0KClcbiAgfVxuXG4gIG9iai5kZWVwRGlydHkgPSBmYWxzZVxuICBvYmouZGVlcEF0b20ucmVwb3J0Q2hhbmdlZCgpXG5cbiAgcmV0dXJuIG9ialxufSlcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IGFkZE9iamVjdENoaWxkID0gYWN0aW9uKChub2RlOiBvYmplY3QsIGNoaWxkOiBvYmplY3QpID0+IHtcbiAgY29uc3Qgb2JqID0gZ2V0T2JqZWN0Q2hpbGRyZW5PYmplY3Qobm9kZSlcbiAgb2JqLnNoYWxsb3cuYWRkKGNoaWxkKVxuICBvYmouc2hhbGxvd0F0b20ucmVwb3J0Q2hhbmdlZCgpXG5cbiAgaW52YWxpZGF0ZURlZXBDaGlsZHJlbihub2RlLCBvYmopXG59KVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgcmVtb3ZlT2JqZWN0Q2hpbGQgPSBhY3Rpb24oKG5vZGU6IG9iamVjdCwgY2hpbGQ6IG9iamVjdCkgPT4ge1xuICBjb25zdCBvYmogPSBnZXRPYmplY3RDaGlsZHJlbk9iamVjdChub2RlKVxuICBvYmouc2hhbGxvdy5kZWxldGUoY2hpbGQpXG4gIG9iai5zaGFsbG93QXRvbS5yZXBvcnRDaGFuZ2VkKClcblxuICBpbnZhbGlkYXRlRGVlcENoaWxkcmVuKG5vZGUsIG9iailcbn0pXG5cbmZ1bmN0aW9uIGludmFsaWRhdGVEZWVwQ2hpbGRyZW4obm9kZTogb2JqZWN0LCBvYmo6IE9iamVjdENoaWxkcmVuRGF0YSkge1xuICBsZXQgY3VycmVudE5vZGU6IG9iamVjdCB8IHVuZGVmaW5lZCA9IG5vZGVcbiAgbGV0IGN1cnJlbnRPYmogPSBvYmpcblxuICB3aGlsZSAoY3VycmVudE5vZGUpIHtcbiAgICBjdXJyZW50T2JqLmRlZXBEaXJ0eSA9IHRydWVcbiAgICBjdXJyZW50T2JqLmRlZXBBdG9tLnJlcG9ydENoYW5nZWQoKVxuXG4gICAgY3VycmVudE5vZGUgPSBmYXN0R2V0UGFyZW50KGN1cnJlbnROb2RlKVxuICAgIGlmIChjdXJyZW50Tm9kZSkge1xuICAgICAgY3VycmVudE9iaiA9IGdldE9iamVjdENoaWxkcmVuT2JqZWN0KGN1cnJlbnROb2RlKVxuICAgIH1cbiAgfVxufVxuXG5jb25zdCBleHRlbnNpb25zID0gbmV3IE1hcDxvYmplY3QsIERlZXBPYmplY3RDaGlsZHJlbkV4dGVuc2lvbjxhbnk+PigpXG5cbmludGVyZmFjZSBEZWVwT2JqZWN0Q2hpbGRyZW5FeHRlbnNpb248RD4ge1xuICBpbml0RGF0YSgpOiBEXG4gIGFkZE5vZGUobm9kZTogYW55LCBkYXRhOiBEKTogdm9pZFxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZWVwT2JqZWN0Q2hpbGRyZW5FeHRlbnNpb248RD4oZXh0ZW5zaW9uOiBEZWVwT2JqZWN0Q2hpbGRyZW5FeHRlbnNpb248RD4pIHtcbiAgY29uc3QgZGF0YVN5bWJvbCA9IHt9XG4gIGV4dGVuc2lvbnMuc2V0KGRhdGFTeW1ib2wsIGV4dGVuc2lvbilcblxuICByZXR1cm4gKGRhdGE6IERlZXBPYmplY3RDaGlsZHJlbik6IEQgPT4ge1xuICAgIHJldHVybiBkYXRhLmV4dGVuc2lvbnNEYXRhLmdldChkYXRhU3ltYm9sKSBhcyBEXG4gIH1cbn1cblxuZnVuY3Rpb24gaW5pdEV4dGVuc2lvbnNEYXRhKCkge1xuICBjb25zdCBleHRlbnNpb25zRGF0YSA9IG5ldyBXZWFrTWFwPG9iamVjdCwgYW55PigpXG5cbiAgZXh0ZW5zaW9ucy5mb3JFYWNoKChleHRlbnNpb24sIGRhdGFTeW1ib2wpID0+IHtcbiAgICBleHRlbnNpb25zRGF0YS5zZXQoZGF0YVN5bWJvbCwgZXh0ZW5zaW9uLmluaXREYXRhKCkpXG4gIH0pXG5cbiAgcmV0dXJuIGV4dGVuc2lvbnNEYXRhXG59XG4iLCJpbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IGdldEN1cnJlbnRBY3Rpb25Db250ZXh0IH0gZnJvbSBcIi4vY29udGV4dFwiXG5cbmZ1bmN0aW9uIGNhbldyaXRlKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gIWdldEFjdGlvblByb3RlY3Rpb24oKSB8fCAhIWdldEN1cnJlbnRBY3Rpb25Db250ZXh0KClcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydENhbldyaXRlKCkge1xuICBpZiAoIWNhbldyaXRlKCkpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFwiZGF0YSBjaGFuZ2VzIG11c3QgYmUgcGVyZm9ybWVkIGluc2lkZSBtb2RlbCBhY3Rpb25zXCIpXG4gIH1cbn1cblxubGV0IGFjdGlvblByb3RlY3Rpb24gPSB0cnVlXG5cbi8qKlxuICogQGludGVybmFsXG4gKlxuICogR2V0cyBpZiB0aGUgYWN0aW9uIHByb3RlY3Rpb24gaXMgY3VycmVudGx5IGVuYWJsZWQgb3Igbm90LlxuICpcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBY3Rpb25Qcm90ZWN0aW9uKCkge1xuICByZXR1cm4gYWN0aW9uUHJvdGVjdGlvblxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICpcbiAqIFNldHMgaWYgdGhlIGFjdGlvbiBwcm90ZWN0aW9uIGlzIGN1cnJlbnRseSBlbmFibGVkIG9yIG5vdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldEFjdGlvblByb3RlY3Rpb24ocHJvdGVjdGlvbjogYm9vbGVhbikge1xuICBhY3Rpb25Qcm90ZWN0aW9uID0gcHJvdGVjdGlvblxufVxuIiwiaW1wb3J0IHsgZ2V0Q3VycmVudEFjdGlvbkNvbnRleHQgfSBmcm9tIFwiLi9jb250ZXh0XCJcclxuaW1wb3J0IHsgZ2V0QWN0aW9uUHJvdGVjdGlvbiB9IGZyb20gXCIuL3Byb3RlY3Rpb25cIlxyXG5cclxuY29uc3QgcGVuZGluZ0FjdGlvbnM6ICgoKSA9PiB2b2lkKVtdID0gW11cclxuXHJcbmZ1bmN0aW9uIGlzQWN0aW9uUnVubmluZygpOiBib29sZWFuIHtcclxuICByZXR1cm4gIWdldEFjdGlvblByb3RlY3Rpb24oKSB8fCAhIWdldEN1cnJlbnRBY3Rpb25Db250ZXh0KClcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGVucXVldWVQZW5kaW5nQWN0aW9uKGFjdGlvbjogKCkgPT4gdm9pZCk6IHZvaWQge1xyXG4gIC8vIGRlbGF5IGFjdGlvbiB1bnRpbCBhbGwgY3VycmVudCBhY3Rpb25zIGFyZSBmaW5pc2hlZFxyXG4gIGlmIChpc0FjdGlvblJ1bm5pbmcoKSkge1xyXG4gICAgcGVuZGluZ0FjdGlvbnMucHVzaChhY3Rpb24pXHJcbiAgfSBlbHNlIHtcclxuICAgIGFjdGlvbigpXHJcbiAgfVxyXG59XHJcblxyXG5sZXQgcGVuZGluZ0FjdGlvbnNSdW5uaW5nID0gZmFsc2VcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiB0cnlSdW5QZW5kaW5nQWN0aW9ucygpOiB2b2lkIHtcclxuICBpZiAoaXNBY3Rpb25SdW5uaW5nKCkgfHwgcGVuZGluZ0FjdGlvbnNSdW5uaW5nKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIHBlbmRpbmdBY3Rpb25zUnVubmluZyA9IHRydWVcclxuXHJcbiAgdHJ5IHtcclxuICAgIHdoaWxlIChwZW5kaW5nQWN0aW9ucy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGNvbnN0IG5leHRBY3Rpb24gPSBwZW5kaW5nQWN0aW9ucy5zaGlmdCgpIVxyXG4gICAgICBuZXh0QWN0aW9uKClcclxuICAgIH1cclxuICB9IGZpbmFsbHkge1xyXG4gICAgcGVuZGluZ0FjdGlvbnNSdW5uaW5nID0gZmFsc2VcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHR5cGUgeyBNb2RlbENsYXNzIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL0Jhc2VNb2RlbFNoYXJlZFwiXG5pbXBvcnQgeyBtb2RlbE1ldGFkYXRhU3ltYm9sIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL21vZGVsU3ltYm9sc1wiXG5pbXBvcnQgdHlwZSB7IEFueVR5cGUgfSBmcm9tIFwiLi4vdHlwZXMvc2NoZW1hc1wiXG5pbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IGdldE9yQ3JlYXRlIH0gZnJvbSBcIi4uL3V0aWxzL21hcFV0aWxzXCJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi9CYXNlTW9kZWxcIlxuaW1wb3J0IHsgaXNNb2RlbCwgaXNNb2RlbENsYXNzIH0gZnJvbSBcIi4vdXRpbHNcIlxuXG4vKipcbiAqIEFzc29jaWF0ZWQgbW9kZWwgbWV0YWRhdGEuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxNZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBBc3NvY2lhdGVkIGRhdGEgdHlwZSBmb3IgcnVudGltZSBjaGVja2luZyAoaWYgYW55KS5cbiAgICovXG4gIGRhdGFUeXBlPzogQW55VHlwZVxuXG4gIC8qKlxuICAgKiBQcm9wZXJ0eSB1c2VkIGFzIG1vZGVsIGlkLlxuICAgKi9cbiAgbW9kZWxJZFByb3BlcnR5OiBzdHJpbmcgfCB1bmRlZmluZWRcblxuICAvKipcbiAgICogQSB2YWx1ZSB0eXBlIHdpbGwgYmUgY2xvbmVkIGF1dG9tYXRpY2FsbHkgd2hlbiBiZWluZyBhdHRhY2hlZCB0byBhIG5ldyB0cmVlLlxuICAgKi9cbiAgdmFsdWVUeXBlOiBib29sZWFuXG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgYXNzb2NpYXRlZCBtZXRhZGF0YSBmb3IgYSBtb2RlbCBpbnN0YW5jZSBvciBjbGFzcy5cbiAqXG4gKiBAcGFyYW0gbW9kZWxDbGFzc09ySW5zdGFuY2UgTW9kZWwgY2xhc3Mgb3IgaW5zdGFuY2UuXG4gKiBAcmV0dXJucyBUaGUgYXNzb2NpYXRlZCBtZXRhZGF0YS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1vZGVsTWV0YWRhdGEoXG4gIG1vZGVsQ2xhc3NPckluc3RhbmNlOiBBbnlNb2RlbCB8IE1vZGVsQ2xhc3M8QW55TW9kZWw+XG4pOiBNb2RlbE1ldGFkYXRhIHtcbiAgaWYgKGlzTW9kZWwobW9kZWxDbGFzc09ySW5zdGFuY2UpKSB7XG4gICAgcmV0dXJuIChtb2RlbENsYXNzT3JJbnN0YW5jZSBhcyBhbnkpLmNvbnN0cnVjdG9yW21vZGVsTWV0YWRhdGFTeW1ib2xdXG4gIH0gZWxzZSBpZiAoaXNNb2RlbENsYXNzKG1vZGVsQ2xhc3NPckluc3RhbmNlKSkge1xuICAgIHJldHVybiAobW9kZWxDbGFzc09ySW5zdGFuY2UgYXMgYW55KVttb2RlbE1ldGFkYXRhU3ltYm9sXVxuICB9IGVsc2Uge1xuICAgIHRocm93IGZhaWx1cmUoYG1vZGVsQ2xhc3NPckluc3RhbmNlIG11c3QgYmUgYSBtb2RlbCBjbGFzcyBvciBpbnN0YW5jZWApXG4gIH1cbn1cblxuY29uc3QgbW9kZWxJZFByb3BlcnR5TmFtZUNhY2hlID0gbmV3IFdlYWtNYXA8b2JqZWN0LCBzdHJpbmcgfCB1bmRlZmluZWQ+KClcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUobW9kZWxDbGFzczogTW9kZWxDbGFzczxBbnlNb2RlbD4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gZ2V0T3JDcmVhdGUoXG4gICAgbW9kZWxJZFByb3BlcnR5TmFtZUNhY2hlLFxuICAgIG1vZGVsQ2xhc3MsXG4gICAgKCkgPT4gZ2V0TW9kZWxNZXRhZGF0YShtb2RlbENsYXNzKS5tb2RlbElkUHJvcGVydHlcbiAgKVxufVxuIiwiLyoqXG4gKiBBIGhvb2sgYWN0aW9uLlxuICovXG5leHBvcnQgZW51bSBIb29rQWN0aW9uIHtcbiAgLyoqXG4gICAqIG9uSW5pdCBob29rXG4gICAqL1xuICBPbkluaXQgPSBcIiQkb25Jbml0XCIsXG4gIC8qKlxuICAgKiBvbkxhenlJbml0IGhvb2tcbiAgICovXG4gIE9uTGF6eUluaXQgPSBcIiQkb25MYXp5SW5pdFwiLFxuICAvKipcbiAgICogb25BdHRhY2hlZFRvUm9vdFN0b3JlIGhvb2tcbiAgICovXG4gIE9uQXR0YWNoZWRUb1Jvb3RTdG9yZSA9IFwiJCRvbkF0dGFjaGVkVG9Sb290U3RvcmVcIixcbiAgLyoqXG4gICAqIGRpc3Bvc2VyIGZvciBvbkF0dGFjaGVkVG9Sb290U3RvcmUgaG9va1xuICAgKi9cbiAgT25BdHRhY2hlZFRvUm9vdFN0b3JlRGlzcG9zZXIgPSBcIiQkb25BdHRhY2hlZFRvUm9vdFN0b3JlRGlzcG9zZXJcIixcbn1cblxuY29uc3QgaG9va0FjdGlvblZhbHVlczogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoT2JqZWN0LnZhbHVlcyhIb29rQWN0aW9uKSlcblxuLyoqXG4gKiBSZXR1cm5zIGlmIGEgZ2l2ZW4gYWN0aW9uIG5hbWUgY29ycmVzcG9uZHMgdG8gYSBob29rLCB0aGlzIGlzLCBvbmUgb2Y6XG4gKiAtIG9uSW5pdCgpIGhvb2tcbiAqIC0gb25MYXp5SW5pdCgpIGhvb2tcbiAqIC0gb25BdHRhY2hlZFRvUm9vdFN0b3JlKCkgaG9va1xuICogLSBkaXNwb3NlciByZXR1cm5lZCBieSBhIG9uQXR0YWNoZWRUb1Jvb3RTdG9yZSgpIGhvb2tcbiAqXG4gKiBAcGFyYW0gYWN0aW9uTmFtZSBBY3Rpb24gbmFtZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHRydWUgaWYgaXQgaXMgYSBob29rLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0hvb2tBY3Rpb24oYWN0aW9uTmFtZTogc3RyaW5nKTogYWN0aW9uTmFtZSBpcyBIb29rQWN0aW9uIHtcbiAgcmV0dXJuIGhvb2tBY3Rpb25WYWx1ZXMuaGFzKGFjdGlvbk5hbWUpXG59XG4iLCJpbXBvcnQgeyBjb21wdXRlZCwgSUNvbXB1dGVkVmFsdWUgfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcclxuaW1wb3J0IHsgZ2V0T2JqZWN0Q2hpbGRyZW4gfSBmcm9tIFwiLi9jb3JlT2JqZWN0Q2hpbGRyZW5cIlxyXG5cclxuLyoqXHJcbiAqIE1vZGUgZm9yIHRoZSBgd2Fsa1RyZWVgIG1ldGhvZC5cclxuICovXHJcbmV4cG9ydCBlbnVtIFdhbGtUcmVlTW9kZSB7XHJcbiAgLyoqXHJcbiAgICogVGhlIHdhbGsgd2lsbCBiZSBkb25lIHBhcmVudCAocm9vdHMpIGZpcnN0LCB0aGVuIGNoaWxkcmVuLlxyXG4gICAqL1xyXG4gIFBhcmVudEZpcnN0ID0gXCJwYXJlbnRGaXJzdFwiLFxyXG4gIC8qKlxyXG4gICAqIFRoZSB3YWxrIHdpbGwgYmUgZG9uZSBjaGlsZHJlbiAobGVhZnMpIGZpcnN0LCB0aGVuIHBhcmVudHMuXHJcbiAgICovXHJcbiAgQ2hpbGRyZW5GaXJzdCA9IFwiY2hpbGRyZW5GaXJzdFwiLFxyXG59XHJcblxyXG4vKipcclxuICogV2Fsa3MgYSB0cmVlLCBydW5uaW5nIHRoZSBwcmVkaWNhdGUgZnVuY3Rpb24gZm9yIGVhY2ggbm9kZS5cclxuICogSWYgdGhlIHByZWRpY2F0ZSBmdW5jdGlvbiByZXR1cm5zIHNvbWV0aGluZyBvdGhlciB0aGFuIHVuZGVmaW5lZCxcclxuICogdGhlbiB0aGUgd2FsayB3aWxsIGJlIHN0b3BwZWQgYW5kIHRoZSBmdW5jdGlvbiB3aWxsIHJldHVybiB0aGUgcmV0dXJuZWQgdmFsdWUuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVCBSZXR1cm5lZCBvYmplY3QgdHlwZSwgZGVmYXVsdHMgdG8gdm9pZC5cclxuICogQHBhcmFtIHJvb3QgU3VidHJlZSByb290IG9iamVjdC5cclxuICogQHBhcmFtIHZpc2l0IEZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBydW4gZm9yIGVhY2ggbm9kZSBvZiB0aGUgdHJlZS5cclxuICogQHBhcmFtIG1vZGUgTW9kZSB0byB3YWxrIHRoZSB0cmVlLCBhcyBkZWZpbmVkIGluIGBXYWxrVHJlZU1vZGVgLlxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHdhbGtUcmVlPFQgPSB2b2lkPihcclxuICByb290OiBvYmplY3QsXHJcbiAgdmlzaXQ6IChub2RlOiBvYmplY3QpID0+IFQgfCB1bmRlZmluZWQsXHJcbiAgbW9kZTogV2Fsa1RyZWVNb2RlXHJcbik6IFQgfCB1bmRlZmluZWQge1xyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qocm9vdCwgXCJyb290XCIpXHJcblxyXG4gIGlmIChtb2RlID09PSBXYWxrVHJlZU1vZGUuUGFyZW50Rmlyc3QpIHtcclxuICAgIHJldHVybiB3YWxrVHJlZVBhcmVudEZpcnN0KHJvb3QsIHZpc2l0KVxyXG4gIH0gZWxzZSB7XHJcbiAgICByZXR1cm4gd2Fsa1RyZWVDaGlsZHJlbkZpcnN0KHJvb3QsIHZpc2l0KVxyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gd2Fsa1RyZWVQYXJlbnRGaXJzdDxUID0gdm9pZD4oXHJcbiAgcm9vdDogb2JqZWN0LFxyXG4gIHZpc2l0OiAobm9kZTogb2JqZWN0KSA9PiBUIHwgdW5kZWZpbmVkXHJcbik6IFQgfCB1bmRlZmluZWQge1xyXG4gIGNvbnN0IHN0YWNrOiBvYmplY3RbXSA9IFtyb290XVxyXG5cclxuICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkge1xyXG4gICAgY29uc3Qgbm9kZSA9IHN0YWNrLnBvcCgpIVxyXG5cclxuICAgIGNvbnN0IHJldCA9IHZpc2l0KG5vZGUpXHJcbiAgICBpZiAocmV0ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuIHJldFxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGNoaWxkcmVuID0gZ2V0T2JqZWN0Q2hpbGRyZW4obm9kZSkhXHJcblxyXG4gICAgc3RhY2subGVuZ3RoICs9IGNoaWxkcmVuLnNpemVcclxuICAgIGxldCBpID0gc3RhY2subGVuZ3RoIC0gMVxyXG5cclxuICAgIGNvbnN0IGNoaWxkcmVuSXRlciA9IGNoaWxkcmVuIS52YWx1ZXMoKVxyXG4gICAgbGV0IGNoID0gY2hpbGRyZW5JdGVyLm5leHQoKVxyXG4gICAgd2hpbGUgKCFjaC5kb25lKSB7XHJcbiAgICAgIHN0YWNrW2ktLV0gPSBjaC52YWx1ZVxyXG4gICAgICBjaCA9IGNoaWxkcmVuSXRlci5uZXh0KClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiB1bmRlZmluZWRcclxufVxyXG5cclxuZnVuY3Rpb24gd2Fsa1RyZWVDaGlsZHJlbkZpcnN0PFQgPSB2b2lkPihcclxuICByb290OiBvYmplY3QsXHJcbiAgdmlzaXQ6IChub2RlOiBvYmplY3QpID0+IFQgfCB1bmRlZmluZWRcclxuKTogVCB8IHVuZGVmaW5lZCB7XHJcbiAgY29uc3QgY2hpbGRyZW5JdGVyID0gZ2V0T2JqZWN0Q2hpbGRyZW4ocm9vdCkhLnZhbHVlcygpXHJcbiAgbGV0IGNoID0gY2hpbGRyZW5JdGVyLm5leHQoKVxyXG4gIHdoaWxlICghY2guZG9uZSkge1xyXG4gICAgY29uc3QgcmV0ID0gd2Fsa1RyZWVDaGlsZHJlbkZpcnN0KGNoLnZhbHVlLCB2aXNpdClcclxuICAgIGlmIChyZXQgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByZXR1cm4gcmV0XHJcbiAgICB9XHJcbiAgICBjaCA9IGNoaWxkcmVuSXRlci5uZXh0KClcclxuICB9XHJcblxyXG4gIGNvbnN0IHJldCA9IHZpc2l0KHJvb3QpXHJcbiAgaWYgKHJldCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICByZXR1cm4gcmV0XHJcbiAgfVxyXG5cclxuICByZXR1cm4gdW5kZWZpbmVkXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0ZWRXYWxrVHJlZUFnZ3JlZ2F0ZTxSPiB7XHJcbiAgd2Fsayh0YXJnZXQ6IG9iamVjdCk6IE1hcDxSLCBvYmplY3Q+IHwgdW5kZWZpbmVkXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldENvbXB1dGVkVHJlZVJlc3VsdDxSPihcclxuICBjb21wdXRlZEZuczogV2Vha01hcDxvYmplY3QsIElDb21wdXRlZFZhbHVlPE1hcDxSLCBvYmplY3Q+IHwgdW5kZWZpbmVkPj4sXHJcbiAgdmlzaXQ6IChub2RlOiBvYmplY3QpID0+IFIgfCB1bmRlZmluZWQsXHJcbiAgdHJlZTogb2JqZWN0XHJcbik6IE1hcDxSLCBvYmplY3Q+IHwgdW5kZWZpbmVkIHtcclxuICBsZXQgY21wdGVkID0gY29tcHV0ZWRGbnMuZ2V0KHRyZWUpXHJcbiAgaWYgKCFjbXB0ZWQpIHtcclxuICAgIGNtcHRlZCA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgICAgcmV0dXJuIHdhbGtUcmVlQWdncmVnYXRlKHRyZWUsIHZpc2l0LCAoY2gpID0+IGdldENvbXB1dGVkVHJlZVJlc3VsdChjb21wdXRlZEZucywgdmlzaXQsIGNoKSlcclxuICAgIH0pXHJcbiAgICBjb21wdXRlZEZucy5zZXQodHJlZSwgY21wdGVkKVxyXG4gIH1cclxuICByZXR1cm4gY21wdGVkLmdldCgpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlZFdhbGtUcmVlQWdncmVnYXRlPFI+KFxyXG4gIHZpc2l0OiAobm9kZTogb2JqZWN0KSA9PiBSIHwgdW5kZWZpbmVkXHJcbik6IENvbXB1dGVkV2Fsa1RyZWVBZ2dyZWdhdGU8Uj4ge1xyXG4gIGNvbnN0IGNvbXB1dGVkRm5zID0gbmV3IFdlYWtNYXA8b2JqZWN0LCBJQ29tcHV0ZWRWYWx1ZTxNYXA8Uiwgb2JqZWN0PiB8IHVuZGVmaW5lZD4+KClcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIHdhbGs6IChuKSA9PiBnZXRDb21wdXRlZFRyZWVSZXN1bHQoY29tcHV0ZWRGbnMsIHZpc2l0LCBuKSxcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHdhbGtUcmVlQWdncmVnYXRlPFI+KFxyXG4gIHRhcmdldDogb2JqZWN0LFxyXG4gIHZpc2l0OiAobm9kZTogb2JqZWN0KSA9PiBSIHwgdW5kZWZpbmVkLFxyXG4gIHJlY3Vyc2U6IChub2RlOiBvYmplY3QpID0+IE1hcDxSLCBvYmplY3Q+IHwgdW5kZWZpbmVkXHJcbik6IE1hcDxSLCBvYmplY3Q+IHwgdW5kZWZpbmVkIHtcclxuICBsZXQgbWFwOiBNYXA8Uiwgb2JqZWN0PiB8IHVuZGVmaW5lZFxyXG4gIGNvbnN0IHJvb3RWYWwgPSB2aXNpdCh0YXJnZXQpXHJcblxyXG4gIGNvbnN0IGNoaWxkcmVuTWFwID0gZ2V0T2JqZWN0Q2hpbGRyZW4odGFyZ2V0KSFcclxuICBjb25zdCBjaGlsZHJlbkl0ZXIgPSBjaGlsZHJlbk1hcCEudmFsdWVzKClcclxuICBsZXQgY2ggPSBjaGlsZHJlbkl0ZXIubmV4dCgpXHJcblxyXG4gIC8vIHNtYWxsIG9wdGltaXphdGlvbiwgaWYgdGhlcmUgaXMgb25seSBvbmUgY2hpbGQgYW5kIHRoaXNcclxuICAvLyBvYmplY3QgcHJvdmlkZXMgbm8gdmFsdWUgd2UgY2FuIGp1c3QgcmV1c2UgdGhlIGNoaWxkIG9uZXNcclxuICBpZiAocm9vdFZhbCA9PT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuTWFwLnNpemUgPT09IDEpIHtcclxuICAgIHJldHVybiByZWN1cnNlKGNoLnZhbHVlKVxyXG4gIH1cclxuXHJcbiAgd2hpbGUgKCFjaC5kb25lKSB7XHJcbiAgICBjb25zdCBjaGlsZE1hcCA9IHJlY3Vyc2UoY2gudmFsdWUpXHJcblxyXG4gICAgaWYgKGNoaWxkTWFwKSB7XHJcbiAgICAgIGlmICghbWFwKSB7XHJcbiAgICAgICAgbWFwID0gbmV3IE1hcCgpXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGFkZCBjaGlsZCBtYXAga2V5cy92YWx1ZXMgdG8gb3duIG1hcFxyXG4gICAgICBjb25zdCBtYXBJdGVyID0gY2hpbGRNYXAua2V5cygpXHJcblxyXG4gICAgICBsZXQgbWFwQ3VyID0gbWFwSXRlci5uZXh0KClcclxuICAgICAgd2hpbGUgKCFtYXBDdXIuZG9uZSkge1xyXG4gICAgICAgIGNvbnN0IGtleSA9IG1hcEN1ci52YWx1ZVxyXG4gICAgICAgIGNvbnN0IHZhbCA9IGNoaWxkTWFwLmdldChrZXkpIVxyXG4gICAgICAgIG1hcC5zZXQoa2V5LCB2YWwpXHJcbiAgICAgICAgbWFwQ3VyID0gbWFwSXRlci5uZXh0KClcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNoID0gY2hpbGRyZW5JdGVyLm5leHQoKVxyXG4gIH1cclxuXHJcbiAgLy8gYWRkIGl0IGF0IHRoZSBlbmQgc28gcGFyZW50IHJlc29sdXRpb25zIGhhdmUgaGlnaGVyXHJcbiAgLy8gcHJpb3JpdHkgdGhhbiBjaGlsZCBvbmVzXHJcbiAgaWYgKHJvb3RWYWwgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgaWYgKCFtYXApIHtcclxuICAgICAgbWFwID0gbmV3IE1hcCgpXHJcbiAgICB9XHJcbiAgICBtYXAuc2V0KHJvb3RWYWwsIHRhcmdldClcclxuICB9XHJcblxyXG4gIHJldHVybiBtYXBcclxufVxyXG4iLCJpbXBvcnQgeyBhY3Rpb24gfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgeyBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZSB9IGZyb20gXCIuLi9hY3Rpb24vY29udGV4dFwiXG5pbXBvcnQgeyBIb29rQWN0aW9uIH0gZnJvbSBcIi4uL2FjdGlvbi9ob29rQWN0aW9uc1wiXG5pbXBvcnQgeyB3cmFwSW5BY3Rpb24sIHdyYXBNb2RlbE1ldGhvZEluQWN0aW9uSWZOZWVkZWQgfSBmcm9tIFwiLi4vYWN0aW9uL3dyYXBJbkFjdGlvblwiXG5pbXBvcnQgeyBBbnlNb2RlbCwgQmFzZU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Jhc2VNb2RlbFwiXG5pbXBvcnQgeyB3YWxrVHJlZSwgV2Fsa1RyZWVNb2RlIH0gZnJvbSBcIi4uL3BhcmVudC93YWxrVHJlZVwiXG5cbmNvbnN0IG9uQXR0YWNoZWREaXNwb3NlcnMgPSBuZXcgV2Vha01hcDxvYmplY3QsICgpID0+IHZvaWQ+KClcbmNvbnN0IGF0dGFjaGVkVG9Sb290U3RvcmUgPSBuZXcgV2Vha1NldDxvYmplY3Q+KClcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IGF0dGFjaFRvUm9vdFN0b3JlID0gYWN0aW9uKFxuICBcImF0dGFjaFRvUm9vdFN0b3JlXCIsXG4gIChyb290U3RvcmU6IG9iamVjdCwgY2hpbGQ6IG9iamVjdCk6IHZvaWQgPT4ge1xuICAgIC8vIHdlIHVzZSBhbiBhcnJheSB0byBlbnN1cmUgdGhleSB3aWxsIGdldCBjYWxsZWQgZXZlbiBpZiB0aGUgYWN0dWFsIGhvb2sgbW9kaWZpZXMgdGhlIHRyZWVcbiAgICBjb25zdCBjaGlsZHJlblRvQ2FsbDogQW55TW9kZWxbXSA9IFtdXG5cbiAgICB3YWxrVHJlZShcbiAgICAgIGNoaWxkLFxuICAgICAgKGNoKSA9PiB7XG4gICAgICAgIC8vIHdlIHVzZSB0aGlzIHRvIGF2b2lkIGNhbGxpbmcgb25BdHRhY2hlZFRvUm9vdFN0b3JlXG4gICAgICAgIC8vIHR3aWNlXG4gICAgICAgIGlmIChhdHRhY2hlZFRvUm9vdFN0b3JlLmhhcyhjaCkpIHtcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICBhdHRhY2hlZFRvUm9vdFN0b3JlLmFkZChjaClcblxuICAgICAgICBpZiAoY2ggaW5zdGFuY2VvZiBCYXNlTW9kZWwgJiYgKGNoIGFzIGFueSkub25BdHRhY2hlZFRvUm9vdFN0b3JlKSB7XG4gICAgICAgICAgd3JhcE1vZGVsTWV0aG9kSW5BY3Rpb25JZk5lZWRlZChcbiAgICAgICAgICAgIGNoIGFzIGFueSxcbiAgICAgICAgICAgIFwib25BdHRhY2hlZFRvUm9vdFN0b3JlXCIsXG4gICAgICAgICAgICBIb29rQWN0aW9uLk9uQXR0YWNoZWRUb1Jvb3RTdG9yZVxuICAgICAgICAgIClcblxuICAgICAgICAgIGNoaWxkcmVuVG9DYWxsLnB1c2goY2ggYXMgQW55TW9kZWwpXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBXYWxrVHJlZU1vZGUuUGFyZW50Rmlyc3RcbiAgICApXG5cbiAgICBjb25zdCBjaGlsZHJlblRvQ2FsbExlbiA9IGNoaWxkcmVuVG9DYWxsLmxlbmd0aFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW5Ub0NhbGxMZW47IGkrKykge1xuICAgICAgY29uc3QgY2ggPSBjaGlsZHJlblRvQ2FsbFtpXVxuXG4gICAgICBjb25zdCBkaXNwb3NlciA9IChjaCBhcyBhbnkpLm9uQXR0YWNoZWRUb1Jvb3RTdG9yZSEocm9vdFN0b3JlKVxuICAgICAgaWYgKGRpc3Bvc2VyKSB7XG4gICAgICAgIG9uQXR0YWNoZWREaXNwb3NlcnMuc2V0KGNoLCBkaXNwb3NlcilcbiAgICAgIH1cbiAgICB9XG4gIH1cbilcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IGRldGFjaEZyb21Sb290U3RvcmUgPSBhY3Rpb24oXCJkZXRhY2hGcm9tUm9vdFN0b3JlXCIsIChjaGlsZDogb2JqZWN0KTogdm9pZCA9PiB7XG4gIC8vIHdlIHVzZSBhbiBhcnJheSB0byBlbnN1cmUgdGhleSB3aWxsIGdldCBjYWxsZWQgZXZlbiBpZiB0aGUgYWN0dWFsIGhvb2sgbW9kaWZpZXMgdGhlIHRyZWVcbiAgY29uc3QgZGlzcG9zZXJzVG9DYWxsOiAoKCkgPT4gdm9pZClbXSA9IFtdXG5cbiAgd2Fsa1RyZWUoXG4gICAgY2hpbGQsXG4gICAgKGNoKSA9PiB7XG4gICAgICBpZiAoIWF0dGFjaGVkVG9Sb290U3RvcmUuZGVsZXRlKGNoKSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc3QgZGlzcG9zZXIgPSBvbkF0dGFjaGVkRGlzcG9zZXJzLmdldChjaClcbiAgICAgIGlmIChkaXNwb3Nlcikge1xuICAgICAgICAvLyB3cmFwIGRpc3Bvc2VyIGluIGFjdGlvblxuICAgICAgICBjb25zdCBkaXNwb3NlckFjdGlvbiA9IHdyYXBJbkFjdGlvbih7XG4gICAgICAgICAgbmFtZU9yTmFtZUZuOiBIb29rQWN0aW9uLk9uQXR0YWNoZWRUb1Jvb3RTdG9yZURpc3Bvc2VyLFxuICAgICAgICAgIGZuOiBkaXNwb3NlcixcbiAgICAgICAgICBhY3Rpb25UeXBlOiBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZS5TeW5jLFxuICAgICAgICB9KS5iaW5kKGNoKVxuICAgICAgICBvbkF0dGFjaGVkRGlzcG9zZXJzLmRlbGV0ZShjaClcblxuICAgICAgICBkaXNwb3NlcnNUb0NhbGwucHVzaChkaXNwb3NlckFjdGlvbilcbiAgICAgIH1cbiAgICB9LFxuICAgIFdhbGtUcmVlTW9kZS5DaGlsZHJlbkZpcnN0XG4gIClcblxuICBjb25zdCBkaXNwb3NlcnNUb0NhbGxMZW4gPSBkaXNwb3NlcnNUb0NhbGwubGVuZ3RoXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGlzcG9zZXJzVG9DYWxsTGVuOyBpKyspIHtcbiAgICBkaXNwb3NlcnNUb0NhbGxbaV0oKVxuICB9XG59KVxuIiwiaW1wb3J0IHsgYWN0aW9uLCBjcmVhdGVBdG9tLCBJQXRvbSB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHsgZmFzdEdldFJvb3QsIGlzUm9vdCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFwiXHJcbmltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcclxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXHJcbmltcG9ydCB7IGdldE9yQ3JlYXRlIH0gZnJvbSBcIi4uL3V0aWxzL21hcFV0aWxzXCJcclxuaW1wb3J0IHsgYXR0YWNoVG9Sb290U3RvcmUsIGRldGFjaEZyb21Sb290U3RvcmUgfSBmcm9tIFwiLi9hdHRhY2hEZXRhY2hcIlxyXG5cclxuY29uc3Qgcm9vdFN0b3JlUmVnaXN0cnkgPSBuZXcgV2Vha01hcDxvYmplY3QsIHsgYXRvbTogSUF0b207IGlzOiBib29sZWFuIH0+KClcclxuXHJcbmNvbnN0IGdldE9yQ3JlYXRlUm9vdFN0b3JlRW50cnkgPSAobm9kZTogb2JqZWN0KSA9PlxyXG4gIGdldE9yQ3JlYXRlKHJvb3RTdG9yZVJlZ2lzdHJ5LCBub2RlLCAoKSA9PiAoe1xyXG4gICAgYXRvbTogY3JlYXRlQXRvbShcInJvb3RTdG9yZVwiKSxcclxuICAgIGlzOiBmYWxzZSxcclxuICB9KSlcclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYSBtb2RlbCAvIHRyZWUgbm9kZSBvYmplY3QgYXMgYSByb290IHN0b3JlIHRyZWUuXHJcbiAqIE1hcmtpbmcgYSBtb2RlbCBvYmplY3QgYXMgYSByb290IHN0b3JlIHRyZWUgc2VydmVzIHNldmVyYWwgcHVycG9zZXM6XHJcbiAqIC0gSXQgYWxsb3dzIHRoZSBgb25BdHRhY2hlZFRvUm9vdFN0b3JlYCBob29rIChwbHVzIGRpc3Bvc2VyKSB0byBiZSBpbnZva2VkIG9uIG1vZGVscyBvbmNlIHRoZXkgYmVjb21lIHBhcnQgb2YgdGhpcyB0cmVlLlxyXG4gKiAgIFRoZXNlIGhvb2tzIGNhbiBiZSB1c2VkIGZvciBleGFtcGxlIHRvIGF0dGFjaCBlZmZlY3RzIGFuZCBzZXJ2ZSBhcyBzb21lIHNvcnQgb2YgaW5pdGlhbGl6YXRpb24uXHJcbiAqIC0gSXQgYWxsb3dzIGF1dG8gZGV0YWNoYWJsZSByZWZlcmVuY2VzIHRvIHdvcmsgcHJvcGVybHkuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVCBPYmplY3QgdHlwZS5cclxuICogQHBhcmFtIG5vZGUgTm9kZSBvYmplY3QgdG8gcmVnaXN0ZXIgYXMgcm9vdCBzdG9yZS5cclxuICogQHJldHVybnMgVGhlIHNhbWUgbW9kZWwgb2JqZWN0IHRoYXQgd2FzIHBhc3NlZC5cclxuICovXHJcbmV4cG9ydCBjb25zdCByZWdpc3RlclJvb3RTdG9yZTogPFQgZXh0ZW5kcyBvYmplY3Q+KG5vZGU6IFQpID0+IFQgPSBhY3Rpb24oXHJcbiAgXCJyZWdpc3RlclJvb3RTdG9yZVwiLFxyXG4gIChub2RlKSA9PiB7XHJcbiAgICBhc3NlcnRUd2Vha2VkT2JqZWN0KG5vZGUsIFwibm9kZVwiKVxyXG5cclxuICAgIGNvbnN0IGVudHJ5ID0gZ2V0T3JDcmVhdGVSb290U3RvcmVFbnRyeShub2RlKVxyXG5cclxuICAgIGlmIChlbnRyeS5pcykge1xyXG4gICAgICB0aHJvdyBmYWlsdXJlKFwib2JqZWN0IGFscmVhZHkgcmVnaXN0ZXJlZCBhcyByb290IHN0b3JlXCIpXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFpc1Jvb3Qobm9kZSkpIHtcclxuICAgICAgdGhyb3cgZmFpbHVyZShcImEgcm9vdCBzdG9yZSBtdXN0IG5vdCBoYXZlIGEgcGFyZW50XCIpXHJcbiAgICB9XHJcblxyXG4gICAgZW50cnkuaXMgPSB0cnVlXHJcblxyXG4gICAgYXR0YWNoVG9Sb290U3RvcmUobm9kZSwgbm9kZSlcclxuXHJcbiAgICBlbnRyeS5hdG9tLnJlcG9ydENoYW5nZWQoKVxyXG4gICAgcmV0dXJuIG5vZGVcclxuICB9XHJcbilcclxuXHJcbi8qKlxyXG4gKiBVbnJlZ2lzdGVycyBhbiBvYmplY3QgdG8gbWFyayBpdCBhcyBubyBsb25nZXIgYSByb290IHN0b3JlLlxyXG4gKlxyXG4gKiBAcGFyYW0gbm9kZSBOb2RlIG9iamVjdCB0byB1bnJlZ2lzdGVyIGFzIHJvb3Qgc3RvcmUuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgdW5yZWdpc3RlclJvb3RTdG9yZTogKG5vZGU6IG9iamVjdCkgPT4gdm9pZCA9IGFjdGlvbihcInVucmVnaXN0ZXJSb290U3RvcmVcIiwgKG5vZGUpID0+IHtcclxuICBpZiAoIWlzUm9vdFN0b3JlKG5vZGUpKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKFwibm90IGEgcm9vdCBzdG9yZVwiKVxyXG4gIH1cclxuXHJcbiAgY29uc3QgZW50cnkgPSBnZXRPckNyZWF0ZVJvb3RTdG9yZUVudHJ5KG5vZGUpXHJcbiAgZW50cnkuaXMgPSBmYWxzZVxyXG5cclxuICBkZXRhY2hGcm9tUm9vdFN0b3JlKG5vZGUpXHJcblxyXG4gIGVudHJ5LmF0b20ucmVwb3J0Q2hhbmdlZCgpXHJcbn0pXHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIGEgZ2l2ZW4gb2JqZWN0IGlzIG1hcmtlZCBhcyBhIHJvb3Qgc3RvcmUuXHJcbiAqXHJcbiAqIEBwYXJhbSBub2RlIE9iamVjdC5cclxuICogQHJldHVybnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1Jvb3RTdG9yZShub2RlOiBvYmplY3QpOiBib29sZWFuIHtcclxuICBhc3NlcnRUd2Vha2VkT2JqZWN0KG5vZGUsIFwibm9kZVwiKVxyXG5cclxuICByZXR1cm4gZmFzdElzUm9vdFN0b3JlKG5vZGUpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmYXN0SXNSb290U3RvcmUobm9kZTogb2JqZWN0KTogYm9vbGVhbiB7XHJcbiAgY29uc3QgZW50cnkgPSBnZXRPckNyZWF0ZVJvb3RTdG9yZUVudHJ5KG5vZGUpXHJcbiAgZW50cnkuYXRvbS5yZXBvcnRPYnNlcnZlZCgpXHJcbiAgcmV0dXJuIGVudHJ5LmlzXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSByb290IHN0b3JlIG9mIGEgZ2l2ZW4gdHJlZSBjaGlsZCwgb3IgdW5kZWZpbmVkIGlmIG5vbmUuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVCBSb290IHN0b3JlIHR5cGUuXHJcbiAqIEBwYXJhbSBub2RlIFRhcmdldCB0byBmaW5kIHRoZSByb290IHN0b3JlIGZvci5cclxuICogQHJldHVybnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRSb290U3RvcmU8VCBleHRlbmRzIG9iamVjdD4obm9kZTogb2JqZWN0KTogVCB8IHVuZGVmaW5lZCB7XHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChub2RlLCBcIm5vZGVcIilcclxuXHJcbiAgcmV0dXJuIGZhc3RHZXRSb290U3RvcmUobm9kZSlcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZhc3RHZXRSb290U3RvcmU8VCBleHRlbmRzIG9iamVjdD4obm9kZTogb2JqZWN0KTogVCB8IHVuZGVmaW5lZCB7XHJcbiAgY29uc3Qgcm9vdCA9IGZhc3RHZXRSb290KG5vZGUpXHJcbiAgcmV0dXJuIGZhc3RJc1Jvb3RTdG9yZShyb290KSA/IHJvb3QgOiB1bmRlZmluZWRcclxufVxyXG4iLCJpbXBvcnQgeyBmYXN0R2V0Um9vdFBhdGggfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxyXG5pbXBvcnQgeyBQYXRoIH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoVHlwZXNcIlxyXG5pbXBvcnQgeyBnZXRTbmFwc2hvdCB9IGZyb20gXCIuLi9zbmFwc2hvdC9nZXRTbmFwc2hvdFwiXHJcbmltcG9ydCB7IGlzVHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxyXG5pbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuXHJcbi8qKlxyXG4gKiBBIHR5cGUgY2hlY2tpbmcgZXJyb3IuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgVHlwZUNoZWNrRXJyb3Ige1xyXG4gIC8qKlxyXG4gICAqIFRoZSB0eXBlIGNoZWNrIGVycm9yIG1lc3NhZ2UuXHJcbiAgICovXHJcbiAgcmVhZG9ubHkgbWVzc2FnZTogc3RyaW5nXHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgVHlwZUVycm9yLlxyXG4gICAqIEBwYXJhbSBwYXRoIFN1Yi1wYXRoICh3aGVyZSB0aGUgcm9vdCBpcyB0aGUgdmFsdWUgYmVpbmcgdHlwZSBjaGVja2VkKSB3aGVyZSB0aGUgZXJyb3Igb2NjdXJlZC5cclxuICAgKiBAcGFyYW0gZXhwZWN0ZWRUeXBlTmFtZSBOYW1lIG9mIHRoZSBleHBlY3RlZCB0eXBlLlxyXG4gICAqIEBwYXJhbSBhY3R1YWxWYWx1ZSBBY3R1YWwgdmFsdWUuXHJcbiAgICogQHBhcmFtIHR5cGVDaGVja2VkVmFsdWUgVGhlIHZhbHVlIHdoZXJlIHRoZSB0eXBlIGNoZWNrIHdhcyBpbnZva2VkLlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcmVhZG9ubHkgcGF0aDogUGF0aCxcclxuICAgIHJlYWRvbmx5IGV4cGVjdGVkVHlwZU5hbWU6IHN0cmluZyxcclxuICAgIHJlYWRvbmx5IGFjdHVhbFZhbHVlOiBhbnksXHJcbiAgICByZWFkb25seSB0eXBlQ2hlY2tlZFZhbHVlPzogYW55XHJcbiAgKSB7XHJcbiAgICBsZXQgcm9vdFBhdGg6IFBhdGggPSBbXVxyXG4gICAgaWYgKHRoaXMudHlwZUNoZWNrZWRWYWx1ZSAmJiBpc1R3ZWFrZWRPYmplY3QodGhpcy50eXBlQ2hlY2tlZFZhbHVlLCB0cnVlKSkge1xyXG4gICAgICByb290UGF0aCA9IGZhc3RHZXRSb290UGF0aCh0aGlzLnR5cGVDaGVja2VkVmFsdWUpLnBhdGhcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBhY3R1YWxWYWx1ZVNuYXBzaG90ID0gaXNUd2Vha2VkT2JqZWN0KHRoaXMuYWN0dWFsVmFsdWUsIHRydWUpXHJcbiAgICAgID8gZ2V0U25hcHNob3QodGhpcy5hY3R1YWxWYWx1ZSlcclxuICAgICAgOiB0aGlzLmFjdHVhbFZhbHVlXHJcblxyXG4gICAgdGhpcy5tZXNzYWdlID0gYFR5cGVDaGVja0Vycm9yOiBbLyR7Wy4uLnJvb3RQYXRoLCAuLi50aGlzLnBhdGhdLmpvaW4oXHJcbiAgICAgIFwiL1wiXHJcbiAgICApfV0gRXhwZWN0ZWQgYSB2YWx1ZSBvZiB0eXBlIDwke3RoaXMuZXhwZWN0ZWRUeXBlTmFtZX0+IGJ1dCBnb3QgdGhlIHZhbHVlIDwke0pTT04uc3RyaW5naWZ5KFxyXG4gICAgICBhY3R1YWxWYWx1ZVNuYXBzaG90XHJcbiAgICApfT4gaW5zdGVhZGBcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRocm93cyB0aGUgdHlwZSBjaGVjayBlcnJvciBhcyBhbiBhY3R1YWwgZXJyb3IuXHJcbiAgICovXHJcbiAgdGhyb3coKTogbmV2ZXIge1xyXG4gICAgdGhyb3cgZmFpbHVyZSh0aGlzLm1lc3NhZ2UpXHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IGZhc3RHZXRQYXJlbnRJbmNsdWRpbmdEYXRhT2JqZWN0cyB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFwiXHJcbmltcG9ydCB0eXBlIHsgUGF0aCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFR5cGVzXCJcclxuaW1wb3J0IHsgaXNUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXHJcbmltcG9ydCB7IGlzQXJyYXksIGlzT2JqZWN0LCBpc1ByaW1pdGl2ZSwgbGF6eSB9IGZyb20gXCIuLi91dGlsc1wiXHJcbmltcG9ydCB7IGdldE9yQ3JlYXRlIH0gZnJvbSBcIi4uL3V0aWxzL21hcFV0aWxzXCJcclxuaW1wb3J0IHR5cGUgeyBBbnlTdGFuZGFyZFR5cGUgfSBmcm9tIFwiLi9zY2hlbWFzXCJcclxuaW1wb3J0IHsgVHlwZUNoZWNrRXJyb3IgfSBmcm9tIFwiLi9UeXBlQ2hlY2tFcnJvclwiXHJcblxyXG50eXBlIENoZWNrRnVuY3Rpb24gPSAodmFsdWU6IGFueSwgcGF0aDogUGF0aCwgdHlwZUNoZWNrZWRWYWx1ZTogYW55KSA9PiBUeXBlQ2hlY2tFcnJvciB8IG51bGxcclxuXHJcbmNvbnN0IGVtcHR5UGF0aDogUGF0aCA9IFtdXHJcblxyXG50eXBlIENoZWNrUmVzdWx0ID0gVHlwZUNoZWNrRXJyb3IgfCBudWxsXHJcbnR5cGUgQ2hlY2tSZXN1bHRDYWNoZSA9IFdlYWtNYXA8b2JqZWN0LCBDaGVja1Jlc3VsdD5cclxuXHJcbmNvbnN0IHR5cGVDaGVja2Vyc1dpdGhDYWNoZWRSZXN1bHRzT2ZPYmplY3QgPSBuZXcgV2Vha01hcDxvYmplY3QsIFNldDxUeXBlQ2hlY2tlcj4+KClcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBlbnVtIFR5cGVDaGVja2VyQmFzZVR5cGUge1xyXG4gIE9iamVjdCA9IFwib2JqZWN0XCIsXHJcbiAgQXJyYXkgPSBcImFycmF5XCIsXHJcbiAgUHJpbWl0aXZlID0gXCJwcmltaXRpdmVcIixcclxuICBBbnkgPSBcImFueVwiLFxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2V0VHlwZUNoZWNrZXJCYXNlVHlwZUZyb21WYWx1ZSh2YWx1ZTogYW55KTogVHlwZUNoZWNrZXJCYXNlVHlwZSB7XHJcbiAgLy8gYXJyYXkgbXVzdCBiZSBiZWZvcmUgb2JqZWN0IHNpbmNlIGFycmF5cyBhcmUgYWxzbyBvYmplY3RzXHJcbiAgaWYgKGlzQXJyYXkodmFsdWUpKSByZXR1cm4gVHlwZUNoZWNrZXJCYXNlVHlwZS5BcnJheVxyXG4gIGlmIChpc09iamVjdCh2YWx1ZSkpIHJldHVybiBUeXBlQ2hlY2tlckJhc2VUeXBlLk9iamVjdFxyXG4gIGlmIChpc1ByaW1pdGl2ZSh2YWx1ZSkpIHJldHVybiBUeXBlQ2hlY2tlckJhc2VUeXBlLlByaW1pdGl2ZVxyXG4gIHJldHVybiBUeXBlQ2hlY2tlckJhc2VUeXBlLkFueVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaW52YWxpZGF0ZUNhY2hlZFR5cGVDaGVja2VyUmVzdWx0KG9iajogb2JqZWN0KSB7XHJcbiAgLy8gd2UgbmVlZCB0byBpbnZhbGlkYXRlIGl0IGZvciB0aGUgb2JqZWN0IGFuZCBhbGwgaXRzIHBhcmVudHNcclxuICBsZXQgY3VycmVudDogYW55ID0gb2JqXHJcbiAgd2hpbGUgKGN1cnJlbnQpIHtcclxuICAgIGNvbnN0IHNldCA9IHR5cGVDaGVja2Vyc1dpdGhDYWNoZWRSZXN1bHRzT2ZPYmplY3QuZ2V0KGN1cnJlbnQpXHJcbiAgICBpZiAoc2V0KSB7XHJcbiAgICAgIHR5cGVDaGVja2Vyc1dpdGhDYWNoZWRSZXN1bHRzT2ZPYmplY3QuZGVsZXRlKGN1cnJlbnQpXHJcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1sb29wLWZ1bmNcclxuICAgICAgc2V0LmZvckVhY2goKHR5cGVDaGVja2VyKSA9PiB0eXBlQ2hlY2tlci5pbnZhbGlkYXRlQ2FjaGVkUmVzdWx0KGN1cnJlbnQpKVxyXG4gICAgfVxyXG5cclxuICAgIGN1cnJlbnQgPSBmYXN0R2V0UGFyZW50SW5jbHVkaW5nRGF0YU9iamVjdHMoY3VycmVudClcclxuICB9XHJcbn1cclxuXHJcbmNvbnN0IHR5cGVDaGVja2Vyc1dpdGhDYWNoZWRTbmFwc2hvdFByb2Nlc3NvclJlc3VsdHNPZk9iamVjdCA9IG5ldyBXZWFrTWFwPFxyXG4gIG9iamVjdCxcclxuICBTZXQ8VHlwZUNoZWNrZXI+XHJcbj4oKVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGludmFsaWRhdGVDYWNoZWRUb1NuYXBzaG90UHJvY2Vzc29yUmVzdWx0KG9iajogb2JqZWN0KSB7XHJcbiAgY29uc3Qgc2V0ID0gdHlwZUNoZWNrZXJzV2l0aENhY2hlZFNuYXBzaG90UHJvY2Vzc29yUmVzdWx0c09mT2JqZWN0LmdldChvYmopXHJcblxyXG4gIGlmIChzZXQpIHtcclxuICAgIHNldC5mb3JFYWNoKCh0eXBlQ2hlY2tlcikgPT4gdHlwZUNoZWNrZXIuaW52YWxpZGF0ZVNuYXBzaG90UHJvY2Vzc29yQ2FjaGVkUmVzdWx0KG9iaikpXHJcbiAgICB0eXBlQ2hlY2tlcnNXaXRoQ2FjaGVkU25hcHNob3RQcm9jZXNzb3JSZXN1bHRzT2ZPYmplY3QuZGVsZXRlKG9iailcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBjbGFzcyBUeXBlQ2hlY2tlciB7XHJcbiAgcHJpdmF0ZSBjaGVja1Jlc3VsdENhY2hlPzogQ2hlY2tSZXN1bHRDYWNoZVxyXG5cclxuICB1bmNoZWNrZWQ6IGJvb2xlYW5cclxuXHJcbiAgcHJpdmF0ZSBjcmVhdGVDYWNoZUlmTmVlZGVkKCk6IENoZWNrUmVzdWx0Q2FjaGUge1xyXG4gICAgaWYgKCF0aGlzLmNoZWNrUmVzdWx0Q2FjaGUpIHtcclxuICAgICAgdGhpcy5jaGVja1Jlc3VsdENhY2hlID0gbmV3IFdlYWtNYXAoKVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXMuY2hlY2tSZXN1bHRDYWNoZVxyXG4gIH1cclxuXHJcbiAgc2V0Q2FjaGVkUmVzdWx0KG9iajogb2JqZWN0LCBuZXdDYWNoZVZhbHVlOiBDaGVja1Jlc3VsdCkge1xyXG4gICAgdGhpcy5jcmVhdGVDYWNoZUlmTmVlZGVkKCkuc2V0KG9iaiwgbmV3Q2FjaGVWYWx1ZSlcclxuXHJcbiAgICAvLyByZWdpc3RlciB0aGlzIHR5cGUgY2hlY2tlciBhcyBsaXN0ZW5lciBvZiB0aGF0IG9iamVjdCBjaGFuZ2VzXHJcbiAgICBjb25zdCB0eXBlQ2hlY2tlclNldCA9IGdldE9yQ3JlYXRlKHR5cGVDaGVja2Vyc1dpdGhDYWNoZWRSZXN1bHRzT2ZPYmplY3QsIG9iaiwgKCkgPT4gbmV3IFNldCgpKVxyXG5cclxuICAgIHR5cGVDaGVja2VyU2V0LmFkZCh0aGlzKVxyXG4gIH1cclxuXHJcbiAgaW52YWxpZGF0ZUNhY2hlZFJlc3VsdChvYmo6IG9iamVjdCkge1xyXG4gICAgdGhpcy5jaGVja1Jlc3VsdENhY2hlPy5kZWxldGUob2JqKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRDYWNoZWRSZXN1bHQob2JqOiBvYmplY3QpOiBDaGVja1Jlc3VsdCB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy5jaGVja1Jlc3VsdENhY2hlPy5nZXQob2JqKVxyXG4gIH1cclxuXHJcbiAgY2hlY2sodmFsdWU6IGFueSwgcGF0aDogUGF0aCwgdHlwZUNoZWNrZWRWYWx1ZTogYW55KTogVHlwZUNoZWNrRXJyb3IgfCBudWxsIHtcclxuICAgIGlmICh0aGlzLnVuY2hlY2tlZCkge1xyXG4gICAgICByZXR1cm4gbnVsbFxyXG4gICAgfVxyXG5cclxuICAgIGlmICghaXNUd2Vha2VkT2JqZWN0KHZhbHVlLCB0cnVlKSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5fY2hlY2shKHZhbHVlLCBwYXRoLCB0eXBlQ2hlY2tlZFZhbHVlKVxyXG4gICAgfVxyXG5cclxuICAgIC8vIG9wdGltaXplZCBjaGVja2luZyB3aXRoIGNhY2hlZCB2YWx1ZXNcclxuXHJcbiAgICBsZXQgY2FjaGVkUmVzdWx0ID0gdGhpcy5nZXRDYWNoZWRSZXN1bHQodmFsdWUpXHJcblxyXG4gICAgaWYgKGNhY2hlZFJlc3VsdCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIC8vIHdlIHNldCB0aGUgcGF0aCBlbXB0eSBhbmQgbm8gcGFyZW50LCBzaW5jZSB0aGUgcmVzdWx0IGNvdWxkIGJlIHVzZWQgZm9yIHBhdGhzIG90aGVyIHRoYW4gdGhpcyBiYXNlXHJcbiAgICAgIGNhY2hlZFJlc3VsdCA9IHRoaXMuX2NoZWNrISh2YWx1ZSwgZW1wdHlQYXRoLCB1bmRlZmluZWQpXHJcbiAgICAgIHRoaXMuc2V0Q2FjaGVkUmVzdWx0KHZhbHVlLCBjYWNoZWRSZXN1bHQpXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGNhY2hlZFJlc3VsdCkge1xyXG4gICAgICByZXR1cm4gbmV3IFR5cGVDaGVja0Vycm9yKFxyXG4gICAgICAgIFsuLi5wYXRoLCAuLi5jYWNoZWRSZXN1bHQucGF0aF0sXHJcbiAgICAgICAgY2FjaGVkUmVzdWx0LmV4cGVjdGVkVHlwZU5hbWUsXHJcbiAgICAgICAgY2FjaGVkUmVzdWx0LmFjdHVhbFZhbHVlLFxyXG4gICAgICAgIHR5cGVDaGVja2VkVmFsdWVcclxuICAgICAgKVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIG51bGxcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2NhY2hlZFR5cGVJbmZvR2VuOiBUeXBlSW5mb0dlblxyXG5cclxuICBnZXQgdHlwZUluZm8oKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fY2FjaGVkVHlwZUluZm9HZW4odGhpcyBhcyBhbnkpXHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHJlYWRvbmx5IGJhc2VUeXBlOiBUeXBlQ2hlY2tlckJhc2VUeXBlLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfY2hlY2s6IENoZWNrRnVuY3Rpb24gfCBudWxsLFxyXG4gICAgcmVhZG9ubHkgZ2V0VHlwZU5hbWU6ICguLi5yZWN1cnNpdmVUeXBlQ2hlY2tlcnM6IFR5cGVDaGVja2VyW10pID0+IHN0cmluZyxcclxuICAgIHJlYWRvbmx5IHR5cGVJbmZvR2VuOiBUeXBlSW5mb0dlbixcclxuICAgIHJlYWRvbmx5IHNuYXBzaG90VHlwZTogKHNuOiB1bmtub3duKSA9PiBUeXBlQ2hlY2tlciB8IG51bGwsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9mcm9tU25hcHNob3RQcm9jZXNzb3I6IChzbjogYW55KSA9PiB1bmtub3duLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfdG9TbmFwc2hvdFByb2Nlc3NvcjogKHNuOiBhbnkpID0+IHVua25vd25cclxuICApIHtcclxuICAgIHRoaXMudW5jaGVja2VkID0gIV9jaGVja1xyXG4gICAgdGhpcy5fY2FjaGVkVHlwZUluZm9HZW4gPSBsYXp5KHR5cGVJbmZvR2VuKVxyXG4gIH1cclxuXHJcbiAgZnJvbVNuYXBzaG90UHJvY2Vzc29yID0gKHNuOiBhbnkpOiB1bmtub3duID0+IHtcclxuICAgIC8vIHdlIGNhbm5vdCBjYWNoZSBmcm9tU25hcHNob3RQcm9jZXNzb3Igc2luY2Ugbm9ib2R5IGVuc3VyZXMgdXNcclxuICAgIC8vIHRoZSBvcmlnaW5hbCBzbmFwc2hvdCB3b24ndCBiZSB0d2Vha2VkIGFmdGVyIHVzZVxyXG4gICAgcmV0dXJuIHRoaXMuX2Zyb21TbmFwc2hvdFByb2Nlc3NvcihzbilcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgX3RvU25hcHNob3RQcm9jZXNzb3JDYWNoZSA9IG5ldyBXZWFrTWFwPG9iamVjdCwgdW5rbm93bj4oKVxyXG5cclxuICBpbnZhbGlkYXRlU25hcHNob3RQcm9jZXNzb3JDYWNoZWRSZXN1bHQob2JqOiBvYmplY3QpIHtcclxuICAgIHRoaXMuX3RvU25hcHNob3RQcm9jZXNzb3JDYWNoZS5kZWxldGUob2JqKVxyXG4gIH1cclxuXHJcbiAgdG9TbmFwc2hvdFByb2Nlc3NvciA9IChzbjogYW55KTogdW5rbm93biA9PiB7XHJcbiAgICBpZiAodHlwZW9mIHNuICE9PSBcIm9iamVjdFwiIHx8IHNuID09PSBudWxsKSB7XHJcbiAgICAgIC8vIG5vdCBjYWNoZWFibGVcclxuICAgICAgcmV0dXJuIHRoaXMuX3RvU25hcHNob3RQcm9jZXNzb3Ioc24pXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuX3RvU25hcHNob3RQcm9jZXNzb3JDYWNoZS5oYXMoc24pKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLl90b1NuYXBzaG90UHJvY2Vzc29yQ2FjaGUuZ2V0KHNuKVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHZhbCA9IHRoaXMuX3RvU25hcHNob3RQcm9jZXNzb3Ioc24pXHJcbiAgICB0aGlzLl90b1NuYXBzaG90UHJvY2Vzc29yQ2FjaGUuc2V0KHNuLCB2YWwpXHJcblxyXG4gICAgLy8gcmVnaXN0ZXIgdGhpcyB0eXBlIGNoZWNrZXIgYXMgbGlzdGVuZXIgb2YgdGhhdCBzbiBjaGFuZ2VzXHJcbiAgICBjb25zdCB0eXBlQ2hlY2tlclNldCA9IGdldE9yQ3JlYXRlKFxyXG4gICAgICB0eXBlQ2hlY2tlcnNXaXRoQ2FjaGVkU25hcHNob3RQcm9jZXNzb3JSZXN1bHRzT2ZPYmplY3QsXHJcbiAgICAgIHNuLFxyXG4gICAgICAoKSA9PiBuZXcgU2V0KClcclxuICAgIClcclxuXHJcbiAgICB0eXBlQ2hlY2tlclNldC5hZGQodGhpcylcclxuXHJcbiAgICByZXR1cm4gdmFsXHJcbiAgfVxyXG59XHJcblxyXG5jb25zdCBsYXRlVHlwZUNoZWNrZXJTeW1ib2wgPSBTeW1ib2woXCJsYXRlVHlwZUNoZWtlclwiKVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBMYXRlVHlwZUNoZWNrZXIge1xyXG4gIFtsYXRlVHlwZUNoZWNrZXJTeW1ib2xdOiB0cnVlXHJcbiAgKCk6IFR5cGVDaGVja2VyXHJcbiAgdHlwZUluZm86IFR5cGVJbmZvXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBsYXRlVHlwZUNoZWNrZXIoZm46ICgpID0+IFR5cGVDaGVja2VyLCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4pOiBMYXRlVHlwZUNoZWNrZXIge1xyXG4gIGxldCBjYWNoZWQ6IFR5cGVDaGVja2VyIHwgdW5kZWZpbmVkXHJcbiAgY29uc3QgbHRjID0gZnVuY3Rpb24gKCkge1xyXG4gICAgaWYgKGNhY2hlZCkge1xyXG4gICAgICByZXR1cm4gY2FjaGVkXHJcbiAgICB9XHJcblxyXG4gICAgY2FjaGVkID0gZm4oKVxyXG4gICAgcmV0dXJuIGNhY2hlZFxyXG4gIH1cclxuICA7KGx0YyBhcyBMYXRlVHlwZUNoZWNrZXIpW2xhdGVUeXBlQ2hlY2tlclN5bWJvbF0gPSB0cnVlXHJcblxyXG4gIGNvbnN0IGNhY2hlZFR5cGVJbmZvR2VuID0gbGF6eSh0eXBlSW5mb0dlbilcclxuXHJcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGx0YywgXCJ0eXBlSW5mb1wiLCB7XHJcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxyXG4gICAgY29uZmlndXJhYmxlOiB0cnVlLFxyXG4gICAgZ2V0KCkge1xyXG4gICAgICByZXR1cm4gY2FjaGVkVHlwZUluZm9HZW4obHRjIGFzIGFueSlcclxuICAgIH0sXHJcbiAgfSlcclxuXHJcbiAgcmV0dXJuIGx0YyBhcyBMYXRlVHlwZUNoZWNrZXJcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzTGF0ZVR5cGVDaGVja2VyKGx0YzogdW5rbm93bik6IGx0YyBpcyBMYXRlVHlwZUNoZWNrZXIge1xyXG4gIHJldHVybiB0eXBlb2YgbHRjID09PSBcImZ1bmN0aW9uXCIgJiYgbGF0ZVR5cGVDaGVja2VyU3ltYm9sIGluIGx0Y1xyXG59XHJcblxyXG4vKipcclxuICogVHlwZSBpbmZvIGJhc2UgY2xhc3MuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgVHlwZUluZm8ge1xyXG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IHRoaXNUeXBlOiBBbnlTdGFuZGFyZFR5cGUpIHt9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCB0eXBlIFR5cGVJbmZvR2VuID0gKHQ6IEFueVN0YW5kYXJkVHlwZSkgPT4gVHlwZUluZm9cclxuIiwiaW1wb3J0IHsgYWN0aW9uLCBjcmVhdGVBdG9tLCBJQXRvbSB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHsgZmFzdEdldFBhcmVudFBhdGgsIFBhcmVudFBhdGggfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxyXG5pbXBvcnQgeyBpbnZhbGlkYXRlQ2FjaGVkVG9TbmFwc2hvdFByb2Nlc3NvclJlc3VsdCB9IGZyb20gXCIuLi90eXBlcy9UeXBlQ2hlY2tlclwiXHJcbmltcG9ydCB7IGlzUHJpbWl0aXZlIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgUHJpbWl0aXZlVmFsdWUgfSBmcm9tIFwiLi4vdXRpbHMvdHlwZXNcIlxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IHR5cGUgU25hcHNob3RUcmFuc2Zvcm1GbiA9IChzbjogdW5rbm93bikgPT4gdW5rbm93blxyXG5cclxuaW50ZXJmYWNlIFNuYXBzaG90RGF0YSB7XHJcbiAgdW50cmFuc2Zvcm1lZDogYW55XHJcbiAgcmVhZG9ubHkgdHJhbnNmb3JtRm46IFNuYXBzaG90VHJhbnNmb3JtRm4gfCB1bmRlZmluZWRcclxuICB0cmFuc2Zvcm1lZDogYW55XHJcbiAgcmVhZG9ubHkgYXRvbTogSUF0b21cclxufVxyXG5cclxuY29uc3Qgc25hcHNob3RzID0gbmV3IFdlYWtNYXA8b2JqZWN0LCBTbmFwc2hvdERhdGE+KClcclxuXHJcbi8vIHRydWUgaWYgaXQgaGFzIGJlZW4gYWNjZXNzZWQgcHVibGljbHkgYW5kIHRoZXJlZm9yZSBzaG91bGQgYmUgY2xvbmVkXHJcbi8vIHJhdGhlciB0aGFuIG1vZGlmaWVkIGluIHBsYWNlXHJcbmNvbnN0IGZyb3plblN0YXRlID0gbmV3IFdlYWtNYXA8b2JqZWN0LCBib29sZWFuPigpXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2V0SW50ZXJuYWxTbmFwc2hvdDxUIGV4dGVuZHMgb2JqZWN0PihcclxuICB2YWx1ZTogVFxyXG4pOiBSZWFkb25seTxTbmFwc2hvdERhdGE+IHwgdW5kZWZpbmVkIHtcclxuICByZXR1cm4gc25hcHNob3RzLmdldCh2YWx1ZSlcclxufVxyXG5cclxuaW50ZXJmYWNlIEludGVybmFsU25hcHNob3RQYXJlbnQge1xyXG4gIHBhcmVudFNuYXBzaG90OiBTbmFwc2hvdERhdGEgfCB1bmRlZmluZWRcclxuICBwYXJlbnRQYXRoOiBQYXJlbnRQYXRoPGFueT5cclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0SW50ZXJuYWxTbmFwc2hvdFBhcmVudChcclxuICBzbjogUmVhZG9ubHk8U25hcHNob3REYXRhPiB8IHVuZGVmaW5lZCxcclxuICBwYXJlbnRQYXRoOiBQYXJlbnRQYXRoPGFueT4gfCB1bmRlZmluZWRcclxuKTogSW50ZXJuYWxTbmFwc2hvdFBhcmVudCB8IHVuZGVmaW5lZCB7XHJcbiAgaWYgKCFwYXJlbnRQYXRoIHx8ICFzbikge1xyXG4gICAgcmV0dXJuIHVuZGVmaW5lZFxyXG4gIH1cclxuXHJcbiAgY29uc3QgcGFyZW50U24gPSBnZXRJbnRlcm5hbFNuYXBzaG90KHBhcmVudFBhdGgucGFyZW50KVxyXG4gIGlmICghcGFyZW50U24pIHtcclxuICAgIHJldHVybiB1bmRlZmluZWRcclxuICB9XHJcblxyXG4gIHJldHVybiB7XHJcbiAgICBwYXJlbnRTbmFwc2hvdDogcGFyZW50U24sXHJcbiAgICBwYXJlbnRQYXRoOiBwYXJlbnRQYXRoLFxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHVuc2V0SW50ZXJuYWxTbmFwc2hvdCA9IGFjdGlvbihcInVuc2V0SW50ZXJuYWxTbmFwc2hvdFwiLCAodmFsdWU6IGFueSkgPT4ge1xyXG4gIGNvbnN0IG9sZFNuID0gZ2V0SW50ZXJuYWxTbmFwc2hvdCh2YWx1ZSlcclxuXHJcbiAgaWYgKG9sZFNuKSB7XHJcbiAgICBzbmFwc2hvdHMuZGVsZXRlKHZhbHVlKVxyXG4gICAgb2xkU24uYXRvbS5yZXBvcnRDaGFuZ2VkKClcclxuICB9XHJcbn0pXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgY29uc3Qgc2V0TmV3SW50ZXJuYWxTbmFwc2hvdCA9IGFjdGlvbihcclxuICBcInNldE5ld0ludGVybmFsU25hcHNob3RcIixcclxuICA8VCBleHRlbmRzIG9iamVjdD4oXHJcbiAgICB2YWx1ZTogYW55LFxyXG4gICAgdW50cmFuc2Zvcm1lZDogVCxcclxuICAgIHRyYW5zZm9ybUZuOiBTbmFwc2hvdFRyYW5zZm9ybUZuIHwgdW5kZWZpbmVkLFxyXG4gICAgbWFya0FzRnJvemVuID0gZmFsc2VcclxuICApOiB2b2lkID0+IHtcclxuICAgIGNvbnN0IHNuOiBTbmFwc2hvdERhdGEgPSB7XHJcbiAgICAgIHVudHJhbnNmb3JtZWQsXHJcbiAgICAgIHRyYW5zZm9ybUZuLFxyXG4gICAgICB0cmFuc2Zvcm1lZDogdHJhbnNmb3JtRm4gPyB0cmFuc2Zvcm1Gbih1bnRyYW5zZm9ybWVkKSA6IHVudHJhbnNmb3JtZWQsXHJcbiAgICAgIGF0b206IGNyZWF0ZUF0b20oXCJzbmFwc2hvdFwiKSxcclxuICAgIH1cclxuICAgIGZyb3plblN0YXRlLnNldChzbi51bnRyYW5zZm9ybWVkLCBtYXJrQXNGcm96ZW4pXHJcbiAgICBpZiAoc24udHJhbnNmb3JtZWQgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICBmcm96ZW5TdGF0ZS5zZXQoc24udHJhbnNmb3JtZWQsIG1hcmtBc0Zyb3plbilcclxuICAgIH1cclxuXHJcbiAgICBzbmFwc2hvdHMuc2V0KHZhbHVlLCBzbilcclxuXHJcbiAgICBzbi5hdG9tLnJlcG9ydENoYW5nZWQoKVxyXG4gIH1cclxuKVxyXG5cclxudHlwZSBNdXRhdGVJbnRlcm5hbFNuYXBzaG90Rm48VD4gPSAocHJldlNuOiBUKSA9PiB2b2lkXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgdXBkYXRlSW50ZXJuYWxTbmFwc2hvdCA9IGFjdGlvbihcclxuICBcInVwZGF0ZUludGVybmFsU25hcHNob3RcIixcclxuICA8VCBleHRlbmRzIG9iamVjdD4odmFsdWU6IGFueSwgbXV0YXRlOiBNdXRhdGVJbnRlcm5hbFNuYXBzaG90Rm48VD4pOiB2b2lkID0+IHtcclxuICAgIGNvbnN0IHNuID0gZ2V0SW50ZXJuYWxTbmFwc2hvdCh2YWx1ZSkhIGFzIFNuYXBzaG90RGF0YVxyXG5cclxuICAgIGxldCB1bnRyYW5zZm9ybWVkID0gc24udW50cmFuc2Zvcm1lZFxyXG4gICAgY29uc3Qgc25Gcm96ZW4gPSBmcm96ZW5TdGF0ZS5nZXQodW50cmFuc2Zvcm1lZCkhXHJcbiAgICBpZiAoc25Gcm96ZW4pIHtcclxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodW50cmFuc2Zvcm1lZCkpIHtcclxuICAgICAgICB1bnRyYW5zZm9ybWVkID0gdW50cmFuc2Zvcm1lZC5zbGljZSgpXHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdW50cmFuc2Zvcm1lZCA9IE9iamVjdC5hc3NpZ24oe30sIHVudHJhbnNmb3JtZWQpXHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIHRoZSBwcm9jZXNzb3IgY2FjaGVkIHJlc3VsdCBpcyBubyBsb25nZXIgdmFsaWQgc2luY2Ugd2Ugd2lsbFxyXG4gICAgICAvLyBtdXRhdGUgdGhlIG9iamVjdFxyXG4gICAgICBpbnZhbGlkYXRlQ2FjaGVkVG9TbmFwc2hvdFByb2Nlc3NvclJlc3VsdCh1bnRyYW5zZm9ybWVkKVxyXG4gICAgfVxyXG5cclxuICAgIG11dGF0ZSh1bnRyYW5zZm9ybWVkKVxyXG5cclxuICAgIHNuLnVudHJhbnNmb3JtZWQgPSB1bnRyYW5zZm9ybWVkXHJcbiAgICBzbi50cmFuc2Zvcm1lZCA9IHNuLnRyYW5zZm9ybUZuID8gc24udHJhbnNmb3JtRm4odW50cmFuc2Zvcm1lZCkgOiB1bnRyYW5zZm9ybWVkXHJcblxyXG4gICAgZnJvemVuU3RhdGUuc2V0KHNuLnVudHJhbnNmb3JtZWQsIGZhbHNlKVxyXG4gICAgaWYgKHNuLnRyYW5zZm9ybWVkICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgZnJvemVuU3RhdGUuc2V0KHNuLnRyYW5zZm9ybWVkLCBmYWxzZSlcclxuICAgIH1cclxuXHJcbiAgICBzbi5hdG9tLnJlcG9ydENoYW5nZWQoKVxyXG5cclxuICAgIC8vIGFsc28gdXBkYXRlIHBhcmVudChzKSBzbmFwc2hvdChzKSBpZiBuZWVkZWRcclxuICAgIGNvbnN0IHBhcmVudCA9IGdldEludGVybmFsU25hcHNob3RQYXJlbnQoc24sIGZhc3RHZXRQYXJlbnRQYXRoKHZhbHVlKSlcclxuICAgIGlmIChwYXJlbnQpIHtcclxuICAgICAgY29uc3QgeyBwYXJlbnRTbmFwc2hvdCwgcGFyZW50UGF0aCB9ID0gcGFyZW50XHJcbiAgICAgIC8vIG1pZ2h0IGJlIGZhbHNlIGluIHRoZSBjYXNlcyB3aGVyZSB0aGUgcGFyZW50IGhhcyBub3QgeWV0IGJlZW4gY3JlYXRlZFxyXG4gICAgICBpZiAocGFyZW50U25hcHNob3QpIHtcclxuICAgICAgICBjb25zdCBwYXRoID0gcGFyZW50UGF0aC5wYXRoXHJcblxyXG4gICAgICAgIC8vIHBhdGNoZXMgZm9yIHBhcmVudCBjaGFuZ2VzIHNob3VsZCBub3QgYmUgZW1pdHRlZFxyXG4gICAgICAgIHVwZGF0ZUludGVybmFsU25hcHNob3QocGFyZW50UGF0aC5wYXJlbnQsIChvYmpPckFycmF5OiBhbnkpID0+IHtcclxuICAgICAgICAgIG9iak9yQXJyYXlbcGF0aF0gPSBzbi50cmFuc2Zvcm1lZFxyXG4gICAgICAgIH0pXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbilcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiByZXBvcnRJbnRlcm5hbFNuYXBzaG90T2JzZXJ2ZWQoc246IFNuYXBzaG90RGF0YSkge1xyXG4gIHNuLmF0b20ucmVwb3J0T2JzZXJ2ZWQoKVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZnJlZXplSW50ZXJuYWxTbmFwc2hvdDxUIGV4dGVuZHMgUHJpbWl0aXZlVmFsdWUgfCBvYmplY3Q+KGRhdGE6IFQpOiBUIHtcclxuICBpZiAoaXNQcmltaXRpdmUoZGF0YSkpIHtcclxuICAgIHJldHVybiBkYXRhXHJcbiAgfVxyXG5cclxuICAvLyB0aGlzIG1pZ2h0IGJlIHVuZGVmaW5lZCBpZiB0aGUgZGF0YSBjb21lcyBmcm9tIGV4YW1wbGUgZnJvbSB0cmFuc2Zvcm1zXHJcbiAgY29uc3QgaXNGcm96ZW4gPSBmcm96ZW5TdGF0ZS5nZXQoZGF0YSlcclxuXHJcbiAgaWYgKGlzRnJvemVuID09PSB1bmRlZmluZWQgfHwgaXNGcm96ZW4gPT09IHRydWUpIHtcclxuICAgIC8vIGFscmVhZHkgZnJvemVuIG9yIGFuIGV4dGVybmFsIGRhdGEgKGUuZy4gZnJvbSBhIHRyYW5zZm9ybSlcclxuICAgIHJldHVybiBkYXRhXHJcbiAgfVxyXG5cclxuICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGZyZWV6ZUludGVybmFsU25hcHNob3QoZGF0YVtpXSlcclxuICAgIH1cclxuICB9IGVsc2Uge1xyXG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGRhdGEpXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgZnJlZXplSW50ZXJuYWxTbmFwc2hvdCgoZGF0YSBhcyBhbnkpW2tleXNbaV1dKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZnJvemVuU3RhdGUuc2V0KGRhdGEsIHRydWUpXHJcblxyXG4gIHJldHVybiBkYXRhXHJcbn1cclxuIiwiaW1wb3J0IHsgYWN0aW9uLCBpc0FjdGlvbiB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHsgZmFzdEdldFBhcmVudFBhdGggfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxyXG5pbXBvcnQgdHlwZSB7IFBhdGhFbGVtZW50IH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoVHlwZXNcIlxyXG5pbXBvcnQgeyBhc3NlcnRUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXHJcbmltcG9ydCB7IGFzc2VydElzRnVuY3Rpb24sIGRlbGV0ZUZyb21BcnJheSwgaXNQcmltaXRpdmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IFBhdGNoIH0gZnJvbSBcIi4vUGF0Y2hcIlxyXG5pbXBvcnQgeyBmcmVlemVJbnRlcm5hbFNuYXBzaG90LCBnZXRJbnRlcm5hbFNuYXBzaG90IH0gZnJvbSBcIi4uL3NuYXBzaG90L2ludGVybmFsXCJcclxuXHJcbmNvbnN0IGVtcHR5UGF0Y2hBcnJheTogUGF0Y2hbXSA9IFtdXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgSW50ZXJuYWxQYXRjaFJlY29yZGVyIHtcclxuICBwYXRjaGVzOiBQYXRjaFtdID0gZW1wdHlQYXRjaEFycmF5XHJcbiAgaW52UGF0Y2hlczogUGF0Y2hbXSA9IGVtcHR5UGF0Y2hBcnJheVxyXG5cclxuICByZXNldCgpIHtcclxuICAgIHRoaXMucGF0Y2hlcyA9IGVtcHR5UGF0Y2hBcnJheVxyXG4gICAgdGhpcy5pbnZQYXRjaGVzID0gZW1wdHlQYXRjaEFycmF5XHJcbiAgfVxyXG5cclxuICByZWNvcmQocGF0Y2hlczogUGF0Y2hbXSwgaW52UGF0Y2hlczogUGF0Y2hbXSkge1xyXG4gICAgdGhpcy5wYXRjaGVzID0gcGF0Y2hlc1xyXG4gICAgdGhpcy5pbnZQYXRjaGVzID0gaW52UGF0Y2hlc1xyXG4gIH1cclxuXHJcbiAgZW1pdChvYmo6IG9iamVjdCkge1xyXG4gICAgZW1pdFBhdGNoZXMob2JqLCB0aGlzLnBhdGNoZXMsIHRoaXMuaW52UGF0Y2hlcylcclxuICAgIHRoaXMucmVzZXQoKVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGVtaXRQYXRjaGVzKG9iajogb2JqZWN0LCBwYXRjaGVzOiBQYXRjaFtdLCBpbnZQYXRjaGVzOiBQYXRjaFtdKTogdm9pZCB7XHJcbiAgaWYgKHBhdGNoZXMubGVuZ3RoID4gMCB8fCBpbnZQYXRjaGVzLmxlbmd0aCA+IDApIHtcclxuICAgIGVtaXRHbG9iYWxQYXRjaChvYmosIHBhdGNoZXMsIGludlBhdGNoZXMpXHJcbiAgICBlbWl0UGF0Y2gob2JqLCBwYXRjaGVzLCBpbnZQYXRjaGVzKVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEEgZnVuY3Rpb24gdGhhdCBnZXRzIGNhbGxlZCB3aGVuIGEgcGF0Y2ggaXMgZW1pdHRlZC5cclxuICovXHJcbmV4cG9ydCB0eXBlIE9uUGF0Y2hlc0xpc3RlbmVyID0gKHBhdGNoZXM6IFBhdGNoW10sIGludmVyc2VQYXRjaGVzOiBQYXRjaFtdKSA9PiB2b2lkXHJcblxyXG4vKipcclxuICogQSBmdW5jdGlvbiB0aGF0IGdldHMgY2FsbGVkIHdoZW4gYSBnbG9iYWwgcGF0Y2ggaXMgZW1pdHRlZC5cclxuICovXHJcbmV4cG9ydCB0eXBlIE9uR2xvYmFsUGF0Y2hlc0xpc3RlbmVyID0gKFxyXG4gIHRhcmdldDogb2JqZWN0LFxyXG4gIHBhdGNoZXM6IFBhdGNoW10sXHJcbiAgaW52ZXJzZVBhdGNoZXM6IFBhdGNoW11cclxuKSA9PiB2b2lkXHJcblxyXG4vKipcclxuICogRGlzcG9zZXIgZnVuY3Rpb24gdG8gc3RvcCBsaXN0ZW5pbmcgdG8gcGF0Y2hlcy5cclxuICovXHJcbmV4cG9ydCB0eXBlIE9uUGF0Y2hlc0Rpc3Bvc2VyID0gKCkgPT4gdm9pZFxyXG5cclxuY29uc3QgcGF0Y2hMaXN0ZW5lcnMgPSBuZXcgV2Vha01hcDxvYmplY3QsIE9uUGF0Y2hlc0xpc3RlbmVyW10+KClcclxuY29uc3QgZ2xvYmFsUGF0Y2hMaXN0ZW5lcnM6IE9uR2xvYmFsUGF0Y2hlc0xpc3RlbmVyW10gPSBbXVxyXG5cclxuLyoqXHJcbiAqIEFkZHMgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgY2FsbGVkIGV2ZXJ5IHRpbWUgYSBwYXRjaCBpcyBnZW5lcmF0ZWQgZm9yIHRoZSB0cmVlIG9mIHRoZSBnaXZlbiB0YXJnZXQgb2JqZWN0LlxyXG4gKlxyXG4gKiBAcGFyYW0gc3VidHJlZVJvb3QgU3VidHJlZSByb290IG9iamVjdCBvZiB0aGUgcGF0Y2ggbGlzdGVuZXIuXHJcbiAqIEBwYXJhbSBsaXN0ZW5lciBUaGUgbGlzdGVuZXIgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCBldmVyeXRpbWUgYSBwYXRjaCBpcyBnZW5lcmF0ZWQgZm9yIHRoZSBvYmplY3Qgb3IgaXRzIGNoaWxkcmVuLlxyXG4gKiBAcmV0dXJucyBBIGRpc3Bvc2VyIHRvIHN0b3AgbGlzdGVuaW5nIHRvIHBhdGNoZXMuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gb25QYXRjaGVzKHN1YnRyZWVSb290OiBvYmplY3QsIGxpc3RlbmVyOiBPblBhdGNoZXNMaXN0ZW5lcik6IE9uUGF0Y2hlc0Rpc3Bvc2VyIHtcclxuICBhc3NlcnRUd2Vha2VkT2JqZWN0KHN1YnRyZWVSb290LCBcInN1YnRyZWVSb290XCIpXHJcbiAgYXNzZXJ0SXNGdW5jdGlvbihsaXN0ZW5lciwgXCJsaXN0ZW5lclwiKVxyXG5cclxuICBpZiAoIWlzQWN0aW9uKGxpc3RlbmVyKSkge1xyXG4gICAgbGlzdGVuZXIgPSBhY3Rpb24obGlzdGVuZXIubmFtZSB8fCBcIm9uUGF0Y2hlc0xpc3RlbmVyXCIsIGxpc3RlbmVyKVxyXG4gIH1cclxuXHJcbiAgbGV0IGxpc3RlbmVyc0Zvck9iamVjdCA9IHBhdGNoTGlzdGVuZXJzLmdldChzdWJ0cmVlUm9vdClcclxuICBpZiAoIWxpc3RlbmVyc0Zvck9iamVjdCkge1xyXG4gICAgbGlzdGVuZXJzRm9yT2JqZWN0ID0gW11cclxuICAgIHBhdGNoTGlzdGVuZXJzLnNldChzdWJ0cmVlUm9vdCwgbGlzdGVuZXJzRm9yT2JqZWN0KVxyXG4gIH1cclxuXHJcbiAgbGlzdGVuZXJzRm9yT2JqZWN0LnB1c2gobGlzdGVuZXIpXHJcbiAgcmV0dXJuICgpID0+IHtcclxuICAgIGRlbGV0ZUZyb21BcnJheShsaXN0ZW5lcnNGb3JPYmplY3QhLCBsaXN0ZW5lcilcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBZGRzIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGNhbGxlZCBldmVyeSB0aW1lIGEgcGF0Y2ggaXMgZ2VuZXJhdGVkIGFueXdoZXJlLlxyXG4gKiBVc3VhbGx5IHByZWZlciB1c2luZyBgb25QYXRjaGVzYC5cclxuICpcclxuICogQHBhcmFtIGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgY2FsbGVkIGV2ZXJ5dGltZSBhIHBhdGNoIGlzIGdlbmVyYXRlZCBhbnl3aGVyZS5cclxuICogQHJldHVybnMgQSBkaXNwb3NlciB0byBzdG9wIGxpc3RlbmluZyB0byBwYXRjaGVzLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIG9uR2xvYmFsUGF0Y2hlcyhsaXN0ZW5lcjogT25HbG9iYWxQYXRjaGVzTGlzdGVuZXIpOiBPblBhdGNoZXNEaXNwb3NlciB7XHJcbiAgYXNzZXJ0SXNGdW5jdGlvbihsaXN0ZW5lciwgXCJsaXN0ZW5lclwiKVxyXG5cclxuICBpZiAoIWlzQWN0aW9uKGxpc3RlbmVyKSkge1xyXG4gICAgbGlzdGVuZXIgPSBhY3Rpb24obGlzdGVuZXIubmFtZSB8fCBcIm9uR2xvYmFsUGF0Y2hlc0xpc3RlbmVyXCIsIGxpc3RlbmVyKVxyXG4gIH1cclxuXHJcbiAgZ2xvYmFsUGF0Y2hMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcilcclxuICByZXR1cm4gKCkgPT4ge1xyXG4gICAgZGVsZXRlRnJvbUFycmF5KGdsb2JhbFBhdGNoTGlzdGVuZXJzLCBsaXN0ZW5lcilcclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGVtaXRHbG9iYWxQYXRjaChvYmo6IG9iamVjdCwgcGF0Y2hlczogUGF0Y2hbXSwgaW52ZXJzZVBhdGNoZXM6IFBhdGNoW10pOiB2b2lkIHtcclxuICBmb3IgKGxldCBpID0gMDsgaSA8IGdsb2JhbFBhdGNoTGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICBjb25zdCBsaXN0ZW5lciA9IGdsb2JhbFBhdGNoTGlzdGVuZXJzW2ldXHJcbiAgICBsaXN0ZW5lcihvYmosIHBhdGNoZXMsIGludmVyc2VQYXRjaGVzKVxyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gZW1pdFBhdGNoRm9yVGFyZ2V0KFxyXG4gIG9iajogb2JqZWN0LFxyXG4gIHBhdGNoZXM6IFBhdGNoW10sXHJcbiAgaW52ZXJzZVBhdGNoZXM6IFBhdGNoW10sXHJcbiAgcGF0aFByZWZpeDogUGF0aEVsZW1lbnRbXVxyXG4pOiB2b2lkIHtcclxuICBjb25zdCBsaXN0ZW5lcnNGb3JPYmplY3QgPSBwYXRjaExpc3RlbmVycy5nZXQob2JqKVxyXG5cclxuICBpZiAoIWxpc3RlbmVyc0Zvck9iamVjdCB8fCBsaXN0ZW5lcnNGb3JPYmplY3QubGVuZ3RoID09PSAwKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIGNvbnN0IGZpeFBhdGggPSAocGF0Y2hlc0FycmF5OiBQYXRjaFtdKSA9PlxyXG4gICAgcGF0aFByZWZpeC5sZW5ndGggPiAwID8gcGF0Y2hlc0FycmF5Lm1hcCgocCkgPT4gYWRkUGF0aFRvUGF0Y2gocCwgcGF0aFByZWZpeCkpIDogcGF0Y2hlc0FycmF5XHJcblxyXG4gIGNvbnN0IHBhdGNoZXNXaXRoUGF0aFByZWZpeCA9IGZpeFBhdGgocGF0Y2hlcylcclxuICBjb25zdCBpbnZQYXRjaGVzV2l0aFBhdGhQcmVmaXggPSBmaXhQYXRoKGludmVyc2VQYXRjaGVzKVxyXG5cclxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RlbmVyc0Zvck9iamVjdC5sZW5ndGg7IGkrKykge1xyXG4gICAgY29uc3QgbGlzdGVuZXIgPSBsaXN0ZW5lcnNGb3JPYmplY3RbaV1cclxuICAgIGxpc3RlbmVyKHBhdGNoZXNXaXRoUGF0aFByZWZpeCwgaW52UGF0Y2hlc1dpdGhQYXRoUHJlZml4KVxyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gZW1pdFBhdGNoKG9iajogb2JqZWN0LCBwYXRjaGVzOiBQYXRjaFtdLCBpbnZlcnNlUGF0Y2hlczogUGF0Y2hbXSk6IHZvaWQge1xyXG4gIGNvbnN0IHBhdGhQcmVmaXg6IFBhdGhFbGVtZW50W10gPSBbXVxyXG5cclxuICBlbWl0UGF0Y2hGb3JUYXJnZXQob2JqLCBwYXRjaGVzLCBpbnZlcnNlUGF0Y2hlcywgcGF0aFByZWZpeClcclxuXHJcbiAgLy8gYW5kIGFsc28gZW1pdCBzdWJ0cmVlIGxpc3RlbmVycyBhbGwgdGhlIHdheSB0byB0aGUgcm9vdFxyXG4gIGxldCBwYXJlbnRQYXRoID0gZmFzdEdldFBhcmVudFBhdGgob2JqKVxyXG4gIHdoaWxlIChwYXJlbnRQYXRoKSB7XHJcbiAgICBwYXRoUHJlZml4LnVuc2hpZnQocGFyZW50UGF0aC5wYXRoKVxyXG4gICAgZW1pdFBhdGNoRm9yVGFyZ2V0KHBhcmVudFBhdGgucGFyZW50LCBwYXRjaGVzLCBpbnZlcnNlUGF0Y2hlcywgcGF0aFByZWZpeClcclxuXHJcbiAgICBwYXJlbnRQYXRoID0gZmFzdEdldFBhcmVudFBhdGgocGFyZW50UGF0aC5wYXJlbnQpXHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBhZGRQYXRoVG9QYXRjaChwYXRjaDogUGF0Y2gsIHBhdGhQcmVmaXg6IHJlYWRvbmx5IFBhdGhFbGVtZW50W10pOiBQYXRjaCB7XHJcbiAgcmV0dXJuIHtcclxuICAgIC4uLnBhdGNoLFxyXG4gICAgcGF0aDogWy4uLnBhdGhQcmVmaXgsIC4uLnBhdGNoLnBhdGhdLFxyXG4gIH1cclxufVxyXG5cclxuY29uc3QgZ2V0VmFsdWVTbmFwc2hvdEZvclBhdGNoID0gKHY6IHVua25vd24pID0+IHtcclxuICBpZiAoaXNQcmltaXRpdmUodikpIHtcclxuICAgIHJldHVybiB2XHJcbiAgfVxyXG4gIGNvbnN0IGludGVybmFsU25hcHNob3QgPSBnZXRJbnRlcm5hbFNuYXBzaG90KHYgYXMgb2JqZWN0KVxyXG4gIGlmICghaW50ZXJuYWxTbmFwc2hvdCkge1xyXG4gICAgLy8gcHJvYmFibHkgYSBwbGFpbiB2YWx1ZVxyXG4gICAgcmV0dXJuIHZcclxuICB9XHJcbiAgcmV0dXJuIGZyZWV6ZUludGVybmFsU25hcHNob3QoaW50ZXJuYWxTbmFwc2hvdC50cmFuc2Zvcm1lZClcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVBhdGNoRm9yT2JqZWN0VmFsdWVDaGFuZ2UoXHJcbiAgcGF0aDogcmVhZG9ubHkgUGF0aEVsZW1lbnRbXSxcclxuICBvbGRWYWx1ZTogdW5rbm93bixcclxuICBuZXdWYWx1ZTogdW5rbm93blxyXG4pOiBQYXRjaCB7XHJcbiAgcmV0dXJuIG5ld1ZhbHVlID09PSB1bmRlZmluZWRcclxuICAgID8geyBvcDogXCJyZW1vdmVcIiwgcGF0aCB9XHJcbiAgICA6IG9sZFZhbHVlID09PSB1bmRlZmluZWRcclxuICAgICAgPyB7XHJcbiAgICAgICAgICBvcDogXCJhZGRcIixcclxuICAgICAgICAgIHBhdGgsXHJcbiAgICAgICAgICB2YWx1ZTogZ2V0VmFsdWVTbmFwc2hvdEZvclBhdGNoKG5ld1ZhbHVlKSxcclxuICAgICAgICB9XHJcbiAgICAgIDoge1xyXG4gICAgICAgICAgb3A6IFwicmVwbGFjZVwiLFxyXG4gICAgICAgICAgcGF0aCxcclxuICAgICAgICAgIHZhbHVlOiBnZXRWYWx1ZVNuYXBzaG90Rm9yUGF0Y2gobmV3VmFsdWUpLFxyXG4gICAgICAgIH1cclxufVxyXG4iLCJpbXBvcnQgeyBzZXQgfSBmcm9tIFwibW9ieFwiXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gc2V0SWZEaWZmZXJlbnQodGFyZ2V0OiBhbnksIGtleTogUHJvcGVydHlLZXksIHZhbHVlOiBhbnkpOiBib29sZWFuIHtcclxuICBjb25zdCBvbGRWYWx1ZSA9IHRhcmdldFtrZXldXHJcblxyXG4gIGlmIChvbGRWYWx1ZSAhPT0gdmFsdWUgfHwgKHZhbHVlID09PSB1bmRlZmluZWQgJiYgIShrZXkgaW4gdGFyZ2V0KSkpIHtcclxuICAgIHNldCh0YXJnZXQsIGtleSwgdmFsdWUpXHJcbiAgICByZXR1cm4gdHJ1ZVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGZhbHNlXHJcbn1cclxuIiwiLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGVudW0gVHdlYWtlclByaW9yaXR5IHtcbiAgTW9kZWwsXG4gIEFycmF5LFxuICBQbGFpbk9iamVjdCxcbiAgRnJvemVuLFxufVxuIiwiaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxyXG5pbXBvcnQgeyBmYXN0R2V0UGFyZW50UGF0aCwgUGFyZW50UGF0aCB9IGZyb20gXCIuL3BhdGhcIlxyXG5pbXBvcnQgdHlwZSB7IFBhdGgsIFdyaXRhYmxlUGF0aCB9IGZyb20gXCIuL3BhdGhUeXBlc1wiXHJcblxyXG4vKipcclxuICogSXRlcmF0ZXMgdGhyb3VnaCBhbGwgdGhlIHBhcmVudHMgKGZyb20gdGhlIG5lYXJlc3QgdW50aWwgdGhlIHJvb3QpXHJcbiAqIHVudGlsIG9uZSBvZiB0aGVtIG1hdGNoZXMgdGhlIGdpdmVuIHByZWRpY2F0ZS5cclxuICogSWYgdGhlIHByZWRpY2F0ZSBpcyBtYXRjaGVkIGl0IHdpbGwgcmV0dXJuIHRoZSBmb3VuZCBub2RlLlxyXG4gKiBJZiBub25lIGlzIGZvdW5kIGl0IHdpbGwgcmV0dXJuIHVuZGVmaW5lZC5cclxuICpcclxuICogQHR5cGVwYXJhbSBUIFBhcmVudCBvYmplY3QgdHlwZS5cclxuICogQHBhcmFtIGNoaWxkIFRhcmdldCBvYmplY3QuXHJcbiAqIEBwYXJhbSBwcmVkaWNhdGUgRnVuY3Rpb24gdGhhdCB3aWxsIGJlIHJ1biBmb3IgZXZlcnkgcGFyZW50IG9mIHRoZSB0YXJnZXQgb2JqZWN0LCBmcm9tIGltbWVkaWF0ZSBwYXJlbnQgdG8gdGhlIHJvb3QuXHJcbiAqIEBwYXJhbSBtYXhEZXB0aCBNYXggZGVwdGgsIG9yIDAgZm9yIGluZmluaXRlLlxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRQYXJlbnQ8VCBleHRlbmRzIG9iamVjdCA9IGFueT4oXHJcbiAgY2hpbGQ6IG9iamVjdCxcclxuICBwcmVkaWNhdGU6IChwYXJlbnROb2RlOiBvYmplY3QpID0+IGJvb2xlYW4sXHJcbiAgbWF4RGVwdGggPSAwXHJcbik6IFQgfCB1bmRlZmluZWQge1xyXG4gIGNvbnN0IGZvdW5kUGFyZW50UGF0aCA9IGZpbmRQYXJlbnRQYXRoKGNoaWxkLCBwcmVkaWNhdGUsIG1heERlcHRoKVxyXG4gIHJldHVybiBmb3VuZFBhcmVudFBhdGggPyBmb3VuZFBhcmVudFBhdGgucGFyZW50IDogdW5kZWZpbmVkXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXN1bHQgb2YgYGZpbmRQYXJlbnRQYXRoYC5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRm91bmRQYXJlbnRQYXRoPFQgZXh0ZW5kcyBvYmplY3Q+IHtcclxuICAvKipcclxuICAgKiBGb3VuZCBwYXJlbnQgb2JqZWN0LlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IHBhcmVudDogVFxyXG5cclxuICAvKipcclxuICAgKiBQYXRoIGZyb20gdGhlIGZvdW5kIHBhcmVudCB0byB0aGUgY2hpbGQuXHJcbiAgICovXHJcbiAgcmVhZG9ubHkgcGF0aDogUGF0aFxyXG59XHJcblxyXG4vKipcclxuICogSXRlcmF0ZXMgdGhyb3VnaCBhbGwgdGhlIHBhcmVudHMgKGZyb20gdGhlIG5lYXJlc3QgdW50aWwgdGhlIHJvb3QpXHJcbiAqIHVudGlsIG9uZSBvZiB0aGVtIG1hdGNoZXMgdGhlIGdpdmVuIHByZWRpY2F0ZS5cclxuICogSWYgdGhlIHByZWRpY2F0ZSBpcyBtYXRjaGVkIGl0IHdpbGwgcmV0dXJuIHRoZSBmb3VuZCBub2RlIHBsdXMgdGhlXHJcbiAqIHBhdGggdG8gZ2V0IGZyb20gdGhlIHBhcmVudCB0byB0aGUgY2hpbGQuXHJcbiAqIElmIG5vbmUgaXMgZm91bmQgaXQgd2lsbCByZXR1cm4gdW5kZWZpbmVkLlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgUGFyZW50IG9iamVjdCB0eXBlLlxyXG4gKiBAcGFyYW0gY2hpbGQgVGFyZ2V0IG9iamVjdC5cclxuICogQHBhcmFtIHByZWRpY2F0ZSBGdW5jdGlvbiB0aGF0IHdpbGwgYmUgcnVuIGZvciBldmVyeSBwYXJlbnQgb2YgdGhlIHRhcmdldCBvYmplY3QsIGZyb20gaW1tZWRpYXRlIHBhcmVudCB0byB0aGUgcm9vdC5cclxuICogQHBhcmFtIG1heERlcHRoIE1heCBkZXB0aCwgb3IgMCBmb3IgaW5maW5pdGUuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZmluZFBhcmVudFBhdGg8VCBleHRlbmRzIG9iamVjdCA9IGFueT4oXHJcbiAgY2hpbGQ6IG9iamVjdCxcclxuICBwcmVkaWNhdGU6IChwYXJlbnROb2RlOiBvYmplY3QpID0+IGJvb2xlYW4sXHJcbiAgbWF4RGVwdGggPSAwXHJcbik6IEZvdW5kUGFyZW50UGF0aDxUPiB8IHVuZGVmaW5lZCB7XHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChjaGlsZCwgXCJjaGlsZFwiKVxyXG5cclxuICBjb25zdCBwYXRoOiBXcml0YWJsZVBhdGggPSBbXVxyXG5cclxuICBsZXQgY3VycmVudDogYW55ID0gY2hpbGRcclxuICBsZXQgZGVwdGggPSAwXHJcblxyXG4gIGxldCBwYXJlbnRQYXRoOiBQYXJlbnRQYXRoPGFueT4gfCB1bmRlZmluZWRcclxuICB3aGlsZSAoKHBhcmVudFBhdGggPSBmYXN0R2V0UGFyZW50UGF0aChjdXJyZW50KSkpIHtcclxuICAgIHBhdGgudW5zaGlmdChwYXJlbnRQYXRoLnBhdGgpXHJcbiAgICBjdXJyZW50ID0gcGFyZW50UGF0aC5wYXJlbnRcclxuICAgIGlmIChwcmVkaWNhdGUoY3VycmVudCkpIHtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBwYXJlbnQ6IGN1cnJlbnQsXHJcbiAgICAgICAgcGF0aCxcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGRlcHRoKytcclxuICAgIGlmIChtYXhEZXB0aCA+IDAgJiYgZGVwdGggPT09IG1heERlcHRoKSB7XHJcbiAgICAgIGJyZWFrXHJcbiAgICB9XHJcbiAgfVxyXG4gIHJldHVybiB1bmRlZmluZWRcclxufVxyXG4iLCJpbXBvcnQgeyBhc3NlcnRUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXHJcbmltcG9ydCB7IGdldERlZXBPYmplY3RDaGlsZHJlbiwgZ2V0T2JqZWN0Q2hpbGRyZW4gfSBmcm9tIFwiLi9jb3JlT2JqZWN0Q2hpbGRyZW5cIlxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYWxsIHRoZSBjaGlsZHJlbiBvYmplY3RzICh0aGlzIGlzLCBleGNsdWRpbmcgcHJpbWl0aXZlcykgb2YgYW4gb2JqZWN0LlxyXG4gKlxyXG4gKiBAcGFyYW0gbm9kZSBPYmplY3QgdG8gZ2V0IHRoZSBsaXN0IG9mIGNoaWxkcmVuIGZyb20uXHJcbiAqIEBwYXJhbSBbb3B0aW9uc10gQW4gb3B0aW9uYWwgb2JqZWN0IHdpdGggdGhlIGBkZWVwYCBvcHRpb24gKGRlZmF1bHRzIHRvIGZhbHNlKSB0byB0cnVlIHRvIGdldFxyXG4gKiB0aGUgY2hpbGRyZW4gZGVlcGx5IG9yIGZhbHNlIHRvIGdldCB0aGVtIHNoYWxsb3dseS5cclxuICogQHJldHVybnMgQSByZWFkb25seSBvYnNlcnZhYmxlIHNldCB3aXRoIHRoZSBjaGlsZHJlbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRDaGlsZHJlbk9iamVjdHMoXHJcbiAgbm9kZTogb2JqZWN0LFxyXG4gIG9wdGlvbnM/OiB7XHJcbiAgICBkZWVwPzogYm9vbGVhblxyXG4gIH1cclxuKTogUmVhZG9ubHlTZXQ8b2JqZWN0PiB7XHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChub2RlLCBcIm5vZGVcIilcclxuXHJcbiAgaWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLmRlZXApIHtcclxuICAgIHJldHVybiBnZXRPYmplY3RDaGlsZHJlbihub2RlKVxyXG4gIH0gZWxzZSB7XHJcbiAgICByZXR1cm4gZ2V0RGVlcE9iamVjdENoaWxkcmVuKG5vZGUpLmRlZXBcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgZ2V0Q2hpbGRyZW5PYmplY3RzIH0gZnJvbSBcIi4vZ2V0Q2hpbGRyZW5PYmplY3RzXCJcblxuLyoqXG4gKiBJdGVyYXRlcyB0aHJvdWdoIGFsbCBjaGlsZHJlbiBhbmQgY29sbGVjdHMgdGhlbSBpbiBhIHNldCBpZiB0aGVcbiAqIGdpdmVuIHByZWRpY2F0ZSBtYXRjaGVzLlxuICpcbiAqIEBwYXJhbSByb290IFJvb3Qgb2JqZWN0IHRvIGdldCB0aGUgbWF0Y2hpbmcgY2hpbGRyZW4gZnJvbS5cbiAqIEBwYXJhbSBwcmVkaWNhdGUgRnVuY3Rpb24gdGhhdCB3aWxsIGJlIHJ1biBmb3IgZXZlcnkgY2hpbGQgb2YgdGhlIHJvb3Qgb2JqZWN0LlxuICogQHBhcmFtIFtvcHRpb25zXSBBbiBvcHRpb25hbCBvYmplY3Qgd2l0aCB0aGUgYGRlZXBgIG9wdGlvbiAoZGVmYXVsdHMgdG8gYGZhbHNlYCkgc2V0IHRvIGB0cnVlYCB0b1xuICogZ2V0IHRoZSBjaGlsZHJlbiBkZWVwbHkgb3IgYGZhbHNlYCB0byBnZXQgdGhlbSBzaGFsbG93bHkuXG4gKiBAcmV0dXJucyBBIHJlYWRvbmx5IG9ic2VydmFibGUgc2V0IHdpdGggdGhlIG1hdGNoaW5nIGNoaWxkcmVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZENoaWxkcmVuPFQgZXh0ZW5kcyBvYmplY3QgPSBhbnk+KFxuICByb290OiBvYmplY3QsXG4gIHByZWRpY2F0ZTogKG5vZGU6IG9iamVjdCkgPT4gYm9vbGVhbixcbiAgb3B0aW9ucz86IHtcbiAgICBkZWVwPzogYm9vbGVhblxuICB9XG4pOiBSZWFkb25seVNldDxUPiB7XG4gIGNvbnN0IGNoaWxkcmVuID0gZ2V0Q2hpbGRyZW5PYmplY3RzKHJvb3QsIG9wdGlvbnMpXG5cbiAgY29uc3Qgc2V0ID0gbmV3IFNldDxhbnk+KClcblxuICBjb25zdCBpdGVyID0gY2hpbGRyZW4udmFsdWVzKClcbiAgbGV0IGN1ciA9IGl0ZXIubmV4dCgpXG4gIHdoaWxlICghY3VyLmRvbmUpIHtcbiAgICBpZiAocHJlZGljYXRlKGN1ci52YWx1ZSkpIHtcbiAgICAgIHNldC5hZGQoY3VyLnZhbHVlKVxuICAgIH1cbiAgICBjdXIgPSBpdGVyLm5leHQoKVxuICB9XG5cbiAgcmV0dXJuIHNldFxufVxuIiwiaW1wb3J0IHsgcmVhY3Rpb24gfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgeyBhc3NlcnRUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXG5pbXBvcnQgeyBhc3NlcnRJc0Z1bmN0aW9uIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IGdldENoaWxkcmVuT2JqZWN0cyB9IGZyb20gXCIuL2dldENoaWxkcmVuT2JqZWN0c1wiXG5cbi8qKlxuICogUnVucyBhIGNhbGxiYWNrIGV2ZXJ5dGltZSBhIG5ldyBvYmplY3QgaXMgYXR0YWNoZWQgdG8gYSBnaXZlbiBub2RlLlxuICogVGhlIGNhbGxiYWNrIGNhbiBvcHRpb25hbGx5IHJldHVybiBhIGRpc3Bvc2VyIHdoaWNoIHdpbGwgYmUgcnVuIHdoZW4gdGhlIGNoaWxkIGlzIGRldGFjaGVkLlxuICpcbiAqIFRoZSBvcHRpb25hbCBvcHRpb25zIHBhcmFtZXRlciBhY2NlcHRzIGFuZCBvYmplY3Qgd2l0aCB0aGUgZm9sbG93aW5nIG9wdGlvbnM6XG4gKiAtIGBkZWVwOiBib29sZWFuYCAoZGVmYXVsdDogYGZhbHNlYCkgLSB0cnVlIGlmIHRoZSBjYWxsYmFjayBzaG91bGQgYmUgcnVuIGZvciBhbGwgY2hpbGRyZW4gZGVlcGx5XG4gKiBvciBmYWxzZSBpZiBpdCBpdCBzaG91bGQgb25seSBydW4gZm9yIHNoYWxsb3cgY2hpbGRyZW4uXG4gKiAtIGBmaXJlRm9yQ3VycmVudENoaWxkcmVuOiBib29sZWFuYCAoZGVmYXVsdDogYHRydWVgKSAtIHRydWUgaWYgdGhlIGNhbGxiYWNrIHNob3VsZCBiZSBpbW1lZGlhdGVseVxuICogY2FsbGVkIGZvciBjdXJyZW50bHkgYXR0YWNoZWQgY2hpbGRyZW4sIGZhbHNlIGlmIG9ubHkgZm9yIGZ1dHVyZSBhdHRhY2htZW50cy5cbiAqXG4gKiBSZXR1cm5zIGEgZGlzcG9zZXIsIHdoaWNoIGhhcyBhIGJvb2xlYW4gcGFyYW1ldGVyIHdoaWNoIHNob3VsZCBiZSB0cnVlIGlmIHBlbmRpbmcgZGV0YWNobWVudFxuICogY2FsbGJhY2tzIHNob3VsZCBiZSBydW4gb3IgZmFsc2Ugb3RoZXJ3aXNlLlxuICpcbiAqIEBwYXJhbSB0YXJnZXQgRnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBvYmplY3Qgd2hvc2UgY2hpbGRyZW4gc2hvdWxkIGJlIHRyYWNrZWQuXG4gKiBAcGFyYW0gZm4gQ2FsbGJhY2sgY2FsbGVkIHdoZW4gYSBjaGlsZCBpcyBhdHRhY2hlZCB0byB0aGUgdGFyZ2V0IG9iamVjdC5cbiAqIEBwYXJhbSBbb3B0aW9uc11cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbkNoaWxkQXR0YWNoZWRUbyhcbiAgdGFyZ2V0OiAoKSA9PiBvYmplY3QsXG4gIGZuOiAoY2hpbGQ6IG9iamVjdCkgPT4gKCgpID0+IHZvaWQpIHwgdm9pZCxcbiAgb3B0aW9ucz86IHtcbiAgICBkZWVwPzogYm9vbGVhblxuICAgIGZpcmVGb3JDdXJyZW50Q2hpbGRyZW4/OiBib29sZWFuXG4gIH1cbik6IChydW5EZXRhY2hEaXNwb3NlcnM6IGJvb2xlYW4pID0+IHZvaWQge1xuICBhc3NlcnRJc0Z1bmN0aW9uKHRhcmdldCwgXCJ0YXJnZXRcIilcbiAgYXNzZXJ0SXNGdW5jdGlvbihmbiwgXCJmblwiKVxuXG4gIGNvbnN0IG9wdHMgPSB7XG4gICAgZGVlcDogZmFsc2UsXG4gICAgcnVuRm9yQ3VycmVudENoaWxkcmVuOiB0cnVlLFxuICAgIC4uLm9wdGlvbnMsXG4gIH1cblxuICBjb25zdCBkZXRhY2hEaXNwb3NlcnMgPSBuZXcgV2Vha01hcDxvYmplY3QsICgpID0+IHZvaWQ+KClcblxuICBjb25zdCBydW5EZXRhY2hEaXNwb3NlciA9IChuOiBvYmplY3QpID0+IHtcbiAgICBjb25zdCBkZXRhY2hEaXNwb3NlciA9IGRldGFjaERpc3Bvc2Vycy5nZXQobilcbiAgICBpZiAoZGV0YWNoRGlzcG9zZXIpIHtcbiAgICAgIGRldGFjaERpc3Bvc2Vycy5kZWxldGUobilcbiAgICAgIGRldGFjaERpc3Bvc2VyKClcbiAgICB9XG4gIH1cblxuICBjb25zdCBhZGREZXRhY2hEaXNwb3NlciA9IChuOiBvYmplY3QsIGRpc3Bvc2VyOiAoKCkgPT4gdm9pZCkgfCB2b2lkKSA9PiB7XG4gICAgaWYgKGRpc3Bvc2VyKSB7XG4gICAgICBkZXRhY2hEaXNwb3NlcnMuc2V0KG4sIGRpc3Bvc2VyKVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGdldENoaWxkcmVuT2JqZWN0T3B0cyA9IHsgZGVlcDogb3B0cy5kZWVwIH1cbiAgY29uc3QgZ2V0Q3VycmVudENoaWxkcmVuID0gKCkgPT4ge1xuICAgIGxldCB0ID0gdGFyZ2V0KClcbiAgICBhc3NlcnRUd2Vha2VkT2JqZWN0KHQsIFwidGFyZ2V0KClcIilcblxuICAgIGNvbnN0IGNoaWxkcmVuID0gZ2V0Q2hpbGRyZW5PYmplY3RzKHQsIGdldENoaWxkcmVuT2JqZWN0T3B0cylcblxuICAgIGNvbnN0IHNldCA9IG5ldyBTZXQ8b2JqZWN0PigpXG5cbiAgICBjb25zdCBpdGVyID0gY2hpbGRyZW4udmFsdWVzKClcbiAgICBsZXQgY3VyID0gaXRlci5uZXh0KClcbiAgICB3aGlsZSAoIWN1ci5kb25lKSB7XG4gICAgICBzZXQuYWRkKGN1ci52YWx1ZSlcbiAgICAgIGN1ciA9IGl0ZXIubmV4dCgpXG4gICAgfVxuXG4gICAgcmV0dXJuIHNldFxuICB9XG5cbiAgY29uc3QgY3VycmVudENoaWxkcmVuID0gb3B0cy5ydW5Gb3JDdXJyZW50Q2hpbGRyZW4gPyBuZXcgU2V0PG9iamVjdD4oKSA6IGdldEN1cnJlbnRDaGlsZHJlbigpXG5cbiAgY29uc3QgZGlzcG9zZXIgPSByZWFjdGlvbihcbiAgICAoKSA9PiBnZXRDdXJyZW50Q2hpbGRyZW4oKSxcbiAgICAobmV3Q2hpbGRyZW4pID0+IHtcbiAgICAgIGNvbnN0IGRpc3Bvc2Vyc1RvUnVuOiBvYmplY3RbXSA9IFtdXG5cbiAgICAgIC8vIGZpbmQgZGVhZFxuICAgICAgY29uc3QgY3VycmVudENoaWxkcmVuSXRlciA9IGN1cnJlbnRDaGlsZHJlbi52YWx1ZXMoKVxuICAgICAgbGV0IGN1cnJlbnRDaGlsZHJlbkN1ciA9IGN1cnJlbnRDaGlsZHJlbkl0ZXIubmV4dCgpXG4gICAgICB3aGlsZSAoIWN1cnJlbnRDaGlsZHJlbkN1ci5kb25lKSB7XG4gICAgICAgIGNvbnN0IG4gPSBjdXJyZW50Q2hpbGRyZW5DdXIudmFsdWVcbiAgICAgICAgaWYgKCFuZXdDaGlsZHJlbi5oYXMobikpIHtcbiAgICAgICAgICBjdXJyZW50Q2hpbGRyZW4uZGVsZXRlKG4pXG5cbiAgICAgICAgICAvLyB3ZSBzaG91bGQgcnVuIGl0IGluIGludmVyc2Ugb3JkZXJcbiAgICAgICAgICBkaXNwb3NlcnNUb1J1bi5wdXNoKG4pXG4gICAgICAgIH1cblxuICAgICAgICBjdXJyZW50Q2hpbGRyZW5DdXIgPSBjdXJyZW50Q2hpbGRyZW5JdGVyLm5leHQoKVxuICAgICAgfVxuXG4gICAgICBpZiAoZGlzcG9zZXJzVG9SdW4ubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3IgKGxldCBpID0gZGlzcG9zZXJzVG9SdW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBydW5EZXRhY2hEaXNwb3NlcihkaXNwb3NlcnNUb1J1bltpXSlcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBmaW5kIG5ld1xuICAgICAgY29uc3QgbmV3Q2hpbGRyZW5JdGVyID0gbmV3Q2hpbGRyZW4udmFsdWVzKClcbiAgICAgIGxldCBuZXdDaGlsZHJlbkN1ciA9IG5ld0NoaWxkcmVuSXRlci5uZXh0KClcbiAgICAgIHdoaWxlICghbmV3Q2hpbGRyZW5DdXIuZG9uZSkge1xuICAgICAgICBjb25zdCBuID0gbmV3Q2hpbGRyZW5DdXIudmFsdWVcbiAgICAgICAgaWYgKCFjdXJyZW50Q2hpbGRyZW4uaGFzKG4pKSB7XG4gICAgICAgICAgY3VycmVudENoaWxkcmVuLmFkZChuKVxuXG4gICAgICAgICAgYWRkRGV0YWNoRGlzcG9zZXIobiwgZm4obikpXG4gICAgICAgIH1cblxuICAgICAgICBuZXdDaGlsZHJlbkN1ciA9IG5ld0NoaWxkcmVuSXRlci5uZXh0KClcbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIGZpcmVJbW1lZGlhdGVseTogdHJ1ZSxcbiAgICB9XG4gIClcblxuICByZXR1cm4gKHJ1bkRldGFjaERpc3Bvc2VyczogYm9vbGVhbikgPT4ge1xuICAgIGRpc3Bvc2VyKClcblxuICAgIGlmIChydW5EZXRhY2hEaXNwb3NlcnMpIHtcbiAgICAgIGNvbnN0IGN1cnJlbnRDaGlsZHJlbkl0ZXIgPSBjdXJyZW50Q2hpbGRyZW4udmFsdWVzKClcbiAgICAgIGxldCBjdXJyZW50Q2hpbGRyZW5DdXIgPSBjdXJyZW50Q2hpbGRyZW5JdGVyLm5leHQoKVxuICAgICAgd2hpbGUgKCFjdXJyZW50Q2hpbGRyZW5DdXIuZG9uZSkge1xuICAgICAgICBjb25zdCBuID0gY3VycmVudENoaWxkcmVuQ3VyLnZhbHVlXG4gICAgICAgIHJ1bkRldGFjaERpc3Bvc2VyKG4pXG5cbiAgICAgICAgY3VycmVudENoaWxkcmVuQ3VyID0gY3VycmVudENoaWxkcmVuSXRlci5uZXh0KClcbiAgICAgIH1cbiAgICB9XG4gICAgY3VycmVudENoaWxkcmVuLmNsZWFyKClcbiAgfVxufVxuIiwiaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgZmFzdEdldFBhcmVudCB9IGZyb20gXCIuL3BhdGhcIlxuXG4vKipcbiAqIFJldHVybnMgaWYgdGhlIHRhcmdldCBpcyBhIFwiY2hpbGRcIiBvZiB0aGUgdHJlZSBvZiB0aGUgZ2l2ZW4gXCJwYXJlbnRcIiBvYmplY3QuXG4gKlxuICogQHBhcmFtIGNoaWxkIFRhcmdldCBvYmplY3QuXG4gKiBAcGFyYW0gcGFyZW50IFBhcmVudCBvYmplY3QuXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNDaGlsZE9mUGFyZW50KGNoaWxkOiBvYmplY3QsIHBhcmVudDogb2JqZWN0KTogYm9vbGVhbiB7XG4gIGFzc2VydFR3ZWFrZWRPYmplY3QoY2hpbGQsIFwiY2hpbGRcIilcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChwYXJlbnQsIFwicGFyZW50XCIpXG5cbiAgbGV0IGN1cnJlbnRQYXJlbnQgPSBmYXN0R2V0UGFyZW50KGNoaWxkKVxuICB3aGlsZSAoY3VycmVudFBhcmVudCkge1xuICAgIGlmIChjdXJyZW50UGFyZW50ID09PSBwYXJlbnQpIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgY3VycmVudFBhcmVudCA9IGZhc3RHZXRQYXJlbnQoY3VycmVudFBhcmVudClcbiAgfVxuXG4gIHJldHVybiBmYWxzZVxufVxuXG4vKipcbiAqIFJldHVybnMgaWYgdGhlIHRhcmdldCBpcyBhIFwicGFyZW50XCIgdGhhdCBoYXMgaW4gaXRzIHRyZWUgdGhlIGdpdmVuIFwiY2hpbGRcIiBvYmplY3QuXG4gKlxuICogQHBhcmFtIHBhcmVudCBUYXJnZXQgb2JqZWN0LlxuICogQHBhcmFtIGNoaWxkIENoaWxkIG9iamVjdC5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1BhcmVudE9mQ2hpbGQocGFyZW50OiBvYmplY3QsIGNoaWxkOiBvYmplY3QpOiBib29sZWFuIHtcbiAgcmV0dXJuIGlzQ2hpbGRPZlBhcmVudChjaGlsZCwgcGFyZW50KVxufVxuIiwibGV0IHR5cGVDaGVja2luZ0FsbG93ZWQgPSB0cnVlXG5cbmV4cG9ydCBmdW5jdGlvbiB3aXRob3V0VHlwZUNoZWNraW5nKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gIGxldCBvbGRUeXBlQ2hlY2tpbmdBbGxvd2VkID0gdHlwZUNoZWNraW5nQWxsb3dlZFxuICB0eXBlQ2hlY2tpbmdBbGxvd2VkID0gZmFsc2VcblxuICB0cnkge1xuICAgIGZuKClcbiAgfSBmaW5hbGx5IHtcbiAgICB0eXBlQ2hlY2tpbmdBbGxvd2VkID0gb2xkVHlwZUNoZWNraW5nQWxsb3dlZFxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1R5cGVDaGVja2luZ0FsbG93ZWQoKSB7XG4gIHJldHVybiB0eXBlQ2hlY2tpbmdBbGxvd2VkXG59XG4iLCIvKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZW51bSBTbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eSB7XG4gIEFycmF5LFxuICBGcm96ZW4sXG4gIE1vZGVsLFxuICBQbGFpbk9iamVjdCxcbn1cbiIsImltcG9ydCB7IHJ1blR5cGVDaGVja2luZ0FmdGVyQ2hhbmdlIH0gZnJvbSBcIi4uL3R3ZWFrZXIvdHlwZUNoZWNraW5nXCJcclxuaW1wb3J0IHsgd2l0aG91dFR5cGVDaGVja2luZyB9IGZyb20gXCIuLi90d2Vha2VyL3dpdGhvdXRUeXBlQ2hlY2tpbmdcIlxyXG5pbXBvcnQgeyBpc0FycmF5IH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgTW9kZWxQb29sIH0gZnJvbSBcIi4uL3V0aWxzL01vZGVsUG9vbFwiXHJcbmltcG9ydCB7IHNldElmRGlmZmVyZW50IH0gZnJvbSBcIi4uL3V0aWxzL3NldElmRGlmZmVyZW50XCJcclxuaW1wb3J0IHR5cGUgeyBTbmFwc2hvdEluT2ZPYmplY3QgfSBmcm9tIFwiLi9TbmFwc2hvdE9mXCJcclxuaW1wb3J0IHsgU25hcHNob3R0ZXJBbmRSZWNvbmNpbGVyUHJpb3JpdHkgfSBmcm9tIFwiLi9TbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eVwiXHJcbmltcG9ydCB7IGZyb21TbmFwc2hvdCB9IGZyb20gXCIuL2Zyb21TbmFwc2hvdFwiXHJcbmltcG9ydCB7IGdldFNuYXBzaG90IH0gZnJvbSBcIi4vZ2V0U25hcHNob3RcIlxyXG5pbXBvcnQgeyBkZXRhY2hJZk5lZWRlZCwgcmVjb25jaWxlU25hcHNob3QsIHJlZ2lzdGVyUmVjb25jaWxlciB9IGZyb20gXCIuL3JlY29uY2lsZVNuYXBzaG90XCJcclxuXHJcbmZ1bmN0aW9uIHJlY29uY2lsZUFycmF5U25hcHNob3QoXHJcbiAgdmFsdWU6IGFueSxcclxuICBzbjogU25hcHNob3RJbk9mT2JqZWN0PGFueVtdPixcclxuICBtb2RlbFBvb2w6IE1vZGVsUG9vbFxyXG4pOiBhbnlbXSB7XHJcbiAgaWYgKCFpc0FycmF5KHZhbHVlKSkge1xyXG4gICAgLy8gbm8gcmVjb25jaWxpYXRpb24gcG9zc2libGVcclxuICAgIHJldHVybiBmcm9tU25hcHNob3Qoc24pXHJcbiAgfVxyXG5cclxuICBjb25zdCBzbmFwc2hvdEJlZm9yZUNoYW5nZXMgPSBnZXRTbmFwc2hvdCh2YWx1ZSlcclxuXHJcbiAgd2l0aG91dFR5cGVDaGVja2luZygoKSA9PiB7XHJcbiAgICAvLyByZW1vdmUgZXhjZXNzIGl0ZW1zXHJcbiAgICBpZiAodmFsdWUubGVuZ3RoID4gc24ubGVuZ3RoKSB7XHJcbiAgICAgIHZhbHVlLnNwbGljZShzbi5sZW5ndGgsIHZhbHVlLmxlbmd0aCAtIHNuLmxlbmd0aClcclxuICAgIH1cclxuXHJcbiAgICAvLyByZWNvbmNpbGUgcHJlc2VudCBpdGVtc1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKykge1xyXG4gICAgICBjb25zdCBvbGRWYWx1ZSA9IHZhbHVlW2ldXHJcbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gcmVjb25jaWxlU25hcHNob3Qob2xkVmFsdWUsIHNuW2ldLCBtb2RlbFBvb2wsIHZhbHVlKVxyXG5cclxuICAgICAgZGV0YWNoSWZOZWVkZWQobmV3VmFsdWUsIG9sZFZhbHVlLCBtb2RlbFBvb2wpXHJcblxyXG4gICAgICBzZXRJZkRpZmZlcmVudCh2YWx1ZSwgaSwgbmV3VmFsdWUpXHJcbiAgICB9XHJcblxyXG4gICAgLy8gYWRkIGV4Y2VzcyBpdGVtc1xyXG4gICAgZm9yIChsZXQgaSA9IHZhbHVlLmxlbmd0aDsgaSA8IHNuLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIHZhbHVlLnB1c2gocmVjb25jaWxlU25hcHNob3QodW5kZWZpbmVkLCBzbltpXSwgbW9kZWxQb29sLCB2YWx1ZSkpXHJcbiAgICB9XHJcbiAgfSlcclxuXHJcbiAgcnVuVHlwZUNoZWNraW5nQWZ0ZXJDaGFuZ2UodmFsdWUsIHVuZGVmaW5lZCwgc25hcHNob3RCZWZvcmVDaGFuZ2VzKVxyXG5cclxuICByZXR1cm4gdmFsdWVcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyQXJyYXlTbmFwc2hvdFJlY29uY2lsZXIoKSB7XHJcbiAgcmVnaXN0ZXJSZWNvbmNpbGVyKFNuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5LkFycmF5LCAodmFsdWUsIHNuLCBtb2RlbFBvb2wpID0+IHtcclxuICAgIGlmIChpc0FycmF5KHNuKSkge1xyXG4gICAgICByZXR1cm4gcmVjb25jaWxlQXJyYXlTbmFwc2hvdCh2YWx1ZSwgc24sIG1vZGVsUG9vbClcclxuICAgIH1cclxuICAgIHJldHVybiB1bmRlZmluZWRcclxuICB9KVxyXG59XHJcbiIsImltcG9ydCB7IGdldEdsb2JhbENvbmZpZyB9IGZyb20gXCIuLi9nbG9iYWxDb25maWdcIlxyXG5pbXBvcnQgdHlwZSB7IFNuYXBzaG90SW5PZkZyb3plbiB9IGZyb20gXCIuLi9zbmFwc2hvdFwiXHJcbmltcG9ydCB7IHR3ZWFrIH0gZnJvbSBcIi4uL3R3ZWFrZXIvdHdlYWtcIlxyXG5pbXBvcnQgeyBmYWlsdXJlLCBpbkRldk1vZGUsIGlzUGxhaW5PYmplY3QsIGlzUHJpbWl0aXZlIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuXHJcbi8qKlxyXG4gKiBTaG91bGQgZnJlZXplIGFuZCBwbGFpbiBqc29uIGNoZWNrcyBiZSBkb25lIHdoZW4gY3JlYXRpbmcgdGhlIGZyb3plbiBvYmplY3Q/XHJcbiAqL1xyXG5leHBvcnQgZW51bSBGcm96ZW5DaGVja01vZGUge1xyXG4gIC8qKiBPbmx5IHdoZW4gaW4gZGV2IG1vZGUgKi9cclxuICBEZXZNb2RlT25seSA9IFwiZGV2TW9kZU9ubHlcIixcclxuICAvKiogQWx3YXlzICovXHJcbiAgT24gPSBcIm9uXCIsXHJcbiAgLyoqIE5ldmVyICovXHJcbiAgT2ZmID0gXCJvZmZcIixcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpZ25vcmVcclxuICovXHJcbmV4cG9ydCBjb25zdCBmcm96ZW5LZXkgPSBcIiRmcm96ZW5cIlxyXG5cclxuLyoqXHJcbiAqIEEgY2xhc3MgdGhhdCBjb250YWlucyBmcm96ZW4gZGF0YS5cclxuICogVXNlIGBmcm96ZW5gIHRvIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzLlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgRGF0YSB0eXBlLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEZyb3plbjxUPiB7XHJcbiAgLyoqXHJcbiAgICogRnJvemVuIGRhdGEsIGRlZXBseSBpbW11dGFibGUuXHJcbiAgICovXHJcbiAgcmVhZG9ubHkgZGF0YTogVFxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIEZyb3plbi5cclxuICAgKiBEbyBub3QgdXNlIGRpcmVjdGx5LCB1c2UgYGZyb3plbmAgaW5zdGVhZC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBkYXRhVG9GcmVlemVcclxuICAgKiBAcGFyYW0gY2hlY2tNb2RlXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoZGF0YVRvRnJlZXplOiBULCBjaGVja01vZGU6IEZyb3plbkNoZWNrTW9kZSA9IEZyb3plbkNoZWNrTW9kZS5EZXZNb2RlT25seSkge1xyXG4gICAgY29uc3QgY2hlY2sgPVxyXG4gICAgICBjaGVja01vZGUgPT09IEZyb3plbkNoZWNrTW9kZS5PbiB8fCAoaW5EZXZNb2RlICYmIGNoZWNrTW9kZSA9PT0gRnJvemVuQ2hlY2tNb2RlLkRldk1vZGVPbmx5KVxyXG4gICAgaWYgKGNoZWNrKSB7XHJcbiAgICAgIGNoZWNrRGF0YUlzU2VyaWFsaXphYmxlQW5kRnJlZXplKGRhdGFUb0ZyZWV6ZSlcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmRhdGEgPSBkYXRhVG9GcmVlemVcclxuXHJcbiAgICBpZiAoY2hlY2spIHtcclxuICAgICAgT2JqZWN0LmZyZWV6ZSh0aGlzLmRhdGEpXHJcbiAgICB9XHJcblxyXG4gICAgdHdlYWsodGhpcywgdW5kZWZpbmVkKVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE1hcmtzIHNvbWUgZGF0YSBhcyBmcm96ZW4uIEZyb3plbiBkYXRhIGJlY29tZXMgaW1tdXRhYmxlIChhdCBsZWFzdCBpbiBkZXYgbW9kZSksIGFuZCBpcyBub3QgZW5oYW5jZWRcclxuICogd2l0aCBjYXBhYmlsaXRpZXMgc3VjaCBhcyBnZXR0aW5nIHRoZSBwYXJlbnQgb2YgdGhlIG9iamVjdHMgKGV4Y2VwdCBmb3IgdGhlIHJvb3Qgb2JqZWN0KSwgaXQgaXMgbm90XHJcbiAqIG1hZGUgZGVlcGx5IG9ic2VydmFibGUgKHRob3VnaCB0aGUgcm9vdCBvYmplY3QgaXMgb2JzZXJ2YWJsZSBieSByZWZlcmVuY2UpLCBldGMuXHJcbiAqIE9uIHRoZSBvdGhlciBoYW5kLCB0aGlzIG1lYW5zIGl0IHdpbGwgYmUgbXVjaCBmYXN0ZXIgdG8gY3JlYXRlL2FjY2Vzcy4gVXNlIHRoaXMgZm9yIGJpZyBkYXRhIHBpZWNlc1xyXG4gKiB0aGF0IGFyZSB1bmxpa2VseSB0byBjaGFuZ2UgdW5sZXNzIGFsbCBvZiB0aGVtIGNoYW5nZSAoZm9yIGV4YW1wbGUgbGlzdHMgb2YgcG9pbnRzIGZvciBhIHBvbHlnb24sIGV0YykuXHJcbiAqXHJcbiAqIE5vdGUgdGhhdCBkYXRhIHBhc3NlZCB0byBmcm96ZW4gbXVzdCBiZSBzZXJpYWxpemFibGUgdG8gSlNPTiwgdGhpcyBpczpcclxuICogLSBwcmltaXRpdmUsIHBsYWluIG9iamVjdCwgb3IgYXJyYXlcclxuICogLSB3aXRob3V0IGN5Y2xlc1xyXG4gKlxyXG4gKiBAcGFyYW0gZGF0YVxyXG4gKiBAcGFyYW0gY2hlY2tNb2RlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZnJvemVuPFQ+KFxyXG4gIGRhdGE6IFQsXHJcbiAgY2hlY2tNb2RlOiBGcm96ZW5DaGVja01vZGUgPSBGcm96ZW5DaGVja01vZGUuRGV2TW9kZU9ubHlcclxuKTogRnJvemVuPFQ+IHtcclxuICByZXR1cm4gbmV3IEZyb3plbjxUPihkYXRhLCBjaGVja01vZGUpXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNoZWNrRGF0YUlzU2VyaWFsaXphYmxlQW5kRnJlZXplKGRhdGE6IGFueSkge1xyXG4gIC8vIFRPRE86IGRldGVjdCBjeWNsZXMgYW5kIHRocm93IGlmIHByZXNlbnQ/XHJcblxyXG4gIC8vIHByaW1pdGl2ZXMgYXJlIG9rXHJcbiAgaWYgKGlzUHJpbWl0aXZlKGRhdGEpKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7XHJcbiAgICBjb25zdCBhcnJMZW4gPSBkYXRhLmxlbmd0aFxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJMZW47IGkrKykge1xyXG4gICAgICBjb25zdCB2ID0gZGF0YVtpXVxyXG4gICAgICBpZiAodiA9PT0gdW5kZWZpbmVkICYmICFnZXRHbG9iYWxDb25maWcoKS5hbGxvd1VuZGVmaW5lZEFycmF5RWxlbWVudHMpIHtcclxuICAgICAgICB0aHJvdyBmYWlsdXJlKFxyXG4gICAgICAgICAgXCJ1bmRlZmluZWQgaXMgbm90IHN1cHBvcnRlZCBpbnNpZGUgYXJyYXlzIHNpbmNlIGl0IGlzIG5vdCBzZXJpYWxpemFibGUgaW4gSlNPTiwgY29uc2lkZXIgdXNpbmcgbnVsbCBpbnN0ZWFkXCJcclxuICAgICAgICApXHJcbiAgICAgIH1cclxuICAgICAgY2hlY2tEYXRhSXNTZXJpYWxpemFibGVBbmRGcmVlemUodilcclxuICAgIH1cclxuICAgIE9iamVjdC5mcmVlemUoZGF0YSlcclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgaWYgKGlzUGxhaW5PYmplY3QoZGF0YSkpIHtcclxuICAgIGNvbnN0IGRhdGFLZXlzID0gT2JqZWN0LmtleXMoZGF0YSlcclxuICAgIGNvbnN0IGRhdGFLZXlzTGVuID0gZGF0YUtleXMubGVuZ3RoXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGFLZXlzTGVuOyBpKyspIHtcclxuICAgICAgY29uc3QgayA9IGRhdGFLZXlzW2ldXHJcbiAgICAgIGNvbnN0IHYgPSBkYXRhW2tdXHJcblxyXG4gICAgICBjaGVja0RhdGFJc1NlcmlhbGl6YWJsZUFuZEZyZWV6ZShrKVxyXG4gICAgICBjaGVja0RhdGFJc1NlcmlhbGl6YWJsZUFuZEZyZWV6ZSh2KVxyXG4gICAgfVxyXG4gICAgT2JqZWN0LmZyZWV6ZShkYXRhKVxyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG5cclxuICB0aHJvdyBmYWlsdXJlKGBmcm96ZW4gZGF0YSBtdXN0IGJlIHBsYWlubHkgc2VyaWFsaXphYmxlIHRvIEpTT04sIGJ1dCAke2RhdGF9IGlzIG5vdGApXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICpcclxuICogQ2hlY2tzIGlmIGFuIHNuYXBzaG90IGlzIGFuIHNuYXBzaG90IGZvciBhIGZyb3plbiBkYXRhLlxyXG4gKlxyXG4gKiBAcGFyYW0gc25hcHNob3RcclxuICogQHJldHVybnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc0Zyb3plblNuYXBzaG90KHNuYXBzaG90OiB1bmtub3duKTogc25hcHNob3QgaXMgU25hcHNob3RJbk9mRnJvemVuPEZyb3plbjxhbnk+PiB7XHJcbiAgcmV0dXJuIGlzUGxhaW5PYmplY3Qoc25hcHNob3QpICYmIGZyb3plbktleSBpbiBzbmFwc2hvdFxyXG59XHJcbiIsImltcG9ydCB7IEZyb3plbiwgZnJvemVuLCBpc0Zyb3plblNuYXBzaG90IH0gZnJvbSBcIi4uL2Zyb3plbi9Gcm96ZW5cIlxuaW1wb3J0IHsgcmVnaXN0ZXJSZWNvbmNpbGVyIH0gZnJvbSBcIi4vcmVjb25jaWxlU25hcHNob3RcIlxuaW1wb3J0IHR5cGUgeyBTbmFwc2hvdEluT2ZGcm96ZW4gfSBmcm9tIFwiLi9TbmFwc2hvdE9mXCJcbmltcG9ydCB7IFNuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5IH0gZnJvbSBcIi4vU25hcHNob3R0ZXJBbmRSZWNvbmNpbGVyUHJpb3JpdHlcIlxuXG5mdW5jdGlvbiByZWNvbmNpbGVGcm96ZW5TbmFwc2hvdCh2YWx1ZTogYW55LCBzbjogU25hcHNob3RJbk9mRnJvemVuPEZyb3plbjxhbnk+Pik6IEZyb3plbjxhbnk+IHtcbiAgLy8gcmVjb25jaWxpYXRpb24gaXMgb25seSBwb3NzaWJsZSBpZiB0aGUgdGFyZ2V0IGlzIGEgRnJvemVuIGluc3RhbmNlIHdpdGggdGhlIHNhbWUgZGF0YSAoYnkgcmVmKVxuICAvLyBpbiB0aGVvcnkgd2UgY291bGQgY29tcGFyZSB0aGUgSlNPTiByZXByZXNlbnRhdGlvbiBvZiBib3RoIGRhdGFzIG9yIGRvIGEgZGVlcCBjb21wYXJpc29uLCBidXQgdGhhdCdkIGJlIHRvbyBzbG93XG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEZyb3plbiAmJiB2YWx1ZS5kYXRhID09PSBzbi5kYXRhKSB7XG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cbiAgcmV0dXJuIGZyb3plbihzbi5kYXRhKVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJGcm96ZW5TbmFwc2hvdFJlY29uY2lsZXIoKSB7XG4gIHJlZ2lzdGVyUmVjb25jaWxlcihTbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eS5Gcm96ZW4sICh2YWx1ZSwgc24pID0+IHtcbiAgICBpZiAoaXNGcm96ZW5TbmFwc2hvdChzbikpIHtcbiAgICAgIHJldHVybiByZWNvbmNpbGVGcm96ZW5TbmFwc2hvdCh2YWx1ZSwgc24pXG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfSlcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxuLy8gZG8gbm90IGVkaXQgLmpzIGZpbGVzIGRpcmVjdGx5IC0gZWRpdCBzcmMvaW5kZXguanN0XG5cblxuICB2YXIgZW52SGFzQmlnSW50NjRBcnJheSA9IHR5cGVvZiBCaWdJbnQ2NEFycmF5ICE9PSAndW5kZWZpbmVkJztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGVxdWFsKGEsIGIpIHtcbiAgaWYgKGEgPT09IGIpIHJldHVybiB0cnVlO1xuXG4gIGlmIChhICYmIGIgJiYgdHlwZW9mIGEgPT0gJ29iamVjdCcgJiYgdHlwZW9mIGIgPT0gJ29iamVjdCcpIHtcbiAgICBpZiAoYS5jb25zdHJ1Y3RvciAhPT0gYi5jb25zdHJ1Y3RvcikgcmV0dXJuIGZhbHNlO1xuXG4gICAgdmFyIGxlbmd0aCwgaSwga2V5cztcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhKSkge1xuICAgICAgbGVuZ3RoID0gYS5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoICE9IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgICBmb3IgKGkgPSBsZW5ndGg7IGktLSAhPT0gMDspXG4gICAgICAgIGlmICghZXF1YWwoYVtpXSwgYltpXSkpIHJldHVybiBmYWxzZTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuXG4gICAgaWYgKChhIGluc3RhbmNlb2YgTWFwKSAmJiAoYiBpbnN0YW5jZW9mIE1hcCkpIHtcbiAgICAgIGlmIChhLnNpemUgIT09IGIuc2l6ZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgZm9yIChpIG9mIGEuZW50cmllcygpKVxuICAgICAgICBpZiAoIWIuaGFzKGlbMF0pKSByZXR1cm4gZmFsc2U7XG4gICAgICBmb3IgKGkgb2YgYS5lbnRyaWVzKCkpXG4gICAgICAgIGlmICghZXF1YWwoaVsxXSwgYi5nZXQoaVswXSkpKSByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoKGEgaW5zdGFuY2VvZiBTZXQpICYmIChiIGluc3RhbmNlb2YgU2V0KSkge1xuICAgICAgaWYgKGEuc2l6ZSAhPT0gYi5zaXplKSByZXR1cm4gZmFsc2U7XG4gICAgICBmb3IgKGkgb2YgYS5lbnRyaWVzKCkpXG4gICAgICAgIGlmICghYi5oYXMoaVswXSkpIHJldHVybiBmYWxzZTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoYSkgJiYgQXJyYXlCdWZmZXIuaXNWaWV3KGIpKSB7XG4gICAgICBsZW5ndGggPSBhLmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGggIT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgIGZvciAoaSA9IGxlbmd0aDsgaS0tICE9PSAwOylcbiAgICAgICAgaWYgKGFbaV0gIT09IGJbaV0pIHJldHVybiBmYWxzZTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuXG4gICAgaWYgKGEuY29uc3RydWN0b3IgPT09IFJlZ0V4cCkgcmV0dXJuIGEuc291cmNlID09PSBiLnNvdXJjZSAmJiBhLmZsYWdzID09PSBiLmZsYWdzO1xuICAgIGlmIChhLnZhbHVlT2YgIT09IE9iamVjdC5wcm90b3R5cGUudmFsdWVPZikgcmV0dXJuIGEudmFsdWVPZigpID09PSBiLnZhbHVlT2YoKTtcbiAgICBpZiAoYS50b1N0cmluZyAhPT0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZykgcmV0dXJuIGEudG9TdHJpbmcoKSA9PT0gYi50b1N0cmluZygpO1xuXG4gICAga2V5cyA9IE9iamVjdC5rZXlzKGEpO1xuICAgIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIGlmIChsZW5ndGggIT09IE9iamVjdC5rZXlzKGIpLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yIChpID0gbGVuZ3RoOyBpLS0gIT09IDA7KVxuICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwga2V5c1tpXSkpIHJldHVybiBmYWxzZTtcblxuICAgIGZvciAoaSA9IGxlbmd0aDsgaS0tICE9PSAwOykge1xuICAgICAgdmFyIGtleSA9IGtleXNbaV07XG5cbiAgICAgIGlmICghZXF1YWwoYVtrZXldLCBiW2tleV0pKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvLyB0cnVlIGlmIGJvdGggTmFOLCBmYWxzZSBvdGhlcndpc2VcbiAgcmV0dXJuIGEhPT1hICYmIGIhPT1iO1xufTtcbiIsImltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcbmltcG9ydCB7IGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUgfSBmcm9tIFwiLi4vbW9kZWwvZ2V0TW9kZWxNZXRhZGF0YVwiXG5pbXBvcnQgeyBtb2RlbElkS2V5LCBtb2RlbFR5cGVLZXkgfSBmcm9tIFwiLi4vbW9kZWwvbWV0YWRhdGFcIlxuaW1wb3J0IHsgaXNNb2RlbCwgaXNNb2RlbFNuYXBzaG90IH0gZnJvbSBcIi4uL21vZGVsL3V0aWxzXCJcbmltcG9ydCB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcbmltcG9ydCB7IGdldE1vZGVsSW5mb0Zvck5hbWUgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxJbmZvXCJcbmltcG9ydCB7IGRhdGFPYmplY3RQYXJlbnQgfSBmcm9tIFwiLi4vcGFyZW50L2NvcmVcIlxuaW1wb3J0IHtcbiAgZ2V0RGVlcE9iamVjdENoaWxkcmVuLFxuICByZWdpc3RlckRlZXBPYmplY3RDaGlsZHJlbkV4dGVuc2lvbixcbn0gZnJvbSBcIi4uL3BhcmVudC9jb3JlT2JqZWN0Q2hpbGRyZW5cIlxuXG5mdW5jdGlvbiBieU1vZGVsVHlwZUFuZElkS2V5KG1vZGVsVHlwZTogc3RyaW5nLCBtb2RlbElkOiBzdHJpbmcpIHtcbiAgcmV0dXJuIG1vZGVsVHlwZSArIFwiIFwiICsgbW9kZWxJZFxufVxuXG5leHBvcnQgY2xhc3MgTW9kZWxQb29sIHtcbiAgcHJpdmF0ZSBwb29sOiBSZWFkb25seU1hcDxzdHJpbmcsIEFueU1vZGVsPlxuXG4gIGNvbnN0cnVjdG9yKHJvb3Q6IG9iamVjdCkge1xuICAgIC8vIG1ha2Ugc3VyZSB3ZSBkb24ndCB1c2UgdGhlIHN1Yi1kYXRhICQgb2JqZWN0XG4gICAgcm9vdCA9IGRhdGFPYmplY3RQYXJlbnQuZ2V0KHJvb3QpID8/IHJvb3RcblxuICAgIHRoaXMucG9vbCA9IGdldERlZXBDaGlsZHJlbk1vZGVscyhnZXREZWVwT2JqZWN0Q2hpbGRyZW4ocm9vdCkpXG4gIH1cblxuICBmaW5kTW9kZWxCeVR5cGVBbmRJZChtb2RlbFR5cGU6IHN0cmluZywgbW9kZWxJZDogc3RyaW5nIHwgdW5kZWZpbmVkKTogQW55TW9kZWwgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBtb2RlbElkID8gdGhpcy5wb29sLmdldChieU1vZGVsVHlwZUFuZElkS2V5KG1vZGVsVHlwZSwgbW9kZWxJZCkpIDogdW5kZWZpbmVkXG4gIH1cblxuICBmaW5kTW9kZWxGb3JTbmFwc2hvdChzbjogYW55KTogQW55TW9kZWwgfCB1bmRlZmluZWQge1xuICAgIGlmICghaXNNb2RlbFNuYXBzaG90KHNuKSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZFxuICAgIH1cblxuICAgIGNvbnN0IG1vZGVsVHlwZSA9IHNuW21vZGVsVHlwZUtleV1cbiAgICBjb25zdCBtb2RlbEluZm8gPSBnZXRNb2RlbEluZm9Gb3JOYW1lKG1vZGVsVHlwZSkhXG4gICAgY29uc3QgbW9kZWxJZFByb3BlcnR5TmFtZSA9IGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUobW9kZWxJbmZvLmNsYXNzIGFzIE1vZGVsQ2xhc3M8QW55TW9kZWw+KVxuXG4gICAgcmV0dXJuIG1vZGVsSWRQcm9wZXJ0eU5hbWVcbiAgICAgID8gdGhpcy5maW5kTW9kZWxCeVR5cGVBbmRJZChtb2RlbFR5cGUsIChzbiBhcyBhbnkpW21vZGVsSWRQcm9wZXJ0eU5hbWVdKVxuICAgICAgOiB1bmRlZmluZWRcbiAgfVxufVxuXG5jb25zdCBnZXREZWVwQ2hpbGRyZW5Nb2RlbHMgPSByZWdpc3RlckRlZXBPYmplY3RDaGlsZHJlbkV4dGVuc2lvbjxNYXA8c3RyaW5nLCBBbnlNb2RlbD4+KHtcbiAgaW5pdERhdGEoKSB7XG4gICAgcmV0dXJuIG5ldyBNYXAoKVxuICB9LFxuXG4gIGFkZE5vZGUobm9kZSwgZGF0YSkge1xuICAgIGlmIChpc01vZGVsKG5vZGUpKSB7XG4gICAgICBjb25zdCBpZCA9IG5vZGVbbW9kZWxJZEtleV1cbiAgICAgIGlmIChpZCkge1xuICAgICAgICBkYXRhLnNldChieU1vZGVsVHlwZUFuZElkS2V5KG5vZGVbbW9kZWxUeXBlS2V5XSwgaWQpLCBub2RlKVxuICAgICAgfVxuICAgIH1cbiAgfSxcbn0pXG4iLCJpbXBvcnQgeyBpc09ic2VydmFibGVPYmplY3QgfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7IEJ1aWx0SW5BY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9uL2J1aWx0SW5BY3Rpb25zXCJcclxuaW1wb3J0IHsgQWN0aW9uQ29udGV4dEFjdGlvblR5cGUgfSBmcm9tIFwiLi4vYWN0aW9uL2NvbnRleHRcIlxyXG5pbXBvcnQgeyB3cmFwSW5BY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9uL3dyYXBJbkFjdGlvblwiXHJcbmltcG9ydCB7IGlzRnJvemVuU25hcHNob3QgfSBmcm9tIFwiLi4vZnJvemVuL0Zyb3plblwiXHJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcclxuaW1wb3J0IHsgZ2V0TW9kZWxJZFByb3BlcnR5TmFtZSB9IGZyb20gXCIuLi9tb2RlbC9nZXRNb2RlbE1ldGFkYXRhXCJcclxuaW1wb3J0IHsgbW9kZWxJZEtleSwgbW9kZWxUeXBlS2V5IH0gZnJvbSBcIi4uL21vZGVsL21ldGFkYXRhXCJcclxuaW1wb3J0IHsgaXNNb2RlbCwgaXNNb2RlbFNuYXBzaG90IH0gZnJvbSBcIi4uL21vZGVsL3V0aWxzXCJcclxuaW1wb3J0IHR5cGUgeyBNb2RlbENsYXNzIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL0Jhc2VNb2RlbFNoYXJlZFwiXHJcbmltcG9ydCB7IGdldE1vZGVsSW5mb0Zvck5hbWUsIG1vZGVsSW5mb0J5Q2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxJbmZvXCJcclxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxyXG5pbXBvcnQge1xyXG4gIGFzc2VydElzT2JqZWN0LFxyXG4gIGZhaWx1cmUsXHJcbiAgaW5EZXZNb2RlLFxyXG4gIGlzQXJyYXksXHJcbiAgaXNNYXAsXHJcbiAgaXNQbGFpbk9iamVjdCxcclxuICBpc1NldCxcclxuICBsYXp5LFxyXG59IGZyb20gXCIuLi91dGlsc1wiXHJcbmltcG9ydCB7IE1vZGVsUG9vbCB9IGZyb20gXCIuLi91dGlscy9Nb2RlbFBvb2xcIlxyXG5pbXBvcnQgeyByZWNvbmNpbGVTbmFwc2hvdCB9IGZyb20gXCIuL3JlY29uY2lsZVNuYXBzaG90XCJcclxuaW1wb3J0IHR5cGUgeyBTbmFwc2hvdEluT2YsIFNuYXBzaG90T3V0T2YgfSBmcm9tIFwiLi9TbmFwc2hvdE9mXCJcclxuXHJcbi8qKlxyXG4gKiBBcHBsaWVzIGEgZnVsbCBzbmFwc2hvdCBvdmVyIGFuIG9iamVjdCwgcmVjb25jaWxpbmcgaXQgd2l0aCB0aGUgY3VycmVudCBjb250ZW50cyBvZiB0aGUgb2JqZWN0LlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgT2JqZWN0IHR5cGUuXHJcbiAqIEBwYXJhbSBub2RlIFRhcmdldCBvYmplY3QgKG1vZGVsIG9iamVjdCwgb2JqZWN0IG9yIGFycmF5KS5cclxuICogQHBhcmFtIHNuYXBzaG90IFNuYXBzaG90IHRvIGFwcGx5LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5U25hcHNob3Q8VCBleHRlbmRzIG9iamVjdD4obm9kZTogVCwgc25hcHNob3Q6IFNuYXBzaG90SW5PZjxUPik6IHZvaWRcclxuXHJcbi8qKlxyXG4gKiBBcHBsaWVzIGEgZnVsbCBzbmFwc2hvdCBvdmVyIGFuIG9iamVjdCwgcmVjb25jaWxpbmcgaXQgd2l0aCB0aGUgY3VycmVudCBjb250ZW50cyBvZiB0aGUgb2JqZWN0LlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgT2JqZWN0IHR5cGUuXHJcbiAqIEBwYXJhbSBub2RlIFRhcmdldCBvYmplY3QgKG1vZGVsIG9iamVjdCwgb2JqZWN0IG9yIGFycmF5KS5cclxuICogQHBhcmFtIHNuYXBzaG90IFNuYXBzaG90IHRvIGFwcGx5LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5U25hcHNob3Q8VCBleHRlbmRzIG9iamVjdD4obm9kZTogVCwgc25hcHNob3Q6IFNuYXBzaG90T3V0T2Y8VD4pOiB2b2lkXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlTbmFwc2hvdChub2RlOiBvYmplY3QsIHNuYXBzaG90OiB1bmtub3duKTogdm9pZCB7XHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChub2RlLCBcIm5vZGVcIilcclxuICBhc3NlcnRJc09iamVjdChzbmFwc2hvdCwgXCJzbmFwc2hvdFwiKVxyXG5cclxuICB3cmFwcGVkSW50ZXJuYWxBcHBseVNuYXBzaG90KCkuY2FsbChub2RlLCBzbmFwc2hvdClcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGludGVybmFsQXBwbHlTbmFwc2hvdDxUIGV4dGVuZHMgb2JqZWN0PihcclxuICB0aGlzOiBULFxyXG4gIHNuOiBTbmFwc2hvdEluT2Y8VD4gfCBTbmFwc2hvdE91dE9mPFQ+XHJcbik6IHZvaWQge1xyXG4gIGNvbnN0IG9iaiA9IHRoaXNcclxuXHJcbiAgY29uc3QgcmVjb25jaWxlID0gKCkgPT4ge1xyXG4gICAgY29uc3QgbW9kZWxQb29sID0gbmV3IE1vZGVsUG9vbChvYmopXHJcbiAgICBjb25zdCByZXQgPSByZWNvbmNpbGVTbmFwc2hvdChvYmosIHNuLCBtb2RlbFBvb2wsIHVuZGVmaW5lZClcclxuXHJcbiAgICBpZiAoaW5EZXZNb2RlKSB7XHJcbiAgICAgIGlmIChyZXQgIT09IG9iaikge1xyXG4gICAgICAgIHRocm93IGZhaWx1cmUoXCJhc3NlcnRpb24gZmFpbGVkOiByZWNvbmNpbGVkIG9iamVjdCBoYXMgdG8gYmUgdGhlIHNhbWVcIilcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgaWYgKGlzQXJyYXkoc24pKSB7XHJcbiAgICBpZiAoIWlzQXJyYXkob2JqKSkge1xyXG4gICAgICB0aHJvdyBmYWlsdXJlKFwiaWYgdGhlIHNuYXBzaG90IGlzIGFuIGFycmF5IHRoZSB0YXJnZXQgbXVzdCBiZSBhbiBhcnJheSB0b29cIilcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gcmVjb25jaWxlKClcclxuICB9XHJcblxyXG4gIGlmIChpc0Zyb3plblNuYXBzaG90KHNuKSkge1xyXG4gICAgdGhyb3cgZmFpbHVyZShcImFwcGx5U25hcHNob3QgY2Fubm90IGJlIHVzZWQgb3ZlciBmcm96ZW4gb2JqZWN0c1wiKVxyXG4gIH1cclxuXHJcbiAgLy8gYWRhcHQgc25hcHNob3QgdG8gdGFyZ2V0IG1vZGVsIGlmIHBvc3NpYmxlXHJcbiAgaWYgKGlzUGxhaW5PYmplY3Qoc24pICYmIChzbiBhcyBhbnkpW21vZGVsVHlwZUtleV0gPT09IHVuZGVmaW5lZCAmJiBpc01vZGVsKG9iaikpIHtcclxuICAgIGNvbnN0IG1vZGVsSW5mbyA9IG1vZGVsSW5mb0J5Q2xhc3MuZ2V0KChvYmogYXMgYW55KS5jb25zdHJ1Y3RvcikhXHJcbiAgICBzbiA9IHsgLi4uc24sIFttb2RlbFR5cGVLZXldOiBtb2RlbEluZm8ubmFtZSB9XHJcbiAgfVxyXG5cclxuICBpZiAoaXNNb2RlbFNuYXBzaG90KHNuKSkge1xyXG4gICAgY29uc3QgdHlwZSA9IHNuW21vZGVsVHlwZUtleV1cclxuXHJcbiAgICBjb25zdCBtb2RlbEluZm8gPSBnZXRNb2RlbEluZm9Gb3JOYW1lKHR5cGUpXHJcbiAgICBpZiAoIW1vZGVsSW5mbykge1xyXG4gICAgICB0aHJvdyBmYWlsdXJlKGBtb2RlbCB3aXRoIG5hbWUgXCIke3R5cGV9XCIgbm90IGZvdW5kIGluIHRoZSByZWdpc3RyeWApXHJcbiAgICB9XHJcblxyXG4gICAgLy8gd2UgZG9uJ3QgY2hlY2sgYnkgYWN0dWFsIGluc3RhbmNlIHNpbmNlIHRoZSBjbGFzcyBtaWdodCBiZSBhIGRpZmZlcmVudCBvbmUgZHVlIHRvIGhvdCByZWxvYWRpbmdcclxuICAgIGlmICghaXNNb2RlbChvYmopKSB7XHJcbiAgICAgIC8vIG5vdCBhIG1vZGVsIGluc3RhbmNlLCBubyByZWNvbmNpbGlhdGlvbiBwb3NzaWJsZVxyXG4gICAgICB0aHJvdyBmYWlsdXJlKGB0aGUgdGFyZ2V0IGZvciBhIG1vZGVsIHNuYXBzaG90IG11c3QgYmUgYSBtb2RlbCBpbnN0YW5jZWApXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG9ialttb2RlbFR5cGVLZXldICE9PSB0eXBlKSB7XHJcbiAgICAgIC8vIGRpZmZlcmVudCBraW5kIG9mIG1vZGVsLCBubyByZWNvbmNpbGlhdGlvbiBwb3NzaWJsZVxyXG4gICAgICB0aHJvdyBmYWlsdXJlKFxyXG4gICAgICAgIGBzbmFwc2hvdCBtb2RlbCB0eXBlICcke3R5cGV9JyBkb2VzIG5vdCBtYXRjaCB0YXJnZXQgbW9kZWwgdHlwZSAnJHtcclxuICAgICAgICAgIChvYmogYXMgYW55KVttb2RlbFR5cGVLZXldXHJcbiAgICAgICAgfSdgXHJcbiAgICAgIClcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBtb2RlbElkUHJvcGVydHlOYW1lID0gZ2V0TW9kZWxJZFByb3BlcnR5TmFtZShtb2RlbEluZm8uY2xhc3MgYXMgTW9kZWxDbGFzczxBbnlNb2RlbD4pXHJcbiAgICBpZiAobW9kZWxJZFByb3BlcnR5TmFtZSkge1xyXG4gICAgICBjb25zdCBpZCA9IChzbiBhcyBhbnkpW21vZGVsSWRQcm9wZXJ0eU5hbWVdXHJcbiAgICAgIGlmIChvYmpbbW9kZWxJZEtleV0gIT09IGlkKSB7XHJcbiAgICAgICAgLy8gZGlmZmVyZW50IGlkLCBubyByZWNvbmNpbGlhdGlvbiBwb3NzaWJsZVxyXG4gICAgICAgIHRocm93IGZhaWx1cmUoXHJcbiAgICAgICAgICBgc25hcHNob3QgbW9kZWwgaWQgJyR7aWR9JyBkb2VzIG5vdCBtYXRjaCB0YXJnZXQgbW9kZWwgaWQgJyR7b2JqW21vZGVsSWRLZXldfSdgXHJcbiAgICAgICAgKVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHJlY29uY2lsZSgpXHJcbiAgfVxyXG5cclxuICBpZiAoaXNQbGFpbk9iamVjdChzbikpIHtcclxuICAgIGlmICghaXNQbGFpbk9iamVjdChvYmopICYmICFpc09ic2VydmFibGVPYmplY3Qob2JqKSkge1xyXG4gICAgICAvLyBubyByZWNvbmNpbGlhdGlvbiBwb3NzaWJsZVxyXG4gICAgICB0aHJvdyBmYWlsdXJlKFwiaWYgdGhlIHNuYXBzaG90IGlzIGFuIG9iamVjdCB0aGUgdGFyZ2V0IG11c3QgYmUgYW4gb2JqZWN0IHRvb1wiKVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByZWNvbmNpbGUoKVxyXG4gIH1cclxuXHJcbiAgaWYgKGlzTWFwKHNuKSkge1xyXG4gICAgdGhyb3cgZmFpbHVyZShcImEgc25hcHNob3QgbXVzdCBub3QgY29udGFpbiBtYXBzXCIpXHJcbiAgfVxyXG5cclxuICBpZiAoaXNTZXQoc24pKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKFwiYSBzbmFwc2hvdCBtdXN0IG5vdCBjb250YWluIHNldHNcIilcclxuICB9XHJcblxyXG4gIHRocm93IGZhaWx1cmUoYHVuc3VwcG9ydGVkIHNuYXBzaG90IC0gJHtzbn1gKVxyXG59XHJcblxyXG5jb25zdCB3cmFwcGVkSW50ZXJuYWxBcHBseVNuYXBzaG90ID0gbGF6eSgoKSA9PlxyXG4gIHdyYXBJbkFjdGlvbih7XHJcbiAgICBuYW1lT3JOYW1lRm46IEJ1aWx0SW5BY3Rpb24uQXBwbHlTbmFwc2hvdCxcclxuICAgIGZuOiBpbnRlcm5hbEFwcGx5U25hcHNob3QsXHJcbiAgICBhY3Rpb25UeXBlOiBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZS5TeW5jLFxyXG4gIH0pXHJcbilcclxuIiwiaW1wb3J0IHsgcmVhY3Rpb24gfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgeyBhc3NlcnRUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXG5pbXBvcnQgeyBnZXRTbmFwc2hvdCB9IGZyb20gXCIuL2dldFNuYXBzaG90XCJcbmltcG9ydCB0eXBlIHsgU25hcHNob3RPdXRPZiB9IGZyb20gXCIuL1NuYXBzaG90T2ZcIlxuXG4vKipcbiAqIExpc3RlbmVyIGZ1bmN0aW9uIGZvciBvblNuYXBzaG90LlxuICovXG5leHBvcnQgdHlwZSBPblNuYXBzaG90TGlzdGVuZXI8VD4gPSAoc246IFNuYXBzaG90T3V0T2Y8VD4sIHByZXZTbjogU25hcHNob3RPdXRPZjxUPikgPT4gdm9pZFxuXG4vKipcbiAqIERpc3Bvc2VyIGZ1bmN0aW9uIGZvciBvblNuYXBzaG90LlxuICovXG5leHBvcnQgdHlwZSBPblNuYXBzaG90RGlzcG9zZXIgPSAoKSA9PiB2b2lkXG5cbi8qKlxuICogQWRkcyBhIHJlYWN0aW9uIHRoYXQgd2lsbCB0cmlnZ2VyIGV2ZXJ5IHRpbWUgYW4gc25hcHNob3QgY2hhbmdlcy5cbiAqXG4gKiBAdHlwZXBhcmFtIFQgT2JqZWN0IHR5cGUuXG4gKiBAcGFyYW0gbm9kZU9yRm4gT2JqZWN0IHRvIGdldCB0aGUgc25hcHNob3QgZnJvbSBvciBhIGZ1bmN0aW9uIHRvIGdldCBpdC5cbiAqIEBwYXJhbSBsaXN0ZW5lciBGdW5jdGlvbiB0aGF0IHdpbGwgYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIHNuYXBzaG90IGNoYW5nZXMuXG4gKiBAcmV0dXJucyBBIGRpc3Bvc2VyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gb25TbmFwc2hvdDxUIGV4dGVuZHMgb2JqZWN0PihcbiAgbm9kZU9yRm46IFQgfCAoKCkgPT4gVCksXG4gIGxpc3RlbmVyOiBPblNuYXBzaG90TGlzdGVuZXI8VD5cbik6IE9uU25hcHNob3REaXNwb3NlciB7XG4gIGNvbnN0IG5vZGVGbiA9IHR5cGVvZiBub2RlT3JGbiA9PT0gXCJmdW5jdGlvblwiID8gKG5vZGVPckZuIGFzICgpID0+IFQpIDogKCkgPT4gbm9kZU9yRm5cblxuICBjb25zdCBub2RlID0gbm9kZUZuKClcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChub2RlLCBcIm5vZGVcIilcblxuICBsZXQgY3VycmVudFNuYXBzaG90ID0gZ2V0U25hcHNob3Qobm9kZSlcblxuICByZXR1cm4gcmVhY3Rpb24oXG4gICAgKCkgPT4gZ2V0U25hcHNob3Qobm9kZUZuKCkpLFxuICAgIChuZXdTbmFwc2hvdCkgPT4ge1xuICAgICAgY29uc3QgcHJldlNuID0gY3VycmVudFNuYXBzaG90XG4gICAgICBjdXJyZW50U25hcHNob3QgPSBuZXdTbmFwc2hvdFxuICAgICAgbGlzdGVuZXIobmV3U25hcHNob3QsIHByZXZTbilcbiAgICB9XG4gIClcbn1cbiIsImltcG9ydCBmYXN0RGVlcEVxdWFsIGZyb20gXCJmYXN0LWRlZXAtZXF1YWwvZXM2XCJcbmltcG9ydCB7IGlzT2JzZXJ2YWJsZSwgdG9KUyB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IGdldFNuYXBzaG90IH0gZnJvbSBcIi4uL3NuYXBzaG90XCJcbmltcG9ydCB7IGlzVHJlZU5vZGUgfSBmcm9tIFwiLi4vdHdlYWtlclwiXG5pbXBvcnQgeyBnZXRNb2J4VmVyc2lvbiB9IGZyb20gXCIuLi91dGlsc1wiXG5cbi8qKlxuICogRGVlcGx5IGNvbXBhcmVzIHR3byB2YWx1ZXMuXG4gKlxuICogU3VwcG9ydGVkIHZhbHVlcyBhcmU6XG4gKiAtIFByaW1pdGl2ZXNcbiAqIC0gQm94ZWQgb2JzZXJ2YWJsZXNcbiAqIC0gT2JqZWN0cywgb2JzZXJ2YWJsZSBvYmplY3RzXG4gKiAtIEFycmF5cywgb2JzZXJ2YWJsZSBhcnJheXNcbiAqIC0gVHlwZWQgYXJyYXlzXG4gKiAtIE1hcHMsIG9ic2VydmFibGUgbWFwc1xuICogLSBTZXRzLCBvYnNlcnZhYmxlIHNldHNcbiAqIC0gVHJlZSBub2RlcyAob3B0aW1pemVkIGJ5IHVzaW5nIHNuYXBzaG90IGNvbXBhcmlzb24gaW50ZXJuYWxseSlcbiAqXG4gKiBOb3RlIHRoYXQgaW4gdGhlIGNhc2Ugb2YgbW9kZWxzIHRoZSByZXN1bHQgd2lsbCBiZSBmYWxzZSBpZiB0aGVpciBtb2RlbCBJRHMgYXJlIGRpZmZlcmVudC5cbiAqXG4gKiBAcGFyYW0gYSBGaXJzdCB2YWx1ZSB0byBjb21wYXJlLlxuICogQHBhcmFtIGIgU2Vjb25kIHZhbHVlIHRvIGNvbXBhcmUuXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhleSBhcmUgdGhlIGVxdWl2YWxlbnQsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVlcEVxdWFscyhhOiBhbnksIGI6IGFueSk6IGJvb2xlYW4ge1xuICAvLyBxdWljayBjaGVjayBmb3IgcmVmZXJlbmNlXG4gIGlmIChhID09PSBiKSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIC8vIHVzZSBzbmFwc2hvdHMgdG8gY29tcGFyZSBpZiBwb3NzaWJsZVxuICAvLyBzaW5jZSBzbmFwc2hvdHMgdXNlIHN0cnVjdHVyYWwgc2hhcmluZyBpdCBpcyBtb3JlIGxpa2VseVxuICAvLyB0byBzcGVlZCB1cCBjb21wYXJpc29uc1xuICBpZiAoaXNUcmVlTm9kZShhKSkge1xuICAgIGEgPSBnZXRTbmFwc2hvdChhKVxuICB9IGVsc2UgaWYgKGlzT2JzZXJ2YWJsZShhKSkge1xuICAgIGEgPSB0b0pTKGEsIHRvSlNPcHRpb25zKVxuICB9XG4gIGlmIChpc1RyZWVOb2RlKGIpKSB7XG4gICAgYiA9IGdldFNuYXBzaG90KGIpXG4gIH0gZWxzZSBpZiAoaXNPYnNlcnZhYmxlKGIpKSB7XG4gICAgYiA9IHRvSlMoYiwgdG9KU09wdGlvbnMpXG4gIH1cblxuICByZXR1cm4gZmFzdERlZXBFcXVhbChhLCBiKVxufVxuXG5jb25zdCB0b0pTT3B0aW9ucyA9XG4gIGdldE1vYnhWZXJzaW9uKCkgPj0gNlxuICAgID8gdW5kZWZpbmVkXG4gICAgOiB7XG4gICAgICAgIGV4cG9ydE1hcHNBc09iamVjdHM6IGZhbHNlLFxuICAgICAgICByZWN1cnNlRXZlcnl0aGluZzogZmFsc2UsXG4gICAgICB9XG4iLCJpbXBvcnQgeyByZW1vdmUgfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcclxuaW1wb3J0IHsgZ2V0TW9kZWxJZFByb3BlcnR5TmFtZSB9IGZyb20gXCIuLi9tb2RlbC9nZXRNb2RlbE1ldGFkYXRhXCJcclxuaW1wb3J0IHsgaXNSZXNlcnZlZE1vZGVsS2V5LCBtb2RlbElkS2V5LCBtb2RlbFR5cGVLZXkgfSBmcm9tIFwiLi4vbW9kZWwvbWV0YWRhdGFcIlxyXG5pbXBvcnQgeyBpc01vZGVsLCBpc01vZGVsU25hcHNob3QgfSBmcm9tIFwiLi4vbW9kZWwvdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcclxuaW1wb3J0IHsgZ2V0TW9kZWxJbmZvRm9yTmFtZSB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9tb2RlbEluZm9cIlxyXG5pbXBvcnQgeyBnZXRJbnRlcm5hbE1vZGVsQ2xhc3NQcm9wc0luZm8gfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxQcm9wc0luZm9cIlxyXG5pbXBvcnQgeyBnZXRNb2RlbFByb3BEZWZhdWx0VmFsdWUsIG5vRGVmYXVsdFZhbHVlIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL3Byb3BcIlxyXG5pbXBvcnQgeyBkZWVwRXF1YWxzIH0gZnJvbSBcIi4uL3RyZWVVdGlscy9kZWVwRXF1YWxzXCJcclxuaW1wb3J0IHsgcnVuVHlwZUNoZWNraW5nQWZ0ZXJDaGFuZ2UgfSBmcm9tIFwiLi4vdHdlYWtlci90eXBlQ2hlY2tpbmdcIlxyXG5pbXBvcnQgeyB3aXRob3V0VHlwZUNoZWNraW5nIH0gZnJvbSBcIi4uL3R3ZWFrZXIvd2l0aG91dFR5cGVDaGVja2luZ1wiXHJcbmltcG9ydCB7IGZhaWx1cmUsIGlzQXJyYXkgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsUG9vbCB9IGZyb20gXCIuLi91dGlscy9Nb2RlbFBvb2xcIlxyXG5pbXBvcnQgeyBzZXRJZkRpZmZlcmVudCB9IGZyb20gXCIuLi91dGlscy9zZXRJZkRpZmZlcmVudFwiXHJcbmltcG9ydCB0eXBlIHsgU25hcHNob3RJbk9mTW9kZWwgfSBmcm9tIFwiLi9TbmFwc2hvdE9mXCJcclxuaW1wb3J0IHsgU25hcHNob3R0ZXJBbmRSZWNvbmNpbGVyUHJpb3JpdHkgfSBmcm9tIFwiLi9TbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eVwiXHJcbmltcG9ydCB7IGZyb21TbmFwc2hvdCB9IGZyb20gXCIuL2Zyb21TbmFwc2hvdFwiXHJcbmltcG9ydCB7IGdldFNuYXBzaG90IH0gZnJvbSBcIi4vZ2V0U25hcHNob3RcIlxyXG5pbXBvcnQgeyBkZXRhY2hJZk5lZWRlZCwgcmVjb25jaWxlU25hcHNob3QsIHJlZ2lzdGVyUmVjb25jaWxlciB9IGZyb20gXCIuL3JlY29uY2lsZVNuYXBzaG90XCJcclxuXHJcbmZ1bmN0aW9uIHJlY29uY2lsZU1vZGVsU25hcHNob3QoXHJcbiAgdmFsdWU6IGFueSxcclxuICBzbjogU25hcHNob3RJbk9mTW9kZWw8QW55TW9kZWw+LFxyXG4gIG1vZGVsUG9vbDogTW9kZWxQb29sLFxyXG4gIHBhcmVudDogYW55XHJcbik6IEFueU1vZGVsIHtcclxuICBjb25zdCB0eXBlID0gc25bbW9kZWxUeXBlS2V5XSFcclxuXHJcbiAgY29uc3QgbW9kZWxJbmZvID0gZ2V0TW9kZWxJbmZvRm9yTmFtZSh0eXBlKVxyXG4gIGlmICghbW9kZWxJbmZvKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKGBtb2RlbCB3aXRoIG5hbWUgXCIke3R5cGV9XCIgbm90IGZvdW5kIGluIHRoZSByZWdpc3RyeWApXHJcbiAgfVxyXG5cclxuICAvLyB0cnkgdG8gdXNlIG1vZGVsIGZyb20gcG9vbCBpZiBwb3NzaWJsZVxyXG4gIGNvbnN0IG1vZGVsSW5Qb29sID0gbW9kZWxQb29sLmZpbmRNb2RlbEZvclNuYXBzaG90KHNuKVxyXG4gIGlmIChtb2RlbEluUG9vbCkge1xyXG4gICAgdmFsdWUgPSBtb2RlbEluUG9vbFxyXG4gIH1cclxuXHJcbiAgLy8gd2UgZG9uJ3QgY2hlY2sgYnkgYWN0dWFsIGluc3RhbmNlIHNpbmNlIHRoZSBjbGFzcyBtaWdodCBiZSBhIGRpZmZlcmVudCBvbmUgZHVlIHRvIGhvdCByZWxvYWRpbmdcclxuICBpZiAoIWlzTW9kZWwodmFsdWUpIHx8IHZhbHVlW21vZGVsVHlwZUtleV0gIT09IHR5cGUpIHtcclxuICAgIC8vIGRpZmZlcmVudCBraW5kIG9mIG1vZGVsIHR5cGUsIG5vIHJlY29uY2lsaWF0aW9uIHBvc3NpYmxlXHJcbiAgICByZXR1cm4gZnJvbVNuYXBzaG90PEFueU1vZGVsPihzbilcclxuICB9XHJcblxyXG4gIGNvbnN0IG1vZGVsQ2xhc3MgPSBtb2RlbEluZm8uY2xhc3MgYXMgTW9kZWxDbGFzczxBbnlNb2RlbD5cclxuICBjb25zdCBtb2RlbFByb3BzID0gZ2V0SW50ZXJuYWxNb2RlbENsYXNzUHJvcHNJbmZvKG1vZGVsQ2xhc3MpXHJcbiAgY29uc3QgbW9kZWxJZFByb3BlcnR5TmFtZSA9IGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUobW9kZWxDbGFzcylcclxuXHJcbiAgaWYgKG1vZGVsSWRQcm9wZXJ0eU5hbWUpIHtcclxuICAgIGNvbnN0IGlkID0gc25bbW9kZWxJZFByb3BlcnR5TmFtZV1cclxuXHJcbiAgICBpZiAodmFsdWVbbW9kZWxJZEtleV0gIT09IGlkKSB7XHJcbiAgICAgIC8vIGRpZmZlcmVudCBpZCwgbm8gcmVjb25jaWxpYXRpb24gcG9zc2libGVcclxuICAgICAgcmV0dXJuIGZyb21TbmFwc2hvdDxBbnlNb2RlbD4oc24pXHJcbiAgICB9XHJcbiAgfSBlbHNlIGlmIChpc0FycmF5KHBhcmVudCkpIHtcclxuICAgIC8vIG5vIGlkIGFuZCBpbnNpZGUgYW4gYXJyYXk/IG5vIHJlY29uY2lsaWF0aW9uIHBvc3NpYmxlLFxyXG4gICAgLy8gdW5sZXNzIHRoZSBzbmFwc2hvdHMgYXJlIGVxdWl2YWxlbnQgKG5vdGUgZGVlcCBlcXVhbHMgd2lsbCB1c2UgdGhlIHNuYXBzaG90IG9mIHZhbHVlIGF1dG8pXHJcbiAgICBpZiAoIWRlZXBFcXVhbHModmFsdWUsIHNuKSkge1xyXG4gICAgICByZXR1cm4gZnJvbVNuYXBzaG90PEFueU1vZGVsPihzbilcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IG1vZGVsT2JqOiBBbnlNb2RlbCA9IHZhbHVlXHJcbiAgY29uc3Qgc25hcHNob3RCZWZvcmVDaGFuZ2VzID0gZ2V0U25hcHNob3QobW9kZWxPYmopXHJcblxyXG4gIHdpdGhvdXRUeXBlQ2hlY2tpbmcoKCkgPT4ge1xyXG4gICAgY29uc3QgbW9kZWxDbGFzczogTW9kZWxDbGFzczxBbnlNb2RlbD4gPSAobW9kZWxPYmogYXMgYW55KS5jb25zdHJ1Y3RvclxyXG4gICAgY29uc3QgcHJvY2Vzc2VkU24gPSBtb2RlbENsYXNzLmZyb21TbmFwc2hvdFByb2Nlc3NvciA/IG1vZGVsQ2xhc3MuZnJvbVNuYXBzaG90UHJvY2Vzc29yKHNuKSA6IHNuXHJcblxyXG4gICAgY29uc3QgZGF0YSA9IG1vZGVsT2JqLiRcclxuXHJcbiAgICAvLyByZW1vdmUgZXhjZXNzIHByb3BzXHJcbiAgICBjb25zdCBkYXRhS2V5cyA9IE9iamVjdC5rZXlzKGRhdGEpXHJcbiAgICBjb25zdCBkYXRhS2V5c0xlbiA9IGRhdGFLZXlzLmxlbmd0aFxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhS2V5c0xlbjsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGsgPSBkYXRhS2V5c1tpXVxyXG4gICAgICBpZiAoIShrIGluIHByb2Nlc3NlZFNuKSkge1xyXG4gICAgICAgIC8vIHVzZSBkZWZhdWx0IHZhbHVlIGlmIGFwcGxpY2FibGVcclxuICAgICAgICBjb25zdCBtb2RlbFByb3AgPSBtb2RlbFByb3BzW2tdXHJcbiAgICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gbW9kZWxQcm9wID8gZ2V0TW9kZWxQcm9wRGVmYXVsdFZhbHVlKG1vZGVsUHJvcCkgOiBub0RlZmF1bHRWYWx1ZVxyXG4gICAgICAgIGlmIChkZWZhdWx0VmFsdWUgPT09IG5vRGVmYXVsdFZhbHVlKSB7XHJcbiAgICAgICAgICByZW1vdmUoZGF0YSwgaylcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgc2V0SWZEaWZmZXJlbnQoZGF0YSwgaywgZGVmYXVsdFZhbHVlKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIHJlY29uY2lsZSB0aGUgcmVzdFxyXG4gICAgY29uc3QgcHJvY2Vzc2VkU25LZXlzID0gT2JqZWN0LmtleXMocHJvY2Vzc2VkU24pXHJcbiAgICBjb25zdCBwcm9jZXNzZWRTbktleXNMZW4gPSBwcm9jZXNzZWRTbktleXMubGVuZ3RoXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHByb2Nlc3NlZFNuS2V5c0xlbjsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGsgPSBwcm9jZXNzZWRTbktleXNbaV1cclxuICAgICAgaWYgKCFpc1Jlc2VydmVkTW9kZWxLZXkoaykpIHtcclxuICAgICAgICBjb25zdCB2ID0gcHJvY2Vzc2VkU25ba11cclxuXHJcbiAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSBkYXRhW2tdXHJcbiAgICAgICAgbGV0IG5ld1ZhbHVlID0gcmVjb25jaWxlU25hcHNob3Qob2xkVmFsdWUsIHYsIG1vZGVsUG9vbCwgbW9kZWxPYmopXHJcblxyXG4gICAgICAgIC8vIHVzZSBkZWZhdWx0IHZhbHVlIGlmIGFwcGxpY2FibGVcclxuICAgICAgICBpZiAobmV3VmFsdWUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgY29uc3QgbW9kZWxQcm9wID0gbW9kZWxQcm9wc1trXVxyXG4gICAgICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gbW9kZWxQcm9wID8gZ2V0TW9kZWxQcm9wRGVmYXVsdFZhbHVlKG1vZGVsUHJvcCkgOiBub0RlZmF1bHRWYWx1ZVxyXG4gICAgICAgICAgaWYgKGRlZmF1bHRWYWx1ZSAhPT0gbm9EZWZhdWx0VmFsdWUpIHtcclxuICAgICAgICAgICAgbmV3VmFsdWUgPSBkZWZhdWx0VmFsdWVcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGRldGFjaElmTmVlZGVkKG5ld1ZhbHVlLCBvbGRWYWx1ZSwgbW9kZWxQb29sKVxyXG5cclxuICAgICAgICBzZXRJZkRpZmZlcmVudChkYXRhLCBrLCBuZXdWYWx1ZSlcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0pXHJcblxyXG4gIHJ1blR5cGVDaGVja2luZ0FmdGVyQ2hhbmdlKG1vZGVsT2JqLCB1bmRlZmluZWQsIHNuYXBzaG90QmVmb3JlQ2hhbmdlcylcclxuXHJcbiAgcmV0dXJuIG1vZGVsT2JqXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiByZWdpc3Rlck1vZGVsU25hcHNob3RSZWNvbmNpbGVyKCkge1xyXG4gIHJlZ2lzdGVyUmVjb25jaWxlcihTbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eS5Nb2RlbCwgKHZhbHVlLCBzbiwgbW9kZWxQb29sLCBwYXJlbnQpID0+IHtcclxuICAgIGlmIChpc01vZGVsU25hcHNob3Qoc24pKSB7XHJcbiAgICAgIHJldHVybiByZWNvbmNpbGVNb2RlbFNuYXBzaG90KHZhbHVlLCBzbiwgbW9kZWxQb29sLCBwYXJlbnQpXHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkXHJcbiAgfSlcclxufVxyXG4iLCJpbXBvcnQgeyBpc09ic2VydmFibGVPYmplY3QsIHJlbW92ZSB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHsgcnVuVHlwZUNoZWNraW5nQWZ0ZXJDaGFuZ2UgfSBmcm9tIFwiLi4vdHdlYWtlci90eXBlQ2hlY2tpbmdcIlxyXG5pbXBvcnQgeyB3aXRob3V0VHlwZUNoZWNraW5nIH0gZnJvbSBcIi4uL3R3ZWFrZXIvd2l0aG91dFR5cGVDaGVja2luZ1wiXHJcbmltcG9ydCB7IGlzUGxhaW5PYmplY3QgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsUG9vbCB9IGZyb20gXCIuLi91dGlscy9Nb2RlbFBvb2xcIlxyXG5pbXBvcnQgeyBzZXRJZkRpZmZlcmVudCB9IGZyb20gXCIuLi91dGlscy9zZXRJZkRpZmZlcmVudFwiXHJcbmltcG9ydCB0eXBlIHsgU25hcHNob3RJbk9mT2JqZWN0IH0gZnJvbSBcIi4vU25hcHNob3RPZlwiXHJcbmltcG9ydCB7IFNuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5IH0gZnJvbSBcIi4vU25hcHNob3R0ZXJBbmRSZWNvbmNpbGVyUHJpb3JpdHlcIlxyXG5pbXBvcnQgeyBmcm9tU25hcHNob3QgfSBmcm9tIFwiLi9mcm9tU25hcHNob3RcIlxyXG5pbXBvcnQgeyBnZXRTbmFwc2hvdCB9IGZyb20gXCIuL2dldFNuYXBzaG90XCJcclxuaW1wb3J0IHsgZGV0YWNoSWZOZWVkZWQsIHJlY29uY2lsZVNuYXBzaG90LCByZWdpc3RlclJlY29uY2lsZXIgfSBmcm9tIFwiLi9yZWNvbmNpbGVTbmFwc2hvdFwiXHJcblxyXG5mdW5jdGlvbiByZWNvbmNpbGVQbGFpbk9iamVjdFNuYXBzaG90KFxyXG4gIHZhbHVlOiBhbnksXHJcbiAgc246IFNuYXBzaG90SW5PZk9iamVjdDxhbnk+LFxyXG4gIG1vZGVsUG9vbDogTW9kZWxQb29sXHJcbik6IG9iamVjdCB7XHJcbiAgLy8gcGxhaW4gb2JqXHJcbiAgaWYgKCFpc1BsYWluT2JqZWN0KHZhbHVlKSAmJiAhaXNPYnNlcnZhYmxlT2JqZWN0KHZhbHVlKSkge1xyXG4gICAgLy8gbm8gcmVjb25jaWxpYXRpb24gcG9zc2libGVcclxuICAgIHJldHVybiBmcm9tU25hcHNob3Qoc24pXHJcbiAgfVxyXG5cclxuICBjb25zdCBwbGFpbk9iaiA9IHZhbHVlXHJcbiAgY29uc3Qgc25hcHNob3RCZWZvcmVDaGFuZ2VzID0gZ2V0U25hcHNob3QocGxhaW5PYmopXHJcblxyXG4gIHdpdGhvdXRUeXBlQ2hlY2tpbmcoKCkgPT4ge1xyXG4gICAgLy8gcmVtb3ZlIGV4Y2VzcyBwcm9wc1xyXG4gICAgY29uc3QgcGxhaW5PYmpLZXlzID0gT2JqZWN0LmtleXMocGxhaW5PYmopXHJcbiAgICBjb25zdCBwbGFpbk9iaktleXNMZW4gPSBwbGFpbk9iaktleXMubGVuZ3RoXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBsYWluT2JqS2V5c0xlbjsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGsgPSBwbGFpbk9iaktleXNbaV1cclxuICAgICAgaWYgKCEoayBpbiBzbikpIHtcclxuICAgICAgICByZW1vdmUocGxhaW5PYmosIGspXHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyByZWNvbmNpbGUgdGhlIHJlc3RcclxuICAgIGNvbnN0IHNuS2V5cyA9IE9iamVjdC5rZXlzKHNuKVxyXG4gICAgY29uc3Qgc25LZXlzTGVuID0gc25LZXlzLmxlbmd0aFxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbktleXNMZW47IGkrKykge1xyXG4gICAgICBjb25zdCBrID0gc25LZXlzW2ldXHJcbiAgICAgIGNvbnN0IHYgPSBzbltrXVxyXG5cclxuICAgICAgY29uc3Qgb2xkVmFsdWUgPSBwbGFpbk9ialtrXVxyXG4gICAgICBjb25zdCBuZXdWYWx1ZSA9IHJlY29uY2lsZVNuYXBzaG90KG9sZFZhbHVlLCB2LCBtb2RlbFBvb2wsIHBsYWluT2JqKVxyXG5cclxuICAgICAgZGV0YWNoSWZOZWVkZWQobmV3VmFsdWUsIG9sZFZhbHVlLCBtb2RlbFBvb2wpXHJcblxyXG4gICAgICBzZXRJZkRpZmZlcmVudChwbGFpbk9iaiwgaywgbmV3VmFsdWUpXHJcbiAgICB9XHJcbiAgfSlcclxuXHJcbiAgcnVuVHlwZUNoZWNraW5nQWZ0ZXJDaGFuZ2UocGxhaW5PYmosIHVuZGVmaW5lZCwgc25hcHNob3RCZWZvcmVDaGFuZ2VzKVxyXG5cclxuICByZXR1cm4gcGxhaW5PYmpcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyUGxhaW5PYmplY3RTbmFwc2hvdFJlY29uY2lsZXIoKSB7XHJcbiAgcmVnaXN0ZXJSZWNvbmNpbGVyKFNuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5LlBsYWluT2JqZWN0LCAodmFsdWUsIHNuLCBtb2RlbFBvb2wpID0+IHtcclxuICAgIGlmIChpc1BsYWluT2JqZWN0KHNuKSkge1xyXG4gICAgICByZXR1cm4gcmVjb25jaWxlUGxhaW5PYmplY3RTbmFwc2hvdCh2YWx1ZSwgc24sIG1vZGVsUG9vbClcclxuICAgIH1cclxuICAgIHJldHVybiB1bmRlZmluZWRcclxuICB9KVxyXG59XHJcbiIsImltcG9ydCB7IHJlZ2lzdGVyQXJyYXlTbmFwc2hvdFJlY29uY2lsZXIgfSBmcm9tIFwiLi9yZWNvbmNpbGVBcnJheVNuYXBzaG90XCJcbmltcG9ydCB7IHJlZ2lzdGVyRnJvemVuU25hcHNob3RSZWNvbmNpbGVyIH0gZnJvbSBcIi4vcmVjb25jaWxlRnJvemVuU25hcHNob3RcIlxuaW1wb3J0IHsgcmVnaXN0ZXJNb2RlbFNuYXBzaG90UmVjb25jaWxlciB9IGZyb20gXCIuL3JlY29uY2lsZU1vZGVsU25hcHNob3RcIlxuaW1wb3J0IHsgcmVnaXN0ZXJQbGFpbk9iamVjdFNuYXBzaG90UmVjb25jaWxlciB9IGZyb20gXCIuL3JlY29uY2lsZVBsYWluT2JqZWN0U25hcHNob3RcIlxuXG5sZXQgZGVmYXVsdFJlY29uY2lsZXJzUmVnaXN0ZXJlZCA9IGZhbHNlXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckRlZmF1bHRSZWNvbmNpbGVycygpIHtcbiAgaWYgKGRlZmF1bHRSZWNvbmNpbGVyc1JlZ2lzdGVyZWQpIHtcbiAgICByZXR1cm5cbiAgfVxuICBkZWZhdWx0UmVjb25jaWxlcnNSZWdpc3RlcmVkID0gdHJ1ZVxuXG4gIHJlZ2lzdGVyQXJyYXlTbmFwc2hvdFJlY29uY2lsZXIoKVxuICByZWdpc3RlckZyb3plblNuYXBzaG90UmVjb25jaWxlcigpXG4gIHJlZ2lzdGVyTW9kZWxTbmFwc2hvdFJlY29uY2lsZXIoKVxuICByZWdpc3RlclBsYWluT2JqZWN0U25hcHNob3RSZWNvbmNpbGVyKClcbn1cbiIsImltcG9ydCB7IHNldCB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHsgbW9kZWxJZEtleSwgbW9kZWxUeXBlS2V5IH0gZnJvbSBcIi4uL21vZGVsL21ldGFkYXRhXCJcclxuaW1wb3J0IHsgaXNNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXHJcbmltcG9ydCB7IGZhc3RHZXRQYXJlbnRQYXRoSW5jbHVkaW5nRGF0YU9iamVjdHMgfSBmcm9tIFwiLi4vcGFyZW50XCJcclxuaW1wb3J0IHsgZmFpbHVyZSwgaXNNYXAsIGlzUHJpbWl0aXZlLCBpc1NldCB9IGZyb20gXCIuLi91dGlsc1wiXHJcbmltcG9ydCB0eXBlIHsgTW9kZWxQb29sIH0gZnJvbSBcIi4uL3V0aWxzL01vZGVsUG9vbFwiXHJcbmltcG9ydCB7IGdldFNuYXBzaG90IH0gZnJvbSBcIi4vZ2V0U25hcHNob3RcIlxyXG5pbXBvcnQgeyByZWdpc3RlckRlZmF1bHRSZWNvbmNpbGVycyB9IGZyb20gXCIuL3JlZ2lzdGVyRGVmYXVsdFJlY29uY2lsZXJzXCJcclxuXHJcbnR5cGUgUmVjb25jaWxlciA9ICh2YWx1ZTogYW55LCBzbjogYW55LCBtb2RlbFBvb2w6IE1vZGVsUG9vbCwgcGFyZW50OiBhbnkpID0+IGFueSB8IHVuZGVmaW5lZFxyXG5cclxuY29uc3QgcmVjb25jaWxlcnM6IHsgcHJpb3JpdHk6IG51bWJlcjsgcmVjb25jaWxlcjogUmVjb25jaWxlciB9W10gPSBbXVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyUmVjb25jaWxlcihwcmlvcml0eTogbnVtYmVyLCByZWNvbmNpbGVyOiBSZWNvbmNpbGVyKTogdm9pZCB7XHJcbiAgcmVjb25jaWxlcnMucHVzaCh7IHByaW9yaXR5LCByZWNvbmNpbGVyIH0pXHJcbiAgcmVjb25jaWxlcnMuc29ydCgoYSwgYikgPT4gYS5wcmlvcml0eSAtIGIucHJpb3JpdHkpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiByZWNvbmNpbGVTbmFwc2hvdCh2YWx1ZTogYW55LCBzbjogYW55LCBtb2RlbFBvb2w6IE1vZGVsUG9vbCwgcGFyZW50OiBhbnkpOiBhbnkge1xyXG4gIGlmIChpc1ByaW1pdGl2ZShzbikpIHtcclxuICAgIHJldHVybiBzblxyXG4gIH1cclxuXHJcbiAgLy8gaWYgdGhlIHNuYXBzaG90IHBhc3NlZCBpcyBleGFjdGx5IHRoZSBzYW1lIGFzIHRoZSBjdXJyZW50IG9uZVxyXG4gIC8vIHRoZW4gaXQgaXMgYWxyZWFkeSByZWNvbmNpbGVkXHJcbiAgaWYgKGdldFNuYXBzaG90KHZhbHVlKSA9PT0gc24pIHtcclxuICAgIHJldHVybiB2YWx1ZVxyXG4gIH1cclxuXHJcbiAgcmVnaXN0ZXJEZWZhdWx0UmVjb25jaWxlcnMoKVxyXG5cclxuICBjb25zdCByZWNvbmNpbGVyc0xlbiA9IHJlY29uY2lsZXJzLmxlbmd0aFxyXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmVjb25jaWxlcnNMZW47IGkrKykge1xyXG4gICAgY29uc3QgeyByZWNvbmNpbGVyIH0gPSByZWNvbmNpbGVyc1tpXVxyXG4gICAgY29uc3QgcmV0ID0gcmVjb25jaWxlcih2YWx1ZSwgc24sIG1vZGVsUG9vbCwgcGFyZW50KVxyXG4gICAgaWYgKHJldCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiByZXRcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlmIChpc01hcChzbikpIHtcclxuICAgIHRocm93IGZhaWx1cmUoXCJhIHNuYXBzaG90IG11c3Qgbm90IGNvbnRhaW4gbWFwc1wiKVxyXG4gIH1cclxuXHJcbiAgaWYgKGlzU2V0KHNuKSkge1xyXG4gICAgdGhyb3cgZmFpbHVyZShcImEgc25hcHNob3QgbXVzdCBub3QgY29udGFpbiBzZXRzXCIpXHJcbiAgfVxyXG5cclxuICB0aHJvdyBmYWlsdXJlKGB1bnN1cHBvcnRlZCBzbmFwc2hvdCAtICR7c259YClcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGRldGFjaElmTmVlZGVkKG5ld1ZhbHVlOiBhbnksIG9sZFZhbHVlOiBhbnksIG1vZGVsUG9vbDogTW9kZWxQb29sKSB7XHJcbiAgLy8gZWRnZSBjYXNlIGZvciB3aGVuIHdlIGFyZSBzd2FwcGluZyBtb2RlbHMgYXJvdW5kIHRoZSB0cmVlXHJcblxyXG4gIGlmIChuZXdWYWx1ZSA9PT0gb2xkVmFsdWUpIHtcclxuICAgIC8vIGFscmVhZHkgd2hlcmUgaXQgc2hvdWxkIGJlXHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIGlmIChcclxuICAgIGlzTW9kZWwobmV3VmFsdWUpICYmXHJcbiAgICBtb2RlbFBvb2wuZmluZE1vZGVsQnlUeXBlQW5kSWQobmV3VmFsdWVbbW9kZWxUeXBlS2V5XSwgbmV3VmFsdWVbbW9kZWxJZEtleV0pXHJcbiAgKSB7XHJcbiAgICBjb25zdCBwYXJlbnRQYXRoID0gZmFzdEdldFBhcmVudFBhdGhJbmNsdWRpbmdEYXRhT2JqZWN0cyhuZXdWYWx1ZSlcclxuICAgIGlmIChwYXJlbnRQYXRoKSB7XHJcbiAgICAgIHNldChwYXJlbnRQYXRoLnBhcmVudCwgcGFyZW50UGF0aC5wYXRoLCBudWxsKVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyByZW1vdmUgfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7IEJ1aWx0SW5BY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9uL2J1aWx0SW5BY3Rpb25zXCJcclxuaW1wb3J0IHsgQWN0aW9uQ29udGV4dEFjdGlvblR5cGUgfSBmcm9tIFwiLi4vYWN0aW9uL2NvbnRleHRcIlxyXG5pbXBvcnQgeyB3cmFwSW5BY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9uL3dyYXBJbkFjdGlvblwiXHJcbmltcG9ydCB7IG1vZGVsVG9EYXRhTm9kZSB9IGZyb20gXCIuLi9wYXJlbnQvY29yZVwiXHJcbmltcG9ydCB0eXBlIHsgUGF0aEVsZW1lbnQgfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhUeXBlc1wiXHJcbmltcG9ydCB0eXBlIHsgUGF0Y2ggfSBmcm9tIFwiLi4vcGF0Y2gvUGF0Y2hcIlxyXG5pbXBvcnQgeyByZWNvbmNpbGVTbmFwc2hvdCB9IGZyb20gXCIuLi9zbmFwc2hvdC9yZWNvbmNpbGVTbmFwc2hvdFwiXHJcbmltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcclxuaW1wb3J0IHsgZmFpbHVyZSwgaW5EZXZNb2RlLCBpc0FycmF5LCBsYXp5IH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgTW9kZWxQb29sIH0gZnJvbSBcIi4uL3V0aWxzL01vZGVsUG9vbFwiXHJcbmltcG9ydCB7IHNldElmRGlmZmVyZW50IH0gZnJvbSBcIi4uL3V0aWxzL3NldElmRGlmZmVyZW50XCJcclxuXHJcbi8qKlxyXG4gKiBBcHBsaWVzIHRoZSBnaXZlbiBwYXRjaGVzIHRvIHRoZSBnaXZlbiB0YXJnZXQgb2JqZWN0LlxyXG4gKlxyXG4gKiBAcGFyYW0gbm9kZSBUYXJnZXQgb2JqZWN0LlxyXG4gKiBAcGFyYW0gcGF0Y2hlcyBMaXN0IG9mIHBhdGNoZXMgdG8gYXBwbHkuXHJcbiAqIEBwYXJhbSByZXZlcnNlIFdoZXRoZXIgcGF0Y2hlcyBhcmUgYXBwbGllZCBpbiByZXZlcnNlIG9yZGVyLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5UGF0Y2hlcyhcclxuICBub2RlOiBvYmplY3QsXHJcbiAgcGF0Y2hlczogUmVhZG9ubHlBcnJheTxQYXRjaD4gfCBSZWFkb25seUFycmF5PFJlYWRvbmx5QXJyYXk8UGF0Y2g+PixcclxuICByZXZlcnNlOiBib29sZWFuID0gZmFsc2VcclxuKTogdm9pZCB7XHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChub2RlLCBcIm5vZGVcIilcclxuXHJcbiAgaWYgKHBhdGNoZXMubGVuZ3RoIDw9IDApIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuXHJcbiAgd3JhcHBlZEludGVybmFsQXBwbHlQYXRjaGVzKCkuY2FsbChub2RlLCBwYXRjaGVzLCByZXZlcnNlKVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJuYWxBcHBseVBhdGNoZXMoXHJcbiAgdGhpczogb2JqZWN0LFxyXG4gIHBhdGNoZXM6IFJlYWRvbmx5QXJyYXk8UGF0Y2g+IHwgUmVhZG9ubHlBcnJheTxSZWFkb25seUFycmF5PFBhdGNoPj4sXHJcbiAgcmV2ZXJzZTogYm9vbGVhbiA9IGZhbHNlXHJcbik6IHZvaWQge1xyXG4gIGNvbnN0IG9iaiA9IHRoaXNcclxuICBjb25zdCBtb2RlbFBvb2wgPSBuZXcgTW9kZWxQb29sKG9iailcclxuXHJcbiAgaWYgKHJldmVyc2UpIHtcclxuICAgIGxldCBpID0gcGF0Y2hlcy5sZW5ndGhcclxuICAgIHdoaWxlIChpLS0pIHtcclxuICAgICAgY29uc3QgcCA9IHBhdGNoZXNbaV1cclxuICAgICAgaWYgKCFpc0FycmF5KHApKSB7XHJcbiAgICAgICAgYXBwbHlTaW5nbGVQYXRjaChvYmosIHAgYXMgUGF0Y2gsIG1vZGVsUG9vbClcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBsZXQgaiA9IHAubGVuZ3RoXHJcbiAgICAgICAgd2hpbGUgKGotLSkge1xyXG4gICAgICAgICAgYXBwbHlTaW5nbGVQYXRjaChvYmosIHBbal0sIG1vZGVsUG9vbClcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9IGVsc2Uge1xyXG4gICAgY29uc3QgbGVuID0gcGF0Y2hlcy5sZW5ndGhcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcclxuICAgICAgY29uc3QgcCA9IHBhdGNoZXNbaV1cclxuICAgICAgaWYgKCFpc0FycmF5KHApKSB7XHJcbiAgICAgICAgYXBwbHlTaW5nbGVQYXRjaChvYmosIHAgYXMgUGF0Y2gsIG1vZGVsUG9vbClcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zdCBsZW4yID0gcC5sZW5ndGhcclxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxlbjI7IGorKykge1xyXG4gICAgICAgICAgYXBwbHlTaW5nbGVQYXRjaChvYmosIHBbal0sIG1vZGVsUG9vbClcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmNvbnN0IHdyYXBwZWRJbnRlcm5hbEFwcGx5UGF0Y2hlcyA9IGxhenkoKCkgPT5cclxuICB3cmFwSW5BY3Rpb24oe1xyXG4gICAgbmFtZU9yTmFtZUZuOiBCdWlsdEluQWN0aW9uLkFwcGx5UGF0Y2hlcyxcclxuICAgIGZuOiBpbnRlcm5hbEFwcGx5UGF0Y2hlcyxcclxuICAgIGFjdGlvblR5cGU6IEFjdGlvbkNvbnRleHRBY3Rpb25UeXBlLlN5bmMsXHJcbiAgfSlcclxuKVxyXG5cclxuZnVuY3Rpb24gYXBwbHlTaW5nbGVQYXRjaChvYmo6IG9iamVjdCwgcGF0Y2g6IFBhdGNoLCBtb2RlbFBvb2w6IE1vZGVsUG9vbCk6IHZvaWQge1xyXG4gIGNvbnN0IHsgdGFyZ2V0LCBwcm9wIH0gPSBwYXRoQXJyYXlUb09iamVjdEFuZFByb3Aob2JqLCBwYXRjaC5wYXRoKVxyXG5cclxuICBpZiAoaXNBcnJheSh0YXJnZXQpKSB7XHJcbiAgICBzd2l0Y2ggKHBhdGNoLm9wKSB7XHJcbiAgICAgIGNhc2UgXCJhZGRcIjoge1xyXG4gICAgICAgIGNvbnN0IGluZGV4ID0gK3Byb3AhXHJcbiAgICAgICAgLy8gcmVjb25jaWxlIGZyb20gdGhlIHBvb2wgaWYgcG9zc2libGVcclxuICAgICAgICBjb25zdCBuZXdWYWx1ZSA9IHJlY29uY2lsZVNuYXBzaG90KHVuZGVmaW5lZCwgcGF0Y2gudmFsdWUsIG1vZGVsUG9vbCwgdGFyZ2V0KVxyXG4gICAgICAgIGlmIChpbmRleCA8IDApIHtcclxuICAgICAgICAgIC8vIGV4dGVuc2lvbiBuZWVkZWQgYnkgbW9ieC1rZXlzdG9uZS15anNcclxuICAgICAgICAgIHRhcmdldC5wdXNoKG5ld1ZhbHVlKVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0YXJnZXQuc3BsaWNlKGluZGV4LCAwLCBuZXdWYWx1ZSlcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgfVxyXG5cclxuICAgICAgY2FzZSBcInJlbW92ZVwiOiB7XHJcbiAgICAgICAgY29uc3QgaW5kZXggPSArcHJvcCFcclxuICAgICAgICAvLyBubyByZWNvbmNpbGlhdGlvbiwgcmVtb3ZpbmdcclxuICAgICAgICB0YXJnZXQuc3BsaWNlKGluZGV4LCAxKVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNhc2UgXCJyZXBsYWNlXCI6IHtcclxuICAgICAgICBpZiAocHJvcCA9PT0gXCJsZW5ndGhcIikge1xyXG4gICAgICAgICAgdGFyZ2V0Lmxlbmd0aCA9IHBhdGNoLnZhbHVlXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnN0IGluZGV4ID0gK3Byb3AhXHJcbiAgICAgICAgICAvLyB0cnkgdG8gcmVjb25jaWxlXHJcbiAgICAgICAgICBjb25zdCBuZXdWYWx1ZSA9IHJlY29uY2lsZVNuYXBzaG90KHRhcmdldFtpbmRleF0sIHBhdGNoLnZhbHVlLCBtb2RlbFBvb2wsIHRhcmdldClcclxuICAgICAgICAgIHNldElmRGlmZmVyZW50KHRhcmdldCwgaW5kZXggYXMgYW55LCBuZXdWYWx1ZSlcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgfVxyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICB0aHJvdyBmYWlsdXJlKGB1bnN1cHBvcnRlZCBwYXRjaCBvcGVyYXRpb246ICR7KHBhdGNoIGFzIGFueSkub3B9YClcclxuICAgIH1cclxuICB9IGVsc2Uge1xyXG4gICAgc3dpdGNoIChwYXRjaC5vcCkge1xyXG4gICAgICBjYXNlIFwiYWRkXCI6IHtcclxuICAgICAgICAvLyByZWNvbmNpbGUgZnJvbSB0aGUgcG9vbCBpZiBwb3NzaWJsZVxyXG4gICAgICAgIGNvbnN0IG5ld1ZhbHVlID0gcmVjb25jaWxlU25hcHNob3QodW5kZWZpbmVkLCBwYXRjaC52YWx1ZSwgbW9kZWxQb29sLCB0YXJnZXQpXHJcbiAgICAgICAgc2V0SWZEaWZmZXJlbnQodGFyZ2V0LCBwcm9wISwgbmV3VmFsdWUpXHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgfVxyXG5cclxuICAgICAgY2FzZSBcInJlbW92ZVwiOiB7XHJcbiAgICAgICAgLy8gbm8gcmVjb25jaWxpYXRpb24sIHJlbW92aW5nXHJcbiAgICAgICAgcmVtb3ZlKHRhcmdldCwgcHJvcClcclxuICAgICAgICBicmVha1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjYXNlIFwicmVwbGFjZVwiOiB7XHJcbiAgICAgICAgLy8gdHJ5IHRvIHJlY29uY2lsZVxyXG4gICAgICAgIC8vIHdlIGRvbid0IG5lZWQgdG8gdHdlYWsgdGhlIHBvb2wgc2luY2UgcmVjb25jaWxlU25hcHNob3Qgd2lsbCBkbyB0aGF0IGZvciB1c1xyXG4gICAgICAgIGNvbnN0IG5ld1ZhbHVlID0gcmVjb25jaWxlU25hcHNob3QodGFyZ2V0W3Byb3AhXSwgcGF0Y2gudmFsdWUsIG1vZGVsUG9vbCwgdGFyZ2V0KVxyXG4gICAgICAgIHNldElmRGlmZmVyZW50KHRhcmdldCwgcHJvcCEsIG5ld1ZhbHVlKVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgdGhyb3cgZmFpbHVyZShgdW5zdXBwb3J0ZWQgcGF0Y2ggb3BlcmF0aW9uOiAkeyhwYXRjaCBhcyBhbnkpLm9wfWApXHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBwYXRoQXJyYXlUb09iamVjdEFuZFByb3AoXHJcbiAgb2JqOiBvYmplY3QsXHJcbiAgcGF0aDogUGF0Y2hbXCJwYXRoXCJdXHJcbik6IHsgdGFyZ2V0OiBhbnk7IHByb3A/OiBQYXRoRWxlbWVudCB9IHtcclxuICBpZiAoaW5EZXZNb2RlKSB7XHJcbiAgICBpZiAoIWlzQXJyYXkocGF0aCkpIHtcclxuICAgICAgdGhyb3cgZmFpbHVyZShgaW52YWxpZCBwYXRoOiAke3BhdGh9YClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGxldCB0YXJnZXQ6IGFueSA9IG1vZGVsVG9EYXRhTm9kZShvYmopXHJcblxyXG4gIGlmIChwYXRoLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgdGFyZ2V0LFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPD0gcGF0aC5sZW5ndGggLSAyOyBpKyspIHtcclxuICAgIHRhcmdldCA9IG1vZGVsVG9EYXRhTm9kZSh0YXJnZXRbcGF0aFtpXV0pXHJcbiAgfVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgdGFyZ2V0LFxyXG4gICAgcHJvcDogcGF0aFtwYXRoLmxlbmd0aCAtIDFdLFxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBpc01vZGVsQXV0b1R5cGVDaGVja2luZ0VuYWJsZWQgfSBmcm9tIFwiLi4vZ2xvYmFsQ29uZmlnL2dsb2JhbENvbmZpZ1wiXG5pbXBvcnQgdHlwZSB7IEFueU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Jhc2VNb2RlbFwiXG5pbXBvcnQgeyBnZXRNb2RlbE1ldGFkYXRhIH0gZnJvbSBcIi4uL21vZGVsL2dldE1vZGVsTWV0YWRhdGFcIlxuaW1wb3J0IHsgaXNNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXG5pbXBvcnQgeyBkYXRhVG9Nb2RlbE5vZGUgfSBmcm9tIFwiLi4vcGFyZW50L2NvcmVcIlxuaW1wb3J0IHsgZmluZFBhcmVudCB9IGZyb20gXCIuLi9wYXJlbnQvZmluZFBhcmVudFwiXG5pbXBvcnQgeyBpbnRlcm5hbEFwcGx5UGF0Y2hlcyB9IGZyb20gXCIuLi9wYXRjaC9hcHBseVBhdGNoZXNcIlxuaW1wb3J0IHsgSW50ZXJuYWxQYXRjaFJlY29yZGVyIH0gZnJvbSBcIi4uL3BhdGNoL2VtaXRQYXRjaFwiXG5pbXBvcnQgeyBpbnRlcm5hbEFwcGx5U25hcHNob3QgfSBmcm9tIFwiLi4vc25hcHNob3QvYXBwbHlTbmFwc2hvdFwiXG5pbXBvcnQgeyBpbnZhbGlkYXRlQ2FjaGVkVHlwZUNoZWNrZXJSZXN1bHQgfSBmcm9tIFwiLi4vdHlwZXMvVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHsgcnVuV2l0aG91dFNuYXBzaG90T3JQYXRjaGVzIH0gZnJvbSBcIi4vY29yZVwiXG5pbXBvcnQgeyBpc1R5cGVDaGVja2luZ0FsbG93ZWQgfSBmcm9tIFwiLi93aXRob3V0VHlwZUNoZWNraW5nXCJcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJ1blR5cGVDaGVja2luZ0FmdGVyQ2hhbmdlKFxuICBvYmo6IG9iamVjdCxcbiAgcGF0Y2hSZWNvcmRlcjogSW50ZXJuYWxQYXRjaFJlY29yZGVyIHwgdW5kZWZpbmVkLFxuICBzbmFwc2hvdEJlZm9yZUNoYW5nZXM/OiBvYmplY3Rcbikge1xuICBpZiAoIWlzVHlwZUNoZWNraW5nQWxsb3dlZCgpKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICAvLyBpbnZhbGlkYXRlIHR5cGUgY2hlY2sgY2FjaGVkIHJlc3VsdFxuICBpbnZhbGlkYXRlQ2FjaGVkVHlwZUNoZWNrZXJSZXN1bHQob2JqKVxuXG4gIGlmIChpc01vZGVsQXV0b1R5cGVDaGVja2luZ0VuYWJsZWQoKSkge1xuICAgIGNvbnN0IHBhcmVudE1vZGVsV2l0aFR5cGVDaGVja2VyID0gZmluZE5lYXJlc3RQYXJlbnRNb2RlbFdpdGhUeXBlQ2hlY2tlcihvYmopXG4gICAgaWYgKHBhcmVudE1vZGVsV2l0aFR5cGVDaGVja2VyKSB7XG4gICAgICBjb25zdCBlcnIgPSBwYXJlbnRNb2RlbFdpdGhUeXBlQ2hlY2tlci50eXBlQ2hlY2soKVxuICAgICAgaWYgKGVycikge1xuICAgICAgICAvLyBxdWlldGx5IGFwcGx5IGludmVyc2UgcGF0Y2hlcyAoZG8gbm90IGdlbmVyYXRlIHBhdGNoZXMsIHNuYXBzaG90cywgYWN0aW9ucywgZXRjKVxuICAgICAgICBydW5XaXRob3V0U25hcHNob3RPclBhdGNoZXMoKCkgPT4ge1xuICAgICAgICAgIGlmIChwYXRjaFJlY29yZGVyKSB7XG4gICAgICAgICAgICBpbnRlcm5hbEFwcGx5UGF0Y2hlcy5jYWxsKG9iaiwgcGF0Y2hSZWNvcmRlci5pbnZQYXRjaGVzLCB0cnVlKVxuICAgICAgICAgIH0gZWxzZSBpZiAoc25hcHNob3RCZWZvcmVDaGFuZ2VzKSB7XG4gICAgICAgICAgICBpbnRlcm5hbEFwcGx5U25hcHNob3QuY2FsbChvYmosIHNuYXBzaG90QmVmb3JlQ2hhbmdlcylcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC8vIGF0IHRoZSBlbmQgb2YgYXBwbHkgcGF0Y2hlcyBpdCB3aWxsIGJlIHR5cGUgY2hlY2tlZCBhZ2FpbiBhbmQgaXRzIHJlc3VsdCBjYWNoZWQgb25jZSBtb3JlXG4gICAgICAgIGVyci50aHJvdygpXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKlxuICogRmluZHMgdGhlIGNsb3Nlc3QgcGFyZW50IG1vZGVsIHRoYXQgaGFzIGEgdHlwZSBjaGVja2VyIGRlZmluZWQuXG4gKlxuICogQHBhcmFtIGNoaWxkXG4gKiBAcmV0dXJuc1xuICovXG5mdW5jdGlvbiBmaW5kTmVhcmVzdFBhcmVudE1vZGVsV2l0aFR5cGVDaGVja2VyKGNoaWxkOiBvYmplY3QpOiBBbnlNb2RlbCB8IHVuZGVmaW5lZCB7XG4gIC8vIGNoaWxkIG1pZ2h0IGJlIC4kLCBzbyB3ZSBuZWVkIHRvIGNoZWNrIHRoZSBwYXJlbnQgbW9kZWwgaW4gdGhhdCBjYXNlXG4gIGNvbnN0IGFjdHVhbENoaWxkID0gZGF0YVRvTW9kZWxOb2RlKGNoaWxkKVxuXG4gIGlmIChjaGlsZCAhPT0gYWN0dWFsQ2hpbGQpIHtcbiAgICBjaGlsZCA9IGFjdHVhbENoaWxkXG4gICAgaWYgKGlzTW9kZWwoY2hpbGQpICYmICEhZ2V0TW9kZWxNZXRhZGF0YShjaGlsZCkuZGF0YVR5cGUpIHtcbiAgICAgIHJldHVybiBjaGlsZFxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmaW5kUGFyZW50KGNoaWxkLCAocGFyZW50KSA9PiB7XG4gICAgcmV0dXJuIGlzTW9kZWwocGFyZW50KSAmJiAhIWdldE1vZGVsTWV0YWRhdGEocGFyZW50KS5kYXRhVHlwZVxuICB9KVxufVxuIiwiaW1wb3J0IHtcbiAgSUFycmF5V2lsbENoYW5nZSxcbiAgSUFycmF5V2lsbFNwbGljZSxcbiAgaW50ZXJjZXB0LFxuICBJT2JzZXJ2YWJsZUFycmF5LFxuICBpc09ic2VydmFibGVBcnJheSxcbiAgb2JzZXJ2YWJsZSxcbiAgb2JzZXJ2ZSxcbn0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgYXNzZXJ0Q2FuV3JpdGUgfSBmcm9tIFwiLi4vYWN0aW9uL3Byb3RlY3Rpb25cIlxuaW1wb3J0IHsgZ2V0R2xvYmFsQ29uZmlnIH0gZnJvbSBcIi4uL2dsb2JhbENvbmZpZ1wiXG5pbXBvcnQgdHlwZSB7IFBhcmVudFBhdGggfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxuaW1wb3J0IHsgc2V0UGFyZW50IH0gZnJvbSBcIi4uL3BhcmVudC9zZXRQYXJlbnRcIlxuaW1wb3J0IHsgSW50ZXJuYWxQYXRjaFJlY29yZGVyIH0gZnJvbSBcIi4uL3BhdGNoL2VtaXRQYXRjaFwiXG5pbXBvcnQgdHlwZSB7IFBhdGNoIH0gZnJvbSBcIi4uL3BhdGNoL1BhdGNoXCJcbmltcG9ydCB7XG4gIGZyZWV6ZUludGVybmFsU25hcHNob3QsXG4gIGdldEludGVybmFsU25hcHNob3QsXG4gIHNldE5ld0ludGVybmFsU25hcHNob3QsXG4gIHVwZGF0ZUludGVybmFsU25hcHNob3QsXG59IGZyb20gXCIuLi9zbmFwc2hvdC9pbnRlcm5hbFwiXG5pbXBvcnQgeyBmYWlsdXJlLCBpbkRldk1vZGUsIGlzQXJyYXksIGlzUHJpbWl0aXZlIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IHNldElmRGlmZmVyZW50IH0gZnJvbSBcIi4uL3V0aWxzL3NldElmRGlmZmVyZW50XCJcbmltcG9ydCB7IHJ1bm5pbmdXaXRob3V0U25hcHNob3RPclBhdGNoZXMsIHR3ZWFrZWRPYmplY3RzIH0gZnJvbSBcIi4vY29yZVwiXG5pbXBvcnQgeyByZWdpc3RlclR3ZWFrZXIsIHR3ZWFrIH0gZnJvbSBcIi4vdHdlYWtcIlxuaW1wb3J0IHsgVHdlYWtlclByaW9yaXR5IH0gZnJvbSBcIi4vVHdlYWtlclByaW9yaXR5XCJcbmltcG9ydCB7IHJ1blR5cGVDaGVja2luZ0FmdGVyQ2hhbmdlIH0gZnJvbSBcIi4vdHlwZUNoZWNraW5nXCJcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR3ZWFrQXJyYXk8VCBleHRlbmRzIGFueVtdPihcbiAgdmFsdWU6IFQsXG4gIHBhcmVudFBhdGg6IFBhcmVudFBhdGg8YW55PiB8IHVuZGVmaW5lZCxcbiAgZG9Ob3RUd2Vha0NoaWxkcmVuOiBib29sZWFuXG4pOiBUIHtcbiAgY29uc3Qgb3JpZ2luYWxBcnI6IFJlYWRvbmx5QXJyYXk8YW55PiA9IHZhbHVlXG4gIGNvbnN0IGFyckxuID0gb3JpZ2luYWxBcnIubGVuZ3RoXG4gIGNvbnN0IHR3ZWFrZWRBcnIgPSBpc09ic2VydmFibGVBcnJheShvcmlnaW5hbEFycilcbiAgICA/IG9yaWdpbmFsQXJyXG4gICAgOiBvYnNlcnZhYmxlLmFycmF5KHVuZGVmaW5lZCwgb2JzZXJ2YWJsZU9wdGlvbnMpXG4gIGlmICh0d2Vha2VkQXJyICE9PSBvcmlnaW5hbEFycikge1xuICAgIHR3ZWFrZWRBcnIubGVuZ3RoID0gb3JpZ2luYWxBcnIubGVuZ3RoXG4gIH1cblxuICBsZXQgaW50ZXJjZXB0RGlzcG9zZXI6ICgpID0+IHZvaWRcbiAgbGV0IG9ic2VydmVEaXNwb3NlcjogKCkgPT4gdm9pZFxuXG4gIGNvbnN0IHVudHdlYWsgPSAoKSA9PiB7XG4gICAgaW50ZXJjZXB0RGlzcG9zZXIoKVxuICAgIG9ic2VydmVEaXNwb3NlcigpXG4gIH1cblxuICB0d2Vha2VkT2JqZWN0cy5zZXQodHdlYWtlZEFyciwgdW50d2VhaylcbiAgc2V0UGFyZW50KHtcbiAgICB2YWx1ZTogdHdlYWtlZEFycixcbiAgICBwYXJlbnRQYXRoLFxuICAgIGluZGV4Q2hhbmdlQWxsb3dlZDogZmFsc2UsXG4gICAgaXNEYXRhT2JqZWN0OiBmYWxzZSxcbiAgICAvLyBhcnJheXMgc2hvdWxkbid0IGJlIGNsb25lZCBhbnl3YXlcbiAgICBjbG9uZUlmQXBwbGljYWJsZTogZmFsc2UsXG4gIH0pXG5cbiAgY29uc3QgdW50cmFuc2Zvcm1lZFNuOiBhbnlbXSA9IFtdXG4gIHVudHJhbnNmb3JtZWRTbi5sZW5ndGggPSBhcnJMblxuXG4gIC8vIHN1YnN0aXR1dGUgaW5pdGlhbCB2YWx1ZXMgYnkgcHJveGllZCB2YWx1ZXNcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJMbjsgaSsrKSB7XG4gICAgY29uc3QgdiA9IG9yaWdpbmFsQXJyW2ldXG5cbiAgICBpZiAoaXNQcmltaXRpdmUodikpIHtcbiAgICAgIGlmICghZG9Ob3RUd2Vha0NoaWxkcmVuKSB7XG4gICAgICAgIHNldElmRGlmZmVyZW50KHR3ZWFrZWRBcnIsIGksIHYpXG4gICAgICB9XG5cbiAgICAgIHVudHJhbnNmb3JtZWRTbltpXSA9IHZcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcGF0aCA9IHsgcGFyZW50OiB0d2Vha2VkQXJyLCBwYXRoOiBpIH1cblxuICAgICAgbGV0IHR3ZWFrZWRWYWx1ZVxuICAgICAgaWYgKGRvTm90VHdlYWtDaGlsZHJlbikge1xuICAgICAgICB0d2Vha2VkVmFsdWUgPSB2XG4gICAgICAgIHNldFBhcmVudCh7XG4gICAgICAgICAgdmFsdWU6IHR3ZWFrZWRWYWx1ZSxcbiAgICAgICAgICBwYXJlbnRQYXRoOiBwYXRoLFxuICAgICAgICAgIGluZGV4Q2hhbmdlQWxsb3dlZDogZmFsc2UsXG4gICAgICAgICAgaXNEYXRhT2JqZWN0OiBmYWxzZSxcbiAgICAgICAgICAvLyB0aGUgdmFsdWUgaXMgYWxyZWFkeSBhIG5ldyB2YWx1ZSAodGhlIHJlc3VsdCBvZiBhIGZyb21TbmFwc2hvdClcbiAgICAgICAgICBjbG9uZUlmQXBwbGljYWJsZTogZmFsc2UsXG4gICAgICAgIH0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0d2Vha2VkVmFsdWUgPSB0d2Vhayh2LCBwYXRoKVxuICAgICAgICBzZXRJZkRpZmZlcmVudCh0d2Vha2VkQXJyLCBpLCB0d2Vha2VkVmFsdWUpXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHZhbHVlU24gPSBnZXRJbnRlcm5hbFNuYXBzaG90KHR3ZWFrZWRWYWx1ZSkhXG4gICAgICB1bnRyYW5zZm9ybWVkU25baV0gPSB2YWx1ZVNuLnRyYW5zZm9ybWVkXG4gICAgfVxuICB9XG5cbiAgc2V0TmV3SW50ZXJuYWxTbmFwc2hvdCh0d2Vha2VkQXJyLCB1bnRyYW5zZm9ybWVkU24sIHVuZGVmaW5lZClcblxuICBpbnRlcmNlcHREaXNwb3NlciA9IGludGVyY2VwdCh0d2Vha2VkQXJyLCBpbnRlcmNlcHRBcnJheU11dGF0aW9uLmJpbmQodW5kZWZpbmVkLCB0d2Vha2VkQXJyKSlcbiAgb2JzZXJ2ZURpc3Bvc2VyID0gb2JzZXJ2ZSh0d2Vha2VkQXJyLCBhcnJheURpZENoYW5nZSlcblxuICByZXR1cm4gdHdlYWtlZEFyciBhcyBhbnlcbn1cblxuZnVuY3Rpb24gbXV0YXRlU2V0KGs6IG51bWJlciwgdjogdW5rbm93biwgc246IHVua25vd25bXSkge1xuICBzbltrXSA9IHZcbn1cblxuZnVuY3Rpb24gbXV0YXRlU3BsaWNlKGluZGV4OiBudW1iZXIsIHJlbW92ZWRDb3VudDogbnVtYmVyLCBhZGRlZEl0ZW1zOiBhbnlbXSwgc246IGFueVtdKSB7XG4gIHNuLnNwbGljZShpbmRleCwgcmVtb3ZlZENvdW50LCAuLi5hZGRlZEl0ZW1zKVxufVxuXG5jb25zdCBwYXRjaFJlY29yZGVyID0gbmV3IEludGVybmFsUGF0Y2hSZWNvcmRlcigpXG5cbmZ1bmN0aW9uIGFycmF5RGlkQ2hhbmdlKGNoYW5nZTogYW55IC8qSUFycmF5RGlkQ2hhbmdlKi8pIHtcbiAgY29uc3QgYXJyID0gY2hhbmdlLm9iamVjdFxuICBsZXQgb2xkU25hcHNob3QgPSBnZXRJbnRlcm5hbFNuYXBzaG90KGFyciBhcyBBcnJheTxhbnk+KSEudW50cmFuc2Zvcm1lZFxuXG4gIHBhdGNoUmVjb3JkZXIucmVzZXQoKVxuXG4gIGxldCBtdXRhdGU6ICgoc246IGFueVtdKSA9PiB2b2lkKSB8IHVuZGVmaW5lZFxuXG4gIHN3aXRjaCAoY2hhbmdlLnR5cGUpIHtcbiAgICBjYXNlIFwic3BsaWNlXCI6XG4gICAgICBtdXRhdGUgPSBhcnJheURpZENoYW5nZVNwbGljZShjaGFuZ2UsIG9sZFNuYXBzaG90KVxuICAgICAgYnJlYWtcblxuICAgIGNhc2UgXCJ1cGRhdGVcIjpcbiAgICAgIG11dGF0ZSA9IGFycmF5RGlkQ2hhbmdlVXBkYXRlKGNoYW5nZSwgb2xkU25hcHNob3QpXG4gICAgICBicmVha1xuICB9XG5cbiAgcnVuVHlwZUNoZWNraW5nQWZ0ZXJDaGFuZ2UoYXJyLCBwYXRjaFJlY29yZGVyKVxuXG4gIGlmICghcnVubmluZ1dpdGhvdXRTbmFwc2hvdE9yUGF0Y2hlcyAmJiBtdXRhdGUpIHtcbiAgICB1cGRhdGVJbnRlcm5hbFNuYXBzaG90KGFyciwgbXV0YXRlKVxuICAgIHBhdGNoUmVjb3JkZXIuZW1pdChhcnIpXG4gIH1cbn1cblxuY29uc3QgdW5kZWZpbmVkSW5zaWRlQXJyYXlFcnJvck1zZyA9XG4gIFwidW5kZWZpbmVkIGlzIG5vdCBzdXBwb3J0ZWQgaW5zaWRlIGFycmF5cyBzaW5jZSBpdCBpcyBub3Qgc2VyaWFsaXphYmxlIGluIEpTT04sIGNvbnNpZGVyIHVzaW5nIG51bGwgaW5zdGVhZFwiXG5cbmZ1bmN0aW9uIGFycmF5RGlkQ2hhbmdlVXBkYXRlKGNoYW5nZTogYW55IC8qSUFycmF5RGlkQ2hhbmdlKi8sIG9sZFNuYXBzaG90OiBhbnkpIHtcbiAgY29uc3QgayA9IGNoYW5nZS5pbmRleFxuICBjb25zdCB2YWwgPSBjaGFuZ2UubmV3VmFsdWVcbiAgY29uc3Qgb2xkVmFsID0gb2xkU25hcHNob3Rba11cbiAgbGV0IG5ld1ZhbDogYW55XG4gIGlmIChpc1ByaW1pdGl2ZSh2YWwpKSB7XG4gICAgbmV3VmFsID0gdmFsXG4gIH0gZWxzZSB7XG4gICAgY29uc3QgdmFsdWVTbiA9IGdldEludGVybmFsU25hcHNob3QodmFsKSFcbiAgICBuZXdWYWwgPSB2YWx1ZVNuLnRyYW5zZm9ybWVkXG4gIH1cbiAgY29uc3QgbXV0YXRlID0gbXV0YXRlU2V0LmJpbmQodW5kZWZpbmVkLCBrLCBuZXdWYWwpXG5cbiAgY29uc3QgcGF0aCA9IFtrXVxuXG4gIHBhdGNoUmVjb3JkZXIucmVjb3JkKFxuICAgIFtcbiAgICAgIHtcbiAgICAgICAgb3A6IFwicmVwbGFjZVwiLFxuICAgICAgICBwYXRoLFxuICAgICAgICB2YWx1ZTogZnJlZXplSW50ZXJuYWxTbmFwc2hvdChuZXdWYWwpLFxuICAgICAgfSxcbiAgICBdLFxuICAgIFtcbiAgICAgIHtcbiAgICAgICAgb3A6IFwicmVwbGFjZVwiLFxuICAgICAgICBwYXRoLFxuICAgICAgICB2YWx1ZTogZnJlZXplSW50ZXJuYWxTbmFwc2hvdChvbGRWYWwpLFxuICAgICAgfSxcbiAgICBdXG4gIClcbiAgcmV0dXJuIG11dGF0ZVxufVxuXG5mdW5jdGlvbiBhcnJheURpZENoYW5nZVNwbGljZShjaGFuZ2U6IGFueSAvKklBcnJheURpZENoYW5nZSovLCBvbGRTbmFwc2hvdDogYW55KSB7XG4gIGNvbnN0IGluZGV4ID0gY2hhbmdlLmluZGV4XG4gIGNvbnN0IGFkZGVkQ291bnQgPSBjaGFuZ2UuYWRkZWRDb3VudFxuICBjb25zdCByZW1vdmVkQ291bnQgPSBjaGFuZ2UucmVtb3ZlZENvdW50XG5cbiAgbGV0IGFkZGVkSXRlbXM6IGFueVtdID0gW11cbiAgYWRkZWRJdGVtcy5sZW5ndGggPSBhZGRlZENvdW50XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYWRkZWRDb3VudDsgaSsrKSB7XG4gICAgY29uc3QgdiA9IGNoYW5nZS5hZGRlZFtpXVxuICAgIGlmIChpc1ByaW1pdGl2ZSh2KSkge1xuICAgICAgYWRkZWRJdGVtc1tpXSA9IHZcbiAgICB9IGVsc2Uge1xuICAgICAgYWRkZWRJdGVtc1tpXSA9IGdldEludGVybmFsU25hcHNob3QodikhLnRyYW5zZm9ybWVkXG4gICAgfVxuICB9XG5cbiAgY29uc3Qgb2xkTGVuID0gb2xkU25hcHNob3QubGVuZ3RoXG4gIGNvbnN0IG11dGF0ZSA9IG11dGF0ZVNwbGljZS5iaW5kKHVuZGVmaW5lZCwgaW5kZXgsIHJlbW92ZWRDb3VudCwgYWRkZWRJdGVtcylcblxuICBjb25zdCBwYXRjaGVzOiBQYXRjaFtdID0gW11cbiAgY29uc3QgaW52UGF0Y2hlczogUGF0Y2hbXSA9IFtdXG5cbiAgLy8gb3B0aW1pemF0aW9uOiBpZiB3ZSBhZGQgYXMgbWFueSBhcyB3ZSByZW1vdmUgdGhlbiByZW1vdmUvcmVhZGQgaW5zdGVhZFxuXG4gIC8vIHdlIGNhbm5vdCByZXBsYWNlIHNpbmNlIHdlIG1pZ2h0IGVuZCB1cCBpbiBhIHNpdHVhdGlvbiB3aGVyZSB0aGUgc2FtZSBub2RlXG4gIC8vIG1pZ2h0IGF0dGVtcHQgdG8gYmUgdGVtcG9yYXJpbHkgdHdpY2UgaW5zaWRlIHRoZSBzYW1lIHRyZWUgKGUuZy4gc29ydGluZylcblxuICAvLyBpdCB3b3VsZCBiZSBmYXN0ZXIgdG8ga2VlcCBob2xlcyByYXRoZXIgdGhhbiByZW1vdmUvcmVhZGQsIGJ1dCBpZiB3ZSBkbyB0aGF0IHRoZW5cbiAgLy8gdmFsaWRhdGlvbiBtaWdodCBmYWlsXG5cbiAgaWYgKGFkZGVkQ291bnQgPT09IHJlbW92ZWRDb3VudCkge1xuICAgIGNvbnN0IHJlYWRkUGF0Y2hlczogUGF0Y2hbXSA9IFtdXG4gICAgY29uc3QgcmVhZGRJbnZQYXRjaGVzOiBQYXRjaFtdID0gW11cbiAgICBsZXQgcmVtb3ZlZCA9IDBcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWRkZWRDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCByZWFsSW5kZXggPSBpbmRleCArIGlcblxuICAgICAgY29uc3QgbmV3VmFsID0gZ2V0VmFsdWVBZnRlclNwbGljZShvbGRTbmFwc2hvdCwgcmVhbEluZGV4LCBpbmRleCwgcmVtb3ZlZENvdW50LCBhZGRlZEl0ZW1zKVxuICAgICAgY29uc3Qgb2xkVmFsID0gb2xkU25hcHNob3RbcmVhbEluZGV4XVxuXG4gICAgICBpZiAobmV3VmFsICE9PSBvbGRWYWwpIHtcbiAgICAgICAgY29uc3QgcmVtb3ZlUGF0aCA9IFtyZWFsSW5kZXggLSByZW1vdmVkXVxuICAgICAgICBwYXRjaGVzLnB1c2goe1xuICAgICAgICAgIG9wOiBcInJlbW92ZVwiLFxuICAgICAgICAgIHBhdGg6IHJlbW92ZVBhdGgsXG4gICAgICAgIH0pXG4gICAgICAgIGludlBhdGNoZXMucHVzaCh7XG4gICAgICAgICAgb3A6IFwicmVtb3ZlXCIsXG4gICAgICAgICAgcGF0aDogcmVtb3ZlUGF0aCxcbiAgICAgICAgfSlcblxuICAgICAgICByZW1vdmVkKytcblxuICAgICAgICBjb25zdCByZWFkZFBhdGggPSBbcmVhbEluZGV4XVxuICAgICAgICByZWFkZFBhdGNoZXMucHVzaCh7XG4gICAgICAgICAgb3A6IFwiYWRkXCIsXG4gICAgICAgICAgcGF0aDogcmVhZGRQYXRoLFxuICAgICAgICAgIHZhbHVlOiBmcmVlemVJbnRlcm5hbFNuYXBzaG90KG5ld1ZhbCksXG4gICAgICAgIH0pXG5cbiAgICAgICAgcmVhZGRJbnZQYXRjaGVzLnB1c2goe1xuICAgICAgICAgIG9wOiBcImFkZFwiLFxuICAgICAgICAgIHBhdGg6IHJlYWRkUGF0aCxcbiAgICAgICAgICB2YWx1ZTogZnJlZXplSW50ZXJuYWxTbmFwc2hvdChvbGRWYWwpLFxuICAgICAgICB9KVxuICAgICAgfVxuICAgIH1cblxuICAgIHBhdGNoZXMucHVzaCguLi5yZWFkZFBhdGNoZXMpXG4gICAgaW52UGF0Y2hlcy5wdXNoKC4uLnJlYWRkSW52UGF0Y2hlcylcbiAgICAvLyB3ZSBuZWVkIHRvIHJldmVyc2Ugc2luY2UgaW52ZXJzZSBwYXRjaGVzIGFyZSBhcHBsaWVkIGluIHJldmVyc2VcbiAgICBpbnZQYXRjaGVzLnJldmVyc2UoKVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IGludGVyaW1MZW4gPSBvbGRMZW4gLSByZW1vdmVkQ291bnRcblxuICAgIC8vIGZpcnN0IHJlbW92ZSBpdGVtc1xuICAgIGlmIChyZW1vdmVkQ291bnQgPiAwKSB7XG4gICAgICAvLyBvcHRpbWl6YXRpb24sIHdoZW4gcmVtb3ZpbmcgZnJvbSB0aGUgZW5kIHNldCB0aGUgbGVuZ3RoIGluc3RlYWRcbiAgICAgIGNvbnN0IHJlbW92ZVVzaW5nU2V0TGVuZ3RoID0gaW5kZXggPj0gaW50ZXJpbUxlblxuICAgICAgaWYgKHJlbW92ZVVzaW5nU2V0TGVuZ3RoKSB7XG4gICAgICAgIHBhdGNoZXMucHVzaCh7XG4gICAgICAgICAgb3A6IFwicmVwbGFjZVwiLFxuICAgICAgICAgIHBhdGg6IFtcImxlbmd0aFwiXSxcbiAgICAgICAgICB2YWx1ZTogaW50ZXJpbUxlbixcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IHJlbW92ZWRDb3VudCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGNvbnN0IHJlYWxJbmRleCA9IGluZGV4ICsgaVxuICAgICAgICBjb25zdCBwYXRoID0gW3JlYWxJbmRleF1cblxuICAgICAgICBpZiAoIXJlbW92ZVVzaW5nU2V0TGVuZ3RoKSB7XG4gICAgICAgICAgLy8gcmVtb3ZlIC4uLjIsIDEsIDBcbiAgICAgICAgICBwYXRjaGVzLnB1c2goe1xuICAgICAgICAgICAgb3A6IFwicmVtb3ZlXCIsXG4gICAgICAgICAgICBwYXRoLFxuICAgICAgICAgIH0pXG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGQgMCwgMSwgMi4uLiBzaW5jZSBpbnZlcnNlIHBhdGNoZXMgYXJlIGFwcGxpZWQgaW4gcmV2ZXJzZVxuICAgICAgICBpbnZQYXRjaGVzLnB1c2goe1xuICAgICAgICAgIG9wOiBcImFkZFwiLFxuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgdmFsdWU6IGZyZWV6ZUludGVybmFsU25hcHNob3Qob2xkU25hcHNob3RbcmVhbEluZGV4XSksXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhlbiBhZGQgaXRlbXNcbiAgICBpZiAoYWRkZWRDb3VudCA+IDApIHtcbiAgICAgIC8vIG9wdGltaXphdGlvbiwgZm9yIGludmVyc2UgcGF0Y2hlcywgd2hlbiBhZGRpbmcgZnJvbSB0aGUgZW5kIHNldCB0aGUgbGVuZ3RoIHRvIHJlc3RvcmUgaW5zdGVhZFxuICAgICAgY29uc3QgcmVzdG9yZVVzaW5nU2V0TGVuZ3RoID0gaW5kZXggPj0gaW50ZXJpbUxlblxuICAgICAgaWYgKHJlc3RvcmVVc2luZ1NldExlbmd0aCkge1xuICAgICAgICBpbnZQYXRjaGVzLnB1c2goe1xuICAgICAgICAgIG9wOiBcInJlcGxhY2VcIixcbiAgICAgICAgICBwYXRoOiBbXCJsZW5ndGhcIl0sXG4gICAgICAgICAgdmFsdWU6IGludGVyaW1MZW4sXG4gICAgICAgIH0pXG4gICAgICB9XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWRkZWRDb3VudDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHJlYWxJbmRleCA9IGluZGV4ICsgaVxuICAgICAgICBjb25zdCBwYXRoID0gW3JlYWxJbmRleF1cblxuICAgICAgICAvLyBhZGQgMCwgMSwgMi4uLlxuICAgICAgICBwYXRjaGVzLnB1c2goe1xuICAgICAgICAgIG9wOiBcImFkZFwiLFxuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgdmFsdWU6IGZyZWV6ZUludGVybmFsU25hcHNob3QoXG4gICAgICAgICAgICBnZXRWYWx1ZUFmdGVyU3BsaWNlKG9sZFNuYXBzaG90LCByZWFsSW5kZXgsIGluZGV4LCByZW1vdmVkQ291bnQsIGFkZGVkSXRlbXMpXG4gICAgICAgICAgKSxcbiAgICAgICAgfSlcblxuICAgICAgICAvLyByZW1vdmUgLi4uMiwgMSwgMCBzaW5jZSBpbnZlcnNlIHBhdGNoZXMgYXJlIGFwcGxpZWQgaW4gcmV2ZXJzZVxuICAgICAgICBpZiAoIXJlc3RvcmVVc2luZ1NldExlbmd0aCkge1xuICAgICAgICAgIGludlBhdGNoZXMucHVzaCh7XG4gICAgICAgICAgICBvcDogXCJyZW1vdmVcIixcbiAgICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBhdGNoUmVjb3JkZXIucmVjb3JkKHBhdGNoZXMsIGludlBhdGNoZXMpXG4gIHJldHVybiBtdXRhdGVcbn1cblxuLy8gVE9ETzogcmVtb3ZlIGFycmF5IHBhcmFtZXRlciBhbmQganVzdCB1c2UgY2hhbmdlLm9iamVjdCBvbmNlIG1vYnggdXBkYXRlIGV2ZW50IGlzIGZpeGVkXG5mdW5jdGlvbiBpbnRlcmNlcHRBcnJheU11dGF0aW9uKFxuICBhcnJheTogSU9ic2VydmFibGVBcnJheSxcbiAgY2hhbmdlOiBJQXJyYXlXaWxsQ2hhbmdlIHwgSUFycmF5V2lsbFNwbGljZVxuKSB7XG4gIGFzc2VydENhbldyaXRlKClcblxuICBzd2l0Y2ggKGNoYW5nZS50eXBlKSB7XG4gICAgY2FzZSBcInNwbGljZVwiOlxuICAgICAgaW50ZXJjZXB0QXJyYXlNdXRhdGlvblNwbGljZShjaGFuZ2UpXG4gICAgICBicmVha1xuXG4gICAgY2FzZSBcInVwZGF0ZVwiOlxuICAgICAgaW50ZXJjZXB0QXJyYXlNdXRhdGlvblVwZGF0ZShjaGFuZ2UsIGFycmF5KVxuICAgICAgYnJlYWtcbiAgfVxuICByZXR1cm4gY2hhbmdlXG59XG5cbmZ1bmN0aW9uIGludGVyY2VwdEFycmF5TXV0YXRpb25VcGRhdGUoY2hhbmdlOiBJQXJyYXlXaWxsQ2hhbmdlLCBhcnJheTogSU9ic2VydmFibGVBcnJheSkge1xuICBpZiAoXG4gICAgaW5EZXZNb2RlICYmXG4gICAgIWdldEdsb2JhbENvbmZpZygpLmFsbG93VW5kZWZpbmVkQXJyYXlFbGVtZW50cyAmJlxuICAgIGNoYW5nZS5uZXdWYWx1ZSA9PT0gdW5kZWZpbmVkXG4gICkge1xuICAgIHRocm93IGZhaWx1cmUodW5kZWZpbmVkSW5zaWRlQXJyYXlFcnJvck1zZylcbiAgfVxuXG4gIC8vIFRPRE86IHNob3VsZCBiZSBjaGFuZ2Uub2JqZWN0LCBidXQgbW9ieCBpcyBidWdnZWQgYW5kIGRvZXNuJ3Qgc2VuZCB0aGUgcHJveHlcbiAgY29uc3Qgb2xkVmFsID0gYXJyYXlbY2hhbmdlLmluZGV4XVxuICB0d2VhayhvbGRWYWwsIHVuZGVmaW5lZCkgLy8gc2V0IG9sZCBwcm9wIG9iaiBwYXJlbnQgdG8gdW5kZWZpbmVkXG5cbiAgY2hhbmdlLm5ld1ZhbHVlID0gdHdlYWsoY2hhbmdlLm5ld1ZhbHVlLCB7IHBhcmVudDogYXJyYXksIHBhdGg6IGNoYW5nZS5pbmRleCB9KVxufVxuXG5mdW5jdGlvbiBpbnRlcmNlcHRBcnJheU11dGF0aW9uU3BsaWNlKGNoYW5nZTogSUFycmF5V2lsbFNwbGljZSkge1xuICBpZiAoaW5EZXZNb2RlICYmICFnZXRHbG9iYWxDb25maWcoKS5hbGxvd1VuZGVmaW5lZEFycmF5RWxlbWVudHMpIHtcbiAgICBjb25zdCBsZW4gPSBjaGFuZ2UuYWRkZWQubGVuZ3RoXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgY29uc3QgdiA9IGNoYW5nZS5hZGRlZFtpXVxuICAgICAgaWYgKHYgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBmYWlsdXJlKHVuZGVmaW5lZEluc2lkZUFycmF5RXJyb3JNc2cpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGFuZ2UucmVtb3ZlZENvdW50OyBpKyspIHtcbiAgICBjb25zdCByZW1vdmVkVmFsdWUgPSBjaGFuZ2Uub2JqZWN0W2NoYW5nZS5pbmRleCArIGldXG4gICAgdHdlYWsocmVtb3ZlZFZhbHVlLCB1bmRlZmluZWQpXG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGNoYW5nZS5hZGRlZC5sZW5ndGg7IGkrKykge1xuICAgIGNoYW5nZS5hZGRlZFtpXSA9IHR3ZWFrKGNoYW5nZS5hZGRlZFtpXSwge1xuICAgICAgcGFyZW50OiBjaGFuZ2Uub2JqZWN0LFxuICAgICAgcGF0aDogY2hhbmdlLmluZGV4ICsgaSxcbiAgICB9KVxuICB9XG5cbiAgLy8gd2UgbWlnaHQgYWxzbyBuZWVkIHRvIHVwZGF0ZSB0aGUgcGFyZW50IG9mIHRoZSBuZXh0IGluZGV4ZXNcbiAgY29uc3Qgb2xkTmV4dEluZGV4ID0gY2hhbmdlLmluZGV4ICsgY2hhbmdlLnJlbW92ZWRDb3VudFxuICBjb25zdCBuZXdOZXh0SW5kZXggPSBjaGFuZ2UuaW5kZXggKyBjaGFuZ2UuYWRkZWQubGVuZ3RoXG5cbiAgaWYgKG9sZE5leHRJbmRleCAhPT0gbmV3TmV4dEluZGV4KSB7XG4gICAgZm9yIChsZXQgaSA9IG9sZE5leHRJbmRleCwgaiA9IG5ld05leHRJbmRleDsgaSA8IGNoYW5nZS5vYmplY3QubGVuZ3RoOyBpKyssIGorKykge1xuICAgICAgc2V0UGFyZW50KHtcbiAgICAgICAgdmFsdWU6IGNoYW5nZS5vYmplY3RbaV0sXG4gICAgICAgIHBhcmVudFBhdGg6IHtcbiAgICAgICAgICBwYXJlbnQ6IGNoYW5nZS5vYmplY3QsXG4gICAgICAgICAgcGF0aDogaixcbiAgICAgICAgfSxcbiAgICAgICAgaW5kZXhDaGFuZ2VBbGxvd2VkOiB0cnVlLFxuICAgICAgICBpc0RhdGFPYmplY3Q6IGZhbHNlLFxuICAgICAgICAvLyBqdXN0IHJlLWluZGV4aW5nXG4gICAgICAgIGNsb25lSWZBcHBsaWNhYmxlOiBmYWxzZSxcbiAgICAgIH0pXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckFycmF5VHdlYWtlcigpIHtcbiAgcmVnaXN0ZXJUd2Vha2VyKFR3ZWFrZXJQcmlvcml0eS5BcnJheSwgKHZhbHVlLCBwYXJlbnRQYXRoKSA9PiB7XG4gICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgICByZXR1cm4gdHdlYWtBcnJheSh2YWx1ZSwgcGFyZW50UGF0aCwgZmFsc2UpXG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfSlcbn1cblxuY29uc3Qgb2JzZXJ2YWJsZU9wdGlvbnMgPSB7XG4gIGRlZXA6IGZhbHNlLFxufVxuXG5mdW5jdGlvbiBnZXRWYWx1ZUFmdGVyU3BsaWNlPFQ+KFxuICBhcnJheTogcmVhZG9ubHkgVFtdLFxuICBpOiBudW1iZXIsXG4gIGluZGV4OiBudW1iZXIsXG4gIHJlbW92ZTogbnVtYmVyLFxuICBhZGRlZEl0ZW1zOiByZWFkb25seSBUW11cbikge1xuICBjb25zdCBiYXNlID0gaSAtIGluZGV4XG4gIGlmIChiYXNlIDwgMCkge1xuICAgIHJldHVybiBhcnJheVtpXVxuICB9XG5cbiAgaWYgKGJhc2UgPCBhZGRlZEl0ZW1zLmxlbmd0aCkge1xuICAgIHJldHVybiBhZGRlZEl0ZW1zW2Jhc2VdXG4gIH1cblxuICByZXR1cm4gYXJyYXlbaSAtIGFkZGVkSXRlbXMubGVuZ3RoICsgcmVtb3ZlXVxufVxuIiwiaW1wb3J0IHsgb2JzZXJ2YWJsZSB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IHR3ZWFrQXJyYXkgfSBmcm9tIFwiLi4vdHdlYWtlci90d2Vha0FycmF5XCJcbmltcG9ydCB7IGlzQXJyYXkgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHtcbiAgRnJvbVNuYXBzaG90Q29udGV4dCxcbiAgaW50ZXJuYWxGcm9tU25hcHNob3QsXG4gIG9ic2VydmFibGVPcHRpb25zLFxuICByZWdpc3RlclNuYXBzaG90dGVyLFxufSBmcm9tIFwiLi9mcm9tU25hcHNob3RcIlxuaW1wb3J0IHsgU25hcHNob3RJbk9mT2JqZWN0IH0gZnJvbSBcIi4vU25hcHNob3RPZlwiXG5pbXBvcnQgeyBTbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eSB9IGZyb20gXCIuL1NuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5XCJcblxuZnVuY3Rpb24gZnJvbUFycmF5U25hcHNob3Qoc246IFNuYXBzaG90SW5PZk9iamVjdDxhbnk+LCBjdHg6IEZyb21TbmFwc2hvdENvbnRleHQpOiBhbnlbXSB7XG4gIGNvbnN0IGFyciA9IG9ic2VydmFibGUuYXJyYXkoW10gYXMgYW55W10sIG9ic2VydmFibGVPcHRpb25zKVxuICBjb25zdCBsbiA9IHNuLmxlbmd0aFxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxuOyBpKyspIHtcbiAgICBhcnIucHVzaChpbnRlcm5hbEZyb21TbmFwc2hvdChzbltpXSwgY3R4KSlcbiAgfVxuICByZXR1cm4gdHdlYWtBcnJheShhcnIsIHVuZGVmaW5lZCwgdHJ1ZSlcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyRnJvbUFycmF5U25hcHNob3R0ZXIoKSB7XG4gIHJlZ2lzdGVyU25hcHNob3R0ZXIoU25hcHNob3R0ZXJBbmRSZWNvbmNpbGVyUHJpb3JpdHkuQXJyYXksIChzbiwgY3R4KSA9PiB7XG4gICAgaWYgKGlzQXJyYXkoc24pKSB7XG4gICAgICByZXR1cm4gZnJvbUFycmF5U25hcHNob3Qoc24sIGN0eClcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9KVxufVxuIiwiaW1wb3J0IHsgZnJvemVuLCBpc0Zyb3plblNuYXBzaG90IH0gZnJvbSBcIi4uL2Zyb3plbi9Gcm96ZW5cIlxuaW1wb3J0IHsgcmVnaXN0ZXJTbmFwc2hvdHRlciB9IGZyb20gXCIuL2Zyb21TbmFwc2hvdFwiXG5pbXBvcnQgeyBTbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eSB9IGZyb20gXCIuL1NuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5XCJcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyRnJvbUZyb3plblNuYXBzaG90dGVyKCkge1xuICByZWdpc3RlclNuYXBzaG90dGVyKFNuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5LkZyb3plbiwgKHNuKSA9PiB7XG4gICAgaWYgKGlzRnJvemVuU25hcHNob3Qoc24pKSB7XG4gICAgICByZXR1cm4gZnJvemVuKHNuLmRhdGEpXG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfSlcbn1cbiIsImltcG9ydCB7IEFueU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Jhc2VNb2RlbFwiXHJcbmltcG9ydCB7IGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUgfSBmcm9tIFwiLi4vbW9kZWwvZ2V0TW9kZWxNZXRhZGF0YVwiXHJcbmltcG9ydCB7IG1vZGVsVHlwZUtleSB9IGZyb20gXCIuLi9tb2RlbC9tZXRhZGF0YVwiXHJcbmltcG9ydCB7IE1vZGVsQ29uc3RydWN0b3JPcHRpb25zIH0gZnJvbSBcIi4uL21vZGVsL01vZGVsQ29uc3RydWN0b3JPcHRpb25zXCJcclxuaW1wb3J0IHsgaXNNb2RlbFNuYXBzaG90IH0gZnJvbSBcIi4uL21vZGVsL3V0aWxzXCJcclxuaW1wb3J0IHsgTW9kZWxDbGFzcyB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9CYXNlTW9kZWxTaGFyZWRcIlxyXG5pbXBvcnQgeyBnZXRNb2RlbEluZm9Gb3JOYW1lIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL21vZGVsSW5mb1wiXHJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQgeyBGcm9tU25hcHNob3RDb250ZXh0LCByZWdpc3RlclNuYXBzaG90dGVyIH0gZnJvbSBcIi4vZnJvbVNuYXBzaG90XCJcclxuaW1wb3J0IHsgU25hcHNob3RJbk9mTW9kZWwgfSBmcm9tIFwiLi9TbmFwc2hvdE9mXCJcclxuaW1wb3J0IHsgU25hcHNob3R0ZXJBbmRSZWNvbmNpbGVyUHJpb3JpdHkgfSBmcm9tIFwiLi9TbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eVwiXHJcblxyXG5mdW5jdGlvbiBmcm9tTW9kZWxTbmFwc2hvdChzbjogU25hcHNob3RJbk9mTW9kZWw8QW55TW9kZWw+LCBjdHg6IEZyb21TbmFwc2hvdENvbnRleHQpOiBBbnlNb2RlbCB7XHJcbiAgY29uc3QgdHlwZSA9IHNuW21vZGVsVHlwZUtleV1cclxuXHJcbiAgaWYgKCF0eXBlKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKGBhIG1vZGVsIHNuYXBzaG90IG11c3QgY29udGFpbiBhIHR5cGUga2V5ICgke21vZGVsVHlwZUtleX0pLCBidXQgbm9uZSB3YXMgZm91bmRgKVxyXG4gIH1cclxuXHJcbiAgY29uc3QgbW9kZWxJbmZvID0gZ2V0TW9kZWxJbmZvRm9yTmFtZSh0eXBlKVxyXG4gIGlmICghbW9kZWxJbmZvKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKGBtb2RlbCB3aXRoIG5hbWUgXCIke3R5cGV9XCIgbm90IGZvdW5kIGluIHRoZSByZWdpc3RyeWApXHJcbiAgfVxyXG5cclxuICBjb25zdCBtb2RlbElkUHJvcGVydHlOYW1lID0gZ2V0TW9kZWxJZFByb3BlcnR5TmFtZShtb2RlbEluZm8uY2xhc3MgYXMgTW9kZWxDbGFzczxBbnlNb2RlbD4pXHJcbiAgaWYgKG1vZGVsSWRQcm9wZXJ0eU5hbWUgJiYgKHNuIGFzIGFueSlbbW9kZWxJZFByb3BlcnR5TmFtZV0gPT09IHVuZGVmaW5lZCkge1xyXG4gICAgdGhyb3cgZmFpbHVyZShcclxuICAgICAgYGEgbW9kZWwgc25hcHNob3Qgb2YgdHlwZSAnJHt0eXBlfScgbXVzdCBjb250YWluIGFuIGlkIGtleSAoJHttb2RlbElkUHJvcGVydHlOYW1lfSksIGJ1dCBub25lIHdhcyBmb3VuZGBcclxuICAgIClcclxuICB9XHJcblxyXG4gIHJldHVybiBuZXcgKG1vZGVsSW5mby5jbGFzcyBhcyBhbnkpKHVuZGVmaW5lZCwge1xyXG4gICAgc25hcHNob3RJbml0aWFsRGF0YToge1xyXG4gICAgICB1bnByb2Nlc3NlZFNuYXBzaG90OiBzbixcclxuICAgICAgdW5wcm9jZXNzZWRNb2RlbFR5cGU6XHJcbiAgICAgICAgdHlwZW9mIGN0eC51bnR5cGVkU25hcHNob3QgPT09IFwib2JqZWN0XCIgJiZcclxuICAgICAgICBjdHgudW50eXBlZFNuYXBzaG90ICYmXHJcbiAgICAgICAgbW9kZWxUeXBlS2V5IGluIGN0eC51bnR5cGVkU25hcHNob3RcclxuICAgICAgICAgID8gY3R4LnVudHlwZWRTbmFwc2hvdFttb2RlbFR5cGVLZXldXHJcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcclxuICAgICAgc25hcHNob3RUb0luaXRpYWxEYXRhOiBjdHguc25hcHNob3RUb0luaXRpYWxEYXRhLFxyXG4gICAgfSxcclxuICAgIGdlbmVyYXRlTmV3SWRzOiBjdHgub3B0aW9ucy5nZW5lcmF0ZU5ld0lkcyxcclxuICB9IGFzIE1vZGVsQ29uc3RydWN0b3JPcHRpb25zKVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJGcm9tTW9kZWxTbmFwc2hvdHRlcigpIHtcclxuICByZWdpc3RlclNuYXBzaG90dGVyKFNuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5Lk1vZGVsLCAoc24sIGN0eCkgPT4ge1xyXG4gICAgaWYgKGlzTW9kZWxTbmFwc2hvdChzbikpIHtcclxuICAgICAgcmV0dXJuIGZyb21Nb2RlbFNuYXBzaG90KHNuLCBjdHgpXHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkXHJcbiAgfSlcclxufVxyXG4iLCJpbXBvcnQge1xuICBpbnRlcmNlcHQsXG4gIElPYmplY3REaWRDaGFuZ2UsXG4gIElPYmplY3RXaWxsQ2hhbmdlLFxuICBpc09ic2VydmFibGVPYmplY3QsXG4gIG9ic2VydmFibGUsXG4gIG9ic2VydmUsXG59IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IGFzc2VydENhbldyaXRlIH0gZnJvbSBcIi4uL2FjdGlvbi9wcm90ZWN0aW9uXCJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcbmltcG9ydCB7IG1vZGVsVHlwZUtleSB9IGZyb20gXCIuLi9tb2RlbC9tZXRhZGF0YVwiXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcbmltcG9ydCB7IGdldE1vZGVsSW5mb0Zvck5hbWUgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxJbmZvXCJcbmltcG9ydCB7IGRhdGFUb01vZGVsTm9kZSB9IGZyb20gXCIuLi9wYXJlbnQvY29yZVwiXG5pbXBvcnQgdHlwZSB7IFBhcmVudFBhdGggfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxuaW1wb3J0IHsgc2V0UGFyZW50IH0gZnJvbSBcIi4uL3BhcmVudC9zZXRQYXJlbnRcIlxuaW1wb3J0IHsgSW50ZXJuYWxQYXRjaFJlY29yZGVyIH0gZnJvbSBcIi4uL3BhdGNoL2VtaXRQYXRjaFwiXG5pbXBvcnQge1xuICBmcmVlemVJbnRlcm5hbFNuYXBzaG90LFxuICBnZXRJbnRlcm5hbFNuYXBzaG90LFxuICBzZXROZXdJbnRlcm5hbFNuYXBzaG90LFxuICBTbmFwc2hvdFRyYW5zZm9ybUZuLFxuICB1cGRhdGVJbnRlcm5hbFNuYXBzaG90LFxufSBmcm9tIFwiLi4vc25hcHNob3QvaW50ZXJuYWxcIlxuaW1wb3J0IHsgZmFpbHVyZSwgaXNQbGFpbk9iamVjdCwgaXNQcmltaXRpdmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHsgc2V0SWZEaWZmZXJlbnQgfSBmcm9tIFwiLi4vdXRpbHMvc2V0SWZEaWZmZXJlbnRcIlxuaW1wb3J0IHsgcnVubmluZ1dpdGhvdXRTbmFwc2hvdE9yUGF0Y2hlcywgdHdlYWtlZE9iamVjdHMgfSBmcm9tIFwiLi9jb3JlXCJcbmltcG9ydCB7IHJlZ2lzdGVyVHdlYWtlciwgdHdlYWsgfSBmcm9tIFwiLi90d2Vha1wiXG5pbXBvcnQgeyBUd2Vha2VyUHJpb3JpdHkgfSBmcm9tIFwiLi9Ud2Vha2VyUHJpb3JpdHlcIlxuaW1wb3J0IHsgcnVuVHlwZUNoZWNraW5nQWZ0ZXJDaGFuZ2UgfSBmcm9tIFwiLi90eXBlQ2hlY2tpbmdcIlxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdHdlYWtQbGFpbk9iamVjdDxUIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55Pj4oXG4gIHZhbHVlOiBULFxuICBwYXJlbnRQYXRoOiBQYXJlbnRQYXRoPGFueT4gfCB1bmRlZmluZWQsXG4gIHNuYXBzaG90TW9kZWxUeXBlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGRvTm90VHdlYWtDaGlsZHJlbjogYm9vbGVhbixcbiAgaXNEYXRhT2JqZWN0OiBib29sZWFuXG4pOiBUIHtcbiAgY29uc3Qgb3JpZ2luYWxPYmo6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB2YWx1ZVxuICBjb25zdCB0d2Vha2VkT2JqID0gaXNPYnNlcnZhYmxlT2JqZWN0KG9yaWdpbmFsT2JqKVxuICAgID8gb3JpZ2luYWxPYmpcbiAgICA6IG9ic2VydmFibGUub2JqZWN0KHt9LCB1bmRlZmluZWQsIG9ic2VydmFibGVPcHRpb25zKVxuXG4gIGxldCBpbnRlcmNlcHREaXNwb3NlcjogKCkgPT4gdm9pZFxuICBsZXQgb2JzZXJ2ZURpc3Bvc2VyOiAoKSA9PiB2b2lkXG5cbiAgY29uc3QgdW50d2VhayA9ICgpID0+IHtcbiAgICBpbnRlcmNlcHREaXNwb3NlcigpXG4gICAgb2JzZXJ2ZURpc3Bvc2VyKClcbiAgfVxuXG4gIHR3ZWFrZWRPYmplY3RzLnNldCh0d2Vha2VkT2JqLCB1bnR3ZWFrKVxuICBzZXRQYXJlbnQoe1xuICAgIHZhbHVlOiB0d2Vha2VkT2JqLFxuICAgIHBhcmVudFBhdGgsXG4gICAgaW5kZXhDaGFuZ2VBbGxvd2VkOiBmYWxzZSxcbiAgICBpc0RhdGFPYmplY3QsXG4gICAgLy8gYW4gb2JqZWN0IHNob3VsZG4ndCBiZSBjbG9uZWRcbiAgICBjbG9uZUlmQXBwbGljYWJsZTogZmFsc2UsXG4gIH0pXG5cbiAgbGV0IHVudHJhbnNmb3JtZWRTbjogYW55ID0ge31cblxuICAvLyBzdWJzdGl0dXRlIGluaXRpYWwgdmFsdWVzIGJ5IHR3ZWFrZWQgdmFsdWVzXG4gIGNvbnN0IG9yaWdpbmFsT2JqS2V5cyA9IE9iamVjdC5rZXlzKG9yaWdpbmFsT2JqKVxuICBjb25zdCBvcmlnaW5hbE9iaktleXNMZW4gPSBvcmlnaW5hbE9iaktleXMubGVuZ3RoXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgb3JpZ2luYWxPYmpLZXlzTGVuOyBpKyspIHtcbiAgICBjb25zdCBrID0gb3JpZ2luYWxPYmpLZXlzW2ldXG4gICAgY29uc3QgdiA9IG9yaWdpbmFsT2JqW2tdXG5cbiAgICBpZiAoaXNQcmltaXRpdmUodikpIHtcbiAgICAgIGlmICghZG9Ob3RUd2Vha0NoaWxkcmVuKSB7XG4gICAgICAgIHNldElmRGlmZmVyZW50KHR3ZWFrZWRPYmosIGssIHYpXG4gICAgICB9XG4gICAgICB1bnRyYW5zZm9ybWVkU25ba10gPSB2XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHBhdGggPSB7IHBhcmVudDogdHdlYWtlZE9iaiwgcGF0aDogayB9XG5cbiAgICAgIGxldCB0d2Vha2VkVmFsdWVcbiAgICAgIGlmIChkb05vdFR3ZWFrQ2hpbGRyZW4pIHtcbiAgICAgICAgdHdlYWtlZFZhbHVlID0gdlxuICAgICAgICBzZXRQYXJlbnQoe1xuICAgICAgICAgIHZhbHVlOiB0d2Vha2VkVmFsdWUsXG4gICAgICAgICAgcGFyZW50UGF0aDogcGF0aCxcbiAgICAgICAgICBpbmRleENoYW5nZUFsbG93ZWQ6IGZhbHNlLFxuICAgICAgICAgIGlzRGF0YU9iamVjdDogZmFsc2UsXG4gICAgICAgICAgLy8gdGhlIHZhbHVlIGlzIGFscmVhZHkgYSBuZXcgdmFsdWUgKHRoZSByZXN1bHQgb2YgYSBmcm9tU25hcHNob3QpXG4gICAgICAgICAgY2xvbmVJZkFwcGxpY2FibGU6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHdlYWtlZFZhbHVlID0gdHdlYWsodiwgcGF0aClcbiAgICAgICAgc2V0SWZEaWZmZXJlbnQodHdlYWtlZE9iaiwgaywgdHdlYWtlZFZhbHVlKVxuICAgICAgfVxuXG4gICAgICBjb25zdCB2YWx1ZVNuID0gZ2V0SW50ZXJuYWxTbmFwc2hvdCh0d2Vha2VkVmFsdWUpIVxuICAgICAgdW50cmFuc2Zvcm1lZFNuW2tdID0gdmFsdWVTbi50cmFuc2Zvcm1lZFxuICAgIH1cbiAgfVxuXG4gIGxldCB0cmFuc2Zvcm1GbjogU25hcHNob3RUcmFuc2Zvcm1GbiB8IHVuZGVmaW5lZFxuICBpZiAoc25hcHNob3RNb2RlbFR5cGUpIHtcbiAgICB1bnRyYW5zZm9ybWVkU25bbW9kZWxUeXBlS2V5XSA9IHNuYXBzaG90TW9kZWxUeXBlXG5cbiAgICBjb25zdCBtb2RlbEluZm8gPSBnZXRNb2RlbEluZm9Gb3JOYW1lKHNuYXBzaG90TW9kZWxUeXBlKVxuICAgIGlmICghbW9kZWxJbmZvKSB7XG4gICAgICB0aHJvdyBmYWlsdXJlKGBtb2RlbCB3aXRoIG5hbWUgXCIke3NuYXBzaG90TW9kZWxUeXBlfVwiIG5vdCBmb3VuZCBpbiB0aGUgcmVnaXN0cnlgKVxuICAgIH1cblxuICAgIGNvbnN0IG9yaWdpbmFsVHJhbnNmb3JtRm4gPSAobW9kZWxJbmZvLmNsYXNzIGFzIE1vZGVsQ2xhc3M8QW55TW9kZWw+KS50b1NuYXBzaG90UHJvY2Vzc29yXG4gICAgaWYgKG9yaWdpbmFsVHJhbnNmb3JtRm4pIHtcbiAgICAgIHRyYW5zZm9ybUZuID0gKHNuKSA9PiBvcmlnaW5hbFRyYW5zZm9ybUZuKHNuLCBkYXRhVG9Nb2RlbE5vZGUodHdlYWtlZE9iaikpXG4gICAgfVxuICB9XG5cbiAgc2V0TmV3SW50ZXJuYWxTbmFwc2hvdChcbiAgICBpc0RhdGFPYmplY3QgPyBkYXRhVG9Nb2RlbE5vZGUodHdlYWtlZE9iaikgOiB0d2Vha2VkT2JqLFxuICAgIHVudHJhbnNmb3JtZWRTbixcbiAgICB0cmFuc2Zvcm1GblxuICApXG5cbiAgaW50ZXJjZXB0RGlzcG9zZXIgPSBpbnRlcmNlcHQodHdlYWtlZE9iaiwgaW50ZXJjZXB0T2JqZWN0TXV0YXRpb24pXG4gIG9ic2VydmVEaXNwb3NlciA9IG9ic2VydmUodHdlYWtlZE9iaiwgb2JqZWN0RGlkQ2hhbmdlKVxuXG4gIHJldHVybiB0d2Vha2VkT2JqIGFzIGFueVxufVxuXG5jb25zdCBvYnNlcnZhYmxlT3B0aW9ucyA9IHtcbiAgZGVlcDogZmFsc2UsXG59XG5cbmZ1bmN0aW9uIG11dGF0ZVNldChrOiBQcm9wZXJ0eUtleSwgdjogdW5rbm93biwgc246IFJlY29yZDxQcm9wZXJ0eUtleSwgdW5rbm93bj4pIHtcbiAgc25ba10gPSB2XG59XG5cbmZ1bmN0aW9uIG11dGF0ZURlbGV0ZShrOiBQcm9wZXJ0eUtleSwgc246IFJlY29yZDxQcm9wZXJ0eUtleSwgdW5rbm93bj4pIHtcbiAgZGVsZXRlIHNuW2tdXG59XG5cbmNvbnN0IHBhdGNoUmVjb3JkZXIgPSBuZXcgSW50ZXJuYWxQYXRjaFJlY29yZGVyKClcblxuZnVuY3Rpb24gb2JqZWN0RGlkQ2hhbmdlKGNoYW5nZTogSU9iamVjdERpZENoYW5nZSk6IHZvaWQge1xuICBjb25zdCBvYmogPSBjaGFuZ2Uub2JqZWN0XG4gIGNvbnN0IGFjdHVhbE5vZGUgPSBkYXRhVG9Nb2RlbE5vZGUob2JqKVxuICBsZXQgb2xkVW50cmFuc2Zvcm1lZFNuID0gZ2V0SW50ZXJuYWxTbmFwc2hvdChhY3R1YWxOb2RlKSEudW50cmFuc2Zvcm1lZFxuXG4gIHBhdGNoUmVjb3JkZXIucmVzZXQoKVxuXG4gIGxldCBtdXRhdGU6ICgoc246IGFueSkgPT4gdm9pZCkgfCB1bmRlZmluZWRcblxuICBzd2l0Y2ggKGNoYW5nZS50eXBlKSB7XG4gICAgY2FzZSBcImFkZFwiOlxuICAgIGNhc2UgXCJ1cGRhdGVcIjpcbiAgICAgIG11dGF0ZSA9IG9iamVjdERpZENoYW5nZUFkZE9yVXBkYXRlKGNoYW5nZSwgb2xkVW50cmFuc2Zvcm1lZFNuKVxuICAgICAgYnJlYWtcblxuICAgIGNhc2UgXCJyZW1vdmVcIjpcbiAgICAgIG11dGF0ZSA9IG9iamVjdERpZENoYW5nZVJlbW92ZShjaGFuZ2UsIG9sZFVudHJhbnNmb3JtZWRTbilcbiAgICAgIGJyZWFrXG4gIH1cblxuICBydW5UeXBlQ2hlY2tpbmdBZnRlckNoYW5nZShvYmosIHBhdGNoUmVjb3JkZXIpXG5cbiAgaWYgKCFydW5uaW5nV2l0aG91dFNuYXBzaG90T3JQYXRjaGVzICYmIG11dGF0ZSkge1xuICAgIHVwZGF0ZUludGVybmFsU25hcHNob3QoYWN0dWFsTm9kZSwgbXV0YXRlKVxuICAgIHBhdGNoUmVjb3JkZXIuZW1pdChhY3R1YWxOb2RlKVxuICB9XG59XG5cbmZ1bmN0aW9uIG9iamVjdERpZENoYW5nZVJlbW92ZShcbiAgY2hhbmdlOiBJT2JqZWN0RGlkQ2hhbmdlICYgeyB0eXBlOiBcInJlbW92ZVwiIH0sXG4gIG9sZFVudHJhbnNmb3JtZWRTbjogYW55XG4pIHtcbiAgY29uc3QgayA9IGNoYW5nZS5uYW1lXG4gIGNvbnN0IG9sZFZhbCA9IG9sZFVudHJhbnNmb3JtZWRTbltrXVxuICBjb25zdCBtdXRhdGUgPSBtdXRhdGVEZWxldGUuYmluZCh1bmRlZmluZWQsIGspXG5cbiAgY29uc3QgcGF0aCA9IFtrIGFzIHN0cmluZ11cblxuICBwYXRjaFJlY29yZGVyLnJlY29yZChcbiAgICBbXG4gICAgICB7XG4gICAgICAgIG9wOiBcInJlbW92ZVwiLFxuICAgICAgICBwYXRoLFxuICAgICAgfSxcbiAgICBdLFxuICAgIFtcbiAgICAgIHtcbiAgICAgICAgb3A6IFwiYWRkXCIsXG4gICAgICAgIHBhdGgsXG4gICAgICAgIHZhbHVlOiBmcmVlemVJbnRlcm5hbFNuYXBzaG90KG9sZFZhbCksXG4gICAgICB9LFxuICAgIF1cbiAgKVxuICByZXR1cm4gbXV0YXRlXG59XG5cbmZ1bmN0aW9uIG9iamVjdERpZENoYW5nZUFkZE9yVXBkYXRlKFxuICBjaGFuZ2U6IElPYmplY3RXaWxsQ2hhbmdlICYgeyB0eXBlOiBcImFkZFwiIHwgXCJ1cGRhdGVcIiB9LFxuICBvbGRVbnRyYW5zZm9ybWVkU246IGFueVxuKSB7XG4gIGNvbnN0IGsgPSBjaGFuZ2UubmFtZVxuICBjb25zdCB2YWwgPSBjaGFuZ2UubmV3VmFsdWVcblxuICBjb25zdCBvbGRWYWwgPSBvbGRVbnRyYW5zZm9ybWVkU25ba11cblxuICBsZXQgbmV3VmFsOiBhbnlcbiAgaWYgKGlzUHJpbWl0aXZlKHZhbCkpIHtcbiAgICBuZXdWYWwgPSB2YWxcbiAgfSBlbHNlIHtcbiAgICBjb25zdCB2YWx1ZVNuID0gZ2V0SW50ZXJuYWxTbmFwc2hvdCh2YWwpIVxuICAgIG5ld1ZhbCA9IHZhbHVlU24udHJhbnNmb3JtZWRcbiAgfVxuXG4gIGNvbnN0IG11dGF0ZSA9IG11dGF0ZVNldC5iaW5kKHVuZGVmaW5lZCwgaywgbmV3VmFsKVxuXG4gIGNvbnN0IHBhdGggPSBbayBhcyBzdHJpbmddXG4gIGlmIChjaGFuZ2UudHlwZSA9PT0gXCJhZGRcIikge1xuICAgIHBhdGNoUmVjb3JkZXIucmVjb3JkKFxuICAgICAgW1xuICAgICAgICB7XG4gICAgICAgICAgb3A6IFwiYWRkXCIsXG4gICAgICAgICAgcGF0aCxcbiAgICAgICAgICB2YWx1ZTogZnJlZXplSW50ZXJuYWxTbmFwc2hvdChuZXdWYWwpLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIFtcbiAgICAgICAge1xuICAgICAgICAgIG9wOiBcInJlbW92ZVwiLFxuICAgICAgICAgIHBhdGgsXG4gICAgICAgIH0sXG4gICAgICBdXG4gICAgKVxuICB9IGVsc2Uge1xuICAgIHBhdGNoUmVjb3JkZXIucmVjb3JkKFxuICAgICAgW1xuICAgICAgICB7XG4gICAgICAgICAgb3A6IFwicmVwbGFjZVwiLFxuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgdmFsdWU6IGZyZWV6ZUludGVybmFsU25hcHNob3QobmV3VmFsKSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBbXG4gICAgICAgIHtcbiAgICAgICAgICBvcDogXCJyZXBsYWNlXCIsXG4gICAgICAgICAgcGF0aCxcbiAgICAgICAgICB2YWx1ZTogZnJlZXplSW50ZXJuYWxTbmFwc2hvdChvbGRWYWwpLFxuICAgICAgICB9LFxuICAgICAgXVxuICAgIClcbiAgfVxuXG4gIHJldHVybiBtdXRhdGVcbn1cblxuZnVuY3Rpb24gaW50ZXJjZXB0T2JqZWN0TXV0YXRpb24oY2hhbmdlOiBJT2JqZWN0V2lsbENoYW5nZSkge1xuICBhc3NlcnRDYW5Xcml0ZSgpXG5cbiAgaWYgKHR5cGVvZiBjaGFuZ2UubmFtZSA9PT0gXCJzeW1ib2xcIikge1xuICAgIHRocm93IGZhaWx1cmUoXCJzeW1ib2wgcHJvcGVydGllcyBhcmUgbm90IHN1cHBvcnRlZFwiKVxuICB9XG5cbiAgc3dpdGNoIChjaGFuZ2UudHlwZSkge1xuICAgIGNhc2UgXCJhZGRcIjpcbiAgICAgIGNoYW5nZS5uZXdWYWx1ZSA9IHR3ZWFrKGNoYW5nZS5uZXdWYWx1ZSwge1xuICAgICAgICBwYXJlbnQ6IGNoYW5nZS5vYmplY3QsXG4gICAgICAgIHBhdGg6IFwiXCIgKyBjaGFuZ2UubmFtZSxcbiAgICAgIH0pXG4gICAgICBicmVha1xuXG4gICAgY2FzZSBcInJlbW92ZVwiOiB7XG4gICAgICBjb25zdCBvbGRWYWwgPSBjaGFuZ2Uub2JqZWN0W2NoYW5nZS5uYW1lXVxuICAgICAgdHdlYWsob2xkVmFsLCB1bmRlZmluZWQpXG4gICAgICBicmVha1xuICAgIH1cblxuICAgIGNhc2UgXCJ1cGRhdGVcIjoge1xuICAgICAgY29uc3Qgb2xkVmFsID0gY2hhbmdlLm9iamVjdFtjaGFuZ2UubmFtZV1cbiAgICAgIGNvbnN0IG5ld1ZhbCA9IGNoYW5nZS5uZXdWYWx1ZVxuICAgICAgaWYgKG5ld1ZhbCAhPT0gb2xkVmFsKSB7XG4gICAgICAgIHR3ZWFrKG9sZFZhbCwgdW5kZWZpbmVkKVxuXG4gICAgICAgIGNoYW5nZS5uZXdWYWx1ZSA9IHR3ZWFrKGNoYW5nZS5uZXdWYWx1ZSwge1xuICAgICAgICAgIHBhcmVudDogY2hhbmdlLm9iamVjdCxcbiAgICAgICAgICBwYXRoOiBcIlwiICsgY2hhbmdlLm5hbWUsXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjaGFuZ2Vcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyUGxhaW5PYmplY3RUd2Vha2VyKCkge1xuICByZWdpc3RlclR3ZWFrZXIoVHdlYWtlclByaW9yaXR5LlBsYWluT2JqZWN0LCAodmFsdWUsIHBhcmVudFBhdGgpID0+IHtcbiAgICAvLyBwbGFpbiBvYmplY3RcbiAgICBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHZhbHVlKSB8fCBpc1BsYWluT2JqZWN0KHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHR3ZWFrUGxhaW5PYmplY3QodmFsdWUgYXMgUmVjb3JkPHN0cmluZywgYW55PiwgcGFyZW50UGF0aCwgdW5kZWZpbmVkLCBmYWxzZSwgZmFsc2UpXG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfSlcbn1cbiIsImltcG9ydCB7IG9ic2VydmFibGUsIHNldCB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IHR3ZWFrUGxhaW5PYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci90d2Vha1BsYWluT2JqZWN0XCJcbmltcG9ydCB7IGlzUGxhaW5PYmplY3QgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHsgU25hcHNob3RJbk9mT2JqZWN0IH0gZnJvbSBcIi4vU25hcHNob3RPZlwiXG5pbXBvcnQgeyBTbmFwc2hvdHRlckFuZFJlY29uY2lsZXJQcmlvcml0eSB9IGZyb20gXCIuL1NuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5XCJcbmltcG9ydCB7XG4gIEZyb21TbmFwc2hvdENvbnRleHQsXG4gIGludGVybmFsRnJvbVNuYXBzaG90LFxuICBvYnNlcnZhYmxlT3B0aW9ucyxcbiAgcmVnaXN0ZXJTbmFwc2hvdHRlcixcbn0gZnJvbSBcIi4vZnJvbVNuYXBzaG90XCJcblxuZnVuY3Rpb24gZnJvbVBsYWluT2JqZWN0U25hcHNob3Qoc246IFNuYXBzaG90SW5PZk9iamVjdDxhbnk+LCBjdHg6IEZyb21TbmFwc2hvdENvbnRleHQpOiBvYmplY3Qge1xuICBjb25zdCBwbGFpbk9iaiA9IG9ic2VydmFibGUub2JqZWN0KHt9LCB1bmRlZmluZWQsIG9ic2VydmFibGVPcHRpb25zKVxuXG4gIGNvbnN0IHNuS2V5cyA9IE9iamVjdC5rZXlzKHNuKVxuICBjb25zdCBzbktleXNMZW4gPSBzbktleXMubGVuZ3RoXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc25LZXlzTGVuOyBpKyspIHtcbiAgICBjb25zdCBrID0gc25LZXlzW2ldXG4gICAgY29uc3QgdiA9IHNuW2tdXG4gICAgLy8gc2V0SWZEaWZmZXJlbnQgbm90IHJlcXVpcmVkXG4gICAgc2V0KHBsYWluT2JqLCBrLCBpbnRlcm5hbEZyb21TbmFwc2hvdCh2LCBjdHgpKVxuICB9XG4gIHJldHVybiB0d2Vha1BsYWluT2JqZWN0KHBsYWluT2JqLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdHJ1ZSwgZmFsc2UpXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckZyb21QbGFpbk9iamVjdFNuYXBzaG90dGVyKCkge1xuICByZWdpc3RlclNuYXBzaG90dGVyKFNuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5LlBsYWluT2JqZWN0LCAoc24sIGN0eCkgPT4ge1xuICAgIGlmIChpc1BsYWluT2JqZWN0KHNuKSkge1xuICAgICAgcmV0dXJuIGZyb21QbGFpbk9iamVjdFNuYXBzaG90KHNuLCBjdHgpXG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfSlcbn1cbiIsImltcG9ydCB7IHJlZ2lzdGVyRnJvbUFycmF5U25hcHNob3R0ZXIgfSBmcm9tIFwiLi9mcm9tQXJyYXlTbmFwc2hvdFwiXG5pbXBvcnQgeyByZWdpc3RlckZyb21Gcm96ZW5TbmFwc2hvdHRlciB9IGZyb20gXCIuL2Zyb21Gcm96ZW5TbmFwc2hvdFwiXG5pbXBvcnQgeyByZWdpc3RlckZyb21Nb2RlbFNuYXBzaG90dGVyIH0gZnJvbSBcIi4vZnJvbU1vZGVsU25hcHNob3RcIlxuaW1wb3J0IHsgcmVnaXN0ZXJGcm9tUGxhaW5PYmplY3RTbmFwc2hvdHRlciB9IGZyb20gXCIuL2Zyb21QbGFpbk9iamVjdFNuYXBzaG90XCJcblxubGV0IGRlZmF1bHRTbmFwc2hvdHRlcnNSZWdpc3RlcmVkID0gZmFsc2VcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyRGVmYXVsdFNuYXBzaG90dGVycygpIHtcbiAgaWYgKGRlZmF1bHRTbmFwc2hvdHRlcnNSZWdpc3RlcmVkKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgZGVmYXVsdFNuYXBzaG90dGVyc1JlZ2lzdGVyZWQgPSB0cnVlXG5cbiAgcmVnaXN0ZXJGcm9tQXJyYXlTbmFwc2hvdHRlcigpXG4gIHJlZ2lzdGVyRnJvbUZyb3plblNuYXBzaG90dGVyKClcbiAgcmVnaXN0ZXJGcm9tTW9kZWxTbmFwc2hvdHRlcigpXG4gIHJlZ2lzdGVyRnJvbVBsYWluT2JqZWN0U25hcHNob3R0ZXIoKVxufVxuIiwiaW1wb3J0IHsgYWN0aW9uLCBvYnNlcnZhYmxlLCBzZXQgfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB0eXBlIHsgQW55RGF0YU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9CYXNlRGF0YU1vZGVsXCJcclxuaW1wb3J0IHR5cGUgeyBBbnlNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9CYXNlTW9kZWxcIlxyXG5pbXBvcnQgeyBpc1Jlc2VydmVkTW9kZWxLZXkgfSBmcm9tIFwiLi4vbW9kZWwvbWV0YWRhdGFcIlxyXG5pbXBvcnQgeyBpc01vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWwvdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcclxuaW1wb3J0IHsgVHlwZUNoZWNrZXIsIGlzTGF0ZVR5cGVDaGVja2VyIH0gZnJvbSBcIi4uL3R5cGVzL1R5cGVDaGVja2VyXCJcclxuaW1wb3J0IHsgcmVzb2x2ZVR5cGVDaGVja2VyIH0gZnJvbSBcIi4uL3R5cGVzL3Jlc29sdmVUeXBlQ2hlY2tlclwiXHJcbmltcG9ydCB0eXBlIHsgQW55U3RhbmRhcmRUeXBlLCBUeXBlVG9EYXRhIH0gZnJvbSBcIi4uL3R5cGVzL3NjaGVtYXNcIlxyXG5pbXBvcnQgeyBmYWlsdXJlLCBpc01hcCwgaXNQcmltaXRpdmUsIGlzU2V0IH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHR5cGUgeyBTbmFwc2hvdEluT2YsIFNuYXBzaG90SW5PZk1vZGVsLCBTbmFwc2hvdE91dE9mIH0gZnJvbSBcIi4vU25hcHNob3RPZlwiXHJcbmltcG9ydCB7IHJlZ2lzdGVyRGVmYXVsdFNuYXBzaG90dGVycyB9IGZyb20gXCIuL3JlZ2lzdGVyRGVmYXVsdFNuYXBzaG90dGVyc1wiXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBTbmFwc2hvdHRlciA9IChzbjogYW55LCBjdHg6IEZyb21TbmFwc2hvdENvbnRleHQpID0+IGFueSB8IHVuZGVmaW5lZFxyXG5cclxuY29uc3Qgc25hcHNob3R0ZXJzOiB7IHByaW9yaXR5OiBudW1iZXI7IHNuYXBzaG90dGVyOiBTbmFwc2hvdHRlciB9W10gPSBbXVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyU25hcHNob3R0ZXIocHJpb3JpdHk6IG51bWJlciwgc25hcHNob3R0ZXI6IFNuYXBzaG90dGVyKTogdm9pZCB7XHJcbiAgc25hcHNob3R0ZXJzLnB1c2goeyBwcmlvcml0eSwgc25hcHNob3R0ZXIgfSlcclxuICBzbmFwc2hvdHRlcnMuc29ydCgoYSwgYikgPT4gYS5wcmlvcml0eSAtIGIucHJpb3JpdHkpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBGcm9tIHNuYXBzaG90IG9wdGlvbnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEZyb21TbmFwc2hvdE9wdGlvbnMge1xyXG4gIC8qKlxyXG4gICAqIFBhc3MgYHRydWVgIHRvIGdlbmVyYXRlIG5ldyBpbnRlcm5hbCBpZHMgZm9yIG1vZGVscyByYXRoZXIgdGhhbiByZXVzaW5nIHRoZW0uIChEZWZhdWx0IGlzIGBmYWxzZWApXHJcbiAgICovXHJcbiAgZ2VuZXJhdGVOZXdJZHM6IGJvb2xlYW5cclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBGcm9tU25hcHNob3RDb250ZXh0IHtcclxuICBvcHRpb25zOiBGcm9tU25hcHNob3RPcHRpb25zXHJcbiAgc25hcHNob3RUb0luaXRpYWxEYXRhKHByb2Nlc3NlZFNuOiBTbmFwc2hvdEluT2ZNb2RlbDxBbnlNb2RlbD4pOiBhbnlcclxuICB1bnR5cGVkU25hcHNob3Q6IHVua25vd25cclxufVxyXG5cclxuLyoqXHJcbiAqIEdpdmVuIGEgdHlwZSBkZXNlcmlhbGl6ZXMgYSBkYXRhIHN0cnVjdHVyZSBmcm9tIGl0cyBzbmFwc2hvdCBmb3JtLlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFRUeXBlIE9iamVjdCB0eXBlLlxyXG4gKiBAcGFyYW0gdHlwZSBUeXBlLlxyXG4gKiBAcGFyYW0gc25hcHNob3QgU25hcHNob3QsIGV2ZW4gaWYgYSBwcmltaXRpdmUuXHJcbiAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnMuXHJcbiAqIEByZXR1cm5zIFRoZSBkZXNlcmlhbGl6ZWQgb2JqZWN0LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZyb21TbmFwc2hvdDxcclxuICBUVHlwZSBleHRlbmRzIEFueVN0YW5kYXJkVHlwZSB8IE1vZGVsQ2xhc3M8QW55TW9kZWw+IHwgTW9kZWxDbGFzczxBbnlEYXRhTW9kZWw+LFxyXG4+KFxyXG4gIHR5cGU6IFRUeXBlLFxyXG4gIHNuYXBzaG90OiBTbmFwc2hvdEluT2Y8VHlwZVRvRGF0YTxUVHlwZT4+LFxyXG4gIG9wdGlvbnM/OiBQYXJ0aWFsPEZyb21TbmFwc2hvdE9wdGlvbnM+XHJcbik6IFR5cGVUb0RhdGE8VFR5cGU+XHJcblxyXG4vKipcclxuICogRGVzZXJpYWxpemVzIGEgZGF0YSBzdHJ1Y3R1cmUgZnJvbSBpdHMgc25hcHNob3QgZm9ybS5cclxuICpcclxuICogQHR5cGVwYXJhbSBUIE9iamVjdCB0eXBlLlxyXG4gKiBAcGFyYW0gc25hcHNob3QgU25hcHNob3QsIGV2ZW4gaWYgYSBwcmltaXRpdmUuXHJcbiAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnMuXHJcbiAqIEByZXR1cm5zIFRoZSBkZXNlcmlhbGl6ZWQgb2JqZWN0LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZyb21TbmFwc2hvdDxUPihcclxuICBzbmFwc2hvdDogU25hcHNob3RJbk9mPFQ+IHwgU25hcHNob3RPdXRPZjxUPixcclxuICBvcHRpb25zPzogUGFydGlhbDxGcm9tU25hcHNob3RPcHRpb25zPlxyXG4pOiBUXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZnJvbVNuYXBzaG90PFQ+KGFyZzE6IGFueSwgYXJnMjogYW55LCBhcmczPzogYW55KTogVCB7XHJcbiAgbGV0IHNuYXBzaG90OiBhbnlcclxuICBsZXQgdW5wcm9jZXNzZWRTbmFwc2hvdDogdW5rbm93blxyXG4gIGxldCBvcHRpb25zOiBQYXJ0aWFsPEZyb21TbmFwc2hvdE9wdGlvbnM+IHwgdW5kZWZpbmVkXHJcblxyXG4gIGlmIChpc0xhdGVUeXBlQ2hlY2tlcihhcmcxKSB8fCBhcmcxIGluc3RhbmNlb2YgVHlwZUNoZWNrZXIgfHwgaXNNb2RlbENsYXNzKGFyZzEpKSB7XHJcbiAgICBjb25zdCB0eXBlQ2hlY2tlciA9IHJlc29sdmVUeXBlQ2hlY2tlcihhcmcxKVxyXG4gICAgdW5wcm9jZXNzZWRTbmFwc2hvdCA9IGFyZzJcclxuICAgIHNuYXBzaG90ID0gdHlwZUNoZWNrZXIuZnJvbVNuYXBzaG90UHJvY2Vzc29yXHJcbiAgICAgID8gdHlwZUNoZWNrZXIuZnJvbVNuYXBzaG90UHJvY2Vzc29yKHVucHJvY2Vzc2VkU25hcHNob3QpXHJcbiAgICAgIDogdW5wcm9jZXNzZWRTbmFwc2hvdFxyXG4gICAgb3B0aW9ucyA9IGFyZzNcclxuICB9IGVsc2Uge1xyXG4gICAgc25hcHNob3QgPSBhcmcxXHJcbiAgICB1bnByb2Nlc3NlZFNuYXBzaG90ID0gc25hcHNob3RcclxuICAgIG9wdGlvbnMgPSBhcmcyXHJcbiAgfVxyXG5cclxuICByZXR1cm4gZnJvbVNuYXBzaG90QWN0aW9uKHNuYXBzaG90LCB1bnByb2Nlc3NlZFNuYXBzaG90LCBvcHRpb25zKVxyXG59XHJcblxyXG5jb25zdCBmcm9tU25hcHNob3RBY3Rpb24gPSBhY3Rpb24oXHJcbiAgXCJmcm9tU25hcHNob3RcIixcclxuICA8VD4oXHJcbiAgICBzbmFwc2hvdDogU25hcHNob3RJbk9mPFQ+LFxyXG4gICAgdW5wcm9jZXNzZWRTbmFwc2hvdDogdW5rbm93bixcclxuICAgIG9wdGlvbnM6IFBhcnRpYWw8RnJvbVNuYXBzaG90T3B0aW9ucz4gfCB1bmRlZmluZWRcclxuICApOiBUID0+IHtcclxuICAgIGNvbnN0IG9wdHMgPSB7XHJcbiAgICAgIGdlbmVyYXRlTmV3SWRzOiBmYWxzZSxcclxuICAgICAgb3ZlcnJpZGVSb290TW9kZWxJZDogdW5kZWZpbmVkLFxyXG4gICAgICAuLi5vcHRpb25zLFxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGN0eDogUGFydGlhbDxGcm9tU25hcHNob3RDb250ZXh0PiA9IHtcclxuICAgICAgb3B0aW9uczogb3B0cyxcclxuICAgICAgdW50eXBlZFNuYXBzaG90OiB1bnByb2Nlc3NlZFNuYXBzaG90LFxyXG4gICAgfVxyXG4gICAgY3R4LnNuYXBzaG90VG9Jbml0aWFsRGF0YSA9IHNuYXBzaG90VG9Jbml0aWFsRGF0YS5iaW5kKHVuZGVmaW5lZCwgY3R4IGFzIEZyb21TbmFwc2hvdENvbnRleHQpXHJcblxyXG4gICAgcmV0dXJuIGludGVybmFsRnJvbVNuYXBzaG90PFQ+KHNuYXBzaG90LCBjdHggYXMgRnJvbVNuYXBzaG90Q29udGV4dClcclxuICB9XHJcbilcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpbnRlcm5hbEZyb21TbmFwc2hvdDxUPihcclxuICBzbjogU25hcHNob3RJbk9mPFQ+IHwgU25hcHNob3RPdXRPZjxUPixcclxuICBjdHg6IEZyb21TbmFwc2hvdENvbnRleHRcclxuKTogVCB7XHJcbiAgaWYgKGlzUHJpbWl0aXZlKHNuKSkge1xyXG4gICAgcmV0dXJuIHNuIGFzIGFueVxyXG4gIH1cclxuXHJcbiAgcmVnaXN0ZXJEZWZhdWx0U25hcHNob3R0ZXJzKClcclxuXHJcbiAgY29uc3Qgc25hcHNob3R0ZXJMZW4gPSBzbmFwc2hvdHRlcnMubGVuZ3RoXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbmFwc2hvdHRlckxlbjsgaSsrKSB7XHJcbiAgICBjb25zdCB7IHNuYXBzaG90dGVyIH0gPSBzbmFwc2hvdHRlcnNbaV1cclxuICAgIGNvbnN0IHJldCA9IHNuYXBzaG90dGVyKHNuLCBjdHgpXHJcbiAgICBpZiAocmV0ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuIHJldFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgaWYgKGlzTWFwKHNuKSkge1xyXG4gICAgdGhyb3cgZmFpbHVyZShcImEgc25hcHNob3QgbXVzdCBub3QgY29udGFpbiBtYXBzXCIpXHJcbiAgfVxyXG5cclxuICBpZiAoaXNTZXQoc24pKSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKFwiYSBzbmFwc2hvdCBtdXN0IG5vdCBjb250YWluIHNldHNcIilcclxuICB9XHJcblxyXG4gIHRocm93IGZhaWx1cmUoYHVuc3VwcG9ydGVkIHNuYXBzaG90IC0gJHtzbn1gKVxyXG59XHJcblxyXG5mdW5jdGlvbiBzbmFwc2hvdFRvSW5pdGlhbERhdGEoXHJcbiAgY3R4OiBGcm9tU25hcHNob3RDb250ZXh0LFxyXG4gIHByb2Nlc3NlZFNuOiBTbmFwc2hvdEluT2ZNb2RlbDxBbnlNb2RlbD5cclxuKTogYW55IHtcclxuICBjb25zdCBpbml0aWFsRGF0YSA9IG9ic2VydmFibGUub2JqZWN0KHt9LCB1bmRlZmluZWQsIG9ic2VydmFibGVPcHRpb25zKVxyXG5cclxuICBjb25zdCBwcm9jZXNzZWRTbktleXMgPSBPYmplY3Qua2V5cyhwcm9jZXNzZWRTbilcclxuICBjb25zdCBwcm9jZXNzZWRTbktleXNMZW4gPSBwcm9jZXNzZWRTbktleXMubGVuZ3RoXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwcm9jZXNzZWRTbktleXNMZW47IGkrKykge1xyXG4gICAgY29uc3QgayA9IHByb2Nlc3NlZFNuS2V5c1tpXVxyXG4gICAgaWYgKCFpc1Jlc2VydmVkTW9kZWxLZXkoaykpIHtcclxuICAgICAgY29uc3QgdiA9IHByb2Nlc3NlZFNuW2tdXHJcbiAgICAgIC8vIHNldElmRGlmZmVyZW50IG5vdCByZXF1aXJlZFxyXG4gICAgICBzZXQoaW5pdGlhbERhdGEsIGssIGludGVybmFsRnJvbVNuYXBzaG90KHYsIGN0eCkpXHJcbiAgICB9XHJcbiAgfVxyXG4gIHJldHVybiBpbml0aWFsRGF0YVxyXG59XHJcblxyXG5leHBvcnQgY29uc3Qgb2JzZXJ2YWJsZU9wdGlvbnMgPSB7XHJcbiAgZGVlcDogZmFsc2UsXHJcbn1cclxuIiwiaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgZnJvbVNuYXBzaG90IH0gZnJvbSBcIi4vZnJvbVNuYXBzaG90XCJcbmltcG9ydCB7IGdldFNuYXBzaG90IH0gZnJvbSBcIi4vZ2V0U25hcHNob3RcIlxuXG4vKipcbiAqIENsb25lIG9wdGlvbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ2xvbmVPcHRpb25zIHtcbiAgLyoqXG4gICAqIFBhc3MgYHRydWVgIHRvIGdlbmVyYXRlIG5ldyBpbnRlcm5hbCBpZHMgZm9yIG1vZGVscyByYXRoZXIgdGhhbiByZXVzaW5nIHRoZW0uIChEZWZhdWx0IGlzIGB0cnVlYClcbiAgICovXG4gIGdlbmVyYXRlTmV3SWRzOiBib29sZWFuXG59XG5cbi8qKlxuICogQ2xvbmVzIGFuIG9iamVjdCBieSBkb2luZyBhIGBmcm9tU25hcHNob3QoZ2V0U25hcHNob3QodmFsdWUpLCB7IGdlbmVyYXRlTmV3SWRzOiB0cnVlIH0pYC5cbiAqXG4gKiBAdHlwZXBhcmFtIFQgT2JqZWN0IHR5cGUuXG4gKiBAcGFyYW0gbm9kZSBPYmplY3QgdG8gY2xvbmUuXG4gKiBAcGFyYW0gW29wdGlvbnNdIE9wdGlvbnMuXG4gKiBAcmV0dXJucyBUaGUgY2xvbmVkIG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsb25lPFQgZXh0ZW5kcyBvYmplY3Q+KG5vZGU6IFQsIG9wdGlvbnM/OiBQYXJ0aWFsPENsb25lT3B0aW9ucz4pOiBUIHtcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChub2RlLCBcIm5vZGVcIilcblxuICBjb25zdCBvcHRzID0ge1xuICAgIGdlbmVyYXRlTmV3SWRzOiB0cnVlLFxuICAgIC4uLm9wdGlvbnMsXG4gIH1cblxuICBjb25zdCBzbiA9IGdldFNuYXBzaG90KG5vZGUpXG4gIHJldHVybiBmcm9tU25hcHNob3Qoc24sIG9wdHMpXG59XG4iLCJpbXBvcnQgeyBhY3Rpb24gfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgeyBlbnF1ZXVlUGVuZGluZ0FjdGlvbiB9IGZyb20gXCIuLi9hY3Rpb24vcGVuZGluZ0FjdGlvbnNcIlxuaW1wb3J0IHsgQmFzZU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Jhc2VNb2RlbFwiXG5pbXBvcnQgeyBnZXRNb2RlbE1ldGFkYXRhIH0gZnJvbSBcIi4uL21vZGVsL2dldE1vZGVsTWV0YWRhdGFcIlxuaW1wb3J0IHsgaXNNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXG5pbXBvcnQgeyBhdHRhY2hUb1Jvb3RTdG9yZSwgZGV0YWNoRnJvbVJvb3RTdG9yZSB9IGZyb20gXCIuLi9yb290U3RvcmUvYXR0YWNoRGV0YWNoXCJcbmltcG9ydCB7IGZhc3RJc1Jvb3RTdG9yZSB9IGZyb20gXCIuLi9yb290U3RvcmUvcm9vdFN0b3JlXCJcbmltcG9ydCB7IGNsb25lIH0gZnJvbSBcIi4uL3NuYXBzaG90L2Nsb25lXCJcbmltcG9ydCB7IGlzVHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgdHJ5VW50d2VhayB9IGZyb20gXCIuLi90d2Vha2VyL3R3ZWFrXCJcbmltcG9ydCB7IGZhaWx1cmUsIGluRGV2TW9kZSwgaXNQcmltaXRpdmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHtcbiAgZGF0YU9iamVjdFBhcmVudCxcbiAgZGF0YVRvTW9kZWxOb2RlLFxuICBvYmplY3RQYXJlbnRzLFxuICBwYXJlbnRQYXRoRXF1YWxzLFxuICByZXBvcnRQYXJlbnRQYXRoQ2hhbmdlZCxcbn0gZnJvbSBcIi4vY29yZVwiXG5pbXBvcnQgeyBhZGRPYmplY3RDaGlsZCwgcmVtb3ZlT2JqZWN0Q2hpbGQgfSBmcm9tIFwiLi9jb3JlT2JqZWN0Q2hpbGRyZW5cIlxuaW1wb3J0IHsgUGFyZW50UGF0aCwgZmFzdEdldFBhcmVudFBhdGgsIGZhc3RHZXRSb290IH0gZnJvbSBcIi4vcGF0aFwiXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjb25zdCBzZXRQYXJlbnQgPSBhY3Rpb24oXG4gIFwic2V0UGFyZW50XCIsXG4gICh7XG4gICAgdmFsdWUsXG4gICAgcGFyZW50UGF0aCxcbiAgICBpbmRleENoYW5nZUFsbG93ZWQsXG4gICAgaXNEYXRhT2JqZWN0LFxuICAgIGNsb25lSWZBcHBsaWNhYmxlLFxuICB9OiB7XG4gICAgdmFsdWU6IGFueVxuICAgIHBhcmVudFBhdGg6IFBhcmVudFBhdGg8YW55PiB8IHVuZGVmaW5lZFxuICAgIGluZGV4Q2hhbmdlQWxsb3dlZDogYm9vbGVhblxuICAgIGlzRGF0YU9iamVjdDogYm9vbGVhblxuICAgIGNsb25lSWZBcHBsaWNhYmxlOiBib29sZWFuXG4gIH0pOiBhbnkgPT4ge1xuICAgIGlmIChpc1ByaW1pdGl2ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB2YWx1ZVxuICAgIH1cblxuICAgIGlmIChpbkRldk1vZGUpIHtcbiAgICAgIGlmIChpbmRleENoYW5nZUFsbG93ZWQgJiYgY2xvbmVJZkFwcGxpY2FibGUpIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShcbiAgICAgICAgICBcImFzc2VydGlvbiBmYWlsZWQ6ICdpbmRleENoYW5nZUFsbG93ZWQnIGFuZCAnY2xvbmVJZkFwcGxpY2FibGUnIGNhbm5vdCBiZSBzZXQgYXQgdGhlIHNhbWUgdGltZVwiXG4gICAgICAgIClcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIiB8fCB0eXBlb2YgdmFsdWUgPT09IFwic3ltYm9sXCIpIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShgYXNzZXJ0aW9uIGZhaWxlZDogdmFsdWUgY2Fubm90IGJlIGEgZnVuY3Rpb24gb3IgYSBzeW1ib2xgKVxuICAgICAgfVxuICAgICAgaWYgKCFpc1R3ZWFrZWRPYmplY3QodmFsdWUsIHRydWUpKSB7XG4gICAgICAgIHRocm93IGZhaWx1cmUoYGFzc2VydGlvbiBmYWlsZWQ6IHZhbHVlIGlzIG5vdCByZWFkeSB0byB0YWtlIGEgcGFyZW50YClcbiAgICAgIH1cbiAgICAgIGlmIChwYXJlbnRQYXRoICYmICFpc1R3ZWFrZWRPYmplY3QocGFyZW50UGF0aC5wYXJlbnQsIHRydWUpKSB7XG4gICAgICAgIHRocm93IGZhaWx1cmUoYGFzc2VydGlvbiBmYWlsZWQ6IHBhcmVudCBpcyBub3QgcmVhZHkgdG8gdGFrZSBjaGlsZHJlbmApXG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IG9sZFBhcmVudFBhdGggPSBmYXN0R2V0UGFyZW50UGF0aCh2YWx1ZSlcbiAgICBpZiAocGFyZW50UGF0aEVxdWFscyhvbGRQYXJlbnRQYXRoLCBwYXJlbnRQYXRoKSkge1xuICAgICAgcmV0dXJuIHZhbHVlXG4gICAgfVxuXG4gICAgaWYgKGZhc3RJc1Jvb3RTdG9yZSh2YWx1ZSkpIHtcbiAgICAgIHRocm93IGZhaWx1cmUoXCJyb290IHN0b3JlcyBjYW5ub3QgYmUgYXR0YWNoZWQgdG8gYW55IHBhcmVudHNcIilcbiAgICB9XG5cbiAgICBpZiAoaXNEYXRhT2JqZWN0KSB7XG4gICAgICBkYXRhT2JqZWN0UGFyZW50LnNldCh2YWx1ZSwgcGFyZW50UGF0aCEucGFyZW50KVxuICAgICAgLy8gZGF0YSBvYmplY3Qgd2lsbCBwcm94eSB0byB1c2UgdGhlIGFjdHVhbCBwYXJlbnQgbW9kZWwgZm9yIGNoaWxkL3BhcmVudCBzdHVmZlxuICAgICAgcmV0dXJuIHZhbHVlXG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIHRoZSBuZXcgcGFyZW50IGFjdHVhbGx5IHBvaW50cyB0byBtb2RlbHMgd2hlbiB3ZSBnaXZlIG1vZGVsIGRhdGEgb2Jqc1xuICAgIGlmIChwYXJlbnRQYXRoKSB7XG4gICAgICBjb25zdCBhY3R1YWxQYXJlbnQgPSBkYXRhVG9Nb2RlbE5vZGUocGFyZW50UGF0aC5wYXJlbnQpXG4gICAgICBpZiAocGFyZW50UGF0aC5wYXJlbnQgIT09IGFjdHVhbFBhcmVudCkge1xuICAgICAgICBwYXJlbnRQYXRoID0ge1xuICAgICAgICAgIHBhcmVudDogYWN0dWFsUGFyZW50LFxuICAgICAgICAgIHBhdGg6IHBhcmVudFBhdGgucGF0aCxcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHZhbHVlIHR5cGUgbW9kZWxzIHNob3VsZCBiZSBjbG9uZWQgd2hlbiB0aGV5IGFyZSBhYm91dCB0byBiZSBhc3NpZ25lZCB0byBhIG5ldyBwYXJlbnRcbiAgICAvLyBhbmQgdGhleSBoYWQgb25lIHByZXZpb3VzbHlcbiAgICBpZiAoXG4gICAgICBjbG9uZUlmQXBwbGljYWJsZSAmJlxuICAgICAgcGFyZW50UGF0aD8ucGFyZW50ICYmXG4gICAgICBvbGRQYXJlbnRQYXRoPy5wYXJlbnQgJiZcbiAgICAgIGlzTW9kZWwodmFsdWUpICYmXG4gICAgICBnZXRNb2RlbE1ldGFkYXRhKHZhbHVlKS52YWx1ZVR5cGVcbiAgICApIHtcbiAgICAgIHZhbHVlID0gY2xvbmUodmFsdWUsIHsgZ2VuZXJhdGVOZXdJZHM6IHRydWUgfSlcbiAgICAgIG9sZFBhcmVudFBhdGggPSBmYXN0R2V0UGFyZW50UGF0aCh2YWx1ZSlcbiAgICB9XG5cbiAgICBpZiAob2xkUGFyZW50UGF0aCAmJiBwYXJlbnRQYXRoKSB7XG4gICAgICBpZiAob2xkUGFyZW50UGF0aC5wYXJlbnQgPT09IHBhcmVudFBhdGgucGFyZW50ICYmIGluZGV4Q2hhbmdlQWxsb3dlZCkge1xuICAgICAgICAvLyBqdXN0IGNoYW5naW5nIHRoZSBpbmRleFxuICAgICAgICBvYmplY3RQYXJlbnRzLnNldCh2YWx1ZSwgcGFyZW50UGF0aClcbiAgICAgICAgcmVwb3J0UGFyZW50UGF0aENoYW5nZWQodmFsdWUpXG4gICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShcImFuIG9iamVjdCBjYW5ub3QgYmUgYXNzaWduZWQgYSBuZXcgcGFyZW50IHdoZW4gaXQgYWxyZWFkeSBoYXMgb25lXCIpXG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHBvc3RVbnR3ZWFrZXI6IFJldHVyblR5cGU8dHlwZW9mIHRyeVVudHdlYWs+IHwgdW5kZWZpbmVkXG5cbiAgICBpZiAoIXBhcmVudFBhdGgpIHtcbiAgICAgIHBvc3RVbnR3ZWFrZXIgPSB0cnlVbnR3ZWFrKHZhbHVlKVxuICAgIH1cblxuICAgIGNvbnN0IGF0dGFjaFRvTmV3UGFyZW50ID0gKCkgPT4ge1xuICAgICAgLy8gZGV0YWNoIGZyb20gb2xkXG4gICAgICBpZiAob2xkUGFyZW50UGF0aD8ucGFyZW50KSB7XG4gICAgICAgIHJlbW92ZU9iamVjdENoaWxkKG9sZFBhcmVudFBhdGgucGFyZW50LCB2YWx1ZSlcbiAgICAgIH1cblxuICAgICAgLy8gYXR0YWNoIHRvIG5ld1xuICAgICAgb2JqZWN0UGFyZW50cy5zZXQodmFsdWUsIHBhcmVudFBhdGgpXG4gICAgICBpZiAocGFyZW50UGF0aD8ucGFyZW50KSB7XG4gICAgICAgIGFkZE9iamVjdENoaWxkKHBhcmVudFBhdGgucGFyZW50LCB2YWx1ZSlcbiAgICAgIH1cbiAgICAgIHJlcG9ydFBhcmVudFBhdGhDaGFuZ2VkKHZhbHVlKVxuICAgIH1cblxuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEJhc2VNb2RlbCkge1xuICAgICAgY29uc3Qgb2xkUm9vdCA9IGZhc3RHZXRSb290KHZhbHVlKVxuICAgICAgY29uc3Qgb2xkUm9vdFN0b3JlID0gZmFzdElzUm9vdFN0b3JlKG9sZFJvb3QpID8gb2xkUm9vdCA6IHVuZGVmaW5lZFxuXG4gICAgICBhdHRhY2hUb05ld1BhcmVudCgpXG5cbiAgICAgIGNvbnN0IG5ld1Jvb3QgPSBmYXN0R2V0Um9vdCh2YWx1ZSlcbiAgICAgIGNvbnN0IG5ld1Jvb3RTdG9yZSA9IGZhc3RJc1Jvb3RTdG9yZShuZXdSb290KSA/IG5ld1Jvb3QgOiB1bmRlZmluZWRcblxuICAgICAgLy8gaW52b2tlIG1vZGVsIHJvb3Qgc3RvcmUgZXZlbnRzXG4gICAgICBpZiAob2xkUm9vdFN0b3JlICE9PSBuZXdSb290U3RvcmUgJiYgKG9sZFJvb3RTdG9yZSB8fCBuZXdSb290U3RvcmUpKSB7XG4gICAgICAgIGVucXVldWVQZW5kaW5nQWN0aW9uKCgpID0+IHtcbiAgICAgICAgICBpZiAob2xkUm9vdFN0b3JlKSB7XG4gICAgICAgICAgICBkZXRhY2hGcm9tUm9vdFN0b3JlKHZhbHVlKVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobmV3Um9vdFN0b3JlKSB7XG4gICAgICAgICAgICBhdHRhY2hUb1Jvb3RTdG9yZShuZXdSb290U3RvcmUsIHZhbHVlKVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYXR0YWNoVG9OZXdQYXJlbnQoKVxuICAgIH1cblxuICAgIHBvc3RVbnR3ZWFrZXI/LigpXG5cbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuKVxuIiwiaW1wb3J0IHsgcmVzb2x2ZVR5cGVDaGVja2VyIH0gZnJvbSBcIi4vcmVzb2x2ZVR5cGVDaGVja2VyXCJcbmltcG9ydCB0eXBlIHsgQW55VHlwZSwgVHlwZVRvRGF0YSB9IGZyb20gXCIuL3NjaGVtYXNcIlxuaW1wb3J0IHR5cGUgeyBUeXBlQ2hlY2tFcnJvciB9IGZyb20gXCIuL1R5cGVDaGVja0Vycm9yXCJcblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBjb25mb3JtcyB0byBhIGdpdmVuIHR5cGUuXG4gKlxuICogQHR5cGVwYXJhbSBUIFR5cGUuXG4gKiBAcGFyYW0gdHlwZSBUeXBlIHRvIGNoZWNrIGZvci5cbiAqIEBwYXJhbSB2YWx1ZSBWYWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIEEgVHlwZUVycm9yIGlmIHRoZSBjaGVjayBmYWlscyBvciBudWxsIGlmIG5vIGVycm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdHlwZUNoZWNrPFQgZXh0ZW5kcyBBbnlUeXBlPih0eXBlOiBULCB2YWx1ZTogVHlwZVRvRGF0YTxUPik6IFR5cGVDaGVja0Vycm9yIHwgbnVsbCB7XG4gIGNvbnN0IHR5cGVDaGVja2VyID0gcmVzb2x2ZVR5cGVDaGVja2VyKHR5cGUpXG5cbiAgaWYgKHR5cGVDaGVja2VyLnVuY2hlY2tlZCkge1xuICAgIHJldHVybiBudWxsXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHR5cGVDaGVja2VyLmNoZWNrKHZhbHVlLCBbXSwgdmFsdWUpXG4gIH1cbn1cbiIsImltcG9ydCB7IEZyb3plbiwgZnJvemVuS2V5IH0gZnJvbSBcIi4uL2Zyb3plbi9Gcm96ZW5cIlxuaW1wb3J0IHR5cGUgeyBQYXJlbnRQYXRoIH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoXCJcbmltcG9ydCB7IHNldFBhcmVudCB9IGZyb20gXCIuLi9wYXJlbnQvc2V0UGFyZW50XCJcbmltcG9ydCB7IHNldE5ld0ludGVybmFsU25hcHNob3QgfSBmcm9tIFwiLi4vc25hcHNob3QvaW50ZXJuYWxcIlxuaW1wb3J0IHsgdHdlYWtlZE9iamVjdHMgfSBmcm9tIFwiLi9jb3JlXCJcbmltcG9ydCB7IHJlZ2lzdGVyVHdlYWtlciB9IGZyb20gXCIuL3R3ZWFrXCJcbmltcG9ydCB7IFR3ZWFrZXJQcmlvcml0eSB9IGZyb20gXCIuL1R3ZWFrZXJQcmlvcml0eVwiXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0d2Vha0Zyb3plbjxUIGV4dGVuZHMgRnJvemVuPGFueT4+KFxuICBmcm96ZW5PYmo6IFQsXG4gIHBhcmVudFBhdGg6IFBhcmVudFBhdGg8YW55PiB8IHVuZGVmaW5lZFxuKTogVCB7XG4gIHR3ZWFrZWRPYmplY3RzLnNldChmcm96ZW5PYmosIHVuZGVmaW5lZClcbiAgc2V0UGFyZW50KHtcbiAgICB2YWx1ZTogZnJvemVuT2JqLFxuICAgIHBhcmVudFBhdGgsXG4gICAgaW5kZXhDaGFuZ2VBbGxvd2VkOiBmYWxzZSxcbiAgICBpc0RhdGFPYmplY3Q6IGZhbHNlLFxuICAgIC8vIGEgZnJvemVuIGlzIG5vdCBhIHZhbHVlLXR5cGVcbiAgICBjbG9uZUlmQXBwbGljYWJsZTogZmFsc2UsXG4gIH0pXG5cbiAgLy8gd2UgRE9OJ1Qgd2FudCBkYXRhIHByb3hpZmllZCwgYnV0IHRoZSBzbmFwc2hvdCBpcyB0aGUgZGF0YSBpdHNlbGZcbiAgc2V0TmV3SW50ZXJuYWxTbmFwc2hvdChmcm96ZW5PYmosIHsgW2Zyb3plbktleV06IHRydWUsIGRhdGE6IGZyb3plbk9iai5kYXRhIH0sIHVuZGVmaW5lZCwgdHJ1ZSlcblxuICByZXR1cm4gZnJvemVuT2JqXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckZyb3plblR3ZWFrZXIoKSB7XG4gIHJlZ2lzdGVyVHdlYWtlcihUd2Vha2VyUHJpb3JpdHkuRnJvemVuLCAodmFsdWUsIHBhcmVudFBhdGgpID0+IHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBGcm96ZW4pIHtcbiAgICAgIHJldHVybiB0d2Vha0Zyb3plbih2YWx1ZSwgcGFyZW50UGF0aClcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9KVxufVxuIiwiaW1wb3J0IHsgaXNNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXG5pbXBvcnQgdHlwZSB7IFBhcmVudFBhdGggfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxuaW1wb3J0IHsgc2V0UGFyZW50IH0gZnJvbSBcIi4uL3BhcmVudC9zZXRQYXJlbnRcIlxuaW1wb3J0IHsgdHdlYWtlZE9iamVjdHMgfSBmcm9tIFwiLi9jb3JlXCJcbmltcG9ydCB7IHJlZ2lzdGVyVHdlYWtlciB9IGZyb20gXCIuL3R3ZWFrXCJcbmltcG9ydCB7IFR3ZWFrZXJQcmlvcml0eSB9IGZyb20gXCIuL1R3ZWFrZXJQcmlvcml0eVwiXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0d2Vha01vZGVsPFQgZXh0ZW5kcyBvYmplY3Q+KHZhbHVlOiBULCBwYXJlbnRQYXRoOiBQYXJlbnRQYXRoPGFueT4gfCB1bmRlZmluZWQpOiBUIHtcbiAgdHdlYWtlZE9iamVjdHMuc2V0KHZhbHVlLCB1bmRlZmluZWQpXG4gIHNldFBhcmVudCh7XG4gICAgdmFsdWUsXG4gICAgcGFyZW50UGF0aCxcbiAgICBpbmRleENoYW5nZUFsbG93ZWQ6IGZhbHNlLFxuICAgIGlzRGF0YU9iamVjdDogZmFsc2UsXG4gICAgY2xvbmVJZkFwcGxpY2FibGU6IHRydWUsXG4gIH0pXG5cbiAgLy8gbm90aGluZyB0byBkbyBmb3IgbW9kZWxzLCBkYXRhIGlzIGFscmVhZHkgcHJveGlmaWVkIGFuZCBpdHMgcGFyZW50IGlzIHNldFxuICAvLyBmb3Igc25hcHNob3RzIHdlIHdpbGwgdXNlIGl0cyBcIiRcIiBvYmplY3Qgc25hcHNob3QgZGlyZWN0bHlcblxuICByZXR1cm4gdmFsdWVcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyTW9kZWxUd2Vha2VyKCkge1xuICByZWdpc3RlclR3ZWFrZXIoVHdlYWtlclByaW9yaXR5Lk1vZGVsLCAodmFsdWUsIHBhcmVudFBhdGgpID0+IHtcbiAgICBpZiAoaXNNb2RlbCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB0d2Vha01vZGVsKHZhbHVlLCBwYXJlbnRQYXRoKVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH0pXG59XG4iLCJpbXBvcnQgeyByZWdpc3RlckFycmF5VHdlYWtlciB9IGZyb20gXCIuL3R3ZWFrQXJyYXlcIlxuaW1wb3J0IHsgcmVnaXN0ZXJGcm96ZW5Ud2Vha2VyIH0gZnJvbSBcIi4vdHdlYWtGcm96ZW5cIlxuaW1wb3J0IHsgcmVnaXN0ZXJNb2RlbFR3ZWFrZXIgfSBmcm9tIFwiLi90d2Vha01vZGVsXCJcbmltcG9ydCB7IHJlZ2lzdGVyUGxhaW5PYmplY3RUd2Vha2VyIH0gZnJvbSBcIi4vdHdlYWtQbGFpbk9iamVjdFwiXG5cbmxldCBkZWZhdWx0VHdlYWtlcnNSZWdpc3RlcmVkID0gZmFsc2VcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyRGVmYXVsdFR3ZWFrZXJzKCkge1xuICBpZiAoZGVmYXVsdFR3ZWFrZXJzUmVnaXN0ZXJlZCkge1xuICAgIHJldHVyblxuICB9XG4gIGRlZmF1bHRUd2Vha2Vyc1JlZ2lzdGVyZWQgPSB0cnVlXG5cbiAgcmVnaXN0ZXJBcnJheVR3ZWFrZXIoKVxuICByZWdpc3RlckZyb3plblR3ZWFrZXIoKVxuICByZWdpc3Rlck1vZGVsVHdlYWtlcigpXG4gIHJlZ2lzdGVyUGxhaW5PYmplY3RUd2Vha2VyKClcbn1cbiIsImltcG9ydCB7IGFjdGlvbiB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IGlzRGF0YU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC91dGlsc1wiXG5pbXBvcnQgeyBpc01vZGVsQXV0b1R5cGVDaGVja2luZ0VuYWJsZWQgfSBmcm9tIFwiLi4vZ2xvYmFsQ29uZmlnL2dsb2JhbENvbmZpZ1wiXG5pbXBvcnQgeyBnZXRPYmplY3RDaGlsZHJlbiB9IGZyb20gXCIuLi9wYXJlbnQvY29yZU9iamVjdENoaWxkcmVuXCJcbmltcG9ydCB7IGZhc3RHZXRQYXJlbnQsIFBhcmVudFBhdGggfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxuaW1wb3J0IHsgc2V0UGFyZW50IH0gZnJvbSBcIi4uL3BhcmVudC9zZXRQYXJlbnRcIlxuaW1wb3J0IHsgdW5zZXRJbnRlcm5hbFNuYXBzaG90IH0gZnJvbSBcIi4uL3NuYXBzaG90L2ludGVybmFsXCJcbmltcG9ydCB0eXBlIHsgQW55U3RhbmRhcmRUeXBlLCBUeXBlVG9EYXRhIH0gZnJvbSBcIi4uL3R5cGVzL3NjaGVtYXNcIlxuaW1wb3J0IHsgdHlwZUNoZWNrIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVDaGVja1wiXG5pbXBvcnQgeyBmYWlsdXJlLCBpbkRldk1vZGUsIGlzTWFwLCBpc09iamVjdCwgaXNQcmltaXRpdmUsIGlzU2V0IH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IGlzVHdlYWtlZE9iamVjdCwgdHdlYWtlZE9iamVjdHMgfSBmcm9tIFwiLi9jb3JlXCJcbmltcG9ydCB7IHJlZ2lzdGVyRGVmYXVsdFR3ZWFrZXJzIH0gZnJvbSBcIi4vcmVnaXN0ZXJEZWZhdWx0VHdlYWtlcnNcIlxuXG4vKipcbiAqIFR1cm5zIGFuIG9iamVjdCAoYXJyYXksIHBsYWluIG9iamVjdCkgaW50byBhIHRyZWUgbm9kZSxcbiAqIHdoaWNoIHRoZW4gY2FuIGFjY2VwdCBjYWxscyB0byBgZ2V0UGFyZW50YCwgYGdldFNuYXBzaG90YCwgZXRjLlxuICogSWYgYSB0cmVlIG5vZGUgaXMgcGFzc2VkIGl0IHdpbGwgcmV0dXJuIHRoZSBwYXNzZWQgYXJndW1lbnQgZGlyZWN0bHkuXG4gKiBBZGRpdGlvbmFsbHkgdGhpcyBtZXRob2Qgd2lsbCB1c2UgdGhlIHR5cGUgcGFzc2VkIHRvIGNoZWNrIHRoZSB2YWx1ZVxuICogY29uZm9ybXMgdG8gdGhlIHR5cGUgd2hlbiBtb2RlbCBhdXRvIHR5cGUgY2hlY2tpbmcgaXMgZW5hYmxlZC5cbiAqXG4gKiBAcGFyYW0gdHlwZSBUeXBlIGNoZWNrZXIuXG4gKiBAcGFyYW0gdmFsdWUgT2JqZWN0IHRvIHR1cm4gaW50byBhIHRyZWUgbm9kZS5cbiAqIEByZXR1cm5zIFRoZSBvYmplY3QgYXMgYSB0cmVlIG5vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1RyZWVOb2RlPFRUeXBlIGV4dGVuZHMgQW55U3RhbmRhcmRUeXBlLCBWIGV4dGVuZHMgVHlwZVRvRGF0YTxUVHlwZT4+KFxuICB0eXBlOiBUVHlwZSxcbiAgdmFsdWU6IFZcbik6IFZcblxuLyoqXG4gKiBUdXJucyBhbiBvYmplY3QgKGFycmF5LCBwbGFpbiBvYmplY3QpIGludG8gYSB0cmVlIG5vZGUsXG4gKiB3aGljaCB0aGVuIGNhbiBhY2NlcHQgY2FsbHMgdG8gYGdldFBhcmVudGAsIGBnZXRTbmFwc2hvdGAsIGV0Yy5cbiAqIElmIGEgdHJlZSBub2RlIGlzIHBhc3NlZCBpdCB3aWxsIHJldHVybiB0aGUgcGFzc2VkIGFyZ3VtZW50IGRpcmVjdGx5LlxuICpcbiAqIEBwYXJhbSB2YWx1ZSBPYmplY3QgdG8gdHVybiBpbnRvIGEgdHJlZSBub2RlLlxuICogQHJldHVybnMgVGhlIG9iamVjdCBhcyBhIHRyZWUgbm9kZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvVHJlZU5vZGU8VCBleHRlbmRzIG9iamVjdD4odmFsdWU6IFQpOiBUXG5cbi8vIGJhc2VcbmV4cG9ydCBmdW5jdGlvbiB0b1RyZWVOb2RlKGFyZzE6IGFueSwgYXJnMj86IGFueSk6IGFueSB7XG4gIGxldCB2YWx1ZTogb2JqZWN0LCB0eXBlOiBBbnlTdGFuZGFyZFR5cGUgfCB1bmRlZmluZWRcbiAgbGV0IGhhc1R5cGVcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICBoYXNUeXBlID0gZmFsc2VcbiAgICB2YWx1ZSA9IGFyZzFcbiAgfSBlbHNlIHtcbiAgICB0eXBlID0gYXJnMVxuICAgIGhhc1R5cGUgPSB0cnVlXG4gICAgdmFsdWUgPSBhcmcyXG4gIH1cblxuICBpZiAoIWlzT2JqZWN0KHZhbHVlKSkge1xuICAgIHRocm93IGZhaWx1cmUoXCJvbmx5IG9iamVjdHMgY2FuIGJlIHR1cm5lZCBpbnRvIHRyZWUgbm9kZXNcIilcbiAgfVxuXG4gIGlmIChoYXNUeXBlICYmIGlzTW9kZWxBdXRvVHlwZUNoZWNraW5nRW5hYmxlZCgpKSB7XG4gICAgY29uc3QgZXJyb3JzID0gdHlwZUNoZWNrKHR5cGUsIHZhbHVlKVxuICAgIGlmIChlcnJvcnMpIHtcbiAgICAgIGVycm9ycy50aHJvdygpXG4gICAgfVxuICB9XG5cbiAgaWYgKCFpc1R3ZWFrZWRPYmplY3QodmFsdWUsIHRydWUpKSB7XG4gICAgcmV0dXJuIHR3ZWFrKHZhbHVlLCB1bmRlZmluZWQpXG4gIH1cbiAgcmV0dXJuIHZhbHVlXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCB0eXBlIFR3ZWFrZXI8VD4gPSAodmFsdWU6IFQsIHBhcmVudFBhdGg6IFBhcmVudFBhdGg8YW55PiB8IHVuZGVmaW5lZCkgPT4gVCB8IHVuZGVmaW5lZFxuXG5jb25zdCB0d2Vha2VyczogeyBwcmlvcml0eTogbnVtYmVyOyB0d2Vha2VyOiBUd2Vha2VyPGFueT4gfVtdID0gW11cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyVHdlYWtlcjxUPihwcmlvcml0eTogbnVtYmVyLCB0d2Vha2VyOiBUd2Vha2VyPFQ+KTogdm9pZCB7XG4gIHR3ZWFrZXJzLnB1c2goeyBwcmlvcml0eSwgdHdlYWtlciB9KVxuICB0d2Vha2Vycy5zb3J0KChhLCBiKSA9PiBhLnByaW9yaXR5IC0gYi5wcmlvcml0eSlcbn1cblxuZnVuY3Rpb24gaW50ZXJuYWxUd2VhazxUPih2YWx1ZTogVCwgcGFyZW50UGF0aDogUGFyZW50UGF0aDxhbnk+IHwgdW5kZWZpbmVkKTogVCB7XG4gIGlmIChpc1ByaW1pdGl2ZSh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIC8vIGFscmVhZHkgdHdlYWtlZFxuICBpZiAoaXNUd2Vha2VkT2JqZWN0KHZhbHVlLCB0cnVlKSkge1xuICAgIHZhbHVlID0gc2V0UGFyZW50KHtcbiAgICAgIHZhbHVlLFxuICAgICAgcGFyZW50UGF0aCxcbiAgICAgIGluZGV4Q2hhbmdlQWxsb3dlZDogZmFsc2UsXG4gICAgICBpc0RhdGFPYmplY3Q6IGZhbHNlLFxuICAgICAgY2xvbmVJZkFwcGxpY2FibGU6IHRydWUsXG4gICAgfSlcbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIC8vIHVuc3VwcG9ydGVkIChtdXN0IGdvIGJlZm9yZSBwbGFpbiBvYmplY3QgdHdlYWtlcilcbiAgaWYgKGlzRGF0YU1vZGVsKHZhbHVlKSkge1xuICAgIHRocm93IGZhaWx1cmUoXG4gICAgICBcImRhdGEgbW9kZWxzIGFyZSBub3QgZGlyZWN0bHkgc3VwcG9ydGVkLiB5b3UgbWF5IGluc2VydCB0aGUgZGF0YSBpbiB0aGUgdHJlZSBpbnN0ZWFkICgnJCcgcHJvcGVydHkpLlwiXG4gICAgKVxuICB9XG5cbiAgcmVnaXN0ZXJEZWZhdWx0VHdlYWtlcnMoKVxuXG4gIGNvbnN0IHR3ZWFrZXJzTGVuID0gdHdlYWtlcnMubGVuZ3RoXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdHdlYWtlcnNMZW47IGkrKykge1xuICAgIGNvbnN0IHsgdHdlYWtlciB9ID0gdHdlYWtlcnNbaV1cbiAgICBjb25zdCB0d2Vha2VkVmFsID0gdHdlYWtlcih2YWx1ZSwgcGFyZW50UGF0aClcbiAgICBpZiAodHdlYWtlZFZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdHdlYWtlZFZhbFxuICAgIH1cbiAgfVxuXG4gIC8vIHVuc3VwcG9ydGVkXG4gIGlmIChpc01hcCh2YWx1ZSkpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFwibWFwcyBhcmUgbm90IGRpcmVjdGx5IHN1cHBvcnRlZC4gY29uc2lkZXIgdXNpbmcgJ09iamVjdE1hcCcgLyAnYXNNYXAnIGluc3RlYWQuXCIpXG4gIH1cblxuICAvLyB1bnN1cHBvcnRlZFxuICBpZiAoaXNTZXQodmFsdWUpKSB7XG4gICAgdGhyb3cgZmFpbHVyZShcInNldHMgYXJlIG5vdCBkaXJlY3RseSBzdXBwb3J0ZWQuIGNvbnNpZGVyIHVzaW5nICdBcnJheVNldCcgLyAnYXNTZXQnIGluc3RlYWQuXCIpXG4gIH1cblxuICB0aHJvdyBmYWlsdXJlKFxuICAgIGB0d2VhayBjYW4gb25seSB3b3JrIG92ZXIgbW9kZWxzLCBvYnNlcnZhYmxlIG9iamVjdHMvYXJyYXlzLCBvciBwcmltaXRpdmVzLCBidXQgZ290ICR7dmFsdWV9IGluc3RlYWRgXG4gIClcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IHR3ZWFrID0gYWN0aW9uKFwidHdlYWtcIiwgaW50ZXJuYWxUd2VhaylcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyeVVudHdlYWsodmFsdWU6IGFueSk6ICgoKSA9PiB2b2lkKSB8IHVuZGVmaW5lZCB7XG4gIGlmIChpc1ByaW1pdGl2ZSh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cblxuICBpZiAoaW5EZXZNb2RlKSB7XG4gICAgaWYgKCFmYXN0R2V0UGFyZW50KHZhbHVlKSkge1xuICAgICAgdGhyb3cgZmFpbHVyZShcImFzc2VydGlvbiBmYWlsZWQ6IG9iamVjdCBjYW5ub3QgYmUgdW50d2Vha2VkIGlmIGl0IGRvZXMgbm90IGhhdmUgYSBwYXJlbnRcIilcbiAgICB9XG4gIH1cblxuICBjb25zdCB1bnR3ZWFrZXIgPSB0d2Vha2VkT2JqZWN0cy5nZXQodmFsdWUpXG4gIGlmICghdW50d2Vha2VyKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9XG5cbiAgLy8gcHJlLXVudHdlYWtpbmcsIHVudHdlYWsgY2hpbGRyZW4gZmlyc3RcblxuICAvLyB3ZSBoYXZlIHRvIG1ha2UgYSBjb3B5IHNpbmNlIGl0IHdpbGwgYmUgY2hhbmdlZFxuICBjb25zdCBjaGlsZHJlbiA9IEFycmF5LmZyb20oZ2V0T2JqZWN0Q2hpbGRyZW4odmFsdWUpIS52YWx1ZXMoKSlcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgc2V0UGFyZW50KHtcbiAgICAgIHZhbHVlOiBjaGlsZHJlbltpXSxcbiAgICAgIHBhcmVudFBhdGg6IHVuZGVmaW5lZCxcbiAgICAgIGluZGV4Q2hhbmdlQWxsb3dlZDogZmFsc2UsXG4gICAgICBpc0RhdGFPYmplY3Q6IGZhbHNlLFxuICAgICAgLy8gbm8gbmVlZCB0byBjbG9uZSBpZiB1bnNldHRpbmcgdGhlIHBhcmVudFxuICAgICAgY2xvbmVJZkFwcGxpY2FibGU6IGZhbHNlLFxuICAgIH0pXG4gIH1cblxuICByZXR1cm4gKCkgPT4ge1xuICAgIC8vIHBvc3QtdW50d2Vha2luZywgY2FsbCB0aGUgdW50d2Vha2VyXG4gICAgdW50d2Vha2VyKClcblxuICAgIHR3ZWFrZWRPYmplY3RzLmRlbGV0ZSh2YWx1ZSlcbiAgICB1bnNldEludGVybmFsU25hcHNob3QodmFsdWUpXG4gIH1cbn1cbiIsImltcG9ydCB0eXBlIHsgQW55RGF0YU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9CYXNlRGF0YU1vZGVsXCJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcbmltcG9ydCB0eXBlIHsgTW9kZWxDbGFzcyB9IGZyb20gXCIuL0Jhc2VNb2RlbFNoYXJlZFwiXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjb25zdCBtb2RlbEluaXRpYWxpemVyc1N5bWJvbCA9IFN5bWJvbChcIm1vZGVsSW5pdGlhbGl6ZXJzXCIpXG5cbnR5cGUgTW9kZWxDbGFzc0luaXRpYWxpemVyID0gKG1vZGVsSW5zdGFuY2U6IEFueU1vZGVsIHwgQW55RGF0YU1vZGVsKSA9PiB2b2lkXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRNb2RlbENsYXNzSW5pdGlhbGl6ZXIoXG4gIG1vZGVsQ2xhc3M6IE1vZGVsQ2xhc3M8QW55TW9kZWwgfCBBbnlEYXRhTW9kZWw+LFxuICBpbml0OiBNb2RlbENsYXNzSW5pdGlhbGl6ZXJcbikge1xuICBsZXQgaW5pdGlhbGl6ZXJzID0gKG1vZGVsQ2xhc3MgYXMgYW55KVttb2RlbEluaXRpYWxpemVyc1N5bWJvbF1cbiAgaWYgKCFpbml0aWFsaXplcnMpIHtcbiAgICBpbml0aWFsaXplcnMgPSBbXVxuICAgIDsobW9kZWxDbGFzcyBhcyBhbnkpW21vZGVsSW5pdGlhbGl6ZXJzU3ltYm9sXSA9IGluaXRpYWxpemVyc1xuICB9XG4gIGluaXRpYWxpemVycy5wdXNoKGluaXQpXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNb2RlbENsYXNzSW5pdGlhbGl6ZXJzKFxuICBtb2RlbENsYXNzOiBNb2RlbENsYXNzPEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPlxuKTogTW9kZWxDbGFzc0luaXRpYWxpemVyW10gfCB1bmRlZmluZWQge1xuICByZXR1cm4gKG1vZGVsQ2xhc3MgYXMgYW55KVttb2RlbEluaXRpYWxpemVyc1N5bWJvbF1cbn1cbiIsImltcG9ydCB0eXBlIHsgQW55RGF0YU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9CYXNlRGF0YU1vZGVsXCJcclxuaW1wb3J0IHR5cGUgeyBBbnlNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9CYXNlTW9kZWxcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcclxuaW1wb3J0IHsgZ2V0TW9kZWxDbGFzc0luaXRpYWxpemVycyB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9tb2RlbENsYXNzSW5pdGlhbGl6ZXJcIlxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5TW9kZWxJbml0aWFsaXplcnMoXHJcbiAgbW9kZWxDbGFzczogTW9kZWxDbGFzczxBbnlNb2RlbCB8IEFueURhdGFNb2RlbD4sXHJcbiAgbW9kZWxPYmo6IGFueVxyXG4pIHtcclxuICBjb25zdCBpbml0aWFsaXplcnMgPSBnZXRNb2RlbENsYXNzSW5pdGlhbGl6ZXJzKG1vZGVsQ2xhc3MpXHJcbiAgaWYgKGluaXRpYWxpemVycykge1xyXG4gICAgY29uc3QgbGVuID0gaW5pdGlhbGl6ZXJzLmxlbmd0aFxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICBpbml0aWFsaXplcnNbaV0obW9kZWxPYmopXHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IGFjdGlvbiB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHR5cGUgeyBPIH0gZnJvbSBcInRzLXRvb2xiZWx0XCJcclxuaW1wb3J0IHsgaXNNb2RlbEF1dG9UeXBlQ2hlY2tpbmdFbmFibGVkIH0gZnJvbSBcIi4uL2dsb2JhbENvbmZpZy9nbG9iYWxDb25maWdcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsVW50cmFuc2Zvcm1lZERhdGEgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcclxuaW1wb3J0IHsgbW9kZWxJbmZvQnlDbGFzcyB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9tb2RlbEluZm9cIlxyXG5pbXBvcnQgeyBhcHBseU1vZGVsSW5pdGlhbGl6ZXJzIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL25ld01vZGVsXCJcclxuaW1wb3J0IHsgZmFpbHVyZSwgaW5EZXZNb2RlLCBtYWtlUHJvcFJlYWRvbmx5IH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHR5cGUgeyBBbnlEYXRhTW9kZWwgfSBmcm9tIFwiLi9CYXNlRGF0YU1vZGVsXCJcclxuaW1wb3J0IHR5cGUgeyBEYXRhTW9kZWxDb25zdHJ1Y3Rvck9wdGlvbnMgfSBmcm9tIFwiLi9EYXRhTW9kZWxDb25zdHJ1Y3Rvck9wdGlvbnNcIlxyXG5pbXBvcnQgeyBnZXREYXRhTW9kZWxNZXRhZGF0YSB9IGZyb20gXCIuL2dldERhdGFNb2RlbE1ldGFkYXRhXCJcclxuaW1wb3J0IHsgYXNzZXJ0SXNEYXRhTW9kZWxDbGFzcyB9IGZyb20gXCIuL3V0aWxzXCJcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBjb25zdCBpbnRlcm5hbE5ld0RhdGFNb2RlbCA9IGFjdGlvbihcclxuICBcIm5ld01vZGVsXCIsXHJcbiAgPE0gZXh0ZW5kcyBBbnlEYXRhTW9kZWw+KFxyXG4gICAgb3JpZ01vZGVsT2JqOiBNLFxyXG4gICAgdHdlYWtlZERhdGE6IE1vZGVsVW50cmFuc2Zvcm1lZERhdGE8TT4sXHJcbiAgICBvcHRpb25zOiBQaWNrPERhdGFNb2RlbENvbnN0cnVjdG9yT3B0aW9ucywgXCJtb2RlbENsYXNzXCI+XHJcbiAgKTogTSA9PiB7XHJcbiAgICBjb25zdCB7IG1vZGVsQ2xhc3M6IF9tb2RlbENsYXNzIH0gPSBvcHRpb25zXHJcbiAgICBjb25zdCBtb2RlbENsYXNzID0gX21vZGVsQ2xhc3MhXHJcblxyXG4gICAgaWYgKGluRGV2TW9kZSkge1xyXG4gICAgICBhc3NlcnRJc0RhdGFNb2RlbENsYXNzKG1vZGVsQ2xhc3MsIFwibW9kZWxDbGFzc1wiKVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IG1vZGVsT2JqID0gb3JpZ01vZGVsT2JqIGFzIE8uV3JpdGFibGU8TT5cclxuXHJcbiAgICBjb25zdCBtb2RlbEluZm8gPSBtb2RlbEluZm9CeUNsYXNzLmdldChtb2RlbENsYXNzKVxyXG4gICAgaWYgKCFtb2RlbEluZm8pIHtcclxuICAgICAgdGhyb3cgZmFpbHVyZShcclxuICAgICAgICBgbm8gbW9kZWwgaW5mbyBmb3IgY2xhc3MgJHttb2RlbENsYXNzLm5hbWV9IGNvdWxkIGJlIGZvdW5kIC0gZGlkIHlvdSBmb3JnZXQgdG8gYWRkIHRoZSBAbW9kZWwgZGVjb3JhdG9yP2BcclxuICAgICAgKVxyXG4gICAgfVxyXG5cclxuICAgIC8vIGxpbmsgaXQsIGFuZCBtYWtlIGl0IHJlYWRvbmx5XHJcbiAgICBtb2RlbE9iai4kID0gdHdlYWtlZERhdGFcclxuICAgIGlmIChpbkRldk1vZGUpIHtcclxuICAgICAgbWFrZVByb3BSZWFkb25seShtb2RlbE9iaiwgXCIkXCIsIHRydWUpXHJcbiAgICB9XHJcblxyXG4gICAgLy8gcnVuIGFueSBleHRyYSBpbml0aWFsaXplcnMgZm9yIHRoZSBjbGFzcyBhcyBuZWVkZWRcclxuICAgIGFwcGx5TW9kZWxJbml0aWFsaXplcnMobW9kZWxDbGFzcywgbW9kZWxPYmopXHJcblxyXG4gICAgLy8gdHlwZSBjaGVjayBpdCBpZiBuZWVkZWRcclxuICAgIGlmIChpc01vZGVsQXV0b1R5cGVDaGVja2luZ0VuYWJsZWQoKSAmJiBnZXREYXRhTW9kZWxNZXRhZGF0YShtb2RlbENsYXNzKS5kYXRhVHlwZSkge1xyXG4gICAgICBjb25zdCBlcnIgPSBtb2RlbE9iai50eXBlQ2hlY2soKVxyXG4gICAgICBpZiAoZXJyKSB7XHJcbiAgICAgICAgZXJyLnRocm93KClcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBtb2RlbE9iaiBhcyBNXHJcbiAgfVxyXG4pXHJcbiIsImltcG9ydCB7IE1vZGVsQ2xhc3MsIHByb3BzVHlwZVN5bWJvbCB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9CYXNlTW9kZWxTaGFyZWRcIlxyXG5pbXBvcnQgeyBtb2RlbEluZm9CeUNsYXNzIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL21vZGVsSW5mb1wiXHJcbmltcG9ydCB7IGdldEludGVybmFsTW9kZWxDbGFzc1Byb3BzSW5mbyB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9tb2RlbFByb3BzSW5mb1wiXHJcbmltcG9ydCB7XHJcbiAgTW9kZWxQcm9wcyxcclxuICBNb2RlbFByb3BzVG9UcmFuc2Zvcm1lZENyZWF0aW9uRGF0YSxcclxuICBNb2RlbFByb3BzVG9VbnRyYW5zZm9ybWVkQ3JlYXRpb25EYXRhLFxyXG4gIE1vZGVsUHJvcHNUb1VudHJhbnNmb3JtZWREYXRhLFxyXG4gIG5vRGVmYXVsdFZhbHVlLFxyXG59IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9wcm9wXCJcclxuaW1wb3J0IHsgZ2V0U25hcHNob3QgfSBmcm9tIFwiLi4vc25hcHNob3QvZ2V0U25hcHNob3RcIlxyXG5pbXBvcnQgeyBpc1RyZWVOb2RlIH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXHJcbmltcG9ydCB7IHRvVHJlZU5vZGUgfSBmcm9tIFwiLi4vdHdlYWtlci90d2Vha1wiXHJcbmltcG9ydCB7IHR5cGVzRGF0YU1vZGVsRGF0YSB9IGZyb20gXCIuLi90eXBlcy9vYmplY3RCYXNlZC90eXBlc0RhdGFNb2RlbERhdGFcIlxyXG5pbXBvcnQgeyB0eXBlQ2hlY2sgfSBmcm9tIFwiLi4vdHlwZXMvdHlwZUNoZWNrXCJcclxuaW1wb3J0IHR5cGUgeyBUeXBlQ2hlY2tFcnJvciB9IGZyb20gXCIuLi90eXBlcy9UeXBlQ2hlY2tFcnJvclwiXHJcbmltcG9ydCB7IGZhaWx1cmUsIGlzT2JqZWN0IH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgZ2V0T3JDcmVhdGUgfSBmcm9tIFwiLi4vdXRpbHMvbWFwVXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IERhdGFNb2RlbENvbnN0cnVjdG9yT3B0aW9ucyB9IGZyb20gXCIuL0RhdGFNb2RlbENvbnN0cnVjdG9yT3B0aW9uc1wiXHJcbmltcG9ydCB7IGludGVybmFsTmV3RGF0YU1vZGVsIH0gZnJvbSBcIi4vbmV3RGF0YU1vZGVsXCJcclxuXHJcbmNvbnN0IGRhdGFNb2RlbEluc3RhbmNlQ2FjaGUgPSBuZXcgV2Vha01hcDxNb2RlbENsYXNzPEFueURhdGFNb2RlbD4sIFdlYWtNYXA8YW55LCBBbnlEYXRhTW9kZWw+PigpXHJcblxyXG4vKipcclxuICogQmFzZSBhYnN0cmFjdCBjbGFzcyBmb3IgZGF0YSBtb2RlbHMuIFVzZSBgRGF0YU1vZGVsYCBpbnN0ZWFkIHdoZW4gZXh0ZW5kaW5nLlxyXG4gKlxyXG4gKiBOZXZlciBvdmVycmlkZSB0aGUgY29uc3RydWN0b3IsIHVzZSBgb25MYXp5SW5pdGAgaW5zdGVhZC5cclxuICpcclxuICogQHR5cGVwYXJhbSBEYXRhIFByb3BzIGRhdGEgdHlwZS5cclxuICovXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlRGF0YU1vZGVsPFRQcm9wcyBleHRlbmRzIE1vZGVsUHJvcHM+IHtcclxuICAvLyBqdXN0IHRvIG1ha2UgdHlwaW5nIHdvcmsgcHJvcGVybHlcclxuICBbcHJvcHNUeXBlU3ltYm9sXSE6IFRQcm9wc1xyXG5cclxuICAvKipcclxuICAgKiBDYWxsZWQgYWZ0ZXIgdGhlIGluc3RhbmNlIGlzIGNyZWF0ZWQgd2hlbiB0aGVyZSdzIHRoZSBmaXJzdCBjYWxsIHRvIGBmbihNLCBkYXRhKWAuXHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIG9uTGF6eUluaXQ/KCk6IHZvaWRcclxuXHJcbiAgLyoqXHJcbiAgICogRGF0YSBwYXJ0IG9mIHRoZSBtb2RlbCwgd2hpY2ggaXMgb2JzZXJ2YWJsZSBhbmQgd2lsbCBiZSBzZXJpYWxpemVkIGluIHNuYXBzaG90cy5cclxuICAgKiBVc2UgaXQgaWYgb25lIG9mIHRoZSBkYXRhIHByb3BlcnRpZXMgbWF0Y2hlcyBvbmUgb2YgdGhlIG1vZGVsIHByb3BlcnRpZXMvZnVuY3Rpb25zLlxyXG4gICAqIFRoaXMgYWxzbyBhbGxvd3MgYWNjZXNzIHRvIHRoZSBiYWNrZWQgdmFsdWVzIG9mIHRyYW5zZm9ybWVkIHByb3BlcnRpZXMuXHJcbiAgICovXHJcbiAgcmVhZG9ubHkgJCE6IE1vZGVsUHJvcHNUb1VudHJhbnNmb3JtZWREYXRhPFRQcm9wcz5cclxuXHJcbiAgLyoqXHJcbiAgICogUGVyZm9ybXMgYSB0eXBlIGNoZWNrIG92ZXIgdGhlIG1vZGVsIGluc3RhbmNlLlxyXG4gICAqIEZvciB0aGlzIHRvIHdvcmsgYSBkYXRhIHR5cGUgaGFzIHRvIGJlIGRlY2xhcmVkIGFzIHBhcnQgb2YgdGhlIG1vZGVsIHByb3BlcnRpZXMuXHJcbiAgICpcclxuICAgKiBAcmV0dXJucyBBIGBUeXBlQ2hlY2tFcnJvcmAgb3IgYG51bGxgIGlmIHRoZXJlIGlzIG5vIGVycm9yLlxyXG4gICAqL1xyXG4gIHR5cGVDaGVjaygpOiBUeXBlQ2hlY2tFcnJvciB8IG51bGwge1xyXG4gICAgY29uc3QgdHlwZSA9IHR5cGVzRGF0YU1vZGVsRGF0YTx0aGlzPih0aGlzLmNvbnN0cnVjdG9yIGFzIGFueSlcclxuICAgIHJldHVybiB0eXBlQ2hlY2sodHlwZSwgdGhpcy4kIGFzIGFueSlcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgYSBkYXRhIG1vZGVsLlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgZGF0YTpcclxuICAgICAgfCBNb2RlbFByb3BzVG9VbnRyYW5zZm9ybWVkQ3JlYXRpb25EYXRhPFRQcm9wcz5cclxuICAgICAgfCBNb2RlbFByb3BzVG9UcmFuc2Zvcm1lZENyZWF0aW9uRGF0YTxUUHJvcHM+XHJcbiAgKSB7XHJcbiAgICBpZiAoIWlzT2JqZWN0KGRhdGEpKSB7XHJcbiAgICAgIHRocm93IGZhaWx1cmUoXCJkYXRhIG1vZGVscyBjYW4gb25seSB3b3JrIG92ZXIgZGF0YSBvYmplY3RzXCIpXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgeyBtb2RlbENsYXNzOiBfbW9kZWxDbGFzcyB9OiBEYXRhTW9kZWxDb25zdHJ1Y3Rvck9wdGlvbnMgPSBhcmd1bWVudHNbMV0gYXMgYW55XHJcbiAgICBjb25zdCBtb2RlbENsYXNzID0gX21vZGVsQ2xhc3MhXHJcblxyXG4gICAgdHlwZSBEYXRhID0gTW9kZWxQcm9wc1RvVW50cmFuc2Zvcm1lZERhdGE8VFByb3BzPlxyXG4gICAgbGV0IHR3ZWFrZWREYXRhOiBEYXRhXHJcbiAgICBpZiAoaXNUcmVlTm9kZShkYXRhKSkge1xyXG4gICAgICAvLyBpbiB0aGVvcnkgYWxyZWFkeSBpbml0aWFsaXplZFxyXG4gICAgICB0d2Vha2VkRGF0YSA9IGRhdGEgYXMgYW55IGFzIERhdGFcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnN0IG1vZGVsSW5mbyA9IG1vZGVsSW5mb0J5Q2xhc3MuZ2V0KG1vZGVsQ2xhc3MpXHJcbiAgICAgIGlmICghbW9kZWxJbmZvKSB7XHJcbiAgICAgICAgdGhyb3cgZmFpbHVyZShcclxuICAgICAgICAgIGBubyBtb2RlbCBpbmZvIGZvciBjbGFzcyAke21vZGVsQ2xhc3MubmFtZX0gY291bGQgYmUgZm91bmQgLSBkaWQgeW91IGZvcmdldCB0byBhZGQgdGhlIEBtb2RlbCBkZWNvcmF0b3I/YFxyXG4gICAgICAgIClcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgbW9kZWxQcm9wcyA9IGdldEludGVybmFsTW9kZWxDbGFzc1Byb3BzSW5mbyhtb2RlbENsYXNzKVxyXG5cclxuICAgICAgY29uc3QgaW5pdGlhbERhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBPYmplY3QuYXNzaWduKHt9LCBkYXRhKVxyXG5cclxuICAgICAgY29uc3QgbW9kZWxQcm9wc0tleXMgPSBPYmplY3Qua2V5cyhtb2RlbFByb3BzKVxyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1vZGVsUHJvcHNLZXlzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgY29uc3QgayA9IG1vZGVsUHJvcHNLZXlzW2ldXHJcbiAgICAgICAgY29uc3QgcHJvcERhdGEgPSBtb2RlbFByb3BzW2tdXHJcblxyXG4gICAgICAgIGxldCBuZXdWYWx1ZSA9IGluaXRpYWxEYXRhIVtrXVxyXG4gICAgICAgIGxldCBjaGFuZ2VkID0gZmFsc2VcclxuXHJcbiAgICAgICAgLy8gYXBwbHkgdW50cmFuc2Zvcm0gKGlmIGFueSlcclxuICAgICAgICBpZiAocHJvcERhdGEuX3RyYW5zZm9ybSkge1xyXG4gICAgICAgICAgY2hhbmdlZCA9IHRydWVcclxuICAgICAgICAgIG5ld1ZhbHVlID0gcHJvcERhdGEuX3RyYW5zZm9ybS51bnRyYW5zZm9ybShuZXdWYWx1ZSwgdGhpcywgaylcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGFwcGx5IGRlZmF1bHQgdmFsdWUgKGlmIG5lZWRlZClcclxuICAgICAgICBpZiAobmV3VmFsdWUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgaWYgKHByb3BEYXRhLl9kZWZhdWx0Rm4gIT09IG5vRGVmYXVsdFZhbHVlKSB7XHJcbiAgICAgICAgICAgIGNoYW5nZWQgPSB0cnVlXHJcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gcHJvcERhdGEuX2RlZmF1bHRGbigpXHJcbiAgICAgICAgICB9IGVsc2UgaWYgKHByb3BEYXRhLl9kZWZhdWx0VmFsdWUgIT09IG5vRGVmYXVsdFZhbHVlKSB7XHJcbiAgICAgICAgICAgIGNoYW5nZWQgPSB0cnVlXHJcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gcHJvcERhdGEuX2RlZmF1bHRWYWx1ZVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGNoYW5nZWQpIHtcclxuICAgICAgICAgIGluaXRpYWxEYXRhW2tdID0gbmV3VmFsdWVcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHR3ZWFrZWREYXRhID0gdG9UcmVlTm9kZShpbml0aWFsRGF0YSBhcyBEYXRhKVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGluc3RhbmNlc0Zvck1vZGVsQ2xhc3MgPSBnZXRPckNyZWF0ZShcclxuICAgICAgZGF0YU1vZGVsSW5zdGFuY2VDYWNoZSxcclxuICAgICAgbW9kZWxDbGFzcyxcclxuICAgICAgKCkgPT4gbmV3IFdlYWtNYXAoKVxyXG4gICAgKVxyXG5cclxuICAgIGNvbnN0IGluc3RhbmNlID0gaW5zdGFuY2VzRm9yTW9kZWxDbGFzcy5nZXQodHdlYWtlZERhdGEpXHJcbiAgICBpZiAoaW5zdGFuY2UpIHtcclxuICAgICAgcmV0dXJuIGluc3RhbmNlXHJcbiAgICB9XHJcblxyXG4gICAgaW5zdGFuY2VzRm9yTW9kZWxDbGFzcy5zZXQodHdlYWtlZERhdGEsIHRoaXMpXHJcblxyXG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIG1vZGVsQ2xhc3MucHJvdG90eXBlKVxyXG5cclxuICAgIGNvbnN0IHNlbGYgPSB0aGlzIGFzIGFueVxyXG5cclxuICAgIC8vIGRlbGV0ZSB1bm5lY2Vzc2FyeSBwcm9wc1xyXG4gICAgZGVsZXRlIHNlbGZbcHJvcHNUeXBlU3ltYm9sXVxyXG5cclxuICAgIGludGVybmFsTmV3RGF0YU1vZGVsKHRoaXMsIHR3ZWFrZWREYXRhIGFzIGFueSwge1xyXG4gICAgICBtb2RlbENsYXNzLFxyXG4gICAgfSlcclxuICB9XHJcblxyXG4gIHRvU3RyaW5nKG9wdGlvbnM/OiB7IHdpdGhEYXRhPzogYm9vbGVhbiB9KSB7XHJcbiAgICBjb25zdCBmaW5hbE9wdGlvbnMgPSB7XHJcbiAgICAgIHdpdGhEYXRhOiB0cnVlLFxyXG4gICAgICAuLi5vcHRpb25zLFxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IG1vZGVsSW5mbyA9IG1vZGVsSW5mb0J5Q2xhc3MuZ2V0KHRoaXMuY29uc3RydWN0b3IgYXMgYW55KVxyXG5cclxuICAgIGNvbnN0IGZpcnN0UGFydCA9IGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0jJHttb2RlbEluZm8hLm5hbWV9YFxyXG5cclxuICAgIHJldHVybiBmaW5hbE9wdGlvbnMud2l0aERhdGFcclxuICAgICAgPyBgWyR7Zmlyc3RQYXJ0fSAke0pTT04uc3RyaW5naWZ5KGdldFNuYXBzaG90KHRoaXMpKX1dYFxyXG4gICAgICA6IGBbJHtmaXJzdFBhcnR9XWBcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaWdub3JlXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBCYXNlRGF0YU1vZGVsS2V5cyA9IGtleW9mIEFueURhdGFNb2RlbCB8IFwib25MYXp5SW5pdFwiXHJcblxyXG4vLyB0aGVzZSBwcm9wcyB3aWxsIG5ldmVyIGJlIGhvaXN0ZWQgdG8gdGhpc1xyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgYmFzZURhdGFNb2RlbFByb3BOYW1lcyA9IG5ldyBTZXQ8QmFzZURhdGFNb2RlbEtleXM+KFtcIm9uTGF6eUluaXRcIiwgXCIkXCIsIFwidHlwZUNoZWNrXCJdKVxyXG5cclxuLyoqXHJcbiAqIEFueSBraW5kIG9mIGRhdGEgbW9kZWwgaW5zdGFuY2UuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEFueURhdGFNb2RlbCBleHRlbmRzIEJhc2VEYXRhTW9kZWw8YW55PiB7fVxyXG5cclxuLyoqXHJcbiAqIEEgZGF0YSBtb2RlbCBjbGFzcyBkZWNsYXJhdGlvbiwgbWFkZSBvZiBhIGJhc2UgbW9kZWwgYW5kIHRoZSBtb2RlbCBpbnRlcmZhY2UuXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBEYXRhTW9kZWxDbGFzc0RlY2xhcmF0aW9uPEJhc2VNb2RlbENsYXNzLCBNb2RlbEludGVyZmFjZT4gPSBCYXNlTW9kZWxDbGFzcyAmIHtcclxuICAoLi4uYXJnczogYW55W10pOiBNb2RlbEludGVyZmFjZVxyXG59XHJcbiIsImltcG9ydCB0eXBlIHsgTW9kZWxDbGFzcyB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9CYXNlTW9kZWxTaGFyZWRcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXG5pbXBvcnQgdHlwZSB7IEFueURhdGFNb2RlbCB9IGZyb20gXCIuL0Jhc2VEYXRhTW9kZWxcIlxuaW1wb3J0IHsgQmFzZURhdGFNb2RlbCB9IGZyb20gXCIuL0Jhc2VEYXRhTW9kZWxcIlxuXG4vKipcbiAqIENoZWNrcyBpZiBhbiBvYmplY3QgaXMgYSBkYXRhIG1vZGVsIGluc3RhbmNlLlxuICpcbiAqIEBwYXJhbSBtb2RlbFxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGF0YU1vZGVsKG1vZGVsOiB1bmtub3duKTogbW9kZWwgaXMgQW55RGF0YU1vZGVsIHtcbiAgcmV0dXJuIG1vZGVsIGluc3RhbmNlb2YgQmFzZURhdGFNb2RlbFxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICpcbiAqIEFzc2VydHMgc29tZXRoaW5nIGlzIGFjdHVhbGx5IGEgZGF0YSBtb2RlbC5cbiAqXG4gKiBAcGFyYW0gbW9kZWxcbiAqIEBwYXJhbSBhcmdOYW1lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRJc0RhdGFNb2RlbChcbiAgbW9kZWw6IHVua25vd24sXG4gIGFyZ05hbWU6IHN0cmluZyxcbiAgY3VzdG9tRXJyTXNnID0gXCJtdXN0IGJlIGEgZGF0YSBtb2RlbCBpbnN0YW5jZVwiXG4pOiBhc3NlcnRzIG1vZGVsIGlzIEFueURhdGFNb2RlbCB7XG4gIGlmICghaXNEYXRhTW9kZWwobW9kZWwpKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgJHthcmdOYW1lfSAke2N1c3RvbUVyck1zZ31gKVxuICB9XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RhdGFNb2RlbENsYXNzKG1vZGVsQ2xhc3M6IHVua25vd24pOiBtb2RlbENsYXNzIGlzIE1vZGVsQ2xhc3M8QW55RGF0YU1vZGVsPiB7XG4gIGlmICh0eXBlb2YgbW9kZWxDbGFzcyAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBpZiAobW9kZWxDbGFzcyAhPT0gQmFzZURhdGFNb2RlbCAmJiAhKG1vZGVsQ2xhc3MucHJvdG90eXBlIGluc3RhbmNlb2YgQmFzZURhdGFNb2RlbCkpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIHJldHVybiB0cnVlXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRJc0RhdGFNb2RlbENsYXNzKFxuICBtb2RlbENsYXNzOiB1bmtub3duLFxuICBhcmdOYW1lOiBzdHJpbmdcbik6IGFzc2VydHMgbW9kZWxDbGFzcyBpcyBNb2RlbENsYXNzPEFueURhdGFNb2RlbD4ge1xuICBpZiAodHlwZW9mIG1vZGVsQ2xhc3MgIT09IFwiZnVuY3Rpb25cIikge1xuICAgIHRocm93IGZhaWx1cmUoYCR7YXJnTmFtZX0gbXVzdCBiZSBhIGNsYXNzYClcbiAgfVxuXG4gIGlmIChtb2RlbENsYXNzICE9PSBCYXNlRGF0YU1vZGVsICYmICEobW9kZWxDbGFzcy5wcm90b3R5cGUgaW5zdGFuY2VvZiBCYXNlRGF0YU1vZGVsKSkge1xuICAgIHRocm93IGZhaWx1cmUoYCR7YXJnTmFtZX0gbXVzdCBleHRlbmQgRGF0YU1vZGVsYClcbiAgfVxufVxuIiwiaW1wb3J0IHR5cGUgeyBNb2RlbENsYXNzIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL0Jhc2VNb2RlbFNoYXJlZFwiXG5pbXBvcnQgeyBtb2RlbE1ldGFkYXRhU3ltYm9sIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL21vZGVsU3ltYm9sc1wiXG5pbXBvcnQgdHlwZSB7IEFueVR5cGUgfSBmcm9tIFwiLi4vdHlwZXMvc2NoZW1hc1wiXG5pbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB0eXBlIHsgQW55RGF0YU1vZGVsIH0gZnJvbSBcIi4vQmFzZURhdGFNb2RlbFwiXG5pbXBvcnQgeyBpc0RhdGFNb2RlbCwgaXNEYXRhTW9kZWxDbGFzcyB9IGZyb20gXCIuL3V0aWxzXCJcblxuLyoqXG4gKiBBc3NvY2lhdGVkIGRhdGEgbW9kZWwgbWV0YWRhdGEuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YU1vZGVsTWV0YWRhdGEge1xuICAvKipcbiAgICogQXNzb2NpYXRlZCBkYXRhIHR5cGUgZm9yIHJ1bnRpbWUgY2hlY2tpbmcgKGlmIGFueSkuXG4gICAqL1xuICBkYXRhVHlwZT86IEFueVR5cGVcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBhc3NvY2lhdGVkIG1ldGFkYXRhIGZvciBhIGRhdGEgbW9kZWwgaW5zdGFuY2Ugb3IgY2xhc3MuXG4gKlxuICogQHBhcmFtIG1vZGVsQ2xhc3NPckluc3RhbmNlIERhdGEgbW9kZWwgY2xhc3Mgb3IgaW5zdGFuY2UuXG4gKiBAcmV0dXJucyBUaGUgYXNzb2NpYXRlZCBtZXRhZGF0YS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldERhdGFNb2RlbE1ldGFkYXRhKFxuICBtb2RlbENsYXNzT3JJbnN0YW5jZTogQW55RGF0YU1vZGVsIHwgTW9kZWxDbGFzczxBbnlEYXRhTW9kZWw+XG4pOiBEYXRhTW9kZWxNZXRhZGF0YSB7XG4gIGlmIChpc0RhdGFNb2RlbChtb2RlbENsYXNzT3JJbnN0YW5jZSkpIHtcbiAgICByZXR1cm4gKG1vZGVsQ2xhc3NPckluc3RhbmNlIGFzIGFueSkuY29uc3RydWN0b3JbbW9kZWxNZXRhZGF0YVN5bWJvbF1cbiAgfSBlbHNlIGlmIChpc0RhdGFNb2RlbENsYXNzKG1vZGVsQ2xhc3NPckluc3RhbmNlKSkge1xuICAgIHJldHVybiAobW9kZWxDbGFzc09ySW5zdGFuY2UgYXMgYW55KVttb2RlbE1ldGFkYXRhU3ltYm9sXVxuICB9IGVsc2Uge1xuICAgIHRocm93IGZhaWx1cmUoYG1vZGVsQ2xhc3NPckluc3RhbmNlIG11c3QgYmUgYSBtb2RlbCBjbGFzcyBvciBpbnN0YW5jZWApXG4gIH1cbn1cbiIsImltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHsgcmVzb2x2ZVN0YW5kYXJkVHlwZSB9IGZyb20gXCIuL3Jlc29sdmVUeXBlQ2hlY2tlclwiXG5pbXBvcnQgdHlwZSB7IEFueVR5cGUgfSBmcm9tIFwiLi9zY2hlbWFzXCJcbmltcG9ydCB0eXBlIHsgTGF0ZVR5cGVDaGVja2VyLCBUeXBlQ2hlY2tlciwgVHlwZUluZm8gfSBmcm9tIFwiLi9UeXBlQ2hlY2tlclwiXG5cbi8qKlxuICogR2V0cyB0aGUgdHlwZSBpbmZvIG9mIGEgZ2l2ZW4gdHlwZS5cbiAqXG4gKiBAcGFyYW0gdHlwZSBUeXBlIHRvIGdldCB0aGUgaW5mbyBmcm9tLlxuICogQHJldHVybnMgVGhlIHR5cGUgaW5mby5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFR5cGVJbmZvKHR5cGU6IEFueVR5cGUpOiBUeXBlSW5mbyB7XG4gIGNvbnN0IHN0ZFR5cGUgPSByZXNvbHZlU3RhbmRhcmRUeXBlKHR5cGUpXG4gIGNvbnN0IHR5cGVJbmZvID0gKHN0ZFR5cGUgYXMgYW55IGFzIFR5cGVDaGVja2VyIHwgTGF0ZVR5cGVDaGVja2VyKS50eXBlSW5mb1xuICBpZiAoIXR5cGVJbmZvKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgdHlwZSBpbmZvIG5vdCBmb3VuZCBmb3IgJHt0eXBlfWApXG4gIH1cbiAgcmV0dXJuIHR5cGVJbmZvXG59XG4iLCJpbXBvcnQgdHlwZSB7IE8gfSBmcm9tIFwidHMtdG9vbGJlbHRcIlxuaW1wb3J0IHR5cGUgeyBBbnlEYXRhTW9kZWwgfSBmcm9tIFwiLi4vLi4vZGF0YU1vZGVsL0Jhc2VEYXRhTW9kZWxcIlxuaW1wb3J0IHsgZ2V0RGF0YU1vZGVsTWV0YWRhdGEgfSBmcm9tIFwiLi4vLi4vZGF0YU1vZGVsL2dldERhdGFNb2RlbE1ldGFkYXRhXCJcbmltcG9ydCB7IGlzRGF0YU1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vLi4vZGF0YU1vZGVsL3V0aWxzXCJcbmltcG9ydCB0eXBlIHtcbiAgTW9kZWxDbGFzcyxcbiAgTW9kZWxEYXRhLFxuICBNb2RlbFVudHJhbnNmb3JtZWREYXRhLFxufSBmcm9tIFwiLi4vLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcbmltcG9ydCB7IG1vZGVsSW5mb0J5Q2xhc3MgfSBmcm9tIFwiLi4vLi4vbW9kZWxTaGFyZWQvbW9kZWxJbmZvXCJcbmltcG9ydCB7IGdldEludGVybmFsTW9kZWxDbGFzc1Byb3BzSW5mbyB9IGZyb20gXCIuLi8uLi9tb2RlbFNoYXJlZC9tb2RlbFByb3BzSW5mb1wiXG5pbXBvcnQgeyBub0RlZmF1bHRWYWx1ZSB9IGZyb20gXCIuLi8uLi9tb2RlbFNoYXJlZC9wcm9wXCJcbmltcG9ydCB7IGZhaWx1cmUsIGxhenkgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIlxuaW1wb3J0IHtcbiAgVHlwZUNoZWNrZXIsXG4gIFR5cGVDaGVja2VyQmFzZVR5cGUsXG4gIFR5cGVJbmZvLFxuICBUeXBlSW5mb0dlbixcbiAgbGF0ZVR5cGVDaGVja2VyLFxufSBmcm9tIFwiLi4vVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHsgZ2V0VHlwZUluZm8gfSBmcm9tIFwiLi4vZ2V0VHlwZUluZm9cIlxuaW1wb3J0IHsgcmVnaXN0ZXJTdGFuZGFyZFR5cGVSZXNvbHZlciwgcmVzb2x2ZVR5cGVDaGVja2VyIH0gZnJvbSBcIi4uL3Jlc29sdmVUeXBlQ2hlY2tlclwiXG5pbXBvcnQgdHlwZSB7IEFueVN0YW5kYXJkVHlwZSwgSWRlbnRpdHlUeXBlIH0gZnJvbSBcIi4uL3NjaGVtYXNcIlxuXG5jb25zdCBjYWNoZWREYXRhTW9kZWxUeXBlQ2hlY2tlciA9IG5ldyBXZWFrTWFwPE1vZGVsQ2xhc3M8QW55RGF0YU1vZGVsPiwgVHlwZUNoZWNrZXI+KClcblxudHlwZSBfQ2xhc3M8VD4gPSBhYnN0cmFjdCBuZXcgKC4uLmFyZ3M6IGFueVtdKSA9PiBUXG50eXBlIF9DbGFzc09yT2JqZWN0PE0sIEs+ID0gSyBleHRlbmRzIE0gPyBvYmplY3QgOiBfQ2xhc3M8Sz4gfCAoKCkgPT4gX0NsYXNzPEs+KVxuXG4vKipcbiAqIEEgdHlwZSB0aGF0IHJlcHJlc2VudHMgYSBkYXRhIG1vZGVsIGRhdGEuXG4gKiBUaGUgdHlwZSByZWZlcmVuY2VkIGluIHRoZSBtb2RlbCBkZWNvcmF0b3Igd2lsbCBiZSB1c2VkIGZvciB0eXBlIGNoZWNraW5nLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogY29uc3Qgc29tZURhdGFNb2RlbERhdGFUeXBlID0gdHlwZXMuZGF0YU1vZGVsRGF0YShTb21lTW9kZWwpXG4gKiAvLyBvciBmb3IgcmVjdXJzaXZlIG1vZGVsc1xuICogY29uc3Qgc29tZURhdGFNb2RlbERhdGFUeXBlID0gdHlwZXMuZGF0YU1vZGVsRGF0YTxTb21lTW9kZWw+KCgpID0+IFNvbWVNb2RlbClcbiAqIGBgYFxuICpcbiAqIEB0eXBlcGFyYW0gTSBEYXRhIG1vZGVsIHR5cGUuXG4gKiBAcGFyYW0gbW9kZWxDbGFzcyBNb2RlbCBjbGFzcy5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc0RhdGFNb2RlbERhdGE8TSA9IG5ldmVyLCBLID0gTT4oXG4gIG1vZGVsQ2xhc3M6IF9DbGFzc09yT2JqZWN0PE0sIEs+XG4pOiBJZGVudGl0eVR5cGU8XG4gIHwgTW9kZWxVbnRyYW5zZm9ybWVkRGF0YTxcbiAgICAgIEsgZXh0ZW5kcyBNID8gKE0gZXh0ZW5kcyBBbnlEYXRhTW9kZWwgPyBNIDogbmV2ZXIpIDogSyBleHRlbmRzIEFueURhdGFNb2RlbCA/IEsgOiBuZXZlclxuICAgID5cbiAgfCBNb2RlbERhdGE8XG4gICAgICBLIGV4dGVuZHMgTSA/IChNIGV4dGVuZHMgQW55RGF0YU1vZGVsID8gTSA6IG5ldmVyKSA6IEsgZXh0ZW5kcyBBbnlEYXRhTW9kZWwgPyBLIDogbmV2ZXJcbiAgICA+XG4+IHtcbiAgLy8gaWYgd2UgdHlwZSBpdCBhbnkgc3Ryb25nZXIgdGhlbiByZWN1cnNpdmUgZGVmcyBhbmQgc28gb24gc3RvcCB3b3JraW5nXG5cbiAgaWYgKCFpc0RhdGFNb2RlbENsYXNzKG1vZGVsQ2xhc3MpICYmIHR5cGVvZiBtb2RlbENsYXNzID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAvLyByZXNvbHZlIGxhdGVyXG4gICAgY29uc3QgbW9kZWxDbGFzc0ZuID0gbW9kZWxDbGFzcyBhcyAoKSA9PiBNb2RlbENsYXNzPEFueURhdGFNb2RlbD5cbiAgICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT4gbmV3IERhdGFNb2RlbERhdGFUeXBlSW5mbyh0LCBtb2RlbENsYXNzRm4oKSlcbiAgICByZXR1cm4gbGF0ZVR5cGVDaGVja2VyKCgpID0+IHR5cGVzRGF0YU1vZGVsRGF0YShtb2RlbENsYXNzRm4oKSkgYXMgYW55LCB0eXBlSW5mb0dlbikgYXMgYW55XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgbW9kZWxDbGF6ejogTW9kZWxDbGFzczxBbnlEYXRhTW9kZWw+ID0gbW9kZWxDbGFzcyBhcyBhbnlcblxuICAgIGNvbnN0IGNhY2hlZFR5cGVDaGVja2VyID0gY2FjaGVkRGF0YU1vZGVsVHlwZUNoZWNrZXIuZ2V0KG1vZGVsQ2xhenopXG4gICAgaWYgKGNhY2hlZFR5cGVDaGVja2VyKSB7XG4gICAgICByZXR1cm4gY2FjaGVkVHlwZUNoZWNrZXIgYXMgYW55XG4gICAgfVxuXG4gICAgY29uc3QgdHlwZUluZm9HZW46IFR5cGVJbmZvR2VuID0gKHQpID0+IG5ldyBEYXRhTW9kZWxEYXRhVHlwZUluZm8odCwgbW9kZWxDbGF6eilcblxuICAgIGNvbnN0IHRjID0gbGF0ZVR5cGVDaGVja2VyKCgpID0+IHtcbiAgICAgIGNvbnN0IG1vZGVsSW5mbyA9IG1vZGVsSW5mb0J5Q2xhc3MuZ2V0KG1vZGVsQ2xhenopIVxuICAgICAgY29uc3QgdHlwZU5hbWUgPSBgRGF0YU1vZGVsRGF0YSgke21vZGVsSW5mby5uYW1lfSlgXG5cbiAgICAgIGNvbnN0IGRhdGFUeXBlQ2hlY2tlciA9IGdldERhdGFNb2RlbE1ldGFkYXRhKG1vZGVsQ2xhenopLmRhdGFUeXBlXG4gICAgICBpZiAoIWRhdGFUeXBlQ2hlY2tlcikge1xuICAgICAgICB0aHJvdyBmYWlsdXJlKFxuICAgICAgICAgIGB0eXBlIGNoZWNraW5nIGNhbm5vdCBiZSBwZXJmb3JtZWQgb3ZlciBkYXRhIG1vZGVsIGRhdGEgb2YgdHlwZSAnJHttb2RlbEluZm8ubmFtZX0nIHNpbmNlIHRoYXQgbW9kZWwgdHlwZSBoYXMgbm8gZGF0YSB0eXBlIGRlY2xhcmVkLCBjb25zaWRlciBhZGRpbmcgYSBkYXRhIHR5cGUgb3IgdXNpbmcgdHlwZXMudW5jaGVja2VkKCkgaW5zdGVhZGBcbiAgICAgICAgKVxuICAgICAgfVxuXG4gICAgICBjb25zdCByZXNvbHZlZERhdGFUeXBlQ2hlY2tlciA9IHJlc29sdmVUeXBlQ2hlY2tlcihkYXRhVHlwZUNoZWNrZXIpXG5cbiAgICAgIGNvbnN0IHRoaXNUYzogVHlwZUNoZWNrZXIgPSBuZXcgVHlwZUNoZWNrZXIoXG4gICAgICAgIFR5cGVDaGVja2VyQmFzZVR5cGUuT2JqZWN0LFxuXG4gICAgICAgICh2YWx1ZSwgcGF0aCwgdHlwZUNoZWNrZWRWYWx1ZSkgPT4ge1xuICAgICAgICAgIHJldHVybiByZXNvbHZlZERhdGFUeXBlQ2hlY2tlci5jaGVjayh2YWx1ZSwgcGF0aCwgdHlwZUNoZWNrZWRWYWx1ZSlcbiAgICAgICAgfSxcblxuICAgICAgICAoKSA9PiB0eXBlTmFtZSxcbiAgICAgICAgdHlwZUluZm9HZW4sXG5cbiAgICAgICAgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHJlc29sdmVkRGF0YVR5cGVDaGVja2VyLnNuYXBzaG90VHlwZSh2YWx1ZSkgPyB0aGlzVGMgOiBudWxsXG4gICAgICAgIH0sXG5cbiAgICAgICAgKHNuOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xuICAgICAgICAgIHJldHVybiByZXNvbHZlZERhdGFUeXBlQ2hlY2tlci5mcm9tU25hcHNob3RQcm9jZXNzb3Ioc24pXG4gICAgICAgIH0sXG5cbiAgICAgICAgKHNuOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xuICAgICAgICAgIHJldHVybiByZXNvbHZlZERhdGFUeXBlQ2hlY2tlci50b1NuYXBzaG90UHJvY2Vzc29yKHNuKVxuICAgICAgICB9XG4gICAgICApXG5cbiAgICAgIHJldHVybiB0aGlzVGNcbiAgICB9LCB0eXBlSW5mb0dlbikgYXMgYW55XG5cbiAgICBjYWNoZWREYXRhTW9kZWxUeXBlQ2hlY2tlci5zZXQobW9kZWxDbGF6eiwgdGMpXG5cbiAgICByZXR1cm4gdGMgYXMgYW55XG4gIH1cbn1cblxuLyoqXG4gKiBgdHlwZXMuZGF0YU1vZGVsRGF0YWAgdHlwZSBpbmZvIGZvciBhIG1vZGVsIHByb3BzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERhdGFNb2RlbERhdGFUeXBlSW5mb1Byb3BzIHtcbiAgcmVhZG9ubHkgW3Byb3BOYW1lOiBzdHJpbmddOiBSZWFkb25seTx7XG4gICAgdHlwZTogQW55U3RhbmRhcmRUeXBlIHwgdW5kZWZpbmVkXG4gICAgdHlwZUluZm86IFR5cGVJbmZvIHwgdW5kZWZpbmVkXG4gICAgaGFzRGVmYXVsdDogYm9vbGVhblxuICAgIGRlZmF1bHQ6IGFueVxuICB9PlxufVxuXG4vKipcbiAqIGB0eXBlcy5kYXRhTW9kZWxEYXRhYCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBEYXRhTW9kZWxEYXRhVHlwZUluZm8gZXh0ZW5kcyBUeXBlSW5mbyB7XG4gIHByaXZhdGUgX3Byb3BzID0gbGF6eSgoKSA9PiB7XG4gICAgY29uc3Qgb2JqU2NoZW1hID0gZ2V0SW50ZXJuYWxNb2RlbENsYXNzUHJvcHNJbmZvKHRoaXMubW9kZWxDbGFzcylcblxuICAgIGNvbnN0IHByb3BUeXBlczogTy5Xcml0YWJsZTxEYXRhTW9kZWxEYXRhVHlwZUluZm9Qcm9wcz4gPSB7fVxuICAgIE9iamVjdC5rZXlzKG9ialNjaGVtYSkuZm9yRWFjaCgocHJvcE5hbWUpID0+IHtcbiAgICAgIGNvbnN0IHByb3BEYXRhID0gb2JqU2NoZW1hW3Byb3BOYW1lXVxuXG4gICAgICBjb25zdCB0eXBlID0gcHJvcERhdGEuX3R5cGVDaGVja2VyIGFzIGFueSBhcyBBbnlTdGFuZGFyZFR5cGVcblxuICAgICAgbGV0IHR5cGVJbmZvOiBUeXBlSW5mbyB8IHVuZGVmaW5lZFxuICAgICAgaWYgKHR5cGUpIHtcbiAgICAgICAgdHlwZUluZm8gPSBnZXRUeXBlSW5mbyh0eXBlKVxuICAgICAgfVxuXG4gICAgICBsZXQgaGFzRGVmYXVsdCA9IGZhbHNlXG4gICAgICBsZXQgZGVmYXVsdFZhbHVlOiBhbnlcbiAgICAgIGlmIChwcm9wRGF0YS5fZGVmYXVsdEZuICE9PSBub0RlZmF1bHRWYWx1ZSkge1xuICAgICAgICBkZWZhdWx0VmFsdWUgPSBwcm9wRGF0YS5fZGVmYXVsdEZuXG4gICAgICAgIGhhc0RlZmF1bHQgPSB0cnVlXG4gICAgICB9IGVsc2UgaWYgKHByb3BEYXRhLl9kZWZhdWx0VmFsdWUgIT09IG5vRGVmYXVsdFZhbHVlKSB7XG4gICAgICAgIGRlZmF1bHRWYWx1ZSA9IHByb3BEYXRhLl9kZWZhdWx0VmFsdWVcbiAgICAgICAgaGFzRGVmYXVsdCA9IHRydWVcbiAgICAgIH1cblxuICAgICAgcHJvcFR5cGVzW3Byb3BOYW1lXSA9IHtcbiAgICAgICAgdHlwZSxcbiAgICAgICAgdHlwZUluZm8sXG4gICAgICAgIGhhc0RlZmF1bHQsXG4gICAgICAgIGRlZmF1bHQ6IGRlZmF1bHRWYWx1ZSxcbiAgICAgIH1cbiAgICB9KVxuICAgIHJldHVybiBwcm9wVHlwZXNcbiAgfSlcblxuICBnZXQgcHJvcHMoKTogRGF0YU1vZGVsRGF0YVR5cGVJbmZvUHJvcHMge1xuICAgIHJldHVybiB0aGlzLl9wcm9wcygpXG4gIH1cblxuICBnZXQgbW9kZWxUeXBlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgbW9kZWxJbmZvID0gbW9kZWxJbmZvQnlDbGFzcy5nZXQodGhpcy5tb2RlbENsYXNzKSFcbiAgICByZXR1cm4gbW9kZWxJbmZvLm5hbWVcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHRoaXNUeXBlOiBBbnlTdGFuZGFyZFR5cGUsXG4gICAgcmVhZG9ubHkgbW9kZWxDbGFzczogTW9kZWxDbGFzczxBbnlEYXRhTW9kZWw+XG4gICkge1xuICAgIHN1cGVyKHRoaXNUeXBlKVxuICB9XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckRhdGFNb2RlbERhdGFTdGFuZGFyZFR5cGVSZXNvbHZlcigpIHtcbiAgcmVnaXN0ZXJTdGFuZGFyZFR5cGVSZXNvbHZlcigodikgPT4gKGlzRGF0YU1vZGVsQ2xhc3ModikgPyB0eXBlc0RhdGFNb2RlbERhdGEodikgOiB1bmRlZmluZWQpKVxufVxuIiwiaW1wb3J0IHR5cGUgeyBPIH0gZnJvbSBcInRzLXRvb2xiZWx0XCJcclxuaW1wb3J0IHR5cGUgeyBBbnlNb2RlbCB9IGZyb20gXCIuLi8uLi9tb2RlbC9CYXNlTW9kZWxcIlxyXG5pbXBvcnQgeyBnZXRNb2RlbE1ldGFkYXRhIH0gZnJvbSBcIi4uLy4uL21vZGVsL2dldE1vZGVsTWV0YWRhdGFcIlxyXG5pbXBvcnQgeyBtb2RlbFR5cGVLZXkgfSBmcm9tIFwiLi4vLi4vbW9kZWwvbWV0YWRhdGFcIlxyXG5pbXBvcnQgeyBpc01vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vLi4vbW9kZWwvdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcclxuaW1wb3J0IHsgbW9kZWxJbmZvQnlDbGFzcyB9IGZyb20gXCIuLi8uLi9tb2RlbFNoYXJlZC9tb2RlbEluZm9cIlxyXG5pbXBvcnQgeyBnZXRJbnRlcm5hbE1vZGVsQ2xhc3NQcm9wc0luZm8gfSBmcm9tIFwiLi4vLi4vbW9kZWxTaGFyZWQvbW9kZWxQcm9wc0luZm9cIlxyXG5pbXBvcnQgeyBub0RlZmF1bHRWYWx1ZSB9IGZyb20gXCIuLi8uLi9tb2RlbFNoYXJlZC9wcm9wXCJcclxuaW1wb3J0IHsgaXNPYmplY3QsIGxhenkgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIlxyXG5pbXBvcnQgeyBUeXBlQ2hlY2tFcnJvciB9IGZyb20gXCIuLi9UeXBlQ2hlY2tFcnJvclwiXHJcbmltcG9ydCB7XHJcbiAgVHlwZUNoZWNrZXIsXHJcbiAgVHlwZUNoZWNrZXJCYXNlVHlwZSxcclxuICBUeXBlSW5mbyxcclxuICBUeXBlSW5mb0dlbixcclxuICBsYXRlVHlwZUNoZWNrZXIsXHJcbn0gZnJvbSBcIi4uL1R5cGVDaGVja2VyXCJcclxuaW1wb3J0IHsgZ2V0VHlwZUluZm8gfSBmcm9tIFwiLi4vZ2V0VHlwZUluZm9cIlxyXG5pbXBvcnQgeyByZWdpc3RlclN0YW5kYXJkVHlwZVJlc29sdmVyLCByZXNvbHZlVHlwZUNoZWNrZXIgfSBmcm9tIFwiLi4vcmVzb2x2ZVR5cGVDaGVja2VyXCJcclxuaW1wb3J0IHR5cGUgeyBBbnlTdGFuZGFyZFR5cGUsIE1vZGVsVHlwZSB9IGZyb20gXCIuLi9zY2hlbWFzXCJcclxuXHJcbmNvbnN0IGNhY2hlZE1vZGVsVHlwZUNoZWNrZXIgPSBuZXcgV2Vha01hcDxNb2RlbENsYXNzPEFueU1vZGVsPiwgVHlwZUNoZWNrZXI+KClcclxuXHJcbnR5cGUgX0NsYXNzPFQ+ID0gYWJzdHJhY3QgbmV3ICguLi5hcmdzOiBhbnlbXSkgPT4gVFxyXG50eXBlIF9DbGFzc09yT2JqZWN0PE0sIEs+ID0gSyBleHRlbmRzIE0gPyBvYmplY3QgOiBfQ2xhc3M8Sz4gfCAoKCkgPT4gX0NsYXNzPEs+KVxyXG5cclxuLyoqXHJcbiAqIEEgdHlwZSB0aGF0IHJlcHJlc2VudHMgYSBtb2RlbC4gVGhlIHR5cGUgcmVmZXJlbmNlZCBpbiB0aGUgbW9kZWwgZGVjb3JhdG9yIHdpbGwgYmUgdXNlZCBmb3IgdHlwZSBjaGVja2luZy5cclxuICpcclxuICogRXhhbXBsZTpcclxuICogYGBgdHNcclxuICogY29uc3Qgc29tZU1vZGVsVHlwZSA9IHR5cGVzLm1vZGVsKFNvbWVNb2RlbClcclxuICogLy8gb3IgZm9yIHJlY3Vyc2l2ZSBtb2RlbHNcclxuICogY29uc3Qgc29tZU1vZGVsVHlwZSA9IHR5cGVzLm1vZGVsPFNvbWVNb2RlbD4oKCkgPT4gU29tZU1vZGVsKVxyXG4gKiBgYGBcclxuICpcclxuICogQHR5cGVwYXJhbSBNIE1vZGVsIHR5cGUuXHJcbiAqIEBwYXJhbSBtb2RlbENsYXNzIE1vZGVsIGNsYXNzLlxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHR5cGVzTW9kZWw8TSA9IG5ldmVyLCBLID0gTT4obW9kZWxDbGFzczogX0NsYXNzT3JPYmplY3Q8TSwgSz4pOiBNb2RlbFR5cGU8Sz4ge1xyXG4gIC8vIGlmIHdlIHR5cGUgaXQgYW55IHN0cm9uZ2VyIHRoZW4gcmVjdXJzaXZlIGRlZnMgYW5kIHNvIG9uIHN0b3Agd29ya2luZ1xyXG5cclxuICBpZiAoIWlzTW9kZWxDbGFzcyhtb2RlbENsYXNzKSAmJiB0eXBlb2YgbW9kZWxDbGFzcyA9PT0gXCJmdW5jdGlvblwiKSB7XHJcbiAgICAvLyByZXNvbHZlIGxhdGVyXHJcbiAgICBjb25zdCBtb2RlbENsYXNzRm4gPSBtb2RlbENsYXNzIGFzICgpID0+IE1vZGVsQ2xhc3M8QW55TW9kZWw+XHJcbiAgICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT4gbmV3IE1vZGVsVHlwZUluZm8odCwgbW9kZWxDbGFzc0ZuKCkpXHJcbiAgICByZXR1cm4gbGF0ZVR5cGVDaGVja2VyKCgpID0+IHR5cGVzTW9kZWwobW9kZWxDbGFzc0ZuKCkpIGFzIGFueSwgdHlwZUluZm9HZW4pIGFzIGFueVxyXG4gIH0gZWxzZSB7XHJcbiAgICBjb25zdCBtb2RlbENsYXp6OiBNb2RlbENsYXNzPEFueU1vZGVsPiA9IG1vZGVsQ2xhc3MgYXMgYW55XHJcblxyXG4gICAgY29uc3QgY2FjaGVkVHlwZUNoZWNrZXIgPSBjYWNoZWRNb2RlbFR5cGVDaGVja2VyLmdldChtb2RlbENsYXp6KVxyXG4gICAgaWYgKGNhY2hlZFR5cGVDaGVja2VyKSB7XHJcbiAgICAgIHJldHVybiBjYWNoZWRUeXBlQ2hlY2tlciBhcyBhbnlcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT4gbmV3IE1vZGVsVHlwZUluZm8odCwgbW9kZWxDbGF6eilcclxuXHJcbiAgICBjb25zdCB0YyA9IGxhdGVUeXBlQ2hlY2tlcigoKSA9PiB7XHJcbiAgICAgIGNvbnN0IG1vZGVsSW5mbyA9IG1vZGVsSW5mb0J5Q2xhc3MuZ2V0KG1vZGVsQ2xhenopIVxyXG4gICAgICBjb25zdCB0eXBlTmFtZSA9IGBNb2RlbCgke21vZGVsSW5mby5uYW1lfSlgXHJcblxyXG4gICAgICBjb25zdCBkYXRhVHlwZUNoZWNrZXIgPSBnZXRNb2RlbE1ldGFkYXRhKG1vZGVsQ2xhenopLmRhdGFUeXBlXHJcbiAgICAgIGNvbnN0IHJlc29sdmVkRGF0YVR5cGVDaGVja2VyID0gZGF0YVR5cGVDaGVja2VyXHJcbiAgICAgICAgPyByZXNvbHZlVHlwZUNoZWNrZXIoZGF0YVR5cGVDaGVja2VyKVxyXG4gICAgICAgIDogdW5kZWZpbmVkXHJcblxyXG4gICAgICBjb25zdCB0aGlzVGM6IFR5cGVDaGVja2VyID0gbmV3IFR5cGVDaGVja2VyKFxyXG4gICAgICAgIFR5cGVDaGVja2VyQmFzZVR5cGUuT2JqZWN0LFxyXG5cclxuICAgICAgICAodmFsdWUsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+IHtcclxuICAgICAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgbW9kZWxDbGF6eikpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCB0eXBlTmFtZSwgdmFsdWUsIHR5cGVDaGVja2VkVmFsdWUpXHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHJlc29sdmVkRGF0YVR5cGVDaGVja2VyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlZERhdGFUeXBlQ2hlY2tlci5jaGVjayh2YWx1ZS4kLCBwYXRoLCB0eXBlQ2hlY2tlZFZhbHVlKVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHJldHVybiBudWxsXHJcbiAgICAgICAgfSxcclxuICAgICAgICAoKSA9PiB0eXBlTmFtZSxcclxuICAgICAgICB0eXBlSW5mb0dlbixcclxuXHJcbiAgICAgICAgKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICBpZiAoIWlzT2JqZWN0KHZhbHVlKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbFxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIGlmICh2YWx1ZVttb2RlbFR5cGVLZXldICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgLy8gZmFzdCBjaGVja1xyXG4gICAgICAgICAgICByZXR1cm4gdmFsdWVbbW9kZWxUeXBlS2V5XSA9PT0gbW9kZWxJbmZvLm5hbWUgPyB0aGlzVGMgOiBudWxsXHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHJlc29sdmVkRGF0YVR5cGVDaGVja2VyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlZERhdGFUeXBlQ2hlY2tlci5zbmFwc2hvdFR5cGUodmFsdWUpID8gdGhpc1RjIDogbnVsbFxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vIG5vdCBlbm91Z2ggaW5mbyB0byBiZSBhYmxlIHRvIHRlbGxcclxuICAgICAgICAgIHJldHVybiBudWxsXHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgKHNuKSA9PiB7XHJcbiAgICAgICAgICBpZiAoc25bbW9kZWxUeXBlS2V5XSkge1xyXG4gICAgICAgICAgICByZXR1cm4gc25cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgLi4uc24sXHJcbiAgICAgICAgICAgICAgW21vZGVsVHlwZUtleV06IG1vZGVsSW5mby5uYW1lLFxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgKHNuKSA9PiBzblxyXG4gICAgICApXHJcblxyXG4gICAgICByZXR1cm4gdGhpc1RjXHJcbiAgICB9LCB0eXBlSW5mb0dlbikgYXMgYW55XHJcblxyXG4gICAgY2FjaGVkTW9kZWxUeXBlQ2hlY2tlci5zZXQobW9kZWxDbGF6eiwgdGMpXHJcblxyXG4gICAgcmV0dXJuIHRjIGFzIGFueVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIGB0eXBlcy5tb2RlbGAgdHlwZSBpbmZvIGZvciBhIG1vZGVsIHByb3BzLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBNb2RlbFR5cGVJbmZvUHJvcHMge1xyXG4gIHJlYWRvbmx5IFtwcm9wTmFtZTogc3RyaW5nXTogUmVhZG9ubHk8e1xyXG4gICAgdHlwZTogQW55U3RhbmRhcmRUeXBlIHwgdW5kZWZpbmVkXHJcbiAgICB0eXBlSW5mbzogVHlwZUluZm8gfCB1bmRlZmluZWRcclxuICAgIGhhc0RlZmF1bHQ6IGJvb2xlYW5cclxuICAgIGRlZmF1bHQ6IGFueVxyXG4gIH0+XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBgdHlwZXMubW9kZWxgIHR5cGUgaW5mby5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBNb2RlbFR5cGVJbmZvIGV4dGVuZHMgVHlwZUluZm8ge1xyXG4gIHByaXZhdGUgX3Byb3BzID0gbGF6eSgoKSA9PiB7XHJcbiAgICBjb25zdCBvYmpTY2hlbWEgPSBnZXRJbnRlcm5hbE1vZGVsQ2xhc3NQcm9wc0luZm8odGhpcy5tb2RlbENsYXNzKVxyXG5cclxuICAgIGNvbnN0IHByb3BUeXBlczogTy5Xcml0YWJsZTxNb2RlbFR5cGVJbmZvUHJvcHM+ID0ge31cclxuICAgIE9iamVjdC5rZXlzKG9ialNjaGVtYSkuZm9yRWFjaCgocHJvcE5hbWUpID0+IHtcclxuICAgICAgY29uc3QgcHJvcERhdGEgPSBvYmpTY2hlbWFbcHJvcE5hbWVdXHJcblxyXG4gICAgICBjb25zdCB0eXBlID0gcHJvcERhdGEuX3R5cGVDaGVja2VyIGFzIGFueSBhcyBBbnlTdGFuZGFyZFR5cGVcclxuXHJcbiAgICAgIGxldCB0eXBlSW5mbzogVHlwZUluZm8gfCB1bmRlZmluZWRcclxuICAgICAgaWYgKHR5cGUpIHtcclxuICAgICAgICB0eXBlSW5mbyA9IGdldFR5cGVJbmZvKHR5cGUpXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGxldCBoYXNEZWZhdWx0ID0gZmFsc2VcclxuICAgICAgbGV0IGRlZmF1bHRWYWx1ZTogYW55XHJcbiAgICAgIGlmIChwcm9wRGF0YS5fZGVmYXVsdEZuICE9PSBub0RlZmF1bHRWYWx1ZSkge1xyXG4gICAgICAgIGRlZmF1bHRWYWx1ZSA9IHByb3BEYXRhLl9kZWZhdWx0Rm5cclxuICAgICAgICBoYXNEZWZhdWx0ID0gdHJ1ZVxyXG4gICAgICB9IGVsc2UgaWYgKHByb3BEYXRhLl9kZWZhdWx0VmFsdWUgIT09IG5vRGVmYXVsdFZhbHVlKSB7XHJcbiAgICAgICAgZGVmYXVsdFZhbHVlID0gcHJvcERhdGEuX2RlZmF1bHRWYWx1ZVxyXG4gICAgICAgIGhhc0RlZmF1bHQgPSB0cnVlXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHByb3BUeXBlc1twcm9wTmFtZV0gPSB7XHJcbiAgICAgICAgdHlwZSxcclxuICAgICAgICB0eXBlSW5mbyxcclxuICAgICAgICBoYXNEZWZhdWx0LFxyXG4gICAgICAgIGRlZmF1bHQ6IGRlZmF1bHRWYWx1ZSxcclxuICAgICAgfVxyXG4gICAgfSlcclxuICAgIHJldHVybiBwcm9wVHlwZXNcclxuICB9KVxyXG5cclxuICBnZXQgcHJvcHMoKTogTW9kZWxUeXBlSW5mb1Byb3BzIHtcclxuICAgIHJldHVybiB0aGlzLl9wcm9wcygpXHJcbiAgfVxyXG5cclxuICBnZXQgbW9kZWxUeXBlKCk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBtb2RlbEluZm8gPSBtb2RlbEluZm9CeUNsYXNzLmdldCh0aGlzLm1vZGVsQ2xhc3MpIVxyXG4gICAgcmV0dXJuIG1vZGVsSW5mby5uYW1lXHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3Rvcih0aGlzVHlwZTogQW55U3RhbmRhcmRUeXBlLCByZWFkb25seSBtb2RlbENsYXNzOiBNb2RlbENsYXNzPEFueU1vZGVsPikge1xyXG4gICAgc3VwZXIodGhpc1R5cGUpXHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJNb2RlbFN0YW5kYXJkVHlwZVJlc29sdmVyKCkge1xyXG4gIHJlZ2lzdGVyU3RhbmRhcmRUeXBlUmVzb2x2ZXIoKHYpID0+IChpc01vZGVsQ2xhc3ModikgPyB0eXBlc01vZGVsKHYpIDogdW5kZWZpbmVkKSlcclxufVxyXG4iLCJpbXBvcnQgeyBhc3NlcnRJc1ByaW1pdGl2ZSwgaWRlbnRpdHlGbiB9IGZyb20gXCIuLi8uLi91dGlsc1wiXG5pbXBvcnQgdHlwZSB7IFByaW1pdGl2ZVZhbHVlIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3R5cGVzXCJcbmltcG9ydCB7IHJlZ2lzdGVyU3RhbmRhcmRUeXBlUmVzb2x2ZXIsIFN0YW5kYXJkVHlwZVJlc29sdmVyRm4gfSBmcm9tIFwiLi4vcmVzb2x2ZVR5cGVDaGVja2VyXCJcbmltcG9ydCB0eXBlIHsgQW55U3RhbmRhcmRUeXBlLCBJZGVudGl0eVR5cGUgfSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQgeyBUeXBlQ2hlY2tlciwgVHlwZUNoZWNrZXJCYXNlVHlwZSwgVHlwZUluZm8sIFR5cGVJbmZvR2VuIH0gZnJvbSBcIi4uL1R5cGVDaGVja2VyXCJcbmltcG9ydCB7IFR5cGVDaGVja0Vycm9yIH0gZnJvbSBcIi4uL1R5cGVDaGVja0Vycm9yXCJcblxuY29uc3Qgc3RhbmRhcmRUeXBlUmVzb2x2ZXJzOiBTdGFuZGFyZFR5cGVSZXNvbHZlckZuW10gPSBbXVxuXG4vKipcbiAqIEEgdHlwZSB0aGF0IHJlcHJlc2VudHMgYSBjZXJ0YWluIHZhbHVlIG9mIGEgcHJpbWl0aXZlIChmb3IgZXhhbXBsZSBhbiAqZXhhY3QqIG51bWJlciBvciBzdHJpbmcpLlxuICpcbiAqIEV4YW1wbGVcbiAqIGBgYHRzXG4gKiBjb25zdCBoaVR5cGUgPSB0eXBlcy5saXRlcmFsKFwiaGlcIikgLy8gdGhlIHN0cmluZyB3aXRoIHZhbHVlIFwiaGlcIlxuICogY29uc3QgbnVtYmVyNVR5cGUgPSB0eXBlcy5saXRlcmFsKDUpIC8vIHRoZSBudW1iZXIgd2l0aCB2YWx1ZSA1XG4gKiBgYGBcbiAqXG4gKiBAdHlwZXBhcmFtIFQgTGl0ZXJhbCB2YWx1ZSB0eXBlLlxuICogQHBhcmFtIGxpdGVyYWwgTGl0ZXJhbCB2YWx1ZS5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc0xpdGVyYWw8VCBleHRlbmRzIFByaW1pdGl2ZVZhbHVlPihsaXRlcmFsOiBUKTogSWRlbnRpdHlUeXBlPFQ+IHtcbiAgYXNzZXJ0SXNQcmltaXRpdmUobGl0ZXJhbCwgXCJsaXRlcmFsXCIpXG4gIGxldCB0eXBlTmFtZTogc3RyaW5nXG4gIHN3aXRjaCAobGl0ZXJhbCkge1xuICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgdHlwZU5hbWUgPSBcInVuZGVmaW5lZFwiXG4gICAgICBicmVha1xuICAgIGNhc2UgbnVsbDpcbiAgICAgIHR5cGVOYW1lID0gXCJudWxsXCJcbiAgICAgIGJyZWFrXG4gICAgZGVmYXVsdDpcbiAgICAgIHR5cGVOYW1lID0gSlNPTi5zdHJpbmdpZnkobGl0ZXJhbClcbiAgICAgIGJyZWFrXG4gIH1cblxuICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT4gbmV3IExpdGVyYWxUeXBlSW5mbyh0LCBsaXRlcmFsKVxuXG4gIGNvbnN0IHRoaXNUYzogVHlwZUNoZWNrZXIgPSBuZXcgVHlwZUNoZWNrZXIoXG4gICAgVHlwZUNoZWNrZXJCYXNlVHlwZS5QcmltaXRpdmUsXG5cbiAgICAodmFsdWUsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+XG4gICAgICB2YWx1ZSA9PT0gbGl0ZXJhbCA/IG51bGwgOiBuZXcgVHlwZUNoZWNrRXJyb3IocGF0aCwgdHlwZU5hbWUsIHZhbHVlLCB0eXBlQ2hlY2tlZFZhbHVlKSxcblxuICAgICgpID0+IHR5cGVOYW1lLFxuICAgIHR5cGVJbmZvR2VuLFxuXG4gICAgKHZhbHVlKSA9PiAodmFsdWUgPT09IGxpdGVyYWwgPyB0aGlzVGMgOiBudWxsKSxcbiAgICBpZGVudGl0eUZuLFxuICAgIGlkZW50aXR5Rm5cbiAgKVxuXG4gIHJldHVybiB0aGlzVGMgYXMgYW55XG59XG5cbi8qKlxuICogYHR5cGVzLmxpdGVyYWxgIHR5cGUgaW5mby5cbiAqL1xuZXhwb3J0IGNsYXNzIExpdGVyYWxUeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHtcbiAgY29uc3RydWN0b3IodGhpc1R5cGU6IEFueVN0YW5kYXJkVHlwZSwgcmVhZG9ubHkgbGl0ZXJhbDogUHJpbWl0aXZlVmFsdWUpIHtcbiAgICBzdXBlcih0aGlzVHlwZSlcbiAgfVxufVxuXG4vKipcbiAqIEEgdHlwZSB0aGF0IHJlcHJlc2VudHMgdGhlIHZhbHVlIHVuZGVmaW5lZC5cbiAqIFN5bnRhY3RpYyBzdWdhciBmb3IgYHR5cGVzLmxpdGVyYWwodW5kZWZpbmVkKWAuXG4gKlxuICogYGBgdHNcbiAqIHR5cGVzLnVuZGVmaW5lZFxuICogYGBgXG4gKi9cbmV4cG9ydCBjb25zdCB0eXBlc1VuZGVmaW5lZCA9IHR5cGVzTGl0ZXJhbCh1bmRlZmluZWQpXG5cbnN0YW5kYXJkVHlwZVJlc29sdmVycy5wdXNoKCh2KSA9PiAodiA9PT0gdW5kZWZpbmVkID8gdHlwZXNVbmRlZmluZWQgOiB1bmRlZmluZWQpKVxuXG4vKipcbiAqIEEgdHlwZSB0aGF0IHJlcHJlc2VudHMgdGhlIHZhbHVlIG51bGwuXG4gKiBTeW50YWN0aWMgc3VnYXIgZm9yIGB0eXBlcy5saXRlcmFsKG51bGwpYC5cbiAqXG4gKiBgYGB0c1xuICogdHlwZXMubnVsbFxuICogYGBgXG4gKi9cbmV4cG9ydCBjb25zdCB0eXBlc051bGwgPSB0eXBlc0xpdGVyYWwobnVsbClcblxuc3RhbmRhcmRUeXBlUmVzb2x2ZXJzLnB1c2goKHYpID0+ICh2ID09PSBudWxsID8gdHlwZXNOdWxsIDogdW5kZWZpbmVkKSlcblxuLyoqXG4gKiBBIHR5cGUgdGhhdCByZXByZXNlbnRzIGFueSBib29sZWFuIHZhbHVlLlxuICpcbiAqIGBgYHRzXG4gKiB0eXBlcy5ib29sZWFuXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNvbnN0IHR5cGVzQm9vbGVhbjogSWRlbnRpdHlUeXBlPGJvb2xlYW4+ID0gbmV3IFR5cGVDaGVja2VyKFxuICBUeXBlQ2hlY2tlckJhc2VUeXBlLlByaW1pdGl2ZSxcblxuICAodmFsdWUsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+XG4gICAgdHlwZW9mIHZhbHVlID09PSBcImJvb2xlYW5cIlxuICAgICAgPyBudWxsXG4gICAgICA6IG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCBcImJvb2xlYW5cIiwgdmFsdWUsIHR5cGVDaGVja2VkVmFsdWUpLFxuXG4gICgpID0+IFwiYm9vbGVhblwiLFxuICAodCkgPT4gbmV3IEJvb2xlYW5UeXBlSW5mbyh0KSxcblxuICAodmFsdWUpID0+ICh0eXBlb2YgdmFsdWUgPT09IFwiYm9vbGVhblwiID8gKHR5cGVzQm9vbGVhbiBhcyBhbnkpIDogbnVsbCksXG4gIGlkZW50aXR5Rm4sXG4gIGlkZW50aXR5Rm5cbikgYXMgYW55XG5cbnN0YW5kYXJkVHlwZVJlc29sdmVycy5wdXNoKCh2KSA9PiAodiA9PT0gQm9vbGVhbiA/IHR5cGVzQm9vbGVhbiA6IHVuZGVmaW5lZCkpXG5cbi8qKlxuICogYHR5cGVzLmJvb2xlYW5gIHR5cGUgaW5mby5cbiAqL1xuZXhwb3J0IGNsYXNzIEJvb2xlYW5UeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHt9XG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBhbnkgbnVtYmVyIHZhbHVlLlxuICpcbiAqIGBgYHRzXG4gKiB0eXBlcy5udW1iZXJcbiAqIGBgYFxuICovXG5leHBvcnQgY29uc3QgdHlwZXNOdW1iZXI6IElkZW50aXR5VHlwZTxudW1iZXI+ID0gbmV3IFR5cGVDaGVja2VyKFxuICBUeXBlQ2hlY2tlckJhc2VUeXBlLlByaW1pdGl2ZSxcblxuICAodmFsdWUsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+XG4gICAgdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiID8gbnVsbCA6IG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCBcIm51bWJlclwiLCB2YWx1ZSwgdHlwZUNoZWNrZWRWYWx1ZSksXG5cbiAgKCkgPT4gXCJudW1iZXJcIixcbiAgKHQpID0+IG5ldyBOdW1iZXJUeXBlSW5mbyh0KSxcblxuICAodmFsdWUpID0+ICh0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIgPyAodHlwZXNOdW1iZXIgYXMgYW55KSA6IG51bGwpLFxuICBpZGVudGl0eUZuLFxuICBpZGVudGl0eUZuXG4pIGFzIGFueVxuXG5zdGFuZGFyZFR5cGVSZXNvbHZlcnMucHVzaCgodikgPT4gKHYgPT09IE51bWJlciA/IHR5cGVzTnVtYmVyIDogdW5kZWZpbmVkKSlcblxuLyoqXG4gKiBgdHlwZXMubnVtYmVyYCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBOdW1iZXJUeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHt9XG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBhbnkgc3RyaW5nIHZhbHVlLlxuICpcbiAqIGBgYHRzXG4gKiB0eXBlcy5zdHJpbmdcbiAqIGBgYFxuICovXG5leHBvcnQgY29uc3QgdHlwZXNTdHJpbmc6IElkZW50aXR5VHlwZTxzdHJpbmc+ID0gbmV3IFR5cGVDaGVja2VyKFxuICBUeXBlQ2hlY2tlckJhc2VUeXBlLlByaW1pdGl2ZSxcblxuICAodmFsdWUsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+XG4gICAgdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiID8gbnVsbCA6IG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCBcInN0cmluZ1wiLCB2YWx1ZSwgdHlwZUNoZWNrZWRWYWx1ZSksXG5cbiAgKCkgPT4gXCJzdHJpbmdcIixcbiAgKHQpID0+IG5ldyBTdHJpbmdUeXBlSW5mbyh0KSxcblxuICAodmFsdWUpID0+ICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgPyAodHlwZXNTdHJpbmcgYXMgYW55KSA6IG51bGwpLFxuICBpZGVudGl0eUZuLFxuICBpZGVudGl0eUZuXG4pIGFzIGFueVxuXG5zdGFuZGFyZFR5cGVSZXNvbHZlcnMucHVzaCgodikgPT4gKHYgPT09IFN0cmluZyA/IHR5cGVzU3RyaW5nIDogdW5kZWZpbmVkKSlcblxuLyoqXG4gKiBgdHlwZXMuc3RyaW5nYCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJpbmdUeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHt9XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlclByaW1pdGl2ZVN0YW5kYXJkVHlwZVJlc29sdmVycygpIHtcbiAgc3RhbmRhcmRUeXBlUmVzb2x2ZXJzLmZvckVhY2goKHN0cikgPT4ge1xuICAgIHJlZ2lzdGVyU3RhbmRhcmRUeXBlUmVzb2x2ZXIoc3RyKVxuICB9KVxufVxuIiwiaW1wb3J0IHsgcmVnaXN0ZXJEYXRhTW9kZWxEYXRhU3RhbmRhcmRUeXBlUmVzb2x2ZXIgfSBmcm9tIFwiLi9vYmplY3RCYXNlZC90eXBlc0RhdGFNb2RlbERhdGFcIlxuaW1wb3J0IHsgcmVnaXN0ZXJNb2RlbFN0YW5kYXJkVHlwZVJlc29sdmVyIH0gZnJvbSBcIi4vb2JqZWN0QmFzZWQvdHlwZXNNb2RlbFwiXG5pbXBvcnQgeyByZWdpc3RlclByaW1pdGl2ZVN0YW5kYXJkVHlwZVJlc29sdmVycyB9IGZyb20gXCIuL3ByaW1pdGl2ZUJhc2VkL3R5cGVzUHJpbWl0aXZlXCJcblxubGV0IGRlZmF1bHRTdGFuZGFyZFR5cGVSZXNvbHZlcnNSZWdpc3RlcmVkID0gZmFsc2VcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyRGVmYXVsdFN0YW5kYXJkVHlwZVJlc29sdmVycygpIHtcbiAgaWYgKGRlZmF1bHRTdGFuZGFyZFR5cGVSZXNvbHZlcnNSZWdpc3RlcmVkKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgZGVmYXVsdFN0YW5kYXJkVHlwZVJlc29sdmVyc1JlZ2lzdGVyZWQgPSB0cnVlXG5cbiAgcmVnaXN0ZXJNb2RlbFN0YW5kYXJkVHlwZVJlc29sdmVyKClcbiAgcmVnaXN0ZXJEYXRhTW9kZWxEYXRhU3RhbmRhcmRUeXBlUmVzb2x2ZXIoKVxuICByZWdpc3RlclByaW1pdGl2ZVN0YW5kYXJkVHlwZVJlc29sdmVycygpXG59XG4iLCJpbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IHJlZ2lzdGVyRGVmYXVsdFN0YW5kYXJkVHlwZVJlc29sdmVycyB9IGZyb20gXCIuL3JlZ2lzdGVyRGVmYXVsdFN0YW5kYXJkVHlwZVJlc29sdmVyc1wiXG5pbXBvcnQgdHlwZSB7IEFueVN0YW5kYXJkVHlwZSwgQW55VHlwZSB9IGZyb20gXCIuL3NjaGVtYXNcIlxuaW1wb3J0IHsgaXNMYXRlVHlwZUNoZWNrZXIsIExhdGVUeXBlQ2hlY2tlciwgVHlwZUNoZWNrZXIgfSBmcm9tIFwiLi9UeXBlQ2hlY2tlclwiXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCB0eXBlIFN0YW5kYXJkVHlwZVJlc29sdmVyRm4gPSAodmFsdWU6IGFueSkgPT4gQW55U3RhbmRhcmRUeXBlIHwgdW5kZWZpbmVkXG5cbmNvbnN0IHN0YW5kYXJkVHlwZVJlc29sdmVyczogU3RhbmRhcmRUeXBlUmVzb2x2ZXJGbltdID0gW11cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyU3RhbmRhcmRUeXBlUmVzb2x2ZXIocmVzb2x2ZXJGbjogU3RhbmRhcmRUeXBlUmVzb2x2ZXJGbikge1xuICBzdGFuZGFyZFR5cGVSZXNvbHZlcnMucHVzaChyZXNvbHZlckZuKVxufVxuXG5mdW5jdGlvbiBmaW5kU3RhbmRhcmRUeXBlKHZhbHVlOiBhbnkpOiBBbnlTdGFuZGFyZFR5cGUgfCB1bmRlZmluZWQge1xuICByZWdpc3RlckRlZmF1bHRTdGFuZGFyZFR5cGVSZXNvbHZlcnMoKVxuXG4gIGZvciAoY29uc3QgcmVzb2x2ZXJGbiBvZiBzdGFuZGFyZFR5cGVSZXNvbHZlcnMpIHtcbiAgICBjb25zdCB0YyA9IHJlc29sdmVyRm4odmFsdWUpXG4gICAgaWYgKHRjKSByZXR1cm4gdGNcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlVHlwZUNoZWNrZXIodjogQW55VHlwZSB8IFR5cGVDaGVja2VyIHwgTGF0ZVR5cGVDaGVja2VyKTogVHlwZUNoZWNrZXIge1xuICBsZXQgbmV4dDogVHlwZUNoZWNrZXIgfCBMYXRlVHlwZUNoZWNrZXIgPSB2IGFzIGFueVxuICB3aGlsZSAodHJ1ZSkge1xuICAgIGlmIChuZXh0IGluc3RhbmNlb2YgVHlwZUNoZWNrZXIpIHtcbiAgICAgIHJldHVybiBuZXh0XG4gICAgfSBlbHNlIGlmIChpc0xhdGVUeXBlQ2hlY2tlcihuZXh0KSkge1xuICAgICAgbmV4dCA9IG5leHQoKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB0YyA9IGZpbmRTdGFuZGFyZFR5cGUodilcbiAgICAgIGlmICh0Yykge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZVR5cGVDaGVja2VyKHRjKVxuICAgICAgfVxuICAgICAgdGhyb3cgZmFpbHVyZShcInR5cGUgY2hlY2tlciBjb3VsZCBub3QgYmUgcmVzb2x2ZWRcIilcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTdGFuZGFyZFR5cGVOb1Rocm93KFxuICB2OiBBbnlUeXBlIHwgVHlwZUNoZWNrZXIgfCBMYXRlVHlwZUNoZWNrZXJcbik6IEFueVN0YW5kYXJkVHlwZSB8IHVuZGVmaW5lZCB7XG4gIGlmICh2IGluc3RhbmNlb2YgVHlwZUNoZWNrZXIgfHwgaXNMYXRlVHlwZUNoZWNrZXIodikpIHtcbiAgICByZXR1cm4gdiBhcyBhbnlcbiAgfSBlbHNlIHtcbiAgICBjb25zdCB0YyA9IGZpbmRTdGFuZGFyZFR5cGUodilcbiAgICBpZiAodGMpIHtcbiAgICAgIHJldHVybiB0Y1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTdGFuZGFyZFR5cGUodjogQW55VHlwZSB8IFR5cGVDaGVja2VyIHwgTGF0ZVR5cGVDaGVja2VyKTogQW55U3RhbmRhcmRUeXBlIHtcbiAgY29uc3QgdGMgPSByZXNvbHZlU3RhbmRhcmRUeXBlTm9UaHJvdyh2KVxuICBpZiAodGMpIHtcbiAgICByZXR1cm4gdGNcbiAgfVxuICB0aHJvdyBmYWlsdXJlKFwic3RhbmRhcmQgdHlwZSBjb3VsZCBub3QgYmUgcmVzb2x2ZWRcIilcbn1cbiIsImltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcclxuaW1wb3J0IHsgcmVzb2x2ZVR5cGVDaGVja2VyIH0gZnJvbSBcIi4uL3R5cGVzL3Jlc29sdmVUeXBlQ2hlY2tlclwiXHJcbmltcG9ydCB7IEFueVR5cGUsIFR5cGVUb0RhdGEgfSBmcm9tIFwiLi4vdHlwZXMvc2NoZW1hc1wiXHJcbmltcG9ydCB7IGZhaWx1cmUsIGlkZW50aXR5Rm4sIGlzUHJpbWl0aXZlIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHtcclxuICBmcmVlemVJbnRlcm5hbFNuYXBzaG90LFxyXG4gIGdldEludGVybmFsU25hcHNob3QsXHJcbiAgcmVwb3J0SW50ZXJuYWxTbmFwc2hvdE9ic2VydmVkLFxyXG59IGZyb20gXCIuL2ludGVybmFsXCJcclxuaW1wb3J0IHR5cGUgeyBTbmFwc2hvdE91dE9mIH0gZnJvbSBcIi4vU25hcHNob3RPZlwiXHJcblxyXG4vKipcclxuICogUmV0cmlldmVzIGFuIGltbXV0YWJsZSBzbmFwc2hvdCBmb3IgYSBkYXRhIHN0cnVjdHVyZS5cclxuICogU2luY2UgcmV0dXJuZWQgc25hcHNob3RzIGFyZSBpbW11dGFibGUgdGhleSB3aWxsIHJlc3BlY3Qgc2hhbGxvdyBlcXVhbGl0eSwgdGhpcyBpcyxcclxuICogaWYgbm8gY2hhbmdlcyBhcmUgbWFkZSB0aGVuIHRoZSBzbmFwc2hvdCB3aWxsIGJlIGtlcHQgdGhlIHNhbWUuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVCBPYmplY3QgdHlwZS5cclxuICogQHBhcmFtIG5vZGVPclByaW1pdGl2ZSBEYXRhIHN0cnVjdHVyZSwgaW5jbHVkaW5nIHByaW10aXZlcy5cclxuICogQHJldHVybnMgVGhlIHNuYXBzaG90LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdldFNuYXBzaG90PFQgZXh0ZW5kcyBBbnlUeXBlPihcclxuICB0eXBlOiBULFxyXG4gIG5vZGVPclByaW1pdGl2ZTogVHlwZVRvRGF0YTxUPlxyXG4pOiBTbmFwc2hvdE91dE9mPFR5cGVUb0RhdGE8VD4+XHJcblxyXG4vKipcclxuICogUmV0cmlldmVzIGFuIGltbXV0YWJsZSBzbmFwc2hvdCBmb3IgYSBkYXRhIHN0cnVjdHVyZS5cclxuICogU2luY2UgcmV0dXJuZWQgc25hcHNob3RzIGFyZSBpbW11dGFibGUgdGhleSB3aWxsIHJlc3BlY3Qgc2hhbGxvdyBlcXVhbGl0eSwgdGhpcyBpcyxcclxuICogaWYgbm8gY2hhbmdlcyBhcmUgbWFkZSB0aGVuIHRoZSBzbmFwc2hvdCB3aWxsIGJlIGtlcHQgdGhlIHNhbWUuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVCBPYmplY3QgdHlwZS5cclxuICogQHBhcmFtIG5vZGVPclByaW1pdGl2ZSBEYXRhIHN0cnVjdHVyZSwgaW5jbHVkaW5nIHByaW10aXZlcy5cclxuICogQHJldHVybnMgVGhlIHNuYXBzaG90LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdldFNuYXBzaG90PFQ+KG5vZGVPclByaW1pdGl2ZTogVCk6IFNuYXBzaG90T3V0T2Y8VD5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRTbmFwc2hvdChhcmcxOiBhbnksIGFyZzI/OiBhbnkpOiBhbnkge1xyXG4gIGxldCB0b1NuYXBzaG90UHJvY2Vzc29yID0gaWRlbnRpdHlGbiBhcyAoc246IGFueSkgPT4gdW5rbm93blxyXG4gIGxldCBub2RlT3JQcmltaXRpdmU6IGFueVxyXG5cclxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSAyKSB7XHJcbiAgICB0b1NuYXBzaG90UHJvY2Vzc29yID0gcmVzb2x2ZVR5cGVDaGVja2VyKGFyZzEpLnRvU25hcHNob3RQcm9jZXNzb3JcclxuICAgIG5vZGVPclByaW1pdGl2ZSA9IGFyZzJcclxuICB9IGVsc2Uge1xyXG4gICAgbm9kZU9yUHJpbWl0aXZlID0gYXJnMVxyXG4gIH1cclxuXHJcbiAgaWYgKGlzUHJpbWl0aXZlKG5vZGVPclByaW1pdGl2ZSkpIHtcclxuICAgIHJldHVybiB0b1NuYXBzaG90UHJvY2Vzc29yKG5vZGVPclByaW1pdGl2ZSlcclxuICB9XHJcblxyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZU9yUHJpbWl0aXZlLCBcIm5vZGVPclByaW1pdGl2ZVwiKVxyXG5cclxuICBjb25zdCBzbmFwc2hvdCA9IGdldEludGVybmFsU25hcHNob3Qobm9kZU9yUHJpbWl0aXZlKVxyXG4gIGlmICghc25hcHNob3QpIHtcclxuICAgIHRocm93IGZhaWx1cmUoXCJnZXRTbmFwc2hvdCBpcyBub3Qgc3VwcG9ydGVkIGZvciB0aGlzIGtpbmQgb2Ygb2JqZWN0XCIpXHJcbiAgfVxyXG5cclxuICBmcmVlemVJbnRlcm5hbFNuYXBzaG90KHNuYXBzaG90LnRyYW5zZm9ybWVkKVxyXG4gIHJlcG9ydEludGVybmFsU25hcHNob3RPYnNlcnZlZChzbmFwc2hvdClcclxuICByZXR1cm4gdG9TbmFwc2hvdFByb2Nlc3NvcihzbmFwc2hvdC50cmFuc2Zvcm1lZClcclxufVxyXG4iLCJpbXBvcnQgeyBhY3Rpb24sIHNldCB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHR5cGUgeyBPIH0gZnJvbSBcInRzLXRvb2xiZWx0XCJcclxuaW1wb3J0IHsgaXNNb2RlbEF1dG9UeXBlQ2hlY2tpbmdFbmFibGVkIH0gZnJvbSBcIi4uL2dsb2JhbENvbmZpZy9nbG9iYWxDb25maWdcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ3JlYXRpb25EYXRhIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL0Jhc2VNb2RlbFNoYXJlZFwiXHJcbmltcG9ydCB7IG1vZGVsSW5mb0J5Q2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxJbmZvXCJcclxuaW1wb3J0IHsgZ2V0SW50ZXJuYWxNb2RlbENsYXNzUHJvcHNJbmZvIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL21vZGVsUHJvcHNJbmZvXCJcclxuaW1wb3J0IHsgYXBwbHlNb2RlbEluaXRpYWxpemVycyB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9uZXdNb2RlbFwiXHJcbmltcG9ydCB7IGdldE1vZGVsUHJvcERlZmF1bHRWYWx1ZSwgbm9EZWZhdWx0VmFsdWUgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvcHJvcFwiXHJcbmltcG9ydCB7IHR3ZWFrTW9kZWwgfSBmcm9tIFwiLi4vdHdlYWtlci90d2Vha01vZGVsXCJcclxuaW1wb3J0IHsgdHdlYWtQbGFpbk9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL3R3ZWFrUGxhaW5PYmplY3RcIlxyXG5pbXBvcnQgeyBmYWlsdXJlLCBpbkRldk1vZGUsIG1ha2VQcm9wUmVhZG9ubHkgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IEFueU1vZGVsIH0gZnJvbSBcIi4vQmFzZU1vZGVsXCJcclxuaW1wb3J0IHR5cGUgeyBNb2RlbENvbnN0cnVjdG9yT3B0aW9ucyB9IGZyb20gXCIuL01vZGVsQ29uc3RydWN0b3JPcHRpb25zXCJcclxuaW1wb3J0IHsgZ2V0TW9kZWxJZFByb3BlcnR5TmFtZSwgZ2V0TW9kZWxNZXRhZGF0YSB9IGZyb20gXCIuL2dldE1vZGVsTWV0YWRhdGFcIlxyXG5pbXBvcnQgeyBtb2RlbFR5cGVLZXkgfSBmcm9tIFwiLi9tZXRhZGF0YVwiXHJcbmltcG9ydCB7IGFzc2VydElzTW9kZWxDbGFzcyB9IGZyb20gXCIuL3V0aWxzXCJcclxuaW1wb3J0IHsgc2V0SWZEaWZmZXJlbnQgfSBmcm9tIFwiLi4vdXRpbHMvc2V0SWZEaWZmZXJlbnRcIlxyXG5pbXBvcnQgeyBQYXRjaCB9IGZyb20gXCIuLi9wYXRjaC9QYXRjaFwiXHJcbmltcG9ydCB7IGVtaXRQYXRjaGVzLCBjcmVhdGVQYXRjaEZvck9iamVjdFZhbHVlQ2hhbmdlIH0gZnJvbSBcIi4uL3BhdGNoL2VtaXRQYXRjaFwiXHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgaW50ZXJuYWxOZXdNb2RlbCA9IGFjdGlvbihcclxuICBcIm5ld01vZGVsXCIsXHJcbiAgPE0gZXh0ZW5kcyBBbnlNb2RlbD4oXHJcbiAgICBvcmlnTW9kZWxPYmo6IE0sXHJcbiAgICBpbml0aWFsRGF0YTogTW9kZWxDcmVhdGlvbkRhdGE8TT4gfCB1bmRlZmluZWQsXHJcbiAgICBvcHRpb25zOiBQaWNrPE1vZGVsQ29uc3RydWN0b3JPcHRpb25zLCBcIm1vZGVsQ2xhc3NcIiB8IFwic25hcHNob3RJbml0aWFsRGF0YVwiIHwgXCJnZW5lcmF0ZU5ld0lkc1wiPlxyXG4gICk6IE0gPT4ge1xyXG4gICAgY29uc3QgbW9kZSA9IGluaXRpYWxEYXRhID8gXCJuZXdcIiA6IFwiZnJvbVNuYXBzaG90XCJcclxuICAgIGNvbnN0IHsgbW9kZWxDbGFzczogX21vZGVsQ2xhc3MsIHNuYXBzaG90SW5pdGlhbERhdGEsIGdlbmVyYXRlTmV3SWRzIH0gPSBvcHRpb25zXHJcbiAgICBjb25zdCBtb2RlbENsYXNzID0gX21vZGVsQ2xhc3MhXHJcblxyXG4gICAgaWYgKGluRGV2TW9kZSkge1xyXG4gICAgICBhc3NlcnRJc01vZGVsQ2xhc3MobW9kZWxDbGFzcywgXCJtb2RlbENsYXNzXCIpXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgbW9kZWxPYmogPSBvcmlnTW9kZWxPYmogYXMgTy5Xcml0YWJsZTxNPlxyXG5cclxuICAgIGNvbnN0IG1vZGVsSW5mbyA9IG1vZGVsSW5mb0J5Q2xhc3MuZ2V0KG1vZGVsQ2xhc3MpXHJcbiAgICBpZiAoIW1vZGVsSW5mbykge1xyXG4gICAgICB0aHJvdyBmYWlsdXJlKFxyXG4gICAgICAgIGBubyBtb2RlbCBpbmZvIGZvciBjbGFzcyAke21vZGVsQ2xhc3MubmFtZX0gY291bGQgYmUgZm91bmQgLSBkaWQgeW91IGZvcmdldCB0byBhZGQgdGhlIEBtb2RlbCBkZWNvcmF0b3I/YFxyXG4gICAgICApXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgbW9kZWxJZFByb3BlcnR5TmFtZSA9IGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUobW9kZWxDbGFzcylcclxuICAgIGNvbnN0IG1vZGVsUHJvcHMgPSBnZXRJbnRlcm5hbE1vZGVsQ2xhc3NQcm9wc0luZm8obW9kZWxDbGFzcylcclxuICAgIGNvbnN0IG1vZGVsSWRQcm9wRGF0YSA9IG1vZGVsSWRQcm9wZXJ0eU5hbWUgPyBtb2RlbFByb3BzW21vZGVsSWRQcm9wZXJ0eU5hbWVdISA6IHVuZGVmaW5lZFxyXG5cclxuICAgIGxldCBpZDogc3RyaW5nIHwgdW5kZWZpbmVkXHJcbiAgICBpZiAoc25hcHNob3RJbml0aWFsRGF0YSkge1xyXG4gICAgICBsZXQgc24gPSBzbmFwc2hvdEluaXRpYWxEYXRhLnVucHJvY2Vzc2VkU25hcHNob3RcclxuXHJcbiAgICAgIGlmIChtb2RlbElkUHJvcERhdGEgJiYgbW9kZWxJZFByb3BlcnR5TmFtZSkge1xyXG4gICAgICAgIGlmIChnZW5lcmF0ZU5ld0lkcykge1xyXG4gICAgICAgICAgaWQgPSAobW9kZWxJZFByb3BEYXRhLl9kZWZhdWx0Rm4gYXMgKCkgPT4gc3RyaW5nKSgpXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlkID0gc25bbW9kZWxJZFByb3BlcnR5TmFtZV1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChtb2RlbENsYXNzLmZyb21TbmFwc2hvdFByb2Nlc3Nvcikge1xyXG4gICAgICAgIHNuID0gbW9kZWxDbGFzcy5mcm9tU25hcHNob3RQcm9jZXNzb3Ioc24pXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGluaXRpYWxEYXRhID0gc25hcHNob3RJbml0aWFsRGF0YS5zbmFwc2hvdFRvSW5pdGlhbERhdGEoc24pXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyB1c2Ugc3ltYm9sIGlmIHByb3ZpZGVkXHJcbiAgICAgIGlmIChtb2RlbElkUHJvcERhdGEgJiYgbW9kZWxJZFByb3BlcnR5TmFtZSkge1xyXG4gICAgICAgIGlmIChpbml0aWFsRGF0YSFbbW9kZWxJZFByb3BlcnR5TmFtZV0pIHtcclxuICAgICAgICAgIGlkID0gaW5pdGlhbERhdGEhW21vZGVsSWRQcm9wZXJ0eU5hbWVdXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlkID0gKG1vZGVsSWRQcm9wRGF0YS5fZGVmYXVsdEZuIGFzICgpID0+IHN0cmluZykoKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIG1vZGVsT2JqW21vZGVsVHlwZUtleV0gPSBtb2RlbEluZm8ubmFtZVxyXG5cclxuICAgIGNvbnN0IHBhdGNoZXM6IFBhdGNoW10gPSBbXVxyXG4gICAgY29uc3QgaW52ZXJzZVBhdGNoZXM6IFBhdGNoW10gPSBbXVxyXG5cclxuICAgIC8vIGZpbGwgaW4gZGVmYXVsdHMgaW4gaW5pdGlhbCBkYXRhXHJcbiAgICBjb25zdCBtb2RlbFByb3BzS2V5cyA9IE9iamVjdC5rZXlzKG1vZGVsUHJvcHMpXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1vZGVsUHJvcHNLZXlzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGsgPSBtb2RlbFByb3BzS2V5c1tpXVxyXG5cclxuICAgICAgLy8gaWQgaXMgYWxyZWFkeSBpbml0aWFsaXplZCBhYm92ZVxyXG4gICAgICBpZiAoayA9PT0gbW9kZWxJZFByb3BlcnR5TmFtZSkge1xyXG4gICAgICAgIGNvbnRpbnVlXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IHByb3BEYXRhID0gbW9kZWxQcm9wc1trXVxyXG5cclxuICAgICAgY29uc3QgaW5pdGlhbFZhbHVlID0gaW5pdGlhbERhdGEhW2tdXHJcbiAgICAgIGxldCBuZXdWYWx1ZSA9IGluaXRpYWxWYWx1ZVxyXG4gICAgICBsZXQgY2hhbmdlZCA9IGZhbHNlXHJcblxyXG4gICAgICAvLyBhcHBseSB1bnRyYW5zZm9ybSAoaWYgYW55KSBpZiBub3QgaW4gc25hcHNob3QgbW9kZVxyXG4gICAgICBpZiAobW9kZSA9PT0gXCJuZXdcIiAmJiBwcm9wRGF0YS5fdHJhbnNmb3JtKSB7XHJcbiAgICAgICAgY2hhbmdlZCA9IHRydWVcclxuICAgICAgICBuZXdWYWx1ZSA9IHByb3BEYXRhLl90cmFuc2Zvcm0udW50cmFuc2Zvcm0obmV3VmFsdWUsIG1vZGVsT2JqLCBrKVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBhcHBseSBkZWZhdWx0IHZhbHVlIChpZiBuZWVkZWQpXHJcbiAgICAgIGlmIChuZXdWYWx1ZSA9PSBudWxsKSB7XHJcbiAgICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gZ2V0TW9kZWxQcm9wRGVmYXVsdFZhbHVlKHByb3BEYXRhKVxyXG4gICAgICAgIGlmIChkZWZhdWx0VmFsdWUgIT09IG5vRGVmYXVsdFZhbHVlKSB7XHJcbiAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZVxyXG4gICAgICAgICAgbmV3VmFsdWUgPSBkZWZhdWx0VmFsdWVcclxuICAgICAgICB9IGVsc2UgaWYgKCEoayBpbiBpbml0aWFsRGF0YSEpKSB7XHJcbiAgICAgICAgICAvLyBmb3IgbW9ieDQsIHdlIG5lZWQgdG8gc2V0IHVwIHByb3BlcnRpZXMgZXZlbiBpZiB0aGV5IGFyZSB1bmRlZmluZWRcclxuICAgICAgICAgIGNoYW5nZWQgPSB0cnVlXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoY2hhbmdlZCkge1xyXG4gICAgICAgIC8vIHNldElmRGlmZmVyZW50IG5vdCByZXF1aXJlZFxyXG4gICAgICAgIHNldChpbml0aWFsRGF0YSEsIGssIG5ld1ZhbHVlKVxyXG5cclxuICAgICAgICBpZiAobW9kZSA9PT0gXCJmcm9tU25hcHNob3RcIiAmJiBuZXdWYWx1ZSAhPT0gaW5pdGlhbFZhbHVlKSB7XHJcbiAgICAgICAgICBjb25zdCBwcm9wUGF0aCA9IFtrXVxyXG5cclxuICAgICAgICAgIHBhdGNoZXMucHVzaChjcmVhdGVQYXRjaEZvck9iamVjdFZhbHVlQ2hhbmdlKHByb3BQYXRoLCBpbml0aWFsVmFsdWUsIG5ld1ZhbHVlKSlcclxuICAgICAgICAgIGludmVyc2VQYXRjaGVzLnB1c2goY3JlYXRlUGF0Y2hGb3JPYmplY3RWYWx1ZUNoYW5nZShwcm9wUGF0aCwgbmV3VmFsdWUsIGluaXRpYWxWYWx1ZSkpXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG1vZGVsSWRQcm9wZXJ0eU5hbWUpIHtcclxuICAgICAgY29uc3QgaW5pdGlhbFZhbHVlID0gaW5pdGlhbERhdGEhW21vZGVsSWRQcm9wZXJ0eU5hbWVdXHJcbiAgICAgIGNvbnN0IHZhbHVlQ2hhbmdlZCA9IHNldElmRGlmZmVyZW50KGluaXRpYWxEYXRhLCBtb2RlbElkUHJvcGVydHlOYW1lLCBpZClcclxuXHJcbiAgICAgIGlmICh2YWx1ZUNoYW5nZWQgJiYgbW9kZSA9PT0gXCJmcm9tU25hcHNob3RcIikge1xyXG4gICAgICAgIGNvbnN0IG1vZGVsSWRQYXRoID0gW21vZGVsSWRQcm9wZXJ0eU5hbWVdXHJcblxyXG4gICAgICAgIHBhdGNoZXMucHVzaChjcmVhdGVQYXRjaEZvck9iamVjdFZhbHVlQ2hhbmdlKG1vZGVsSWRQYXRoLCBpbml0aWFsVmFsdWUsIGlkKSlcclxuICAgICAgICBpbnZlcnNlUGF0Y2hlcy5wdXNoKGNyZWF0ZVBhdGNoRm9yT2JqZWN0VmFsdWVDaGFuZ2UobW9kZWxJZFBhdGgsIGlkLCBpbml0aWFsVmFsdWUpKVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG1vZGUgPT09IFwiZnJvbVNuYXBzaG90XCIpIHtcclxuICAgICAgLy8gYWxzbyBlbWl0IGEgcGF0Y2ggZm9yIG1vZGVsVHlwZSwgc2luY2UgaXQgd2lsbCBnZXQgaW5jbHVkZWQgaW4gdGhlIHNuYXBzaG90XHJcbiAgICAgIGNvbnN0IGluaXRpYWxNb2RlbFR5cGUgPSBzbmFwc2hvdEluaXRpYWxEYXRhPy51bnByb2Nlc3NlZE1vZGVsVHlwZVxyXG4gICAgICBjb25zdCBuZXdNb2RlbFR5cGUgPSBtb2RlbEluZm8ubmFtZVxyXG4gICAgICBpZiAoaW5pdGlhbE1vZGVsVHlwZSAhPT0gbmV3TW9kZWxUeXBlKSB7XHJcbiAgICAgICAgY29uc3QgbW9kZWxUeXBlUGF0aCA9IFttb2RlbFR5cGVLZXldXHJcblxyXG4gICAgICAgIHBhdGNoZXMucHVzaChjcmVhdGVQYXRjaEZvck9iamVjdFZhbHVlQ2hhbmdlKG1vZGVsVHlwZVBhdGgsIGluaXRpYWxNb2RlbFR5cGUsIG5ld01vZGVsVHlwZSkpXHJcbiAgICAgICAgaW52ZXJzZVBhdGNoZXMucHVzaChcclxuICAgICAgICAgIGNyZWF0ZVBhdGNoRm9yT2JqZWN0VmFsdWVDaGFuZ2UobW9kZWxUeXBlUGF0aCwgbmV3TW9kZWxUeXBlLCBpbml0aWFsTW9kZWxUeXBlKVxyXG4gICAgICAgIClcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHR3ZWFrTW9kZWwobW9kZWxPYmosIHVuZGVmaW5lZClcclxuXHJcbiAgICAvLyBjcmVhdGUgb2JzZXJ2YWJsZSBkYXRhIG9iamVjdCB3aXRoIGluaXRpYWwgZGF0YVxyXG4gICAgbW9kZWxPYmouJCA9IHR3ZWFrUGxhaW5PYmplY3QoXHJcbiAgICAgIGluaXRpYWxEYXRhISxcclxuICAgICAgeyBwYXJlbnQ6IG1vZGVsT2JqLCBwYXRoOiBcIiRcIiB9LFxyXG4gICAgICBtb2RlbE9ialttb2RlbFR5cGVLZXldLFxyXG4gICAgICBmYWxzZSxcclxuICAgICAgdHJ1ZVxyXG4gICAgKVxyXG5cclxuICAgIGlmIChpbkRldk1vZGUpIHtcclxuICAgICAgbWFrZVByb3BSZWFkb25seShtb2RlbE9iaiwgXCIkXCIsIHRydWUpXHJcbiAgICB9XHJcblxyXG4gICAgLy8gcnVuIGFueSBleHRyYSBpbml0aWFsaXplcnMgZm9yIHRoZSBjbGFzcyBhcyBuZWVkZWRcclxuICAgIGFwcGx5TW9kZWxJbml0aWFsaXplcnMobW9kZWxDbGFzcywgbW9kZWxPYmopXHJcblxyXG4gICAgZW1pdFBhdGNoZXMobW9kZWxPYmosIHBhdGNoZXMsIGludmVyc2VQYXRjaGVzKVxyXG5cclxuICAgIC8vIHR5cGUgY2hlY2sgaXQgaWYgbmVlZGVkXHJcbiAgICBpZiAoaXNNb2RlbEF1dG9UeXBlQ2hlY2tpbmdFbmFibGVkKCkgJiYgZ2V0TW9kZWxNZXRhZGF0YShtb2RlbENsYXNzKS5kYXRhVHlwZSkge1xyXG4gICAgICBjb25zdCBlcnIgPSBtb2RlbE9iai50eXBlQ2hlY2soKVxyXG4gICAgICBpZiAoZXJyKSB7XHJcbiAgICAgICAgZXJyLnRocm93KClcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBtb2RlbE9iaiBhcyBNXHJcbiAgfVxyXG4pXHJcbiIsImltcG9ydCB7IG9ic2VydmFibGUgfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7XHJcbiAgZnJvbVNuYXBzaG90T3ZlcnJpZGVUeXBlU3ltYm9sLFxyXG4gIE1vZGVsQ2xhc3MsXHJcbiAgcHJvcHNUeXBlU3ltYm9sLFxyXG4gIHRvU25hcHNob3RPdmVycmlkZVR5cGVTeW1ib2wsXHJcbn0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL0Jhc2VNb2RlbFNoYXJlZFwiXHJcbmltcG9ydCB7IG1vZGVsSW5mb0J5Q2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxJbmZvXCJcclxuaW1wb3J0IHR5cGUge1xyXG4gIE1vZGVsUHJvcHMsXHJcbiAgTW9kZWxQcm9wc1RvVHJhbnNmb3JtZWRDcmVhdGlvbkRhdGEsXHJcbiAgTW9kZWxQcm9wc1RvVW50cmFuc2Zvcm1lZERhdGEsXHJcbn0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL3Byb3BcIlxyXG5pbXBvcnQgeyBnZXRTbmFwc2hvdCB9IGZyb20gXCIuLi9zbmFwc2hvdC9nZXRTbmFwc2hvdFwiXHJcbmltcG9ydCB0eXBlIHsgU25hcHNob3RJbk9mTW9kZWwsIFNuYXBzaG90T3V0T2ZNb2RlbCB9IGZyb20gXCIuLi9zbmFwc2hvdC9TbmFwc2hvdE9mXCJcclxuaW1wb3J0IHsgdHlwZXNNb2RlbCB9IGZyb20gXCIuLi90eXBlcy9vYmplY3RCYXNlZC90eXBlc01vZGVsXCJcclxuaW1wb3J0IHsgdHlwZUNoZWNrIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVDaGVja1wiXHJcbmltcG9ydCB0eXBlIHsgVHlwZUNoZWNrRXJyb3IgfSBmcm9tIFwiLi4vdHlwZXMvVHlwZUNoZWNrRXJyb3JcIlxyXG5pbXBvcnQgeyBhc3NlcnRJc09iamVjdCwgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXHJcbmltcG9ydCB7IGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUgfSBmcm9tIFwiLi9nZXRNb2RlbE1ldGFkYXRhXCJcclxuaW1wb3J0IHsgbW9kZWxJZEtleSwgbW9kZWxUeXBlS2V5IH0gZnJvbSBcIi4vbWV0YWRhdGFcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ29uc3RydWN0b3JPcHRpb25zIH0gZnJvbSBcIi4vTW9kZWxDb25zdHJ1Y3Rvck9wdGlvbnNcIlxyXG5pbXBvcnQgeyBpbnRlcm5hbE5ld01vZGVsIH0gZnJvbSBcIi4vbmV3TW9kZWxcIlxyXG5pbXBvcnQgeyBhc3NlcnRJc01vZGVsQ2xhc3MgfSBmcm9tIFwiLi91dGlsc1wiXHJcblxyXG4vKipcclxuICogQGlnbm9yZVxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IG1vZGVsSWRQcm9wZXJ0eU5hbWVTeW1ib2wgPSBTeW1ib2woXCJtb2RlbElkUHJvcGVydHlOYW1lXCIpXHJcblxyXG4vKipcclxuICogQGlnbm9yZVxyXG4gKi9cclxuZXhwb3J0IHR5cGUgTW9kZWxJZFByb3BlcnR5VHlwZTxUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLCBNb2RlbElkUHJvcGVydHlOYW1lIGV4dGVuZHMgc3RyaW5nPiA9IFtcclxuICBNb2RlbElkUHJvcGVydHlOYW1lXHJcbl0gZXh0ZW5kcyBbbmV2ZXJdXHJcbiAgPyBuZXZlclxyXG4gIDogTW9kZWxQcm9wc1RvVW50cmFuc2Zvcm1lZERhdGE8UGljazxUUHJvcHMsIE1vZGVsSWRQcm9wZXJ0eU5hbWU+PltNb2RlbElkUHJvcGVydHlOYW1lXVxyXG5cclxuLyoqXHJcbiAqIEJhc2UgYWJzdHJhY3QgY2xhc3MgZm9yIG1vZGVscy4gVXNlIGBNb2RlbGAgaW5zdGVhZCB3aGVuIGV4dGVuZGluZy5cclxuICpcclxuICogTmV2ZXIgb3ZlcnJpZGUgdGhlIGNvbnN0cnVjdG9yLCB1c2UgYG9uSW5pdGAgb3IgYG9uQXR0YWNoZWRUb1Jvb3RTdG9yZWAgaW5zdGVhZC5cclxuICpcclxuICogQHR5cGVwYXJhbSBEYXRhIERhdGEgdHlwZS5cclxuICogQHR5cGVwYXJhbSBDcmVhdGlvbkRhdGEgQ3JlYXRpb24gZGF0YSB0eXBlLlxyXG4gKiBAdHlwZXBhcmFtIE1vZGVsSWRQcm9wZXJ0eU5hbWUgTW9kZWwgaWQgcHJvcGVydHkgbmFtZS5cclxuICovXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlTW9kZWw8XHJcbiAgVFByb3BzIGV4dGVuZHMgTW9kZWxQcm9wcyxcclxuICBGcm9tU25hcHNob3RPdmVycmlkZSBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4sXHJcbiAgVG9TbmFwc2hvdE92ZXJyaWRlIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PixcclxuICBNb2RlbElkUHJvcGVydHlOYW1lIGV4dGVuZHMgc3RyaW5nID0gbmV2ZXJcclxuPiB7XHJcbiAgLy8ganVzdCB0byBtYWtlIHR5cGluZyB3b3JrIHByb3Blcmx5XHJcbiAgW3Byb3BzVHlwZVN5bWJvbF0hOiBUUHJvcHM7XHJcbiAgW2Zyb21TbmFwc2hvdE92ZXJyaWRlVHlwZVN5bWJvbF0hOiBGcm9tU25hcHNob3RPdmVycmlkZTtcclxuICBbdG9TbmFwc2hvdE92ZXJyaWRlVHlwZVN5bWJvbF0hOiBUb1NuYXBzaG90T3ZlcnJpZGU7XHJcbiAgW21vZGVsSWRQcm9wZXJ0eU5hbWVTeW1ib2xdITogTW9kZWxJZFByb3BlcnR5TmFtZTtcclxuXHJcbiAgLyoqXHJcbiAgICogTW9kZWwgdHlwZSBuYW1lLlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IFttb2RlbFR5cGVLZXldITogc3RyaW5nXHJcblxyXG4gIC8qKlxyXG4gICAqIE1vZGVsIGludGVybmFsIGlkLiBDYW4gYmUgbW9kaWZpZWQgaW5zaWRlIGEgbW9kZWwgYWN0aW9uLlxyXG4gICAqIEl0IHdpbGwgcmV0dXJuIGB1bmRlZmluZWRgIGlmIHRoZXJlJ3Mgbm8gaWQgcHJvcCBzZXQuXHJcbiAgICovXHJcbiAgZ2V0IFttb2RlbElkS2V5XSgpOiBNb2RlbElkUHJvcGVydHlUeXBlPFRQcm9wcywgTW9kZWxJZFByb3BlcnR5TmFtZT4ge1xyXG4gICAgY29uc3QgaWRQcm9wID0gZ2V0TW9kZWxJZFByb3BlcnR5TmFtZSh0aGlzLmNvbnN0cnVjdG9yIGFzIGFueSlcclxuICAgIHJldHVybiBpZFByb3AgPyB0aGlzLiRbaWRQcm9wXSA6ICh1bmRlZmluZWQgYXMgYW55KVxyXG4gIH1cclxuXHJcbiAgc2V0IFttb2RlbElkS2V5XShuZXdJZDogTW9kZWxJZFByb3BlcnR5VHlwZTxUUHJvcHMsIE1vZGVsSWRQcm9wZXJ0eU5hbWU+KSB7XHJcbiAgICBjb25zdCBpZFByb3AgPSBnZXRNb2RlbElkUHJvcGVydHlOYW1lKHRoaXMuY29uc3RydWN0b3IgYXMgYW55KVxyXG4gICAgaWYgKCFpZFByb3ApIHtcclxuICAgICAgdGhyb3cgZmFpbHVyZShcIiRtb2RlbElkIGNhbm5vdCBiZSBzZXQgd2hlbiB0aGVyZSBpcyBubyBpZFByb3Agc2V0IGluIHRoZSBtb2RlbFwiKVxyXG4gICAgfVxyXG4gICAgOyh0aGlzLiQgYXMgYW55KVtpZFByb3BdID0gbmV3SWRcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENhbiBiZSBvdmVycmlkZGVuIHRvIG9mZmVyIGEgcmVmZXJlbmNlIGlkIHRvIGJlIHVzZWQgaW4gcmVmZXJlbmNlIHJlc29sdXRpb24uXHJcbiAgICogQnkgZGVmYXVsdCBpdCB3aWxsIHVzZSB0aGUgYGlkUHJvcGAgaWYgYXZhaWxhYmxlIG9yIHJldHVybiBgdW5kZWZpbmVkYCBvdGhlcndpc2UuXHJcbiAgICovXHJcbiAgZ2V0UmVmSWQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzW21vZGVsSWRLZXldXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDYWxsZWQgYWZ0ZXIgdGhlIG1vZGVsIGhhcyBiZWVuIGNyZWF0ZWQuXHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIG9uSW5pdD8oKTogdm9pZFxyXG5cclxuICAvKipcclxuICAgKiBEYXRhIHBhcnQgb2YgdGhlIG1vZGVsLCB3aGljaCBpcyBvYnNlcnZhYmxlIGFuZCB3aWxsIGJlIHNlcmlhbGl6ZWQgaW4gc25hcHNob3RzLlxyXG4gICAqIFVzZSBpdCBpZiBvbmUgb2YgdGhlIGRhdGEgcHJvcGVydGllcyBtYXRjaGVzIG9uZSBvZiB0aGUgbW9kZWwgcHJvcGVydGllcy9mdW5jdGlvbnMuXHJcbiAgICovXHJcbiAgcmVhZG9ubHkgJCE6IE1vZGVsUHJvcHNUb1VudHJhbnNmb3JtZWREYXRhPFRQcm9wcz5cclxuXHJcbiAgLyoqXHJcbiAgICogT3B0aW9uYWwgaG9vayB0aGF0IHdpbGwgcnVuIG9uY2UgdGhpcyBtb2RlbCBpbnN0YW5jZSBpcyBhdHRhY2hlZCB0byB0aGUgdHJlZSBvZiBhIG1vZGVsIG1hcmtlZCBhc1xyXG4gICAqIHJvb3Qgc3RvcmUgdmlhIGByZWdpc3RlclJvb3RTdG9yZWAuXHJcbiAgICogQmFzaWNhbGx5IHRoaXMgaXMgdGhlIHBsYWNlIHdoZXJlIHlvdSBrbm93IHRoZSBmdWxsIHJvb3Qgc3RvcmUgaXMgY29tcGxldGUgYW5kIHdoZXJlIHRoaW5ncyBzdWNoIGFzXHJcbiAgICogbWlkZGxld2FyZXMsIGVmZmVjdHMgKHJlYWN0aW9ucywgZXRjKSwgYW5kIG90aGVyIHNpZGUgZWZmZWN0cyBzaG91bGQgYmUgcmVnaXN0ZXJlZCwgc2luY2UgaXQgbWVhbnNcclxuICAgKiB0aGF0IHRoZSBtb2RlbCBpcyBub3cgcGFydCBvZiB0aGUgYWN0aXZlIGFwcGxpY2F0aW9uIHN0YXRlLlxyXG4gICAqXHJcbiAgICogSXQgY2FuIHJldHVybiBhIGRpc3Bvc2VyIHRoYXQgd2lsbCBiZSBydW4gb25jZSB0aGlzIG1vZGVsIGluc3RhbmNlIGlzIGRldGFjaGVkIGZyb20gc3VjaCByb290IHN0b3JlIHRyZWUuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gcm9vdFN0b3JlXHJcbiAgICogQHJldHVybnNcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgb25BdHRhY2hlZFRvUm9vdFN0b3JlPyhyb290U3RvcmU6IG9iamVjdCk6ICgoKSA9PiB2b2lkKSB8IHZvaWRcclxuXHJcbiAgLyoqXHJcbiAgICogUGVyZm9ybXMgYSB0eXBlIGNoZWNrIG92ZXIgdGhlIG1vZGVsIGluc3RhbmNlLlxyXG4gICAqIEZvciB0aGlzIHRvIHdvcmsgYSBkYXRhIHR5cGUgaGFzIHRvIGJlIGRlY2xhcmVkIGFzIHBhcnQgb2YgdGhlIG1vZGVsIHByb3BlcnRpZXMuXHJcbiAgICpcclxuICAgKiBAcmV0dXJucyBBIGBUeXBlQ2hlY2tFcnJvcmAgb3IgYG51bGxgIGlmIHRoZXJlIGlzIG5vIGVycm9yLlxyXG4gICAqL1xyXG4gIHR5cGVDaGVjaygpOiBUeXBlQ2hlY2tFcnJvciB8IG51bGwge1xyXG4gICAgY29uc3QgdHlwZSA9IHR5cGVzTW9kZWw8dGhpcz4odGhpcy5jb25zdHJ1Y3RvciBhcyBhbnkpXHJcbiAgICByZXR1cm4gdHlwZUNoZWNrKHR5cGUsIHRoaXMgYXMgYW55KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBhIG1vZGVsLlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKGRhdGE6IE1vZGVsUHJvcHNUb1RyYW5zZm9ybWVkQ3JlYXRpb25EYXRhPFRQcm9wcz4pIHtcclxuICAgIGxldCBpbml0aWFsRGF0YSA9IGRhdGEgYXMgYW55XHJcbiAgICBjb25zdCB7IHNuYXBzaG90SW5pdGlhbERhdGEsIG1vZGVsQ2xhc3MsIGdlbmVyYXRlTmV3SWRzIH06IE1vZGVsQ29uc3RydWN0b3JPcHRpb25zID1cclxuICAgICAgYXJndW1lbnRzWzFdIGFzIGFueVxyXG5cclxuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBtb2RlbENsYXNzIS5wcm90b3R5cGUpXHJcblxyXG4gICAgY29uc3Qgc2VsZiA9IHRoaXMgYXMgYW55XHJcblxyXG4gICAgLy8gZGVsZXRlIHVubmVjZXNzYXJ5IHByb3BzXHJcbiAgICBkZWxldGUgc2VsZltwcm9wc1R5cGVTeW1ib2xdXHJcbiAgICBkZWxldGUgc2VsZltmcm9tU25hcHNob3RPdmVycmlkZVR5cGVTeW1ib2xdXHJcbiAgICBkZWxldGUgc2VsZlt0b1NuYXBzaG90T3ZlcnJpZGVUeXBlU3ltYm9sXVxyXG4gICAgZGVsZXRlIHNlbGZbbW9kZWxJZFByb3BlcnR5TmFtZVN5bWJvbF1cclxuXHJcbiAgICBpZiAoIXNuYXBzaG90SW5pdGlhbERhdGEpIHtcclxuICAgICAgLy8gcGxhaW4gbmV3XHJcbiAgICAgIGFzc2VydElzT2JqZWN0KGluaXRpYWxEYXRhLCBcImluaXRpYWxEYXRhXCIpXHJcblxyXG4gICAgICBpbnRlcm5hbE5ld01vZGVsKHRoaXMsIG9ic2VydmFibGUub2JqZWN0KGluaXRpYWxEYXRhIGFzIGFueSwgdW5kZWZpbmVkLCB7IGRlZXA6IGZhbHNlIH0pLCB7XHJcbiAgICAgICAgbW9kZWxDbGFzcyxcclxuICAgICAgICBnZW5lcmF0ZU5ld0lkczogdHJ1ZSxcclxuICAgICAgfSlcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIGZyb20gc25hcHNob3RcclxuICAgICAgaW50ZXJuYWxOZXdNb2RlbCh0aGlzLCB1bmRlZmluZWQsIHsgbW9kZWxDbGFzcywgc25hcHNob3RJbml0aWFsRGF0YSwgZ2VuZXJhdGVOZXdJZHMgfSlcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHRvU3RyaW5nKG9wdGlvbnM/OiB7IHdpdGhEYXRhPzogYm9vbGVhbiB9KSB7XHJcbiAgICBjb25zdCBmaW5hbE9wdGlvbnMgPSB7XHJcbiAgICAgIHdpdGhEYXRhOiB0cnVlLFxyXG4gICAgICAuLi5vcHRpb25zLFxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZpcnN0UGFydCA9IGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0jJHt0aGlzW21vZGVsVHlwZUtleV19YFxyXG5cclxuICAgIHJldHVybiBmaW5hbE9wdGlvbnMud2l0aERhdGFcclxuICAgICAgPyBgWyR7Zmlyc3RQYXJ0fSAke0pTT04uc3RyaW5naWZ5KGdldFNuYXBzaG90KHRoaXMpKX1dYFxyXG4gICAgICA6IGBbJHtmaXJzdFBhcnR9XWBcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaWdub3JlXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBCYXNlTW9kZWxLZXlzID0ga2V5b2YgQW55TW9kZWwgfCBcIm9uSW5pdFwiIHwgXCJvbkF0dGFjaGVkVG9Sb290U3RvcmVcIlxyXG5cclxuLy8gdGhlc2UgcHJvcHMgd2lsbCBuZXZlciBiZSBob2lzdGVkIHRvIHRoaXMgKGV4Y2VwdCBmb3IgbW9kZWwgaWQpXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBjb25zdCBiYXNlTW9kZWxQcm9wTmFtZXMgPSBuZXcgU2V0PEJhc2VNb2RlbEtleXM+KFtcclxuICBtb2RlbFR5cGVLZXksXHJcbiAgbW9kZWxJZEtleSxcclxuICBcIm9uSW5pdFwiLFxyXG4gIFwiJFwiLFxyXG4gIFwiZ2V0UmVmSWRcIixcclxuICBcIm9uQXR0YWNoZWRUb1Jvb3RTdG9yZVwiLFxyXG4gIFwidHlwZUNoZWNrXCIsXHJcbl0pXHJcblxyXG4vKipcclxuICogQW55IGtpbmQgb2YgbW9kZWwgaW5zdGFuY2UuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEFueU1vZGVsIGV4dGVuZHMgQmFzZU1vZGVsPGFueSwgYW55LCBhbnksIGFueT4ge31cclxuXHJcbi8qKlxyXG4gKiBAZGVwcmVjYXRlZCBTaG91bGQgbm90IGJlIG5lZWRlZCBhbnltb3JlLlxyXG4gKlxyXG4gKiBUcmlja3MgVHlwZVNjcmlwdCBpbnRvIGFjY2VwdGluZyBhYnN0cmFjdCBjbGFzc2VzIGFzIGEgcGFyYW1ldGVyIGZvciBgRXh0ZW5kZWRNb2RlbGAuXHJcbiAqIERvZXMgbm90aGluZyBpbiBydW50aW1lLlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgQWJzdHJhY3QgbW9kZWwgY2xhc3MgdHlwZS5cclxuICogQHBhcmFtIHR5cGUgQWJzdHJhY3QgbW9kZWwgY2xhc3MuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYWJzdHJhY3RNb2RlbENsYXNzPFQ+KHR5cGU6IFQpOiBUICYgT2JqZWN0IHtcclxuICByZXR1cm4gdHlwZSBhcyBhbnlcclxufVxyXG5cclxuLyoqXHJcbiAqIFRoZSBtb2RlbCBpZCBwcm9wZXJ0eSBuYW1lLlxyXG4gKi9cclxuZXhwb3J0IHR5cGUgTW9kZWxJZFByb3BlcnR5TmFtZTxNIGV4dGVuZHMgQW55TW9kZWw+ID0gTVt0eXBlb2YgbW9kZWxJZFByb3BlcnR5TmFtZVN5bWJvbF1cclxuXHJcbi8qKlxyXG4gKiBBZGQgbWlzc2luZyBtb2RlbCBtZXRhZGF0YSB0byBhIG1vZGVsIGNyZWF0aW9uIHNuYXBzaG90IHRvIGdlbmVyYXRlIGEgcHJvcGVyIG1vZGVsIHNuYXBzaG90LlxyXG4gKiBVc3VhbGx5IHVzZWQgYWxvbmdzaWRlIGBmcm9tU25hcHNob3RgLlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIE0gTW9kZWwgdHlwZS5cclxuICogQHBhcmFtIG1vZGVsQ2xhc3MgTW9kZWwgY2xhc3MuXHJcbiAqIEBwYXJhbSBzbmFwc2hvdCBNb2RlbCBjcmVhdGlvbiBzbmFwc2hvdCB3aXRob3V0IG1ldGFkYXRhLlxyXG4gKiBAcmV0dXJucyBUaGUgbW9kZWwgc25hcHNob3QgKGluY2x1ZGluZyBtZXRhZGF0YSkuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gbW9kZWxTbmFwc2hvdEluV2l0aE1ldGFkYXRhPE0gZXh0ZW5kcyBBbnlNb2RlbD4oXHJcbiAgbW9kZWxDbGFzczogTW9kZWxDbGFzczxNPixcclxuICBzbmFwc2hvdDogT21pdDxTbmFwc2hvdEluT2ZNb2RlbDxNPiwgdHlwZW9mIG1vZGVsVHlwZUtleT5cclxuKTogU25hcHNob3RJbk9mTW9kZWw8TT4ge1xyXG4gIGFzc2VydElzTW9kZWxDbGFzcyhtb2RlbENsYXNzLCBcIm1vZGVsQ2xhc3NcIilcclxuICBhc3NlcnRJc09iamVjdChzbmFwc2hvdCwgXCJpbml0aWFsRGF0YVwiKVxyXG5cclxuICBjb25zdCBtb2RlbEluZm8gPSBtb2RlbEluZm9CeUNsYXNzLmdldChtb2RlbENsYXNzKSFcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIC4uLnNuYXBzaG90LFxyXG4gICAgW21vZGVsVHlwZUtleV06IG1vZGVsSW5mby5uYW1lLFxyXG4gIH0gYXMgYW55XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBZGQgbWlzc2luZyBtb2RlbCBtZXRhZGF0YSB0byBhIG1vZGVsIG91dHB1dCBzbmFwc2hvdCB0byBnZW5lcmF0ZSBhIHByb3BlciBtb2RlbCBzbmFwc2hvdC5cclxuICogVXN1YWxseSB1c2VkIGFsb25nc2lkZSBgYXBwbHlTbmFwc2hvdGAuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gTSBNb2RlbCB0eXBlLlxyXG4gKiBAcGFyYW0gbW9kZWxDbGFzcyBNb2RlbCBjbGFzcy5cclxuICogQHBhcmFtIHNuYXBzaG90IE1vZGVsIG91dHB1dCBzbmFwc2hvdCB3aXRob3V0IG1ldGFkYXRhLlxyXG4gKiBAcmV0dXJucyBUaGUgbW9kZWwgc25hcHNob3QgKGluY2x1ZGluZyBtZXRhZGF0YSkuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gbW9kZWxTbmFwc2hvdE91dFdpdGhNZXRhZGF0YTxNIGV4dGVuZHMgQW55TW9kZWw+KFxyXG4gIG1vZGVsQ2xhc3M6IE1vZGVsQ2xhc3M8TT4sXHJcbiAgc25hcHNob3Q6IE9taXQ8U25hcHNob3RPdXRPZk1vZGVsPE0+LCB0eXBlb2YgbW9kZWxUeXBlS2V5PlxyXG4pOiBTbmFwc2hvdE91dE9mTW9kZWw8TT4ge1xyXG4gIGFzc2VydElzTW9kZWxDbGFzcyhtb2RlbENsYXNzLCBcIm1vZGVsQ2xhc3NcIilcclxuICBhc3NlcnRJc09iamVjdChzbmFwc2hvdCwgXCJpbml0aWFsRGF0YVwiKVxyXG5cclxuICBjb25zdCBtb2RlbEluZm8gPSBtb2RlbEluZm9CeUNsYXNzLmdldChtb2RlbENsYXNzKSFcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIC4uLnNuYXBzaG90LFxyXG4gICAgW21vZGVsVHlwZUtleV06IG1vZGVsSW5mby5uYW1lLFxyXG4gIH0gYXMgYW55XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBIG1vZGVsIGNsYXNzIGRlY2xhcmF0aW9uLCBtYWRlIG9mIGEgYmFzZSBtb2RlbCBhbmQgdGhlIG1vZGVsIGludGVyZmFjZS5cclxuICovXHJcbmV4cG9ydCB0eXBlIE1vZGVsQ2xhc3NEZWNsYXJhdGlvbjxCYXNlTW9kZWxDbGFzcywgTW9kZWxJbnRlcmZhY2U+ID0gQmFzZU1vZGVsQ2xhc3MgJiB7XHJcbiAgbmV3ICguLi5hcmdzOiBhbnlbXSk6IE1vZGVsSW50ZXJmYWNlXHJcbn1cclxuIiwiaW1wb3J0IHR5cGUgeyBNb2RlbENsYXNzIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL0Jhc2VNb2RlbFNoYXJlZFwiXG5pbXBvcnQgeyBmYWlsdXJlLCBpc1BsYWluT2JqZWN0IH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IEFueU1vZGVsLCBCYXNlTW9kZWwgfSBmcm9tIFwiLi9CYXNlTW9kZWxcIlxuaW1wb3J0IHsgbW9kZWxUeXBlS2V5IH0gZnJvbSBcIi4vbWV0YWRhdGFcIlxuXG4vKipcbiAqIENoZWNrcyBpZiBhbiBvYmplY3QgaXMgYSBtb2RlbCBpbnN0YW5jZS5cbiAqXG4gKiBAcGFyYW0gbW9kZWxcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc01vZGVsKG1vZGVsOiB1bmtub3duKTogbW9kZWwgaXMgQW55TW9kZWwge1xuICByZXR1cm4gbW9kZWwgaW5zdGFuY2VvZiBCYXNlTW9kZWxcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqXG4gKiBBc3NlcnRzIHNvbWV0aGluZyBpcyBhY3R1YWxseSBhIG1vZGVsLlxuICpcbiAqIEBwYXJhbSBtb2RlbFxuICogQHBhcmFtIGFyZ05hbWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydElzTW9kZWwoXG4gIG1vZGVsOiB1bmtub3duLFxuICBhcmdOYW1lOiBzdHJpbmcsXG4gIGN1c3RvbUVyck1zZyA9IFwibXVzdCBiZSBhIG1vZGVsIGluc3RhbmNlXCJcbik6IGFzc2VydHMgbW9kZWwgaXMgQW55TW9kZWwge1xuICBpZiAoIWlzTW9kZWwobW9kZWwpKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgJHthcmdOYW1lfSAke2N1c3RvbUVyck1zZ31gKVxuICB9XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc01vZGVsQ2xhc3MobW9kZWxDbGFzczogdW5rbm93bik6IG1vZGVsQ2xhc3MgaXMgTW9kZWxDbGFzczxBbnlNb2RlbD4ge1xuICBpZiAodHlwZW9mIG1vZGVsQ2xhc3MgIT09IFwiZnVuY3Rpb25cIikge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgaWYgKG1vZGVsQ2xhc3MgIT09IEJhc2VNb2RlbCAmJiAhKG1vZGVsQ2xhc3MucHJvdG90eXBlIGluc3RhbmNlb2YgQmFzZU1vZGVsKSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgcmV0dXJuIHRydWVcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydElzTW9kZWxDbGFzcyhcbiAgbW9kZWxDbGFzczogdW5rbm93bixcbiAgYXJnTmFtZTogc3RyaW5nXG4pOiBhc3NlcnRzIG1vZGVsQ2xhc3MgaXMgTW9kZWxDbGFzczxBbnlNb2RlbD4ge1xuICBpZiAodHlwZW9mIG1vZGVsQ2xhc3MgIT09IFwiZnVuY3Rpb25cIikge1xuICAgIHRocm93IGZhaWx1cmUoYCR7YXJnTmFtZX0gbXVzdCBiZSBhIGNsYXNzYClcbiAgfVxuXG4gIGlmIChtb2RlbENsYXNzICE9PSBCYXNlTW9kZWwgJiYgIShtb2RlbENsYXNzLnByb3RvdHlwZSBpbnN0YW5jZW9mIEJhc2VNb2RlbCkpIHtcbiAgICB0aHJvdyBmYWlsdXJlKGAke2FyZ05hbWV9IG11c3QgZXh0ZW5kIE1vZGVsYClcbiAgfVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNNb2RlbFNuYXBzaG90KHNuOiB1bmtub3duKTogc24gaXMgeyBbbW9kZWxUeXBlS2V5XTogc3RyaW5nIH0ge1xuICByZXR1cm4gaXNQbGFpbk9iamVjdChzbikgJiYgbW9kZWxUeXBlS2V5IGluIHNuXG59XG4iLCJpbXBvcnQgeyBtb2RlbElkS2V5IH0gZnJvbSBcIi4uL21vZGVsL21ldGFkYXRhXCJcclxuaW1wb3J0IHsgaXNNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXHJcbmltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcclxuaW1wb3J0IHsgaXNBcnJheSwgaXNPYmplY3QgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQge1xyXG4gIGRhdGFPYmplY3RQYXJlbnQsXHJcbiAgZGF0YVRvTW9kZWxOb2RlLFxyXG4gIG1vZGVsVG9EYXRhTm9kZSxcclxuICBvYmplY3RQYXJlbnRzLFxyXG4gIHJlcG9ydFBhcmVudFBhdGhPYnNlcnZlZCxcclxufSBmcm9tIFwiLi9jb3JlXCJcclxuaW1wb3J0IHR5cGUgeyBQYXRoLCBQYXRoRWxlbWVudCwgV3JpdGFibGVQYXRoIH0gZnJvbSBcIi4vcGF0aFR5cGVzXCJcclxuXHJcbi8qKlxyXG4gKiBQYXRoIGZyb20gYW4gb2JqZWN0IHRvIGl0cyBpbW1lZGlhdGUgcGFyZW50LlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgUGFyZW50IG9iamVjdCB0eXBlLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBQYXJlbnRQYXRoPFQgZXh0ZW5kcyBvYmplY3Q+IHtcclxuICAvKipcclxuICAgKiBQYXJlbnQgb2JqZWN0LlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IHBhcmVudDogVFxyXG4gIC8qKlxyXG4gICAqIFByb3BlcnR5IG5hbWUgKGlmIHRoZSBwYXJlbnQgaXMgYW4gb2JqZWN0KSBvciBpbmRleCBudW1iZXIgKGlmIHRoZSBwYXJlbnQgaXMgYW4gYXJyYXkpLlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IHBhdGg6IFBhdGhFbGVtZW50XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBQYXRoIGZyb20gYW4gb2JqZWN0IHRvIGl0cyByb290LlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgUm9vdCBvYmplY3QgdHlwZS5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgUm9vdFBhdGg8VCBleHRlbmRzIG9iamVjdD4ge1xyXG4gIC8qKlxyXG4gICAqIFJvb3Qgb2JqZWN0LlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IHJvb3Q6IFRcclxuICAvKipcclxuICAgKiBQYXRoIGZyb20gdGhlIHJvb3QgdG8gdGhlIGdpdmVuIHRhcmdldCwgYXMgYSBzdHJpbmcgYXJyYXkuXHJcbiAgICogSWYgdGhlIHRhcmdldCBpcyBhIHJvb3QgaXRzZWxmIHRoZW4gdGhlIGFycmF5IHdpbGwgYmUgZW1wdHkuXHJcbiAgICovXHJcbiAgcmVhZG9ubHkgcGF0aDogUGF0aFxyXG5cclxuICAvKipcclxuICAgKiBPYmplY3RzIGluIHRoZSBwYXRoLCBmcm9tIHJvb3QgKGluY2x1ZGVkKSB1bnRpbCB0YXJnZXQgKGluY2x1ZGVkKS5cclxuICAgKiBJZiB0aGUgdGFyZ2V0IGlzIGEgcm9vdCB0aGVuIG9ubHkgdGhlIHRhcmdldCB3aWxsIGJlIGluY2x1ZGVkLlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IHBhdGhPYmplY3RzOiBSZWFkb25seUFycmF5PHVua25vd24+XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBwYXJlbnQgb2YgdGhlIHRhcmdldCBwbHVzIHRoZSBwYXRoIGZyb20gdGhlIHBhcmVudCB0byB0aGUgdGFyZ2V0LCBvciB1bmRlZmluZWQgaWYgaXQgaGFzIG5vIHBhcmVudC5cclxuICpcclxuICogQHR5cGVwYXJhbSBUIFBhcmVudCBvYmplY3QgdHlwZS5cclxuICogQHBhcmFtIHZhbHVlIFRhcmdldCBvYmplY3QuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2V0UGFyZW50UGF0aDxUIGV4dGVuZHMgb2JqZWN0ID0gYW55Pih2YWx1ZTogb2JqZWN0KTogUGFyZW50UGF0aDxUPiB8IHVuZGVmaW5lZCB7XHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdCh2YWx1ZSwgXCJ2YWx1ZVwiKVxyXG5cclxuICByZXR1cm4gZmFzdEdldFBhcmVudFBhdGgodmFsdWUpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmYXN0R2V0UGFyZW50UGF0aDxUIGV4dGVuZHMgb2JqZWN0ID0gYW55PihcclxuICB2YWx1ZTogb2JqZWN0XHJcbik6IFBhcmVudFBhdGg8VD4gfCB1bmRlZmluZWQge1xyXG4gIHJlcG9ydFBhcmVudFBhdGhPYnNlcnZlZCh2YWx1ZSlcclxuICByZXR1cm4gb2JqZWN0UGFyZW50cy5nZXQodmFsdWUpIGFzIFBhcmVudFBhdGg8VD4gfCB1bmRlZmluZWRcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZhc3RHZXRQYXJlbnRQYXRoSW5jbHVkaW5nRGF0YU9iamVjdHM8VCBleHRlbmRzIG9iamVjdCA9IGFueT4oXHJcbiAgdmFsdWU6IG9iamVjdFxyXG4pOiBQYXJlbnRQYXRoPFQ+IHwgdW5kZWZpbmVkIHtcclxuICBjb25zdCBwYXJlbnRNb2RlbCA9IGRhdGFPYmplY3RQYXJlbnQuZ2V0KHZhbHVlKVxyXG4gIGlmIChwYXJlbnRNb2RlbCkge1xyXG4gICAgcmV0dXJuIHsgcGFyZW50OiBwYXJlbnRNb2RlbCBhcyBULCBwYXRoOiBcIiRcIiB9XHJcbiAgfVxyXG5cclxuICBjb25zdCBwYXJlbnRQYXRoID0gZmFzdEdldFBhcmVudFBhdGgodmFsdWUpXHJcbiAgaWYgKHBhcmVudFBhdGggJiYgaXNNb2RlbChwYXJlbnRQYXRoLnBhcmVudCkpIHtcclxuICAgIHJldHVybiB7IHBhcmVudDogcGFyZW50UGF0aC5wYXJlbnQuJCBhcyBULCBwYXRoOiBwYXJlbnRQYXRoLnBhdGggfVxyXG4gIH1cclxuICByZXR1cm4gcGFyZW50UGF0aFxyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgcGFyZW50IG9iamVjdCBvZiB0aGUgdGFyZ2V0IG9iamVjdCwgb3IgdW5kZWZpbmVkIGlmIHRoZXJlJ3Mgbm8gcGFyZW50LlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgUGFyZW50IG9iamVjdCB0eXBlLlxyXG4gKiBAcGFyYW0gdmFsdWUgVGFyZ2V0IG9iamVjdC5cclxuICogQHJldHVybnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXJlbnQ8VCBleHRlbmRzIG9iamVjdCA9IGFueT4odmFsdWU6IG9iamVjdCk6IFQgfCB1bmRlZmluZWQge1xyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3QodmFsdWUsIFwidmFsdWVcIilcclxuXHJcbiAgcmV0dXJuIGZhc3RHZXRQYXJlbnQodmFsdWUpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmYXN0R2V0UGFyZW50PFQgZXh0ZW5kcyBvYmplY3QgPSBhbnk+KHZhbHVlOiBvYmplY3QpOiBUIHwgdW5kZWZpbmVkIHtcclxuICByZXR1cm4gZmFzdEdldFBhcmVudFBhdGgodmFsdWUpPy5wYXJlbnRcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZhc3RHZXRQYXJlbnRJbmNsdWRpbmdEYXRhT2JqZWN0czxUIGV4dGVuZHMgb2JqZWN0ID0gYW55PihcclxuICB2YWx1ZTogb2JqZWN0XHJcbik6IFQgfCB1bmRlZmluZWQge1xyXG4gIHJldHVybiBmYXN0R2V0UGFyZW50UGF0aEluY2x1ZGluZ0RhdGFPYmplY3RzKHZhbHVlKT8ucGFyZW50XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGlmIGEgZ2l2ZW4gb2JqZWN0IGlzIGEgbW9kZWwgaW50ZXJpbSBkYXRhIG9iamVjdCAoYCRgKS5cclxuICpcclxuICogQHBhcmFtIHZhbHVlIE9iamVjdCB0byBjaGVjay5cclxuICogQHJldHVybnMgdHJ1ZSBpZiBpdCBpcywgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzTW9kZWxEYXRhT2JqZWN0KHZhbHVlOiBvYmplY3QpOiBib29sZWFuIHtcclxuICBhc3NlcnRUd2Vha2VkT2JqZWN0KHZhbHVlLCBcInZhbHVlXCIsIHRydWUpXHJcblxyXG4gIHJldHVybiBmYXN0SXNNb2RlbERhdGFPYmplY3QodmFsdWUpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmYXN0SXNNb2RlbERhdGFPYmplY3QodmFsdWU6IG9iamVjdCk6IGJvb2xlYW4ge1xyXG4gIHJldHVybiBkYXRhT2JqZWN0UGFyZW50Lmhhcyh2YWx1ZSlcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHJvb3Qgb2YgdGhlIHRhcmdldCBwbHVzIHRoZSBwYXRoIGZyb20gdGhlIHJvb3QgdG8gZ2V0IHRvIHRoZSB0YXJnZXQuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVCBSb290IG9iamVjdCB0eXBlLlxyXG4gKiBAcGFyYW0gdmFsdWUgVGFyZ2V0IG9iamVjdC5cclxuICogQHJldHVybnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRSb290UGF0aDxUIGV4dGVuZHMgb2JqZWN0ID0gYW55Pih2YWx1ZTogb2JqZWN0KTogUm9vdFBhdGg8VD4ge1xyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3QodmFsdWUsIFwidmFsdWVcIilcclxuXHJcbiAgcmV0dXJuIGZhc3RHZXRSb290UGF0aCh2YWx1ZSlcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZhc3RHZXRSb290UGF0aDxUIGV4dGVuZHMgb2JqZWN0ID0gYW55Pih2YWx1ZTogb2JqZWN0KTogUm9vdFBhdGg8VD4ge1xyXG4gIGxldCByb290ID0gdmFsdWVcclxuICBsZXQgcGF0aCA9IFtdIGFzIFdyaXRhYmxlUGF0aFxyXG4gIGxldCBwYXRoT2JqZWN0cyA9IFt2YWx1ZV0gYXMgdW5rbm93bltdXHJcblxyXG4gIGxldCBwYXJlbnRQYXRoOiBQYXJlbnRQYXRoPGFueT4gfCB1bmRlZmluZWRcclxuICB3aGlsZSAoKHBhcmVudFBhdGggPSBmYXN0R2V0UGFyZW50UGF0aChyb290KSkpIHtcclxuICAgIHJvb3QgPSBwYXJlbnRQYXRoLnBhcmVudFxyXG4gICAgcGF0aC51bnNoaWZ0KHBhcmVudFBhdGgucGF0aClcclxuICAgIHBhdGhPYmplY3RzLnVuc2hpZnQocGFyZW50UGF0aC5wYXJlbnQpXHJcbiAgfVxyXG5cclxuICByZXR1cm4geyByb290LCBwYXRoLCBwYXRoT2JqZWN0cyB9IGFzIFJvb3RQYXRoPGFueT5cclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHJvb3Qgb2YgdGhlIHRhcmdldCBvYmplY3QsIG9yIGl0c2VsZiBpZiB0aGUgdGFyZ2V0IGlzIGEgcm9vdC5cclxuICpcclxuICogQHR5cGVwYXJhbSBUIFJvb3Qgb2JqZWN0IHR5cGUuXHJcbiAqIEBwYXJhbSB2YWx1ZSBUYXJnZXQgb2JqZWN0LlxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdldFJvb3Q8VCBleHRlbmRzIG9iamVjdCA9IGFueT4odmFsdWU6IG9iamVjdCk6IFQge1xyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3QodmFsdWUsIFwidmFsdWVcIilcclxuXHJcbiAgcmV0dXJuIGZhc3RHZXRSb290KHZhbHVlKVxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZmFzdEdldFJvb3Q8VCBleHRlbmRzIG9iamVjdCA9IGFueT4odmFsdWU6IG9iamVjdCk6IFQge1xyXG4gIGxldCByb290ID0gdmFsdWVcclxuXHJcbiAgbGV0IHBhcmVudFBhdGg6IFBhcmVudFBhdGg8YW55PiB8IHVuZGVmaW5lZFxyXG4gIHdoaWxlICgocGFyZW50UGF0aCA9IGZhc3RHZXRQYXJlbnRQYXRoKHJvb3QpKSkge1xyXG4gICAgcm9vdCA9IHBhcmVudFBhdGgucGFyZW50XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcm9vdCBhcyBUXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGlmIGEgZ2l2ZW4gb2JqZWN0IGlzIGEgcm9vdCBvYmplY3QuXHJcbiAqXHJcbiAqIEBwYXJhbSB2YWx1ZSBUYXJnZXQgb2JqZWN0LlxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzUm9vdCh2YWx1ZTogb2JqZWN0KTogYm9vbGVhbiB7XHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdCh2YWx1ZSwgXCJ2YWx1ZVwiKVxyXG5cclxuICByZXR1cm4gIWZhc3RHZXRQYXJlbnQodmFsdWUpXHJcbn1cclxuXHJcbmNvbnN0IHVucmVzb2x2ZWQgPSB7IHJlc29sdmVkOiBmYWxzZSB9IGFzIGNvbnN0XHJcblxyXG4vKipcclxuICogVHJpZXMgdG8gcmVzb2x2ZSBhIHBhdGggZnJvbSBhbiBvYmplY3QuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVCBSZXR1cm5lZCB2YWx1ZSB0eXBlLlxyXG4gKiBAcGFyYW0gcGF0aFJvb3RPYmplY3QgT2JqZWN0IHRoYXQgc2VydmVzIGFzIHBhdGggcm9vdC5cclxuICogQHBhcmFtIHBhdGggUGF0aCBhcyBhbiBzdHJpbmcgb3IgbnVtYmVyIGFycmF5LlxyXG4gKiBAcmV0dXJucyBBbiBvYmplY3Qgd2l0aCBgeyByZXNvbHZlZDogdHJ1ZSwgdmFsdWU6IFQgfWAgb3IgYHsgcmVzb2x2ZWQ6IGZhbHNlIH1gLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVQYXRoPFQgPSBhbnk+KFxyXG4gIHBhdGhSb290T2JqZWN0OiBvYmplY3QsXHJcbiAgcGF0aDogUGF0aFxyXG4pOlxyXG4gIHwge1xyXG4gICAgICByZXNvbHZlZDogdHJ1ZVxyXG4gICAgICB2YWx1ZTogVFxyXG4gICAgfVxyXG4gIHwge1xyXG4gICAgICByZXNvbHZlZDogZmFsc2VcclxuICAgICAgdmFsdWU/OiB1bmRlZmluZWRcclxuICAgIH0ge1xyXG4gIC8vIHVuaXQgdGVzdHMgcmVseSBvbiB0aGlzIHRvIHdvcmsgd2l0aCBhbnkgb2JqZWN0XHJcbiAgLy8gYXNzZXJ0VHdlYWtlZE9iamVjdChwYXRoUm9vdE9iamVjdCwgXCJwYXRoUm9vdE9iamVjdFwiKVxyXG5cclxuICBsZXQgY3VycmVudDogYW55ID0gcGF0aFJvb3RPYmplY3RcclxuXHJcbiAgbGV0IGxlbiA9IHBhdGgubGVuZ3RoXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gICAgaWYgKCFpc09iamVjdChjdXJyZW50KSkge1xyXG4gICAgICByZXR1cm4gdW5yZXNvbHZlZFxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHAgPSBwYXRoW2ldXHJcblxyXG4gICAgLy8gY2hlY2sganVzdCB0byBhdm9pZCBtb2J4IHdhcm5pbmdzIGFib3V0IHRyeWluZyB0byBhY2Nlc3Mgb3V0IG9mIGJvdW5kcyBpbmRleFxyXG4gICAgaWYgKGlzQXJyYXkoY3VycmVudCkgJiYgK3AgPj0gY3VycmVudC5sZW5ndGgpIHtcclxuICAgICAgcmV0dXJuIHVucmVzb2x2ZWRcclxuICAgIH1cclxuXHJcbiAgICBpZiAoaXNNb2RlbChjdXJyZW50KSkge1xyXG4gICAgICBjb25zdCBkYXRhTm9kZSA9IG1vZGVsVG9EYXRhTm9kZShjdXJyZW50KVxyXG4gICAgICBpZiAocCBpbiBkYXRhTm9kZSkge1xyXG4gICAgICAgIGN1cnJlbnQgPSBkYXRhTm9kZVxyXG4gICAgICB9IGVsc2UgaWYgKCEocCBpbiBjdXJyZW50KSkge1xyXG4gICAgICAgIHJldHVybiB1bnJlc29sdmVkXHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjdXJyZW50ID0gY3VycmVudFtwXVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHsgcmVzb2x2ZWQ6IHRydWUsIHZhbHVlOiBjdXJyZW50IH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHNraXBJZENoZWNraW5nID0gU3ltYm9sKFwic2tpcElkQ2hlY2tpbmdcIilcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICpcclxuICogVHJpZXMgdG8gcmVzb2x2ZSBhIHBhdGggZnJvbSBhbiBvYmplY3Qgd2hpbGUgY2hlY2tpbmcgaWRzLlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgUmV0dXJuZWQgdmFsdWUgdHlwZS5cclxuICogQHBhcmFtIHBhdGhSb290T2JqZWN0IE9iamVjdCB0aGF0IHNlcnZlcyBhcyBwYXRoIHJvb3QuXHJcbiAqIEBwYXJhbSBwYXRoIFBhdGggYXMgYW4gc3RyaW5nIG9yIG51bWJlciBhcnJheS5cclxuICogQHBhcmFtIHBhdGhJZHMgQW4gYXJyYXkgb2YgaWRzIG9mIHRoZSBtb2RlbHMgdGhhdCBtdXN0IGJlIGNoZWNrZWQsIG51bGwgaWYgbm90IGEgbW9kZWwgb3IgYHNraXBJZENoZWNraW5nYCB0byBza2lwIGl0LlxyXG4gKiBAcmV0dXJucyBBbiBvYmplY3Qgd2l0aCBgeyByZXNvbHZlZDogdHJ1ZSwgdmFsdWU6IFQgfWAgb3IgYHsgcmVzb2x2ZWQ6IGZhbHNlIH1gLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVQYXRoQ2hlY2tpbmdJZHM8VCA9IGFueT4oXHJcbiAgcGF0aFJvb3RPYmplY3Q6IG9iamVjdCxcclxuICBwYXRoOiBQYXRoLFxyXG4gIHBhdGhJZHM6IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVsbCB8IHR5cGVvZiBza2lwSWRDaGVja2luZz5cclxuKTpcclxuICB8IHtcclxuICAgICAgcmVzb2x2ZWQ6IHRydWVcclxuICAgICAgdmFsdWU6IFRcclxuICAgIH1cclxuICB8IHtcclxuICAgICAgcmVzb2x2ZWQ6IGZhbHNlXHJcbiAgICAgIHZhbHVlPzogdW5kZWZpbmVkXHJcbiAgICB9IHtcclxuICAvLyB1bml0IHRlc3RzIHJlbHkgb24gdGhpcyB0byB3b3JrIHdpdGggYW55IG9iamVjdFxyXG4gIC8vIGFzc2VydFR3ZWFrZWRPYmplY3QocGF0aFJvb3RPYmplY3QsIFwicGF0aFJvb3RPYmplY3RcIilcclxuXHJcbiAgbGV0IGN1cnJlbnQ6IGFueSA9IG1vZGVsVG9EYXRhTm9kZShwYXRoUm9vdE9iamVjdClcclxuICAvLyByb290IGlkIGlzIG5ldmVyIGNoZWNrZWRcclxuXHJcbiAgbGV0IGxlbiA9IHBhdGgubGVuZ3RoXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gICAgaWYgKCFpc09iamVjdChjdXJyZW50KSkge1xyXG4gICAgICByZXR1cm4geyByZXNvbHZlZDogZmFsc2UgfVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHAgPSBwYXRoW2ldXHJcblxyXG4gICAgLy8gY2hlY2sganVzdCB0byBhdm9pZCBtb2J4IHdhcm5pbmdzIGFib3V0IHRyeWluZyB0byBhY2Nlc3Mgb3V0IG9mIGJvdW5kcyBpbmRleFxyXG4gICAgaWYgKGlzQXJyYXkoY3VycmVudCkgJiYgK3AgPj0gY3VycmVudC5sZW5ndGgpIHtcclxuICAgICAgcmV0dXJuIHsgcmVzb2x2ZWQ6IGZhbHNlIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjdXJyZW50TWF5YmVNb2RlbCA9IGN1cnJlbnRbcF1cclxuICAgIGN1cnJlbnQgPSBtb2RlbFRvRGF0YU5vZGUoY3VycmVudE1heWJlTW9kZWwgYXMgb2JqZWN0KVxyXG5cclxuICAgIGNvbnN0IGV4cGVjdGVkSWQgPSBwYXRoSWRzW2ldXHJcbiAgICBpZiAoZXhwZWN0ZWRJZCAhPT0gc2tpcElkQ2hlY2tpbmcpIHtcclxuICAgICAgY29uc3QgY3VycmVudElkID0gaXNNb2RlbChjdXJyZW50TWF5YmVNb2RlbCkgPyBjdXJyZW50TWF5YmVNb2RlbFttb2RlbElkS2V5XSA/PyBudWxsIDogbnVsbFxyXG4gICAgICBpZiAoZXhwZWN0ZWRJZCAhPT0gY3VycmVudElkKSB7XHJcbiAgICAgICAgcmV0dXJuIHsgcmVzb2x2ZWQ6IGZhbHNlIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHsgcmVzb2x2ZWQ6IHRydWUsIHZhbHVlOiBkYXRhVG9Nb2RlbE5vZGUoY3VycmVudCkgfVxyXG59XHJcblxyXG4vKipcclxuICogR2V0cyB0aGUgcGF0aCB0byBnZXQgZnJvbSBhIHBhcmVudCB0byBhIGdpdmVuIGNoaWxkLlxyXG4gKiBSZXR1cm5zIGFuIGVtcHR5IGFycmF5IGlmIHRoZSBjaGlsZCBpcyBhY3R1YWxseSB0aGUgZ2l2ZW4gcGFyZW50IG9yIHVuZGVmaW5lZCBpZiB0aGUgY2hpbGQgaXMgbm90IGEgY2hpbGQgb2YgdGhlIHBhcmVudC5cclxuICpcclxuICogQHBhcmFtIGZyb21QYXJlbnRcclxuICogQHBhcmFtIHRvQ2hpbGRcclxuICogQHJldHVybnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXJlbnRUb0NoaWxkUGF0aChmcm9tUGFyZW50OiBvYmplY3QsIHRvQ2hpbGQ6IG9iamVjdCk6IFBhdGggfCB1bmRlZmluZWQge1xyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3QoZnJvbVBhcmVudCwgXCJmcm9tUGFyZW50XCIpXHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdCh0b0NoaWxkLCBcInRvQ2hpbGRcIilcclxuXHJcbiAgaWYgKGZyb21QYXJlbnQgPT09IHRvQ2hpbGQpIHtcclxuICAgIHJldHVybiBbXVxyXG4gIH1cclxuXHJcbiAgY29uc3QgcGF0aDogV3JpdGFibGVQYXRoID0gW11cclxuXHJcbiAgbGV0IGN1cnJlbnQgPSB0b0NoaWxkXHJcbiAgbGV0IHBhcmVudFBhdGhcclxuICB3aGlsZSAoKHBhcmVudFBhdGggPSBmYXN0R2V0UGFyZW50UGF0aChjdXJyZW50KSkpIHtcclxuICAgIHBhdGgudW5zaGlmdChwYXJlbnRQYXRoLnBhdGgpXHJcblxyXG4gICAgY3VycmVudCA9IHBhcmVudFBhdGgucGFyZW50XHJcbiAgICBpZiAoY3VycmVudCA9PT0gZnJvbVBhcmVudCkge1xyXG4gICAgICByZXR1cm4gcGF0aFxyXG4gICAgfVxyXG4gIH1cclxuICByZXR1cm4gdW5kZWZpbmVkXHJcbn1cclxuIiwiaW1wb3J0IHsgZmFzdEdldFBhcmVudCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFwiXHJcbmltcG9ydCB7IGlzQ2hpbGRPZlBhcmVudCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aDJcIlxyXG5pbXBvcnQgeyBhc3NlcnRUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXHJcbmltcG9ydCB7IGFzc2VydElzRnVuY3Rpb24sIGFzc2VydElzT2JqZWN0LCBkZWxldGVGcm9tQXJyYXksIGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IEFjdGlvbkNvbnRleHQgfSBmcm9tIFwiLi9jb250ZXh0XCJcclxuXHJcbi8qKlxyXG4gKiBBbiBhY3Rpb24gbWlkZGxld2FyZS5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uTWlkZGxld2FyZSB7XHJcbiAgLyoqXHJcbiAgICogU3VidHJlZSByb290IG9iamVjdCAob2JqZWN0IGFuZCBjaGlsZCBvYmplY3RzKSB0aGlzIG1pZGRsZXdhcmUgd2lsbCBydW4gZm9yLlxyXG4gICAqIFRoaXMgdGFyZ2V0IFwiZmlsdGVyXCIgd2lsbCBiZSBydW4gYmVmb3JlIHRoZSBjdXN0b20gZmlsdGVyLlxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IHN1YnRyZWVSb290OiBvYmplY3RcclxuXHJcbiAgLyoqXHJcbiAgICogQSBmaWx0ZXIgZnVuY3Rpb24gdG8gZGVjaWRlIGlmIGFuIGFjdGlvbiBtaWRkbGV3YXJlIGZ1bmN0aW9uIHNob3VsZCBiZSBydW4gb3Igbm90LlxyXG4gICAqL1xyXG4gIGZpbHRlcj8oY3R4OiBBY3Rpb25Db250ZXh0KTogYm9vbGVhblxyXG5cclxuICAvKipcclxuICAgKiBBbiBhY3Rpb24gbWlkZGxld2FyZSBmdW5jdGlvbi5cclxuICAgKiBSZW1iZXIgdG8gYHJldHVybiBuZXh0KClgIGlmIHlvdSB3YW50IHRvIGNvbnRpbnVlIHRoZSBhY3Rpb24gb3IgdGhyb3cgaWYgeW91IHdhbnQgdG8gY2FuY2VsIGl0LlxyXG4gICAqL1xyXG4gIG1pZGRsZXdhcmUoY3R4OiBBY3Rpb25Db250ZXh0LCBuZXh0OiAoKSA9PiBhbnkpOiBhbnlcclxufVxyXG5cclxuLyoqXHJcbiAqIFRoZSBkaXNwb3NlciBvZiBhbiBhY3Rpb24gbWlkZGxld2FyZS5cclxuICovXHJcbmV4cG9ydCB0eXBlIEFjdGlvbk1pZGRsZXdhcmVEaXNwb3NlciA9ICgpID0+IHZvaWRcclxuXHJcbnR5cGUgUGFydGlhbEFjdGlvbk1pZGRsZXdhcmUgPSBQaWNrPEFjdGlvbk1pZGRsZXdhcmUsIFwiZmlsdGVyXCIgfCBcIm1pZGRsZXdhcmVcIj5cclxuXHJcbmNvbnN0IHBlck9iamVjdEFjdGlvbk1pZGRsZXdhcmVzID0gbmV3IFdlYWtNYXA8b2JqZWN0LCBQYXJ0aWFsQWN0aW9uTWlkZGxld2FyZVtdPigpXHJcblxyXG5pbnRlcmZhY2UgQWN0aW9uTWlkZGxld2FyZXNJdGVyYXRvciBleHRlbmRzIEl0ZXJhYmxlPFBhcnRpYWxBY3Rpb25NaWRkbGV3YXJlPiB7fVxyXG5cclxuY29uc3QgcGVyT2JqZWN0QWN0aW9uTWlkZGxld2FyZXNJdGVyYXRvciA9IG5ldyBXZWFrTWFwPG9iamVjdCwgQWN0aW9uTWlkZGxld2FyZXNJdGVyYXRvcj4oKVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKlxyXG4gKiBHZXRzIHRoZSBjdXJyZW50IGFjdGlvbiBtaWRkbGV3YXJlcyB0byBiZSBydW4gb3ZlciBhIGdpdmVuIG9iamVjdCBhcyBhbiBpdGVyYWJsZSBvYmplY3QuXHJcbiAqXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aW9uTWlkZGxld2FyZXMob2JqOiBvYmplY3QpOiBBY3Rpb25NaWRkbGV3YXJlc0l0ZXJhdG9yIHtcclxuICAvLyB3aGVuIHdlIGNhbGwgYSBtaWRkbGV3YXJlIHdlIHdpbGwgY2FsbCB0aGUgbWlkZGxld2FyZXMgb2YgdGhhdCBvYmplY3QgcGx1cyBhbGwgcGFyZW50IG9iamVjdHNcclxuICAvLyB0aGUgcGFyZW50IG9iamVjdCBtaWRkbGV3YXJlcyBhcmUgcnVuIGxhc3RcclxuXHJcbiAgLy8gc2luY2UgYW4gYXJyYXkgbGlrZSBbYSwgYiwgY10gd2lsbCBiZSBjYWxsZWQgbGlrZSBjKGIoYSgpKSkgdGhpcyBtZWFucyB0aGF0IHdlIG5lZWQgdG8gcHV0XHJcbiAgLy8gdGhlIHBhcmVudCBvYmplY3Qgb25lcyBhdCB0aGUgZW5kIG9mIHRoZSBhcnJheVxyXG5cclxuICBsZXQgaXRlcmFibGUgPSBwZXJPYmplY3RBY3Rpb25NaWRkbGV3YXJlc0l0ZXJhdG9yLmdldChvYmopXHJcbiAgaWYgKCFpdGVyYWJsZSkge1xyXG4gICAgaXRlcmFibGUgPSB7XHJcbiAgICAgIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xyXG4gICAgICAgIGxldCBjdXJyZW50OiBhbnkgPSBvYmpcclxuXHJcbiAgICAgICAgZnVuY3Rpb24gZ2V0Q3VycmVudEl0ZXJhdG9yKCkge1xyXG4gICAgICAgICAgY29uc3Qgb2JqTXdhcmVzID0gY3VycmVudCA/IHBlck9iamVjdEFjdGlvbk1pZGRsZXdhcmVzLmdldChjdXJyZW50KSA6IHVuZGVmaW5lZFxyXG4gICAgICAgICAgaWYgKCFvYmpNd2FyZXMgfHwgb2JqTXdhcmVzLmxlbmd0aCA8PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWRcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHJldHVybiBvYmpNd2FyZXNbU3ltYm9sLml0ZXJhdG9yXSgpXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmdW5jdGlvbiBmaW5kTmV4dEl0ZXJhdG9yKCkge1xyXG4gICAgICAgICAgbGV0IG5leHRJdGVyXHJcbiAgICAgICAgICB3aGlsZSAoY3VycmVudCAmJiAhbmV4dEl0ZXIpIHtcclxuICAgICAgICAgICAgY3VycmVudCA9IGZhc3RHZXRQYXJlbnQoY3VycmVudClcclxuICAgICAgICAgICAgbmV4dEl0ZXIgPSBnZXRDdXJyZW50SXRlcmF0b3IoKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgcmV0dXJuIG5leHRJdGVyXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgaXRlciA9IGdldEN1cnJlbnRJdGVyYXRvcigpXHJcbiAgICAgICAgaWYgKCFpdGVyKSB7XHJcbiAgICAgICAgICBpdGVyID0gZmluZE5leHRJdGVyYXRvcigpXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBpdGVyYXRvcjogSXRlcmF0b3I8UGFydGlhbEFjdGlvbk1pZGRsZXdhcmU+ID0ge1xyXG4gICAgICAgICAgbmV4dCgpIHtcclxuICAgICAgICAgICAgaWYgKCFpdGVyKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IHVuZGVmaW5lZCwgZG9uZTogdHJ1ZSB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCByZXN1bHQgPSBpdGVyLm5leHQoKVxyXG4gICAgICAgICAgICBpZiAoIXJlc3VsdC5kb25lKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpdGVyID0gZmluZE5leHRJdGVyYXRvcigpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm5leHQoKVxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBpdGVyYXRvclxyXG4gICAgICB9LFxyXG4gICAgfVxyXG4gICAgcGVyT2JqZWN0QWN0aW9uTWlkZGxld2FyZXNJdGVyYXRvci5zZXQob2JqLCBpdGVyYWJsZSlcclxuICB9XHJcbiAgcmV0dXJuIGl0ZXJhYmxlXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBZGRzIGEgZ2xvYmFsIGFjdGlvbiBtaWRkbGV3YXJlIHRvIGJlIHJ1biB3aGVuIGFuIGFjdGlvbiBpcyBwZXJmb3JtZWQuXHJcbiAqIEl0IGlzIHVzdWFsbHkgcHJlZmVyYWJsZSB0byB1c2UgYG9uQWN0aW9uTWlkZGxld2FyZWAgaW5zdGVhZCB0byBsaW1pdCBpdCB0byBhIGdpdmVuIHRyZWUgYW5kIG9ubHkgdG8gdG9wbW9zdCBsZXZlbCBhY3Rpb25zXHJcbiAqIG9yIGBhY3Rpb25UcmFja2luZ01pZGRsZXdhcmVgIGZvciBhIHNpbXBsaWZpZWQgbWlkZGxld2FyZS5cclxuICpcclxuICogQHBhcmFtIG13YXJlIEFjdGlvbiBtaWRkbGV3YXJlIHRvIGJlIHJ1bi5cclxuICogQHJldHVybnMgQSBkaXNwb3NlciB0byBjYW5jZWwgdGhlIG1pZGRsZXdhcmUuIE5vdGUgdGhhdCBpZiB5b3UgZG9uJ3QgcGxhbiB0byBkbyBhbiBlYXJseSBkaXNwb3NhbCBvZiB0aGUgbWlkZGxld2FyZVxyXG4gKiBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gYmVjb21lcyBvcHRpb25hbC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhZGRBY3Rpb25NaWRkbGV3YXJlKG13YXJlOiBBY3Rpb25NaWRkbGV3YXJlKTogQWN0aW9uTWlkZGxld2FyZURpc3Bvc2VyIHtcclxuICBhc3NlcnRJc09iamVjdChtd2FyZSwgXCJtaWRkbGV3YXJlXCIpXHJcblxyXG4gIGxldCB7IG1pZGRsZXdhcmUsIGZpbHRlciwgc3VidHJlZVJvb3QgfSA9IG13YXJlXHJcblxyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qoc3VidHJlZVJvb3QsIFwibWlkZGxld2FyZS5zdWJ0cmVlUm9vdFwiKVxyXG4gIGFzc2VydElzRnVuY3Rpb24obWlkZGxld2FyZSwgXCJtaWRkbGV3YXJlLm1pZGRsZXdhcmVcIilcclxuICBpZiAoZmlsdGVyICYmIHR5cGVvZiBmaWx0ZXIgIT09IFwiZnVuY3Rpb25cIikge1xyXG4gICAgdGhyb3cgZmFpbHVyZShcIm1pZGRsZXdhcmUuZmlsdGVyIG11c3QgYmUgYSBmdW5jdGlvbiBvciB1bmRlZmluZWRcIilcclxuICB9XHJcblxyXG4gIC8vIHJlbWluZGVyOiBuZXZlciB0dXJuIG1pZGRsZXdhcmVzIGludG8gYWN0aW9ucyBvciBlbHNlXHJcbiAgLy8gcmVhY3Rpb25zIHdpbGwgbm90IGJlIHBpY2tlZCB1cCBieSB0aGUgdW5kbyBtYW5hZ2VyXHJcblxyXG4gIGlmIChzdWJ0cmVlUm9vdCkge1xyXG4gICAgY29uc3QgdGFyZ2V0RmlsdGVyID0gKGN0eDogQWN0aW9uQ29udGV4dCkgPT5cclxuICAgICAgY3R4LnRhcmdldCA9PT0gc3VidHJlZVJvb3QgfHwgaXNDaGlsZE9mUGFyZW50KGN0eC50YXJnZXQsIHN1YnRyZWVSb290ISlcclxuXHJcbiAgICBpZiAoIWZpbHRlcikge1xyXG4gICAgICBmaWx0ZXIgPSB0YXJnZXRGaWx0ZXJcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnN0IGN1c3RvbUZpbHRlciA9IGZpbHRlclxyXG4gICAgICBmaWx0ZXIgPSAoY3R4KSA9PiB7XHJcbiAgICAgICAgcmV0dXJuIHRhcmdldEZpbHRlcihjdHgpICYmIGN1c3RvbUZpbHRlcihjdHgpXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IGFjdHVhbE13YXJlID0geyBtaWRkbGV3YXJlLCBmaWx0ZXIgfVxyXG5cclxuICBsZXQgb2JqTXdhcmVzID0gcGVyT2JqZWN0QWN0aW9uTWlkZGxld2FyZXMuZ2V0KHN1YnRyZWVSb290KSFcclxuICBpZiAoIW9iak13YXJlcykge1xyXG4gICAgb2JqTXdhcmVzID0gW2FjdHVhbE13YXJlXVxyXG4gICAgcGVyT2JqZWN0QWN0aW9uTWlkZGxld2FyZXMuc2V0KHN1YnRyZWVSb290LCBvYmpNd2FyZXMpXHJcbiAgfSBlbHNlIHtcclxuICAgIG9iak13YXJlcy5wdXNoKGFjdHVhbE13YXJlKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuICgpID0+IHtcclxuICAgIGRlbGV0ZUZyb21BcnJheShvYmpNd2FyZXMsIGFjdHVhbE13YXJlKVxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBhY3Rpb24gfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgdHlwZSB7IE8gfSBmcm9tIFwidHMtdG9vbGJlbHRcIlxuaW1wb3J0IHR5cGUgeyBBbnlEYXRhTW9kZWwgfSBmcm9tIFwiLi4vZGF0YU1vZGVsL0Jhc2VEYXRhTW9kZWxcIlxuaW1wb3J0IHR5cGUgeyBBbnlNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9CYXNlTW9kZWxcIlxuaW1wb3J0IHtcbiAgQWN0aW9uQ29udGV4dCxcbiAgQWN0aW9uQ29udGV4dEFjdGlvblR5cGUsXG4gIGdldEN1cnJlbnRBY3Rpb25Db250ZXh0LFxuICBzZXRDdXJyZW50QWN0aW9uQ29udGV4dCxcbn0gZnJvbSBcIi4vY29udGV4dFwiXG5pbXBvcnQgeyBpc01vZGVsQWN0aW9uLCBtb2RlbEFjdGlvblN5bWJvbCB9IGZyb20gXCIuL2lzTW9kZWxBY3Rpb25cIlxuaW1wb3J0IHsgZ2V0QWN0aW9uTWlkZGxld2FyZXMgfSBmcm9tIFwiLi9taWRkbGV3YXJlXCJcbmltcG9ydCB0eXBlIHsgRmxvd0ZpbmlzaGVyIH0gZnJvbSBcIi4vbW9kZWxGbG93XCJcbmltcG9ydCB7IHRyeVJ1blBlbmRpbmdBY3Rpb25zIH0gZnJvbSBcIi4vcGVuZGluZ0FjdGlvbnNcIlxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgdHlwZSBXcmFwSW5BY3Rpb25PdmVycmlkZUNvbnRleHRGbiA9IChjdHg6IE8uV3JpdGFibGU8QWN0aW9uQ29udGV4dD4sIHNlbGY6IGFueSkgPT4gdm9pZFxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gd3JhcEluQWN0aW9uPFQgZXh0ZW5kcyBGdW5jdGlvbj4oe1xuICBuYW1lT3JOYW1lRm4sXG4gIGZuLFxuICBhY3Rpb25UeXBlLFxuICBvdmVycmlkZUNvbnRleHQsXG4gIGlzRmxvd0ZpbmlzaGVyID0gZmFsc2UsXG59OiB7XG4gIG5hbWVPck5hbWVGbjogc3RyaW5nIHwgKCgpID0+IHN0cmluZylcbiAgZm46IFRcbiAgYWN0aW9uVHlwZTogQWN0aW9uQ29udGV4dEFjdGlvblR5cGVcbiAgb3ZlcnJpZGVDb250ZXh0PzogV3JhcEluQWN0aW9uT3ZlcnJpZGVDb250ZXh0Rm5cbiAgaXNGbG93RmluaXNoZXI/OiBib29sZWFuXG59KTogVCB7XG4gIGxldCBmbkluQWN0aW9uID0gZmFsc2VcblxuICBjb25zdCB3cmFwcGVkQWN0aW9uID0gZnVuY3Rpb24gKHRoaXM6IGFueSkge1xuICAgIGNvbnN0IG5hbWUgPSB0eXBlb2YgbmFtZU9yTmFtZUZuID09PSBcImZ1bmN0aW9uXCIgPyBuYW1lT3JOYW1lRm4oKSA6IG5hbWVPck5hbWVGblxuXG4gICAgaWYgKCFmbkluQWN0aW9uKSB7XG4gICAgICBmbkluQWN0aW9uID0gdHJ1ZVxuXG4gICAgICAvLyB3ZSBuZWVkIHRvIG1ha2Ugb25seSBpbm5lciBhY3Rpb25zIGFjdHVhbCBtb2J4IGFjdGlvbnNcbiAgICAgIC8vIHNvIHJlYWN0aW9ucyAoZS5nLiByZWZlcmVuY2UgZGV0YWNoaW5nKSBhcmUgcGlja2VkIHVwIGluIHRoZVxuICAgICAgLy8gcmlnaHQgY29udGV4dFxuICAgICAgZm4gPSBhY3Rpb24obmFtZSwgZm4pXG4gICAgfVxuXG4gICAgY29uc3QgdGFyZ2V0ID0gdGhpc1xuXG4gICAgY29uc3QgcGFyZW50Q29udGV4dCA9IGdldEN1cnJlbnRBY3Rpb25Db250ZXh0KClcblxuICAgIGNvbnN0IGNvbnRleHQ6IE8uV3JpdGFibGU8QWN0aW9uQ29udGV4dD4gPSB7XG4gICAgICBhY3Rpb25OYW1lOiBuYW1lLFxuICAgICAgdHlwZTogYWN0aW9uVHlwZSxcbiAgICAgIHRhcmdldCxcbiAgICAgIGFyZ3M6IEFycmF5LmZyb20oYXJndW1lbnRzKSxcbiAgICAgIHBhcmVudENvbnRleHQsXG4gICAgICBkYXRhOiB7fSxcbiAgICAgIHJvb3RDb250ZXh0OiB1bmRlZmluZWQgYXMgYW55LCAvLyB3aWxsIGJlIHNldCBhZnRlciB0aGUgb3ZlcnJpZGVcbiAgICB9XG4gICAgaWYgKG92ZXJyaWRlQ29udGV4dCkge1xuICAgICAgb3ZlcnJpZGVDb250ZXh0KGNvbnRleHQsIHRoaXMpXG4gICAgfVxuICAgIGlmICghY29udGV4dC5yb290Q29udGV4dCkge1xuICAgICAgaWYgKGNvbnRleHQucHJldmlvdXNBc3luY1N0ZXBDb250ZXh0KSB7XG4gICAgICAgIGNvbnRleHQucm9vdENvbnRleHQgPSBjb250ZXh0LnByZXZpb3VzQXN5bmNTdGVwQ29udGV4dC5yb290Q29udGV4dFxuICAgICAgfSBlbHNlIGlmIChjb250ZXh0LnBhcmVudENvbnRleHQpIHtcbiAgICAgICAgY29udGV4dC5yb290Q29udGV4dCA9IGNvbnRleHQucGFyZW50Q29udGV4dC5yb290Q29udGV4dFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29udGV4dC5yb290Q29udGV4dCA9IGNvbnRleHRcbiAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRDdXJyZW50QWN0aW9uQ29udGV4dChjb250ZXh0KVxuXG4gICAgbGV0IG13YXJlRm46ICgpID0+IGFueSA9IGZuLmJpbmQodGFyZ2V0LCAuLi5hcmd1bWVudHMpXG4gICAgY29uc3QgbXdhcmVJdGVyID0gZ2V0QWN0aW9uTWlkZGxld2FyZXMoY29udGV4dC50YXJnZXQpW1N5bWJvbC5pdGVyYXRvcl0oKVxuICAgIGxldCBtd2FyZUN1ciA9IG13YXJlSXRlci5uZXh0KClcbiAgICB3aGlsZSAoIW13YXJlQ3VyLmRvbmUpIHtcbiAgICAgIGNvbnN0IG13YXJlID0gbXdhcmVDdXIudmFsdWVcblxuICAgICAgY29uc3QgZmlsdGVyUGFzc2VkID0gbXdhcmUuZmlsdGVyID8gbXdhcmUuZmlsdGVyKGNvbnRleHQpIDogdHJ1ZVxuICAgICAgaWYgKGZpbHRlclBhc3NlZCkge1xuICAgICAgICBtd2FyZUZuID0gbXdhcmUubWlkZGxld2FyZS5iaW5kKHVuZGVmaW5lZCwgY29udGV4dCwgbXdhcmVGbilcbiAgICAgIH1cblxuICAgICAgbXdhcmVDdXIgPSBtd2FyZUl0ZXIubmV4dCgpXG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJldCA9IG13YXJlRm4oKVxuXG4gICAgICBpZiAoaXNGbG93RmluaXNoZXIpIHtcbiAgICAgICAgY29uc3QgZmxvd0ZpbmlzaGVyID0gcmV0IGFzIEZsb3dGaW5pc2hlclxuICAgICAgICBjb25zdCB2YWx1ZSA9IGZsb3dGaW5pc2hlci52YWx1ZVxuICAgICAgICBpZiAoZmxvd0ZpbmlzaGVyLnJlc29sdXRpb24gPT09IFwiYWNjZXB0XCIpIHtcbiAgICAgICAgICBmbG93RmluaXNoZXIuYWNjZXB0ZXIodmFsdWUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmxvd0ZpbmlzaGVyLnJlamVjdGVyKHZhbHVlKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZSAvLyBub3Qgc3VyZSBpZiB0aGlzIGlzIGV2ZW4gbmVlZGVkXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gcmV0XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNldEN1cnJlbnRBY3Rpb25Db250ZXh0KGNvbnRleHQucGFyZW50Q29udGV4dClcblxuICAgICAgdHJ5UnVuUGVuZGluZ0FjdGlvbnMoKVxuICAgIH1cbiAgfVxuICA7KHdyYXBwZWRBY3Rpb24gYXMgYW55KVttb2RlbEFjdGlvblN5bWJvbF0gPSB0cnVlXG5cbiAgcmV0dXJuIHdyYXBwZWRBY3Rpb24gYXMgYW55XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3cmFwTW9kZWxNZXRob2RJbkFjdGlvbklmTmVlZGVkPE0gZXh0ZW5kcyBBbnlNb2RlbCB8IEFueURhdGFNb2RlbD4oXG4gIG1vZGVsOiBNLFxuICBwcm9wZXJ0eUtleToga2V5b2YgTSxcbiAgbmFtZTogc3RyaW5nXG4pOiB2b2lkIHtcbiAgY29uc3QgZm4gPSBtb2RlbFtwcm9wZXJ0eUtleV0gYXMgYW55XG4gIGlmIChpc01vZGVsQWN0aW9uKGZuKSkge1xuICAgIHJldHVyblxuICB9XG5cbiAgY29uc3Qgd3JhcHBlZEZuID0gd3JhcEluQWN0aW9uKHtcbiAgICBuYW1lT3JOYW1lRm46IG5hbWUsXG4gICAgZm4sXG4gICAgYWN0aW9uVHlwZTogQWN0aW9uQ29udGV4dEFjdGlvblR5cGUuU3luYyxcbiAgfSlcbiAgY29uc3QgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YobW9kZWwpXG4gIGNvbnN0IHByb3RvRm4gPSBwcm90b1twcm9wZXJ0eUtleV1cbiAgaWYgKHByb3RvRm4gPT09IGZuKSB7XG4gICAgcHJvdG9bcHJvcGVydHlLZXldID0gd3JhcHBlZEZuXG4gIH0gZWxzZSB7XG4gICAgbW9kZWxbcHJvcGVydHlLZXldID0gd3JhcHBlZEZuXG4gIH1cbn1cbiIsImltcG9ydCB7IGlzT2JzZXJ2YWJsZUFycmF5LCBpc09ic2VydmFibGVPYmplY3QsIHJlbW92ZSB9IGZyb20gXCJtb2J4XCJcclxuaW1wb3J0IHsgQnVpbHRJbkFjdGlvbiB9IGZyb20gXCIuLi9hY3Rpb24vYnVpbHRJbkFjdGlvbnNcIlxyXG5pbXBvcnQgeyBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZSB9IGZyb20gXCIuLi9hY3Rpb24vY29udGV4dFwiXHJcbmltcG9ydCB7IHdyYXBJbkFjdGlvbiB9IGZyb20gXCIuLi9hY3Rpb24vd3JhcEluQWN0aW9uXCJcclxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxyXG5pbXBvcnQgeyBmYWlsdXJlLCBsYXp5IH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgZmFzdEdldFBhcmVudFBhdGhJbmNsdWRpbmdEYXRhT2JqZWN0cyB9IGZyb20gXCIuL3BhdGhcIlxyXG5cclxuLyoqXHJcbiAqIERldGFjaGVzIGEgZ2l2ZW4gb2JqZWN0IGZyb20gYSB0cmVlLlxyXG4gKiBJZiB0aGUgcGFyZW50IGlzIGFuIG9iamVjdCAvIG1vZGVsLCBkZXRhY2hpbmcgd2lsbCBkZWxldGUgdGhlIHByb3BlcnR5LlxyXG4gKiBJZiB0aGUgcGFyZW50IGlzIGFuIGFycmF5IGRldGFjaGluZyB3aWxsIHJlbW92ZSB0aGUgbm9kZSBieSBzcGxpY2luZyBpdC5cclxuICogSWYgdGhlcmUncyBubyBwYXJlbnQgaXQgd2lsbCB0aHJvdy5cclxuICpcclxuICogQHBhcmFtIG5vZGUgT2JqZWN0IHRvIGJlIGRldGFjaGVkLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGRldGFjaChub2RlOiBvYmplY3QpOiB2b2lkIHtcclxuICBhc3NlcnRUd2Vha2VkT2JqZWN0KG5vZGUsIFwibm9kZVwiKVxyXG5cclxuICB3cmFwcGVkSW50ZXJuYWxEZXRhY2goKS5jYWxsKG5vZGUpXHJcbn1cclxuXHJcbmNvbnN0IHdyYXBwZWRJbnRlcm5hbERldGFjaCA9IGxhenkoKCkgPT5cclxuICB3cmFwSW5BY3Rpb24oe1xyXG4gICAgbmFtZU9yTmFtZUZuOiBCdWlsdEluQWN0aW9uLkRldGFjaCxcclxuICAgIGZuOiBpbnRlcm5hbERldGFjaCxcclxuICAgIGFjdGlvblR5cGU6IEFjdGlvbkNvbnRleHRBY3Rpb25UeXBlLlN5bmMsXHJcbiAgfSlcclxuKVxyXG5cclxuZnVuY3Rpb24gaW50ZXJuYWxEZXRhY2godGhpczogb2JqZWN0KTogdm9pZCB7XHJcbiAgY29uc3Qgbm9kZSA9IHRoaXNcclxuXHJcbiAgY29uc3QgcGFyZW50UGF0aCA9IGZhc3RHZXRQYXJlbnRQYXRoSW5jbHVkaW5nRGF0YU9iamVjdHMobm9kZSlcclxuICBpZiAoIXBhcmVudFBhdGgpIHJldHVyblxyXG5cclxuICBjb25zdCB7IHBhcmVudCwgcGF0aCB9ID0gcGFyZW50UGF0aFxyXG4gIGlmIChpc09ic2VydmFibGVBcnJheShwYXJlbnQpKSB7XHJcbiAgICBwYXJlbnQuc3BsaWNlKCtwYXRoLCAxKVxyXG4gIH0gZWxzZSBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHBhcmVudCkpIHtcclxuICAgIHJlbW92ZShwYXJlbnQsIFwiXCIgKyBwYXRoKVxyXG4gIH0gZWxzZSB7XHJcbiAgICB0aHJvdyBmYWlsdXJlKFwicGFyZW50IG11c3QgYmUgYW4gb2JzZXJ2YWJsZSBvYmplY3Qgb3IgYW4gb2JzZXJ2YWJsZSBhcnJheVwiKVxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBXcmFwSW5BY3Rpb25PdmVycmlkZUNvbnRleHRGbiB9IGZyb20gXCIuLi9hY3Rpb24vd3JhcEluQWN0aW9uXCJcbmltcG9ydCB7IHNldERhdGFNb2RlbEFjdGlvbiB9IGZyb20gXCIuLi9kYXRhTW9kZWwvYWN0aW9uc1wiXG5pbXBvcnQgeyBCYXNlRGF0YU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9CYXNlRGF0YU1vZGVsXCJcbmltcG9ydCB7IGlzRGF0YU1vZGVsLCBpc0RhdGFNb2RlbENsYXNzIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC91dGlsc1wiXG5pbXBvcnQgeyBhZGRMYXRlSW5pdGlhbGl6YXRpb25GdW5jdGlvbiwgZmFpbHVyZSwgaW5EZXZNb2RlLCBydW5BZnRlck5ld1N5bWJvbCB9IGZyb20gXCIuL2luZGV4XCJcbmltcG9ydCB7IEJhc2VNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9CYXNlTW9kZWxcIlxuaW1wb3J0IHsgbW9kZWxJbmZvQnlDbGFzcyB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9tb2RlbEluZm9cIlxuaW1wb3J0IHsgcnVuQWZ0ZXJNb2RlbERlY29yYXRvclN5bWJvbCB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9tb2RlbFN5bWJvbHNcIlxuXG50eXBlIFdyYXBGdW5jdGlvbiA9IChcbiAgZGF0YToge1xuICAgIGFjdGlvbk5hbWU6IHN0cmluZyB8ICgoKSA9PiBzdHJpbmcpXG4gICAgb3ZlcnJpZGVDb250ZXh0OiBXcmFwSW5BY3Rpb25PdmVycmlkZUNvbnRleHRGbiB8IHVuZGVmaW5lZFxuICB9LFxuICBmbjogYW55XG4pID0+IGFueVxuXG5jb25zdCB1bmJvdW5kTWV0aG9kU3ltYm9sID0gU3ltYm9sKFwidW5ib3VuZE1ldGhvZFwiKVxuXG5jb25zdCBiaW5kTWV0aG9kID0gKG1ldGhvZDogYW55LCBpbnN0YW5jZTogYW55KSA9PiB7XG4gIGNvbnN0IHVuYm91bmRNZXRob2QgPSB1bmJvdW5kTWV0aG9kU3ltYm9sIGluIG1ldGhvZCA/IG1ldGhvZFt1bmJvdW5kTWV0aG9kU3ltYm9sXSA6IG1ldGhvZFxuXG4gIGNvbnN0IGJvdW5kTWV0aG9kID0gdW5ib3VuZE1ldGhvZC5iaW5kKGluc3RhbmNlKVxuICAvLyBjb3B5IG1vZGVsQWN0aW9uIHN5bWJvbCwgZXRjLlxuICBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHVuYm91bmRNZXRob2QpLmZvckVhY2goKHMpID0+IHtcbiAgICBib3VuZE1ldGhvZFtzXSA9IHVuYm91bmRNZXRob2Rbc11cbiAgfSlcbiAgYm91bmRNZXRob2RbdW5ib3VuZE1ldGhvZFN5bWJvbF0gPSB1bmJvdW5kTWV0aG9kXG5cbiAgcmV0dXJuIGJvdW5kTWV0aG9kXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvcmF0ZVdyYXBNZXRob2RPckZpZWxkKFxuICBkZWNvcmF0b3JOYW1lOiBzdHJpbmcsXG4gIGFyZ3M6IGFueVtdLFxuICB3cmFwOiBXcmFwRnVuY3Rpb25cbik6IGFueSB7XG4gIGlmICh0eXBlb2YgYXJnc1sxXSAhPT0gXCJvYmplY3RcIikge1xuICAgIC8vIG5vbi1zdGFuZGFyZCBkZWNvcmF0b3JzXG5cbiAgICBjb25zdCB0YXJnZXQgPSBhcmdzWzBdXG4gICAgY29uc3QgcHJvcGVydHlLZXk6IHN0cmluZyA9IGFyZ3NbMV1cbiAgICBjb25zdCBiYXNlRGVzY3JpcHRvcjogUHJvcGVydHlEZXNjcmlwdG9yIHwgdW5kZWZpbmVkID0gYXJnc1syXVxuXG4gICAgY2hlY2tNb2RlbERlY29yYXRvclRhZ2V0KGRlY29yYXRvck5hbWUsIHRhcmdldClcbiAgICBjaGVja0RlY29yYXRvckNvbnRleHQoXCJ0cmFuc2FjdGlvblwiLCBwcm9wZXJ0eUtleSwgZmFsc2UpXG5cbiAgICBjb25zdCBkYXRhID0gZ2V0QWN0aW9uTmFtZUFuZENvbnRleHRPdmVycmlkZSh0YXJnZXQsIHByb3BlcnR5S2V5LCB0cnVlKVxuXG4gICAgY29uc3QgYWRkRmllbGREZWNvcmF0b3IgPSAoKSA9PiB7XG4gICAgICBhZGRMYXRlSW5pdGlhbGl6YXRpb25GdW5jdGlvbih0YXJnZXQsIHJ1bkFmdGVyTmV3U3ltYm9sLCAoaW5zdGFuY2UpID0+IHtcbiAgICAgICAgY29uc3QgbWV0aG9kID0gd3JhcChkYXRhLCBpbnN0YW5jZVtwcm9wZXJ0eUtleV0pXG5cbiAgICAgICAgLy8gYWxsIG9mIHRoaXMgaXMgdG8gbWFrZSBtZXRob2QgZGVzdHJ1Y3R1cmluZyB3b3JrXG4gICAgICAgIGluc3RhbmNlW3Byb3BlcnR5S2V5XSA9IGJpbmRNZXRob2QobWV0aG9kLCBpbnN0YW5jZSlcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgaWYgKGJhc2VEZXNjcmlwdG9yKSB7XG4gICAgICBpZiAoYmFzZURlc2NyaXB0b3IuZ2V0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShgQCR7ZGVjb3JhdG9yTmFtZX0gY2Fubm90IGJlIHVzZWQgd2l0aCBnZXR0ZXJzYClcbiAgICAgIH1cblxuICAgICAgaWYgKGJhc2VEZXNjcmlwdG9yLnZhbHVlKSB7XG4gICAgICAgIC8vIGJhYmVsIC8gdHlwZXNjcmlwdCAtIG1ldGhvZCBkZWNvcmF0b3JcbiAgICAgICAgLy8gQGFjdGlvbiBtZXRob2QoKSB7IH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgdmFsdWU6IHdyYXAoZGF0YSwgYmFzZURlc2NyaXB0b3IudmFsdWUpLFxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBiYWJlbCAtIGZpZWxkIGRlY29yYXRvcjogQGFjdGlvbiBtZXRob2QgPSAoKSA9PiB7fVxuICAgICAgICBhZGRGaWVsZERlY29yYXRvcigpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHR5cGVzY3JpcHQgLSBmaWVsZCBkZWNvcmF0b3I6IEBhY3Rpb24gbWV0aG9kID0gKCkgPT4ge31cbiAgICAgIGFkZEZpZWxkRGVjb3JhdG9yKClcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gc3RhbmRhcmQgZGVjb3JhdG9yc1xuICAgIGNvbnN0IGN0eCA9IGFyZ3NbMV0gYXMgQ2xhc3NNZXRob2REZWNvcmF0b3JDb250ZXh0IHwgQ2xhc3NGaWVsZERlY29yYXRvckNvbnRleHRcblxuICAgIGNoZWNrRGVjb3JhdG9yQ29udGV4dChkZWNvcmF0b3JOYW1lLCBjdHgubmFtZSwgY3R4LnN0YXRpYylcbiAgICBpZiAoY3R4LmtpbmQgIT09IFwibWV0aG9kXCIgJiYgY3R4LmtpbmQgIT09IFwiZmllbGRcIikge1xuICAgICAgdGhyb3cgZmFpbHVyZShgQCR7ZGVjb3JhdG9yTmFtZX0gY2FuIG9ubHkgYmUgdXNlZCBvbiBmaWVsZHMgb3IgbWV0aG9kc31gKVxuICAgIH1cblxuICAgIGlmIChjdHgua2luZCA9PT0gXCJtZXRob2RcIikge1xuICAgICAgLy8gQGFjdGlvbiBtZXRob2QoKSB7IH1cbiAgICAgIGNvbnN0IHZhbHVlID0gYXJnc1swXVxuICAgICAgY29uc3QgcHJvcGVydHlLZXkgPSBjdHgubmFtZSBhcyBzdHJpbmdcblxuICAgICAgbGV0IGluaXRlZCA9IGZhbHNlXG5cbiAgICAgIGN0eC5hZGRJbml0aWFsaXplcihmdW5jdGlvbiAodGhpczogYW55KSB7XG4gICAgICAgIC8vIG9ubHkgZG8gb25lIG92ZXJyaWRlIG9uIGZpcnN0IGluaXRpYWxpemF0aW9uIGZvciB0aGUgd2hvbGUgY2xhc3NcbiAgICAgICAgaWYgKGluaXRlZCkge1xuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICAgIGluaXRlZCA9IHRydWVcblxuICAgICAgICBjb25zdCB0YXJnZXQgPSB0aGlzXG4gICAgICAgIGNoZWNrTW9kZWxEZWNvcmF0b3JUYWdldChkZWNvcmF0b3JOYW1lLCB0YXJnZXQpXG5cbiAgICAgICAgLy8gZmluZCB0aGUgZGVlcGVzdCBwcm90byB0aGF0IG1hdGNoZXMgdGhlIHZhbHVlXG4gICAgICAgIGxldCBwcm90byA9IHRoaXNcbiAgICAgICAgbGV0IG5leHRQcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihwcm90bylcbiAgICAgICAgd2hpbGUgKG5leHRQcm90byAmJiBuZXh0UHJvdG9bcHJvcGVydHlLZXldID09PSB2YWx1ZSkge1xuICAgICAgICAgIHByb3RvID0gbmV4dFByb3RvXG4gICAgICAgICAgbmV4dFByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvKVxuICAgICAgICB9XG5cbiAgICAgICAgcHJvdG9bcHJvcGVydHlLZXldID0gd3JhcChcbiAgICAgICAgICBnZXRBY3Rpb25OYW1lQW5kQ29udGV4dE92ZXJyaWRlKHRhcmdldCwgcHJvcGVydHlLZXksIGZhbHNlKSxcbiAgICAgICAgICBwcm90b1twcm9wZXJ0eUtleV1cbiAgICAgICAgKVxuICAgICAgfSlcbiAgICB9IGVsc2UgaWYgKGN0eC5raW5kID09PSBcImZpZWxkXCIpIHtcbiAgICAgIC8vIEBhY3Rpb24gbWV0aG9kID0gKCkgPT4ge31cbiAgICAgIGNvbnN0IHByb3BlcnR5S2V5ID0gY3R4Lm5hbWUgYXMgc3RyaW5nXG5cbiAgICAgIGxldCBkYXRhOiBSZXR1cm5UeXBlPHR5cGVvZiBnZXRBY3Rpb25OYW1lQW5kQ29udGV4dE92ZXJyaWRlPiB8IHVuZGVmaW5lZFxuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKHRoaXM6IGFueSwgdmFsdWU6IGFueSkge1xuICAgICAgICBjb25zdCBpbnN0YW5jZSA9IHRoaXNcblxuICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICBjaGVja01vZGVsRGVjb3JhdG9yVGFnZXQoZGVjb3JhdG9yTmFtZSwgaW5zdGFuY2UpXG4gICAgICAgICAgZGF0YSA9IGdldEFjdGlvbk5hbWVBbmRDb250ZXh0T3ZlcnJpZGUoaW5zdGFuY2UsIHByb3BlcnR5S2V5LCBmYWxzZSlcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG1ldGhvZCA9IHdyYXAoZGF0YSwgdmFsdWUpXG5cbiAgICAgICAgLy8gYWxsIG9mIHRoaXMgaXMgdG8gbWFrZSBtZXRob2QgZGVzdHJ1Y3R1cmluZyB3b3JrXG4gICAgICAgIHJldHVybiBiaW5kTWV0aG9kKG1ldGhvZCwgaW5zdGFuY2UpXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGVja0RlY29yYXRvckNvbnRleHQoXG4gIGRlY29yYXRvck5hbWU6IHN0cmluZyxcbiAgcHJvcGVydHlLZXk6IHN0cmluZyB8IHN5bWJvbCxcbiAgaXNTdGF0aWM6IGJvb2xlYW5cbikge1xuICBpZiAoIWluRGV2TW9kZSkge1xuICAgIHJldHVyblxuICB9XG5cbiAgaWYgKHR5cGVvZiBwcm9wZXJ0eUtleSAhPT0gXCJzdHJpbmdcIikge1xuICAgIHRocm93IGZhaWx1cmUoYEAke2RlY29yYXRvck5hbWV9IGNhbm5vdCBkZWNvcmF0ZSBzeW1ib2wgcHJvcGVydGllc2ApXG4gIH1cbiAgaWYgKGlzU3RhdGljKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgQCR7ZGVjb3JhdG9yTmFtZX0gY2Fubm90IGJlIHVzZWQgd2l0aCBzdGF0aWMgZmllbGRzIG9yIG1ldGhvZHNgKVxuICB9XG59XG5cbmNvbnN0IGRhdGFNb2RlbE92ZXJyaWRlQ29udGV4dDogV3JhcEluQWN0aW9uT3ZlcnJpZGVDb250ZXh0Rm4gPSAoY3R4LCBzZWxmKSA9PiB7XG4gIGN0eC50YXJnZXQgPSBzZWxmLiRcbn1cblxuZnVuY3Rpb24gZ2V0QWN0aW9uTmFtZUFuZENvbnRleHRPdmVycmlkZShcbiAgdGFyZ2V0OiBhbnksXG4gIHByb3BlcnR5S2V5OiBzdHJpbmcsXG4gIHJ1bkxhdGU6IGJvb2xlYW5cbik6IHtcbiAgYWN0aW9uTmFtZTogc3RyaW5nIHwgKCgpID0+IHN0cmluZylcbiAgb3ZlcnJpZGVDb250ZXh0OiBXcmFwSW5BY3Rpb25PdmVycmlkZUNvbnRleHRGbiB8IHVuZGVmaW5lZFxufSB7XG4gIGlmIChpc0RhdGFNb2RlbENsYXNzKHRhcmdldCkgfHwgaXNEYXRhTW9kZWwodGFyZ2V0KSkge1xuICAgIGNvbnN0IG1vZGVsQ2xhc3M6IGFueSA9IGlzRGF0YU1vZGVsQ2xhc3ModGFyZ2V0KSA/IHRhcmdldCA6IHRhcmdldC5jb25zdHJ1Y3RvclxuXG4gICAgbGV0IGZ1bGxBY3Rpb25OYW1lOiBzdHJpbmdcblxuICAgIGNvbnN0IGxhdGVJbml0ID0gKGZpbmFsQ2xhc3M6IGFueSkgPT4ge1xuICAgICAgY29uc3QgbW9kZWxJbmZvID0gbW9kZWxJbmZvQnlDbGFzcy5nZXQoZmluYWxDbGFzcykhXG4gICAgICBmdWxsQWN0aW9uTmFtZSA9IGBmbjo6JHttb2RlbEluZm8ubmFtZX06OiR7cHJvcGVydHlLZXl9YFxuICAgICAgc2V0RGF0YU1vZGVsQWN0aW9uKGZ1bGxBY3Rpb25OYW1lLCBtb2RlbEluZm8uY2xhc3MsIHByb3BlcnR5S2V5KVxuICAgIH1cblxuICAgIGlmIChydW5MYXRlKSB7XG4gICAgICBhZGRMYXRlSW5pdGlhbGl6YXRpb25GdW5jdGlvbihtb2RlbENsYXNzLCBydW5BZnRlck1vZGVsRGVjb3JhdG9yU3ltYm9sLCBsYXRlSW5pdClcbiAgICB9IGVsc2Uge1xuICAgICAgbGF0ZUluaXQobW9kZWxDbGFzcylcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgYWN0aW9uTmFtZTogKCkgPT4gZnVsbEFjdGlvbk5hbWUsXG4gICAgICBvdmVycmlkZUNvbnRleHQ6IGRhdGFNb2RlbE92ZXJyaWRlQ29udGV4dCxcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHsgYWN0aW9uTmFtZTogcHJvcGVydHlLZXksIG92ZXJyaWRlQ29udGV4dDogdW5kZWZpbmVkIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja01vZGVsRGVjb3JhdG9yVGFnZXQoZGVjb3JhdG9yTmFtZTogc3RyaW5nLCB0YXJnZXQ6IGFueSkge1xuICBpZiAoIWluRGV2TW9kZSkge1xuICAgIHJldHVyblxuICB9XG5cbiAgY29uc3QgZXJyTWVzc2FnZSA9IGBAJHtkZWNvcmF0b3JOYW1lfSBtdXN0IGJlIHVzZWQgb3ZlciBtb2RlbCBjbGFzc2VzIG9yIGluc3RhbmNlc2BcblxuICBpZiAoIXRhcmdldCkge1xuICAgIHRocm93IGZhaWx1cmUoZXJyTWVzc2FnZSlcbiAgfVxuXG4gIC8vIGNoZWNrIHRhcmdldCBpcyBhIG1vZGVsIG9iamVjdCBvciBleHRlbmRlZCBjbGFzc1xuICBjb25zdCBpc01vZGVsID1cbiAgICB0YXJnZXQgaW5zdGFuY2VvZiBCYXNlTW9kZWwgfHwgdGFyZ2V0ID09PSBCYXNlTW9kZWwgfHwgdGFyZ2V0LnByb3RvdHlwZSBpbnN0YW5jZW9mIEJhc2VNb2RlbFxuICBpZiAoaXNNb2RlbCkgcmV0dXJuXG5cbiAgY29uc3QgaXNEYXRhTW9kZWwgPVxuICAgIHRhcmdldCBpbnN0YW5jZW9mIEJhc2VEYXRhTW9kZWwgfHxcbiAgICB0YXJnZXQgPT09IEJhc2VEYXRhTW9kZWwgfHxcbiAgICB0YXJnZXQucHJvdG90eXBlIGluc3RhbmNlb2YgQmFzZURhdGFNb2RlbFxuICBpZiAoaXNEYXRhTW9kZWwpIHJldHVyblxuXG4gIHRocm93IGZhaWx1cmUoZXJyTWVzc2FnZSlcbn1cbiIsImltcG9ydCB0eXBlIHsgTyB9IGZyb20gXCJ0cy10b29sYmVsdFwiXHJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQgeyBBY3Rpb25Db250ZXh0LCBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZSwgQWN0aW9uQ29udGV4dEFzeW5jU3RlcFR5cGUgfSBmcm9tIFwiLi9jb250ZXh0XCJcclxuaW1wb3J0IHsgV3JhcEluQWN0aW9uT3ZlcnJpZGVDb250ZXh0Rm4sIHdyYXBJbkFjdGlvbiB9IGZyb20gXCIuL3dyYXBJbkFjdGlvblwiXHJcbmltcG9ydCB7IGRlY29yYXRlV3JhcE1ldGhvZE9yRmllbGQgfSBmcm9tIFwiLi4vdXRpbHMvZGVjb3JhdG9yc1wiXHJcblxyXG5jb25zdCBtb2RlbEZsb3dTeW1ib2wgPSBTeW1ib2woXCJtb2RlbEZsb3dcIilcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmbG93PFIsIEFyZ3MgZXh0ZW5kcyBhbnlbXT4oe1xyXG4gIG5hbWVPck5hbWVGbixcclxuICBnZW5lcmF0b3IsXHJcbiAgb3ZlcnJpZGVDb250ZXh0LFxyXG59OiB7XHJcbiAgbmFtZU9yTmFtZUZuOiBzdHJpbmcgfCAoKCkgPT4gc3RyaW5nKVxyXG4gIGdlbmVyYXRvcjogKC4uLmFyZ3M6IEFyZ3MpID0+IEl0ZXJhYmxlSXRlcmF0b3I8YW55PlxyXG4gIG92ZXJyaWRlQ29udGV4dD86IFdyYXBJbkFjdGlvbk92ZXJyaWRlQ29udGV4dEZuXHJcbn0pOiAoLi4uYXJnczogQXJncykgPT4gUHJvbWlzZTxhbnk+IHtcclxuICAvLyBJbXBsZW1lbnRhdGlvbiBiYXNlZCBvbiBodHRwczovL2dpdGh1Yi5jb20vdGovY28vYmxvYi9tYXN0ZXIvaW5kZXguanNcclxuICBjb25zdCBmbG93Rm4gPSBmdW5jdGlvbiAodGhpczogYW55LCAuLi5hcmdzOiBhbnlbXSkge1xyXG4gICAgY29uc3QgbmFtZSA9IHR5cGVvZiBuYW1lT3JOYW1lRm4gPT09IFwiZnVuY3Rpb25cIiA/IG5hbWVPck5hbWVGbigpIDogbmFtZU9yTmFtZUZuXHJcblxyXG4gICAgY29uc3QgdGFyZ2V0ID0gdGhpc1xyXG5cclxuICAgIGxldCBwcmV2aW91c0FzeW5jU3RlcENvbnRleHQ6IEFjdGlvbkNvbnRleHQgfCB1bmRlZmluZWRcclxuXHJcbiAgICBjb25zdCBjdHhPdmVycmlkZSA9IChzdGVwVHlwZTogQWN0aW9uQ29udGV4dEFzeW5jU3RlcFR5cGUpOiBXcmFwSW5BY3Rpb25PdmVycmlkZUNvbnRleHRGbiA9PiB7XHJcbiAgICAgIHJldHVybiAoY3R4OiBPLldyaXRhYmxlPEFjdGlvbkNvbnRleHQ+LCBzZWxmKSA9PiB7XHJcbiAgICAgICAgaWYgKG92ZXJyaWRlQ29udGV4dCkge1xyXG4gICAgICAgICAgb3ZlcnJpZGVDb250ZXh0KGN0eCwgc2VsZilcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGN0eC5wcmV2aW91c0FzeW5jU3RlcENvbnRleHQgPSBwcmV2aW91c0FzeW5jU3RlcENvbnRleHRcclxuICAgICAgICBjdHguc3Bhd25Bc3luY1N0ZXBDb250ZXh0ID0gcHJldmlvdXNBc3luY1N0ZXBDb250ZXh0XHJcbiAgICAgICAgICA/IHByZXZpb3VzQXN5bmNTdGVwQ29udGV4dC5zcGF3bkFzeW5jU3RlcENvbnRleHRcclxuICAgICAgICAgIDogY3R4XHJcbiAgICAgICAgY3R4LmFzeW5jU3RlcFR5cGUgPSBzdGVwVHlwZVxyXG4gICAgICAgIGN0eC5hcmdzID0gYXJnc1xyXG5cclxuICAgICAgICBwcmV2aW91c0FzeW5jU3RlcENvbnRleHQgPSBjdHhcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBnZW5lcmF0b3JSdW4gPSBmYWxzZVxyXG4gICAgY29uc3QgZ2VuID0gd3JhcEluQWN0aW9uKHtcclxuICAgICAgbmFtZU9yTmFtZUZuOiBuYW1lLFxyXG4gICAgICBmbjogKCkgPT4ge1xyXG4gICAgICAgIGdlbmVyYXRvclJ1biA9IHRydWVcclxuICAgICAgICByZXR1cm4gZ2VuZXJhdG9yLmFwcGx5KHRhcmdldCwgYXJncyBhcyBBcmdzKVxyXG4gICAgICB9LFxyXG4gICAgICBhY3Rpb25UeXBlOiBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZS5Bc3luYyxcclxuICAgICAgb3ZlcnJpZGVDb250ZXh0OiBjdHhPdmVycmlkZShBY3Rpb25Db250ZXh0QXN5bmNTdGVwVHlwZS5TcGF3biksXHJcbiAgICB9KS5hcHBseSh0YXJnZXQpXHJcblxyXG4gICAgaWYgKCFnZW5lcmF0b3JSdW4pIHtcclxuICAgICAgLy8gbWF5YmUgaXQgZ290IG92ZXJyaWRkZW4gaW50byBhIHN5bmMgYWN0aW9uXHJcblxyXG4gICAgICByZXR1cm4gZ2VuIGluc3RhbmNlb2YgUHJvbWlzZSA/IGdlbiA6IFByb21pc2UucmVzb2x2ZShnZW4pXHJcbiAgICB9XHJcblxyXG4gICAgLy8gdXNlIGJvdW5kIGZ1bmN0aW9ucyB0byBmaXggZXM2IGNvbXBpbGF0aW9uXHJcbiAgICBjb25zdCBnZW5OZXh0ID0gZ2VuLm5leHQuYmluZChnZW4pXHJcbiAgICBjb25zdCBnZW5UaHJvdyA9IGdlbi50aHJvdyEuYmluZChnZW4pXHJcblxyXG4gICAgY29uc3QgcHJvbWlzZSA9IG5ldyBQcm9taXNlPFI+KGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgZnVuY3Rpb24gb25GdWxmaWxsZWQocmVzOiBhbnkpOiB2b2lkIHtcclxuICAgICAgICBsZXQgcmV0XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIHJldCA9IHdyYXBJbkFjdGlvbih7XHJcbiAgICAgICAgICAgIG5hbWVPck5hbWVGbjogbmFtZSxcclxuICAgICAgICAgICAgZm46IGdlbk5leHQsXHJcbiAgICAgICAgICAgIGFjdGlvblR5cGU6IEFjdGlvbkNvbnRleHRBY3Rpb25UeXBlLkFzeW5jLFxyXG4gICAgICAgICAgICBvdmVycmlkZUNvbnRleHQ6IGN0eE92ZXJyaWRlKEFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlLlJlc3VtZSksXHJcbiAgICAgICAgICB9KS5jYWxsKHRhcmdldCwgcmVzKVxyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgIHdyYXBJbkFjdGlvbih7XHJcbiAgICAgICAgICAgIG5hbWVPck5hbWVGbjogbmFtZSxcclxuICAgICAgICAgICAgZm46IChlcnI6IGFueSkgPT4ge1xyXG4gICAgICAgICAgICAgIC8vIHdlIHVzZSBhIGZsb3cgZmluaXNoZXIgdG8gYWxsb3cgbWlkZGxld2FyZXMgdG8gdHdlYWsgdGhlIHJldHVybiB2YWx1ZSBiZWZvcmUgcmVzb2x1dGlvblxyXG4gICAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICB2YWx1ZTogZXJyLFxyXG4gICAgICAgICAgICAgICAgcmVzb2x1dGlvbjogXCJyZWplY3RcIixcclxuXHJcbiAgICAgICAgICAgICAgICBhY2NlcHRlcjogcmVzb2x2ZSxcclxuICAgICAgICAgICAgICAgIHJlamVjdGVyOiByZWplY3QsXHJcbiAgICAgICAgICAgICAgfSBhcyBGbG93RmluaXNoZXJcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgYWN0aW9uVHlwZTogQWN0aW9uQ29udGV4dEFjdGlvblR5cGUuQXN5bmMsXHJcbiAgICAgICAgICAgIG92ZXJyaWRlQ29udGV4dDogY3R4T3ZlcnJpZGUoQWN0aW9uQ29udGV4dEFzeW5jU3RlcFR5cGUuVGhyb3cpLFxyXG4gICAgICAgICAgICBpc0Zsb3dGaW5pc2hlcjogdHJ1ZSxcclxuICAgICAgICAgIH0pLmNhbGwodGFyZ2V0LCBlKVxyXG4gICAgICAgICAgcmV0dXJuXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBuZXh0KHJldClcclxuICAgICAgfVxyXG5cclxuICAgICAgZnVuY3Rpb24gb25SZWplY3RlZChlcnI6IGFueSk6IHZvaWQge1xyXG4gICAgICAgIGxldCByZXRcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgcmV0ID0gd3JhcEluQWN0aW9uKHtcclxuICAgICAgICAgICAgbmFtZU9yTmFtZUZuOiBuYW1lLFxyXG4gICAgICAgICAgICBmbjogZ2VuVGhyb3csXHJcbiAgICAgICAgICAgIGFjdGlvblR5cGU6IEFjdGlvbkNvbnRleHRBY3Rpb25UeXBlLkFzeW5jLFxyXG4gICAgICAgICAgICBvdmVycmlkZUNvbnRleHQ6IGN0eE92ZXJyaWRlKEFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlLlJlc3VtZUVycm9yKSxcclxuICAgICAgICAgIH0pLmNhbGwodGFyZ2V0LCBlcnIpXHJcbiAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgd3JhcEluQWN0aW9uKHtcclxuICAgICAgICAgICAgbmFtZU9yTmFtZUZuOiBuYW1lLFxyXG4gICAgICAgICAgICBmbjogKGVycjogYW55KSA9PiB7XHJcbiAgICAgICAgICAgICAgLy8gd2UgdXNlIGEgZmxvdyBmaW5pc2hlciB0byBhbGxvdyBtaWRkbGV3YXJlcyB0byB0d2VhayB0aGUgcmV0dXJuIHZhbHVlIGJlZm9yZSByZXNvbHV0aW9uXHJcbiAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIHZhbHVlOiBlcnIsXHJcbiAgICAgICAgICAgICAgICByZXNvbHV0aW9uOiBcInJlamVjdFwiLFxyXG5cclxuICAgICAgICAgICAgICAgIGFjY2VwdGVyOiByZXNvbHZlLFxyXG4gICAgICAgICAgICAgICAgcmVqZWN0ZXI6IHJlamVjdCxcclxuICAgICAgICAgICAgICB9IGFzIEZsb3dGaW5pc2hlclxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBhY3Rpb25UeXBlOiBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZS5Bc3luYyxcclxuICAgICAgICAgICAgb3ZlcnJpZGVDb250ZXh0OiBjdHhPdmVycmlkZShBY3Rpb25Db250ZXh0QXN5bmNTdGVwVHlwZS5UaHJvdyksXHJcbiAgICAgICAgICAgIGlzRmxvd0ZpbmlzaGVyOiB0cnVlLFxyXG4gICAgICAgICAgfSkuY2FsbCh0YXJnZXQsIGUpXHJcbiAgICAgICAgICByZXR1cm5cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIG5leHQocmV0KVxyXG4gICAgICB9XHJcblxyXG4gICAgICBmdW5jdGlvbiBuZXh0KHJldDogYW55KTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHJldCAmJiB0eXBlb2YgcmV0LnRoZW4gPT09IFwiZnVuY3Rpb25cIikge1xyXG4gICAgICAgICAgLy8gYW4gYXN5bmMgaXRlcmF0b3JcclxuICAgICAgICAgIHJldC50aGVuKG5leHQsIHJlamVjdClcclxuICAgICAgICB9IGVsc2UgaWYgKHJldC5kb25lKSB7XHJcbiAgICAgICAgICAvLyBkb25lXHJcbiAgICAgICAgICB3cmFwSW5BY3Rpb24oe1xyXG4gICAgICAgICAgICBuYW1lT3JOYW1lRm46IG5hbWUsXHJcbiAgICAgICAgICAgIGZuOiAodmFsOiBhbnkpID0+IHtcclxuICAgICAgICAgICAgICAvLyB3ZSB1c2UgYSBmbG93IGZpbmlzaGVyIHRvIGFsbG93IG1pZGRsZXdhcmVzIHRvIHR3ZWFrIHRoZSByZXR1cm4gdmFsdWUgYmVmb3JlIHJlc29sdXRpb25cclxuICAgICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgdmFsdWU6IHZhbCxcclxuICAgICAgICAgICAgICAgIHJlc29sdXRpb246IFwiYWNjZXB0XCIsXHJcblxyXG4gICAgICAgICAgICAgICAgYWNjZXB0ZXI6IHJlc29sdmUsXHJcbiAgICAgICAgICAgICAgICByZWplY3RlcjogcmVqZWN0LFxyXG4gICAgICAgICAgICAgIH0gYXMgRmxvd0ZpbmlzaGVyXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGFjdGlvblR5cGU6IEFjdGlvbkNvbnRleHRBY3Rpb25UeXBlLkFzeW5jLFxyXG4gICAgICAgICAgICBvdmVycmlkZUNvbnRleHQ6IGN0eE92ZXJyaWRlKEFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlLlJldHVybiksXHJcbiAgICAgICAgICAgIGlzRmxvd0ZpbmlzaGVyOiB0cnVlLFxyXG4gICAgICAgICAgfSkuY2FsbCh0YXJnZXQsIHJldC52YWx1ZSlcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLy8gY29udGludWVcclxuICAgICAgICAgIFByb21pc2UucmVzb2x2ZShyZXQudmFsdWUpLnRoZW4ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBvbkZ1bGZpbGxlZCh1bmRlZmluZWQpIC8vIGtpY2sgb2ZmIHRoZSBwcm9jZXNzXHJcbiAgICB9KVxyXG5cclxuICAgIHJldHVybiBwcm9taXNlXHJcbiAgfVxyXG4gIDsoZmxvd0ZuIGFzIGFueSlbbW9kZWxGbG93U3ltYm9sXSA9IHRydWVcclxuXHJcbiAgcmV0dXJuIGZsb3dGblxyXG59XHJcblxyXG4vKipcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEZsb3dGaW5pc2hlciB7XHJcbiAgdmFsdWU6IGFueVxyXG4gIHJlc29sdXRpb246IFwiYWNjZXB0XCIgfCBcInJlamVjdFwiXHJcblxyXG4gIGFjY2VwdGVyKHZhbHVlOiBhbnkpOiB2b2lkXHJcbiAgcmVqZWN0ZXIodmFsdWU6IGFueSk6IHZvaWRcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgaWYgdGhlIGdpdmVuIGZ1bmN0aW9uIGlzIGEgbW9kZWwgZmxvdyBvciBub3QuXHJcbiAqXHJcbiAqIEBwYXJhbSBmbiBGdW5jdGlvbiB0byBjaGVjay5cclxuICogQHJldHVybnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc01vZGVsRmxvdyhmbjogdW5rbm93bikge1xyXG4gIHJldHVybiB0eXBlb2YgZm4gPT09IFwiZnVuY3Rpb25cIiAmJiBtb2RlbEZsb3dTeW1ib2wgaW4gZm5cclxufVxyXG5cclxuLyoqXHJcbiAqIERlY29yYXRvciB0aGF0IHR1cm5zIGEgZnVuY3Rpb24gZ2VuZXJhdG9yIGludG8gYSBtb2RlbCBmbG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIG1vZGVsRmxvdyguLi5hcmdzOiBhbnlbXSk6IHZvaWQge1xyXG4gIHJldHVybiBkZWNvcmF0ZVdyYXBNZXRob2RPckZpZWxkKFwibW9kZWxGbG93XCIsIGFyZ3MsIChkYXRhLCBmbikgPT4ge1xyXG4gICAgaWYgKGlzTW9kZWxGbG93KGZuKSkge1xyXG4gICAgICByZXR1cm4gZm5cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICh0eXBlb2YgZm4gIT09IFwiZnVuY3Rpb25cIikge1xyXG4gICAgICAgIHRocm93IGZhaWx1cmUoXCJtb2RlbEZsb3cgaGFzIHRvIGJlIHVzZWQgb3ZlciBmdW5jdGlvbnNcIilcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIGZsb3coe1xyXG4gICAgICAgIG5hbWVPck5hbWVGbjogZGF0YS5hY3Rpb25OYW1lLFxyXG4gICAgICAgIGdlbmVyYXRvcjogZm4sXHJcbiAgICAgICAgb3ZlcnJpZGVDb250ZXh0OiBkYXRhLm92ZXJyaWRlQ29udGV4dCxcclxuICAgICAgfSlcclxuICAgIH1cclxuICB9KVxyXG59XHJcblxyXG4vKipcclxuICogVHJpY2tzIHRoZSBUUyBjb21waWxlciBpbnRvIHRoaW5raW5nIHRoYXQgYSBtb2RlbCBmbG93IGdlbmVyYXRvciBmdW5jdGlvbiBjYW4gYmUgYXdhaXRlZFxyXG4gKiAoaXMgYSBwcm9taXNlKS5cclxuICpcclxuICogQHR5cGVwYXJhbSBBIEZ1bmN0aW9uIGFyZ3VtZW50cy5cclxuICogQHR5cGVwYXJhbSBSIFJldHVybiB2YWx1ZS5cclxuICogQHBhcmFtIGZuIEZsb3cgZnVuY3Rpb24uXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gX2FzeW5jPEEgZXh0ZW5kcyBhbnlbXSwgUj4oXHJcbiAgZm46ICguLi5hcmdzOiBBKSA9PiBHZW5lcmF0b3I8YW55LCBSLCBhbnk+XHJcbik6ICguLi5hcmdzOiBBKSA9PiBQcm9taXNlPFI+IHtcclxuICByZXR1cm4gZm4gYXMgYW55XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBNYWtlcyBhIHByb21pc2UgYSBmbG93LCBzbyBpdCBjYW4gYmUgYXdhaXRlZCB3aXRoIHlpZWxkKi5cclxuICpcclxuICogQHR5cGVwYXJhbSBUIFByb21pc2UgcmV0dXJuIHR5cGUuXHJcbiAqIEBwYXJhbSBwcm9taXNlIFByb21pc2UuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gX2F3YWl0PFQ+KHByb21pc2U6IFByb21pc2U8VD4pOiBHZW5lcmF0b3I8UHJvbWlzZTxUPiwgVCwgdW5rbm93bj4ge1xyXG4gIHJldHVybiBwcm9taXNlR2VuZXJhdG9yLmNhbGwocHJvbWlzZSlcclxufVxyXG5cclxuLypcclxuZnVuY3Rpb24qIHByb21pc2VHZW5lcmF0b3I8VD4oXHJcbiAgdGhpczogUHJvbWlzZTxUPlxyXG4pIHtcclxuICBjb25zdCByZXQ6IFQgPSB5aWVsZCB0aGlzXHJcbiAgcmV0dXJuIHJldFxyXG59XHJcbiovXHJcblxyXG4vLyBhYm92ZSBjb2RlIGJ1dCBjb21waWxlZCBieSBUUyBmb3IgRVM1XHJcbi8vIHNvIHdlIGRvbid0IGluY2x1ZGUgYSBkZXBlbmRlbmN5IHRvIHJlZ2VuZXJhdG9yIHJ1bnRpbWVcclxuXHJcbmNvbnN0IF9fZ2VuZXJhdG9yID0gZnVuY3Rpb24gKHRoaXNBcmc6IGFueSwgYm9keTogYW55KSB7XHJcbiAgbGV0IF86IGFueSA9IHtcclxuICAgICAgbGFiZWw6IDAsXHJcbiAgICAgIHNlbnQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBpZiAodFswXSAmIDEpIHRocm93IHRbMV1cclxuICAgICAgICByZXR1cm4gdFsxXVxyXG4gICAgICB9LFxyXG4gICAgICB0cnlzOiBbXSxcclxuICAgICAgb3BzOiBbXSxcclxuICAgIH0sXHJcbiAgICBmOiBhbnksXHJcbiAgICB5OiBhbnksXHJcbiAgICB0OiBhbnksXHJcbiAgICBnOiBhbnlcclxuICByZXR1cm4gKFxyXG4gICAgKGcgPSB7IG5leHQ6IHZlcmIoMCksIHRocm93OiB2ZXJiKDEpLCByZXR1cm46IHZlcmIoMikgfSksXHJcbiAgICB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiZcclxuICAgICAgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gdGhpc1xyXG4gICAgICB9KSxcclxuICAgIGdcclxuICApXHJcbiAgZnVuY3Rpb24gdmVyYihuOiBhbnkpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodjogYW55KSB7XHJcbiAgICAgIHJldHVybiBzdGVwKFtuLCB2XSlcclxuICAgIH1cclxuICB9XHJcbiAgZnVuY3Rpb24gc3RlcChvcDogYW55KSB7XHJcbiAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIilcclxuICAgIHdoaWxlIChfKVxyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgICgoZiA9IDEpLFxyXG4gICAgICAgICAgeSAmJlxyXG4gICAgICAgICAgICAodCA9XHJcbiAgICAgICAgICAgICAgb3BbMF0gJiAyXHJcbiAgICAgICAgICAgICAgICA/IHlbXCJyZXR1cm5cIl1cclxuICAgICAgICAgICAgICAgIDogb3BbMF1cclxuICAgICAgICAgICAgICAgID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMClcclxuICAgICAgICAgICAgICAgIDogeS5uZXh0KSAmJlxyXG4gICAgICAgICAgICAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKVxyXG4gICAgICAgIClcclxuICAgICAgICAgIHJldHVybiB0XHJcbiAgICAgICAgaWYgKCgoeSA9IDApLCB0KSkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXVxyXG4gICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgIGNhc2UgMDpcclxuICAgICAgICAgIGNhc2UgMTpcclxuICAgICAgICAgICAgdCA9IG9wXHJcbiAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICBjYXNlIDQ6XHJcbiAgICAgICAgICAgIF8ubGFiZWwrK1xyXG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH1cclxuICAgICAgICAgIGNhc2UgNTpcclxuICAgICAgICAgICAgXy5sYWJlbCsrXHJcbiAgICAgICAgICAgIHkgPSBvcFsxXVxyXG4gICAgICAgICAgICBvcCA9IFswXVxyXG4gICAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgICAgY2FzZSA3OlxyXG4gICAgICAgICAgICBvcCA9IF8ub3BzLnBvcCgpXHJcbiAgICAgICAgICAgIF8udHJ5cy5wb3AoKVxyXG4gICAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICEoKHQgPSBfLnRyeXMpLCAodCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pKSAmJlxyXG4gICAgICAgICAgICAgIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMilcclxuICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgXyA9IDBcclxuICAgICAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkge1xyXG4gICAgICAgICAgICAgIF8ubGFiZWwgPSBvcFsxXVxyXG4gICAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7XHJcbiAgICAgICAgICAgICAgXy5sYWJlbCA9IHRbMV1cclxuICAgICAgICAgICAgICB0ID0gb3BcclxuICAgICAgICAgICAgICBicmVha1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7XHJcbiAgICAgICAgICAgICAgXy5sYWJlbCA9IHRbMl1cclxuICAgICAgICAgICAgICBfLm9wcy5wdXNoKG9wKVxyXG4gICAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpXHJcbiAgICAgICAgICAgIF8udHJ5cy5wb3AoKVxyXG4gICAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgIH1cclxuICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKVxyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgb3AgPSBbNiwgZV1cclxuICAgICAgICB5ID0gMFxyXG4gICAgICB9IGZpbmFsbHkge1xyXG4gICAgICAgIGYgPSB0ID0gMFxyXG4gICAgICB9XHJcbiAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXVxyXG4gICAgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfVxyXG4gIH1cclxufVxyXG5cclxuZnVuY3Rpb24gcHJvbWlzZUdlbmVyYXRvcih0aGlzOiBQcm9taXNlPGFueT4pIHtcclxuICBsZXQgcmV0XHJcbiAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uICh0aGlzOiBhbnksIF9hOiBhbnkpIHtcclxuICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcclxuICAgICAgY2FzZSAwOlxyXG4gICAgICAgIHJldHVybiBbNCAvKnlpZWxkKi8sIHRoaXNdXHJcbiAgICAgIGNhc2UgMTpcclxuICAgICAgICByZXQgPSBfYS5zZW50KClcclxuICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qLywgcmV0XVxyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIHJldHVyblxyXG4gICAgfVxyXG4gIH0pXHJcbn1cclxuIiwiaW1wb3J0IHsgQWN0aW9uQ29udGV4dEFjdGlvblR5cGUgfSBmcm9tIFwiLi4vYWN0aW9uL2NvbnRleHRcIlxuaW1wb3J0IHsgaXNNb2RlbEFjdGlvbiB9IGZyb20gXCIuLi9hY3Rpb24vaXNNb2RlbEFjdGlvblwiXG5pbXBvcnQgeyBmbG93LCBpc01vZGVsRmxvdyB9IGZyb20gXCIuLi9hY3Rpb24vbW9kZWxGbG93XCJcbmltcG9ydCB7IHdyYXBJbkFjdGlvbiB9IGZyb20gXCIuLi9hY3Rpb24vd3JhcEluQWN0aW9uXCJcbmltcG9ydCB7IGFzc2VydElzVHJlZU5vZGUgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcbmltcG9ydCB7IGFzc2VydElzRnVuY3Rpb24sIGZhaWx1cmUsIGxvZ1dhcm5pbmcgfSBmcm9tIFwiLi4vdXRpbHNcIlxuXG4vKipcbiAqIEEgZnVuY3Rpb24gd2l0aCBhbiBvYmplY3QgYXMgdGFyZ2V0LlxuICovXG50eXBlIFRhcmdldGVkQWN0aW9uID0gKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnlcblxuY29uc3Qgc3RhbmRhbG9uZUFjdGlvblJlZ2lzdHJ5ID0gbmV3IE1hcDxzdHJpbmcsIFRhcmdldGVkQWN0aW9uPigpXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFuZGFsb25lQWN0aW9uKGFjdGlvbk5hbWU6IHN0cmluZykge1xuICByZXR1cm4gc3RhbmRhbG9uZUFjdGlvblJlZ2lzdHJ5LmdldChhY3Rpb25OYW1lKVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRkU3RhbmRhbG9uZUFjdGlvbihmdWxsQWN0aW9uTmFtZTogc3RyaW5nLCBmbjogVGFyZ2V0ZWRBY3Rpb24sIGlzRmxvdzogYm9vbGVhbikge1xuICBhc3NlcnRJc0Z1bmN0aW9uKGZuLCBmdWxsQWN0aW9uTmFtZSlcblxuICBpZiAoc3RhbmRhbG9uZUFjdGlvblJlZ2lzdHJ5LmhhcyhmdWxsQWN0aW9uTmFtZSkpIHtcbiAgICBsb2dXYXJuaW5nKFxuICAgICAgXCJ3YXJuXCIsXG4gICAgICBgYW4gc3RhbmRhbG9uZSBhY3Rpb24gd2l0aCBuYW1lIFwiJHtmdWxsQWN0aW9uTmFtZX1cIiBhbHJlYWR5IGV4aXN0cyAoaWYgeW91IGFyZSB1c2luZyBob3QtcmVsb2FkaW5nIHlvdSBtYXkgc2FmZWx5IGlnbm9yZSB0aGlzIHdhcm5pbmcpYCxcbiAgICAgIGBkdXBsaWNhdGVBY3Rpb25OYW1lIC0gJHtmdWxsQWN0aW9uTmFtZX1gXG4gICAgKVxuICB9XG5cbiAgaWYgKGlzTW9kZWxBY3Rpb24oZm4pKSB7XG4gICAgdGhyb3cgZmFpbHVyZShcInRoZSBzdGFuZGFsb25lIGFjdGlvbiBtdXN0IG5vdCBiZSBwcmV2aW91c2x5IG1hcmtlZCBhcyBhbiBhY3Rpb25cIilcbiAgfVxuICBpZiAoaXNNb2RlbEZsb3coZm4pKSB7XG4gICAgdGhyb3cgZmFpbHVyZShcInRoZSBzdGFuZGFsb25lIGFjdGlvbiBtdXN0IG5vdCBiZSBwcmV2aW91c2x5IG1hcmtlZCBhcyBhIGZsb3cgYWN0aW9uXCIpXG4gIH1cblxuICBjb25zdCB3cmFwcGVkQWN0aW9uID0gaXNGbG93XG4gICAgPyBmbG93KHsgbmFtZU9yTmFtZUZuOiBmdWxsQWN0aW9uTmFtZSwgZ2VuZXJhdG9yOiBmbiB9KVxuICAgIDogd3JhcEluQWN0aW9uKHtcbiAgICAgICAgbmFtZU9yTmFtZUZuOiBmdWxsQWN0aW9uTmFtZSxcbiAgICAgICAgZm4sXG4gICAgICAgIGFjdGlvblR5cGU6IEFjdGlvbkNvbnRleHRBY3Rpb25UeXBlLlN5bmMsXG4gICAgICB9KVxuXG4gIGNvbnN0IGZpbmFsQWN0aW9uID0gKHRhcmdldDogYW55LCAuLi5hcmdzOiBhbnlbXSkgPT4ge1xuICAgIGFzc2VydElzVHJlZU5vZGUodGFyZ2V0LCBcInRhcmdldFwiKVxuXG4gICAgLy8gd2UgbmVlZCB0byBwdXQgdGhlIHRhcmdldCBpbnRvIHRoaXNcbiAgICByZXR1cm4gd3JhcHBlZEFjdGlvbi5jYWxsKHRhcmdldCwgdGFyZ2V0LCAuLi5hcmdzKVxuICB9XG5cbiAgc3RhbmRhbG9uZUFjdGlvblJlZ2lzdHJ5LnNldChmdWxsQWN0aW9uTmFtZSwgZmluYWxBY3Rpb24pXG4gIHJldHVybiBmaW5hbEFjdGlvblxufVxuIiwiaW1wb3J0IHsgcmVtb3ZlIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgbGF6eSB9IGZyb20gXCIuLi91dGlsc1wiXG5pbXBvcnQgeyBCdWlsdEluQWN0aW9uIH0gZnJvbSBcIi4vYnVpbHRJbkFjdGlvbnNcIlxuaW1wb3J0IHsgQWN0aW9uQ29udGV4dEFjdGlvblR5cGUgfSBmcm9tIFwiLi9jb250ZXh0XCJcbmltcG9ydCB7IHdyYXBJbkFjdGlvbiB9IGZyb20gXCIuL3dyYXBJbkFjdGlvblwiXG5cbi8qKlxuICogRGVsZXRlcyBhbiBvYmplY3QgZmllbGQgd3JhcHBlZCBpbiBhbiBhY3Rpb24uXG4gKlxuICogQHBhcmFtIG5vZGUgIFRhcmdldCBvYmplY3QuXG4gKiBAcGFyYW0gZmllbGROYW1lIEZpZWxkIG5hbWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseURlbGV0ZTxPIGV4dGVuZHMgb2JqZWN0LCBLIGV4dGVuZHMga2V5b2YgTz4obm9kZTogTywgZmllbGROYW1lOiBLKTogdm9pZCB7XG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZSwgXCJub2RlXCIsIHRydWUpXG5cbiAgd3JhcHBlZEludGVybmFsQXBwbHlEZWxldGUoKS5jYWxsKG5vZGUsIGZpZWxkTmFtZSBhcyBzdHJpbmcgfCBudW1iZXIpXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcm5hbEFwcGx5RGVsZXRlPE8gZXh0ZW5kcyBvYmplY3Q+KHRoaXM6IE8sIGZpZWxkTmFtZTogc3RyaW5nIHwgbnVtYmVyKTogdm9pZCB7XG4gIHJlbW92ZSh0aGlzLCBcIlwiICsgZmllbGROYW1lKVxufVxuXG5jb25zdCB3cmFwcGVkSW50ZXJuYWxBcHBseURlbGV0ZSA9IGxhenkoKCkgPT5cbiAgd3JhcEluQWN0aW9uKHtcbiAgICBuYW1lT3JOYW1lRm46IEJ1aWx0SW5BY3Rpb24uQXBwbHlEZWxldGUsXG4gICAgZm46IGludGVybmFsQXBwbHlEZWxldGUsXG4gICAgYWN0aW9uVHlwZTogQWN0aW9uQ29udGV4dEFjdGlvblR5cGUuU3luYyxcbiAgfSlcbilcbiIsImltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcbmltcG9ydCB7IGxhenkgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHsgQnVpbHRJbkFjdGlvbiB9IGZyb20gXCIuL2J1aWx0SW5BY3Rpb25zXCJcbmltcG9ydCB7IEFjdGlvbkNvbnRleHRBY3Rpb25UeXBlIH0gZnJvbSBcIi4vY29udGV4dFwiXG5pbXBvcnQgeyB3cmFwSW5BY3Rpb24gfSBmcm9tIFwiLi93cmFwSW5BY3Rpb25cIlxuXG50eXBlIEFueUZ1bmN0aW9uID0gKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnlcblxuLyoqXG4gKiBDYWxscyBhbiBvYmplY3QgbWV0aG9kIHdyYXBwZWQgaW4gYW4gYWN0aW9uLlxuICpcbiAqIEBwYXJhbSBub2RlICBUYXJnZXQgb2JqZWN0LlxuICogQHBhcmFtIG1ldGhvZE5hbWUgTWV0aG9kIG5hbWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseU1ldGhvZENhbGw8TyBleHRlbmRzIG9iamVjdCwgSyBleHRlbmRzIGtleW9mIE8sIEZOIGV4dGVuZHMgT1tLXT4oXG4gIG5vZGU6IE8sXG4gIG1ldGhvZE5hbWU6IEssXG4gIC4uLmFyZ3M6IEZOIGV4dGVuZHMgQW55RnVuY3Rpb24gPyBQYXJhbWV0ZXJzPEZOPiA6IG5ldmVyXG4pOiBGTiBleHRlbmRzIEFueUZ1bmN0aW9uID8gUmV0dXJuVHlwZTxGTj4gOiBuZXZlciB7XG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZSwgXCJub2RlXCIpXG5cbiAgcmV0dXJuIHdyYXBwZWRJbnRlcm5hbEFwcGx5TWV0aG9kQ2FsbCgpLmNhbGwobm9kZSwgbWV0aG9kTmFtZSBhcyBzdHJpbmcgfCBudW1iZXIsIGFyZ3MpXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcm5hbEFwcGx5TWV0aG9kQ2FsbCh0aGlzOiBhbnksIG1ldGhvZE5hbWU6IHN0cmluZyB8IG51bWJlciwgYXJnczogYW55W10pOiBhbnkge1xuICByZXR1cm4gdGhpc1ttZXRob2ROYW1lXSguLi5hcmdzKVxufVxuXG5jb25zdCB3cmFwcGVkSW50ZXJuYWxBcHBseU1ldGhvZENhbGwgPSBsYXp5KCgpID0+XG4gIHdyYXBJbkFjdGlvbih7XG4gICAgbmFtZU9yTmFtZUZuOiBCdWlsdEluQWN0aW9uLkFwcGx5TWV0aG9kQ2FsbCxcbiAgICBmbjogaW50ZXJuYWxBcHBseU1ldGhvZENhbGwsXG4gICAgYWN0aW9uVHlwZTogQWN0aW9uQ29udGV4dEFjdGlvblR5cGUuU3luYyxcbiAgfSlcbilcbiIsImltcG9ydCB7IGlzT2JzZXJ2YWJsZSB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IGlzTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvdXRpbHNcIlxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgbGF6eSB9IGZyb20gXCIuLi91dGlsc1wiXG5pbXBvcnQgeyBzZXRJZkRpZmZlcmVudCB9IGZyb20gXCIuLi91dGlscy9zZXRJZkRpZmZlcmVudFwiXG5pbXBvcnQgeyBCdWlsdEluQWN0aW9uIH0gZnJvbSBcIi4vYnVpbHRJbkFjdGlvbnNcIlxuaW1wb3J0IHsgQWN0aW9uQ29udGV4dEFjdGlvblR5cGUgfSBmcm9tIFwiLi9jb250ZXh0XCJcbmltcG9ydCB7IHdyYXBJbkFjdGlvbiB9IGZyb20gXCIuL3dyYXBJbkFjdGlvblwiXG5cbi8qKlxuICogU2V0cyBhbiBvYmplY3QgZmllbGQgd3JhcHBlZCBpbiBhbiBhY3Rpb24uXG4gKlxuICogQHBhcmFtIG5vZGUgIFRhcmdldCBvYmplY3QuXG4gKiBAcGFyYW0gZmllbGROYW1lIEZpZWxkIG5hbWUuXG4gKiBAcGFyYW0gdmFsdWUgVmFsdWUgdG8gc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlTZXQ8TyBleHRlbmRzIG9iamVjdCwgSyBleHRlbmRzIGtleW9mIE8sIFYgZXh0ZW5kcyBPW0tdPihcbiAgbm9kZTogTyxcbiAgZmllbGROYW1lOiBLLFxuICB2YWx1ZTogVlxuKTogdm9pZCB7XG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZSwgXCJub2RlXCIsIHRydWUpXG5cbiAgd3JhcHBlZEludGVybmFsQXBwbHlTZXQoKS5jYWxsKG5vZGUsIGZpZWxkTmFtZSBhcyBzdHJpbmcgfCBudW1iZXIsIHZhbHVlKVxufVxuXG5mdW5jdGlvbiBpbnRlcm5hbEFwcGx5U2V0PE8gZXh0ZW5kcyBvYmplY3Q+KHRoaXM6IE8sIGZpZWxkTmFtZTogc3RyaW5nIHwgbnVtYmVyLCB2YWx1ZTogYW55KTogdm9pZCB7XG4gIC8vIHdlIG5lZWQgdG8gY2hlY2sgaWYgaXQgaXMgYSBtb2RlbCBzaW5jZSBtb2RlbHMgY2FuIGJlY29tZSBvYnNlcnZhYmxlIG9iamVjdHNcbiAgLy8gKGUuZy4gYnkgaGF2aW5nIGEgY29tcHV0ZWQgdmFsdWUpXG4gIGlmICghaXNNb2RlbCh0aGlzKSAmJiBpc09ic2VydmFibGUodGhpcykpIHtcbiAgICBzZXRJZkRpZmZlcmVudCh0aGlzLCBmaWVsZE5hbWUsIHZhbHVlKVxuICB9IGVsc2Uge1xuICAgIDsodGhpcyBhcyBhbnkpW2ZpZWxkTmFtZV0gPSB2YWx1ZVxuICB9XG59XG5cbmNvbnN0IHdyYXBwZWRJbnRlcm5hbEFwcGx5U2V0ID0gbGF6eSgoKSA9PlxuICB3cmFwSW5BY3Rpb24oe1xuICAgIG5hbWVPck5hbWVGbjogQnVpbHRJbkFjdGlvbi5BcHBseVNldCxcbiAgICBmbjogaW50ZXJuYWxBcHBseVNldCxcbiAgICBhY3Rpb25UeXBlOiBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZS5TeW5jLFxuICB9KVxuKVxuIiwiaW1wb3J0IHsgZ2V0RGF0YU1vZGVsQWN0aW9uIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9hY3Rpb25zXCJcbmltcG9ydCB7IGRldGFjaCB9IGZyb20gXCIuLi9wYXJlbnQvZGV0YWNoXCJcbmltcG9ydCB7IHJlc29sdmVQYXRoQ2hlY2tpbmdJZHMgfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxuaW1wb3J0IHsgUGF0aCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFR5cGVzXCJcbmltcG9ydCB7IGFwcGx5UGF0Y2hlcyB9IGZyb20gXCIuLi9wYXRjaC9hcHBseVBhdGNoZXNcIlxuaW1wb3J0IHsgYXBwbHlTbmFwc2hvdCB9IGZyb20gXCIuLi9zbmFwc2hvdC9hcHBseVNuYXBzaG90XCJcbmltcG9ydCB7IGdldFN0YW5kYWxvbmVBY3Rpb24gfSBmcm9tIFwiLi4vc3RhbmRhcmRBY3Rpb25zL2FjdGlvbnNcIlxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXG5pbXBvcnQgeyBhcHBseURlbGV0ZSB9IGZyb20gXCIuL2FwcGx5RGVsZXRlXCJcbmltcG9ydCB7IGFwcGx5TWV0aG9kQ2FsbCB9IGZyb20gXCIuL2FwcGx5TWV0aG9kQ2FsbFwiXG5pbXBvcnQgeyBhcHBseVNldCB9IGZyb20gXCIuL2FwcGx5U2V0XCJcbmltcG9ydCB7IEJ1aWx0SW5BY3Rpb24sIGlzQnVpbHRJbkFjdGlvbiB9IGZyb20gXCIuL2J1aWx0SW5BY3Rpb25zXCJcbmltcG9ydCB7IGlzSG9va0FjdGlvbiB9IGZyb20gXCIuL2hvb2tBY3Rpb25zXCJcblxuLyoqXG4gKiBBbiBhY3Rpb24gY2FsbC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBY3Rpb25DYWxsIHtcbiAgLyoqXG4gICAqIEFjdGlvbiBuYW1lIChuYW1lIG9mIHRoZSBmdW5jdGlvbikuXG4gICAqL1xuICByZWFkb25seSBhY3Rpb25OYW1lOiBzdHJpbmdcblxuICAvKipcbiAgICogQWN0aW9uIGFyZ3VtZW50cy5cbiAgICovXG4gIHJlYWRvbmx5IGFyZ3M6IFJlYWRvbmx5QXJyYXk8YW55PlxuXG4gIC8qKlxuICAgKiBQYXRoIHRvIHRoZSBtb2RlbCB3aGVyZSB0aGUgYWN0aW9uIHdpbGwgYmUgcnVuLCBhcyBhbiBhcnJheSBvZiBzdHJpbmcgfCBudW1iZXIuXG4gICAqL1xuICByZWFkb25seSB0YXJnZXRQYXRoOiBQYXRoXG5cbiAgLyoqXG4gICAqIElkcyBvZiBtb2RlbHMgYWxvbmcgdGhlIHBhdGggdG8gdGhlIHRhcmdldCwgbnVsbCBpZiBpdCBpcyBub3QgYSBtb2RlbC5cbiAgICovXG4gIHJlYWRvbmx5IHRhcmdldFBhdGhJZHM6IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVsbD5cblxuICAvKipcbiAgICogTWFya3MgdGhpcyBhY3Rpb24gY2FsbCBhcyBub24tc2VyaWFsaXplZC5cbiAgICovXG4gIHJlYWRvbmx5IHNlcmlhbGl6ZWQ/OiB1bmRlZmluZWRcbn1cblxuY29uc3QgYnVpbHRJbkFjdGlvblRvRnVuY3Rpb24gPSB7XG4gIFtCdWlsdEluQWN0aW9uLkFwcGx5U25hcHNob3RdOiBhcHBseVNuYXBzaG90LFxuICBbQnVpbHRJbkFjdGlvbi5BcHBseVBhdGNoZXNdOiBhcHBseVBhdGNoZXMsXG4gIFtCdWlsdEluQWN0aW9uLkRldGFjaF06IGRldGFjaCxcbiAgW0J1aWx0SW5BY3Rpb24uQXBwbHlTZXRdOiBhcHBseVNldCxcbiAgW0J1aWx0SW5BY3Rpb24uQXBwbHlEZWxldGVdOiBhcHBseURlbGV0ZSxcbiAgW0J1aWx0SW5BY3Rpb24uQXBwbHlNZXRob2RDYWxsXTogYXBwbHlNZXRob2RDYWxsLFxufVxuXG4vKipcbiAqIEFwcGxpZXMgKHJ1bnMpIGFuIGFjdGlvbiBvdmVyIGEgdGFyZ2V0IG9iamVjdC5cbiAqXG4gKiBJZiB5b3UgaW50ZW5kIHRvIGFwcGx5IHNlcmlhbGl6ZWQgYWN0aW9ucyBjaGVjayBvbmUgb2YgdGhlIGBhcHBseVNlcmlhbGl6ZWRBY3Rpb25gIG1ldGhvZHMgaW5zdGVhZC5cbiAqXG4gKiBAcGFyYW0gc3VidHJlZVJvb3QgU3VidHJlZSByb290IHRhcmdldCBvYmplY3QgdG8gcnVuIHRoZSBhY3Rpb24gb3Zlci5cbiAqIEBwYXJhbSBjYWxsIFRoZSBhY3Rpb24sIHVzdWFsbHkgYXMgY29taW5nIGZyb20gYG9uQWN0aW9uTWlkZGxld2FyZWAuXG4gKiBAcmV0dXJucyBUaGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBhY3Rpb24sIGlmIGFueS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5QWN0aW9uPFRSZXQgPSBhbnk+KHN1YnRyZWVSb290OiBvYmplY3QsIGNhbGw6IEFjdGlvbkNhbGwpOiBUUmV0IHtcbiAgaWYgKGNhbGwuc2VyaWFsaXplZCkge1xuICAgIHRocm93IGZhaWx1cmUoXG4gICAgICBcImNhbm5vdCBhcHBseSBhIHNlcmlhbGl6ZWQgYWN0aW9uIGNhbGwsIHVzZSBvbmUgb2YgdGhlICdhcHBseVNlcmlhbGl6ZWRBY3Rpb24nIG1ldGhvZHMgaW5zdGVhZFwiXG4gICAgKVxuICB9XG5cbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChzdWJ0cmVlUm9vdCwgXCJzdWJ0cmVlUm9vdFwiKVxuXG4gIC8vIHJlc29sdmUgcGF0aCB3aGlsZSBjaGVja2luZyBpZHNcbiAgY29uc3QgeyB2YWx1ZTogY3VycmVudCwgcmVzb2x2ZWQgfSA9IHJlc29sdmVQYXRoQ2hlY2tpbmdJZHMoXG4gICAgc3VidHJlZVJvb3QsXG4gICAgY2FsbC50YXJnZXRQYXRoLFxuICAgIGNhbGwudGFyZ2V0UGF0aElkc1xuICApXG4gIGlmICghcmVzb2x2ZWQpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFxuICAgICAgYG9iamVjdCBhdCBwYXRoICR7SlNPTi5zdHJpbmdpZnkoY2FsbC50YXJnZXRQYXRoKX0gd2l0aCBpZHMgJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgY2FsbC50YXJnZXRQYXRoSWRzXG4gICAgICApfSBjb3VsZCBub3QgYmUgcmVzb2x2ZWRgXG4gICAgKVxuICB9XG4gIGFzc2VydFR3ZWFrZWRPYmplY3QoY3VycmVudCwgYHJlc29sdmVkICR7Y3VycmVudH1gLCB0cnVlKVxuXG4gIGlmIChpc0J1aWx0SW5BY3Rpb24oY2FsbC5hY3Rpb25OYW1lKSkge1xuICAgIGNvbnN0IGZuVG9DYWxsOiAoLi4uYXJnczogYW55W10pID0+IGFueSA9IGJ1aWx0SW5BY3Rpb25Ub0Z1bmN0aW9uW2NhbGwuYWN0aW9uTmFtZV1cbiAgICBpZiAoIWZuVG9DYWxsKSB7XG4gICAgICB0aHJvdyBmYWlsdXJlKGBhc3NlcnRpb24gZmFpbGVkOiB1bmtub3duIGJ1aWx0LWluIGFjdGlvbiAtICR7Y2FsbC5hY3Rpb25OYW1lfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIGZuVG9DYWxsLmFwcGx5KGN1cnJlbnQsIFtjdXJyZW50LCAuLi5jYWxsLmFyZ3NdKVxuICB9XG5cbiAgaWYgKGlzSG9va0FjdGlvbihjYWxsLmFjdGlvbk5hbWUpKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgY2FsbHMgdG8gaG9va3MgKCR7Y2FsbC5hY3Rpb25OYW1lfSkgY2Fubm90IGJlIGFwcGxpZWRgKVxuICB9XG5cbiAgY29uc3QgZGF0YU1vZGVsQWN0aW9uID0gZ2V0RGF0YU1vZGVsQWN0aW9uKGNhbGwuYWN0aW9uTmFtZSlcbiAgaWYgKGRhdGFNb2RlbEFjdGlvbikge1xuICAgIGNvbnN0IGluc3RhbmNlOiBhbnkgPSBuZXcgZGF0YU1vZGVsQWN0aW9uLm1vZGVsQ2xhc3MoY3VycmVudClcbiAgICByZXR1cm4gaW5zdGFuY2VbZGF0YU1vZGVsQWN0aW9uLmZuTmFtZV0uYXBwbHkoaW5zdGFuY2UsIGNhbGwuYXJncylcbiAgfVxuXG4gIGNvbnN0IHN0YW5kYWxvbmVBY3Rpb24gPSBnZXRTdGFuZGFsb25lQWN0aW9uKGNhbGwuYWN0aW9uTmFtZSlcbiAgaWYgKHN0YW5kYWxvbmVBY3Rpb24pIHtcbiAgICByZXR1cm4gc3RhbmRhbG9uZUFjdGlvbi5hcHBseShjdXJyZW50LCBjYWxsLmFyZ3MgYXMgYW55KVxuICB9XG5cbiAgcmV0dXJuIChjdXJyZW50IGFzIGFueSlbY2FsbC5hY3Rpb25OYW1lXS5hcHBseShjdXJyZW50LCBjYWxsLmFyZ3MpXG59XG4iLCJpbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgZGVjb3JhdGVXcmFwTWV0aG9kT3JGaWVsZCB9IGZyb20gXCIuLi91dGlscy9kZWNvcmF0b3JzXCJcclxuaW1wb3J0IHsgQWN0aW9uQ29udGV4dEFjdGlvblR5cGUgfSBmcm9tIFwiLi9jb250ZXh0XCJcclxuaW1wb3J0IHsgaXNNb2RlbEFjdGlvbiB9IGZyb20gXCIuL2lzTW9kZWxBY3Rpb25cIlxyXG5pbXBvcnQgeyB3cmFwSW5BY3Rpb24gfSBmcm9tIFwiLi93cmFwSW5BY3Rpb25cIlxyXG5cclxuLyoqXHJcbiAqIERlY29yYXRvciB0aGF0IHR1cm5zIGEgZnVuY3Rpb24gaW50byBhIG1vZGVsIGFjdGlvbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBtb2RlbEFjdGlvbiguLi5hcmdzOiBhbnlbXSk6IHZvaWQge1xyXG4gIHJldHVybiBkZWNvcmF0ZVdyYXBNZXRob2RPckZpZWxkKFwibW9kZWxBY3Rpb25cIiwgYXJncywgKGRhdGEsIGZuKSA9PiB7XHJcbiAgICBpZiAoaXNNb2RlbEFjdGlvbihmbikpIHtcclxuICAgICAgcmV0dXJuIGZuXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAodHlwZW9mIGZuICE9PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgICAgICB0aHJvdyBmYWlsdXJlKFwibW9kZWxBY3Rpb24gaGFzIHRvIGJlIHVzZWQgb3ZlciBmdW5jdGlvbnNcIilcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIHdyYXBJbkFjdGlvbih7XHJcbiAgICAgICAgbmFtZU9yTmFtZUZuOiBkYXRhLmFjdGlvbk5hbWUsXHJcbiAgICAgICAgZm4sXHJcbiAgICAgICAgYWN0aW9uVHlwZTogQWN0aW9uQ29udGV4dEFjdGlvblR5cGUuU3luYyxcclxuICAgICAgICBvdmVycmlkZUNvbnRleHQ6IGRhdGEub3ZlcnJpZGVDb250ZXh0LFxyXG4gICAgICB9KVxyXG4gICAgfVxyXG4gIH0pXHJcbn1cclxuIiwiaW1wb3J0IHsgYWN0aW9uIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgdHJ5UnVuUGVuZGluZ0FjdGlvbnMgfSBmcm9tIFwiLi9wZW5kaW5nQWN0aW9uc1wiXG5pbXBvcnQgeyBnZXRBY3Rpb25Qcm90ZWN0aW9uLCBzZXRBY3Rpb25Qcm90ZWN0aW9uIH0gZnJvbSBcIi4vcHJvdGVjdGlvblwiXG5cbi8qKlxuICogUnVucyBhIGJsb2NrIGluIHVucHJvY3RlZCBtb2RlLCBhcyBpZiBpdCB3ZXJlIHJ1biBpbnNpZGUgYSBtb2RlbCBhY3Rpb24uXG4gKiBDb25zaWRlciB1c2luZyBhIHByb3BlciBtb2RlbCBhY3Rpb24gaW5zdGVhZCBzaW5jZSB0aGVzZSBraW5kIG9mIGFjdGlvbnMgYXJlIG5vdCByZWNvcmRlZC5cbiAqXG4gKiBAdHlwZXBhcmFtIFQgUmV0dXJuIHR5cGUuXG4gKiBAcGFyYW0gbmFtZSBNb2J4IGFjdGlvbiBuYW1lLlxuICogQHBhcmFtIGZuIEFjdGlvbiBibG9jay5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5VbnByb3RlY3RlZDxUPihuYW1lOiBzdHJpbmcsIGZuOiAoKSA9PiBUKTogVFxuXG4vKipcbiAqIFJ1bnMgYSBibG9jayBpbiB1bnByb2N0ZWQgbW9kZSwgYXMgaWYgaXQgd2VyZSBydW4gaW5zaWRlIGEgbW9kZWwgYWN0aW9uLlxuICogQ29uc2lkZXIgdXNpbmcgYSBwcm9wZXIgbW9kZWwgYWN0aW9uIGluc3RlYWQgc2luY2UgdGhlc2Uga2luZCBvZiBhY3Rpb25zIGFyZSBub3QgcmVjb3JkZWQuXG4gKlxuICogQHR5cGVwYXJhbSBUIFJldHVybiB0eXBlLlxuICogQHBhcmFtIGZuIEFjdGlvbiBibG9jay5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5VbnByb3RlY3RlZDxUPihmbjogKCkgPT4gVCk6IFRcblxuLy8gYmFzZSBjYXNlXG5leHBvcnQgZnVuY3Rpb24gcnVuVW5wcm90ZWN0ZWQ8VD4oYXJnMTogYW55LCBhcmcyPzogYW55KTogVCB7XG4gIGNvbnN0IG5hbWUgPSB0eXBlb2YgYXJnMSA9PT0gXCJzdHJpbmdcIiA/IGFyZzEgOiB1bmRlZmluZWRcbiAgY29uc3QgZm46ICgpID0+IFQgPSB0eXBlb2YgYXJnMSA9PT0gXCJzdHJpbmdcIiA/IGFyZzIgOiBhcmcxXG5cbiAgY29uc3QgaW5uZXJBY3Rpb24gPSAoKSA9PiB7XG4gICAgY29uc3Qgb2xkQWN0aW9uUHJvdGVjdGlvbiA9IGdldEFjdGlvblByb3RlY3Rpb24oKVxuICAgIHNldEFjdGlvblByb3RlY3Rpb24oZmFsc2UpXG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGZuKClcbiAgICB9IGZpbmFsbHkge1xuICAgICAgc2V0QWN0aW9uUHJvdGVjdGlvbihvbGRBY3Rpb25Qcm90ZWN0aW9uKVxuXG4gICAgICB0cnlSdW5QZW5kaW5nQWN0aW9ucygpXG4gICAgfVxuICB9XG5cbiAgaWYgKG5hbWUpIHtcbiAgICByZXR1cm4gYWN0aW9uKG5hbWUsIGlubmVyQWN0aW9uKSgpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGFjdGlvbihpbm5lckFjdGlvbikoKVxuICB9XG59XG4iLCJleHBvcnQgY29uc3QgY2Fubm90U2VyaWFsaXplID0gU3ltYm9sKFwiY2Fubm90U2VyaWFsaXplXCIpXG5cbi8qKlxuICogU2VyaWFsaXplciBvZiBhY3Rpb24gY2FsbCBhcmd1bWVudHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcjxUT3JpZ2luYWwsIFRTZXJpYWxpemVkPiB7XG4gIC8qKlxuICAgKiBTZXJpYWxpemVyIElELCBtdXN0IGJlIHVuaXF1ZS5cbiAgICovXG4gIGlkOiBzdHJpbmdcblxuICAvKipcbiAgICogU2VyaWFsaXplcyBhbiBhY3Rpb24gY2FsbCBhcmd1bWVudCwgcmV0dXJuaW5nIGBjYW5ub3RTZXJpYWxpemVgIGlmIG5vdCBwb3NzaWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIFZhbHVlIHRvIHNlcmlhbGl6ZS5cbiAgICogQHBhcmFtIHRhcmdldFJvb3QgVGFyZ2V0IHJvb3QsIGlmIHByb3ZpZGVkLlxuICAgKiBAcGFyYW0gc2VyaWFsaXplQ2hpbGQgU2VyaWFsaXplIGEgY2hpbGQuXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBzZXJpYWxpemUoXG4gICAgdmFsdWU6IHVua25vd24sXG4gICAgc2VyaWFsaXplQ2hpbGQ6ICh2OiB1bmtub3duKSA9PiB1bmtub3duLFxuICAgIHRhcmdldFJvb3Q6IG9iamVjdCB8IHVuZGVmaW5lZFxuICApOiBUU2VyaWFsaXplZCB8IHR5cGVvZiBjYW5ub3RTZXJpYWxpemVcblxuICAvKipcbiAgICogRGVzZXJpYWxpemVzIGFuIGFjdGlvbiBjYWxsIGFyZ3VtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgVmFsdWUgdG8gZGVzZXJpYWxpemUuXG4gICAqIEBwYXJhbSB0YXJnZXRSb290IFRhcmdldCByb290LCBpZiBwcm92aWRlZC5cbiAgICogQHBhcmFtIGRlc2VyaWFsaXplQ2hpbGQgRGVzZXJpYWxpemUgYSBjaGlsZC5cbiAgICogQHJldHVybnNcbiAgICovXG4gIGRlc2VyaWFsaXplKFxuICAgIHZhbHVlOiBUU2VyaWFsaXplZCxcbiAgICBkZXNlcmlhbGl6ZUNoaWxkOiAodjogdW5rbm93bikgPT4gdW5rbm93bixcbiAgICB0YXJnZXRSb290OiBvYmplY3QgfCB1bmRlZmluZWRcbiAgKTogVE9yaWdpbmFsXG59XG4iLCJpbXBvcnQgdHlwZSB7IElPYnNlcnZhYmxlQXJyYXkgfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgeyBpc0FycmF5LCBuYW1lc3BhY2UgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIlxuaW1wb3J0IHsgQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplciwgY2Fubm90U2VyaWFsaXplIH0gZnJvbSBcIi4vY29yZVwiXG5cbmV4cG9ydCBjb25zdCBhcnJheVNlcmlhbGl6ZXI6IEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXI8YW55W10gfCBJT2JzZXJ2YWJsZUFycmF5PGFueT4sIGFueVtdPiA9IHtcbiAgaWQ6IGAke25hbWVzcGFjZX0vYXJyYXlgLFxuXG4gIHNlcmlhbGl6ZSh2YWx1ZSwgc2VyaWFsaXplKSB7XG4gICAgaWYgKCFpc0FycmF5KHZhbHVlKSkgcmV0dXJuIGNhbm5vdFNlcmlhbGl6ZVxuXG4gICAgLy8gdGhpcyB3aWxsIGFsc28gdHJhbnNmb3JtIG9ic2VydmFibGUgYXJyYXlzIGludG8gbm9uLW9ic2VydmFibGUgb25lc1xuICAgIHJldHVybiB2YWx1ZS5tYXAoc2VyaWFsaXplKVxuICB9LFxuXG4gIGRlc2VyaWFsaXplKGFyciwgZGVzZXJpYWxpemUpIHtcbiAgICByZXR1cm4gYXJyLm1hcChkZXNlcmlhbGl6ZSlcbiAgfSxcbn1cbiIsImltcG9ydCB7IG5hbWVzcGFjZSB9IGZyb20gXCIuLi8uLi91dGlsc1wiXG5pbXBvcnQgeyBBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVyLCBjYW5ub3RTZXJpYWxpemUgfSBmcm9tIFwiLi9jb3JlXCJcblxuZXhwb3J0IGNvbnN0IGRhdGVTZXJpYWxpemVyOiBBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVyPERhdGUsIG51bWJlcj4gPSB7XG4gIGlkOiBgJHtuYW1lc3BhY2V9L2RhdGVBc1RpbWVzdGFtcGAsXG5cbiAgc2VyaWFsaXplKGRhdGUpIHtcbiAgICBpZiAoIShkYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHJldHVybiBjYW5ub3RTZXJpYWxpemVcbiAgICByZXR1cm4gK2RhdGVcbiAgfSxcblxuICBkZXNlcmlhbGl6ZSh0aW1lc3RhbXApIHtcbiAgICByZXR1cm4gbmV3IERhdGUodGltZXN0YW1wKVxuICB9LFxufVxuIiwiaW1wb3J0IHsgaXNPYnNlcnZhYmxlTWFwLCBPYnNlcnZhYmxlTWFwIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgbmFtZXNwYWNlIH0gZnJvbSBcIi4uLy4uL3V0aWxzXCJcbmltcG9ydCB7IEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXIsIGNhbm5vdFNlcmlhbGl6ZSB9IGZyb20gXCIuL2NvcmVcIlxuXG5leHBvcnQgY29uc3QgbWFwU2VyaWFsaXplcjogQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcjxcbiAgTWFwPGFueSwgYW55PiB8IE9ic2VydmFibGVNYXA8YW55LCBhbnk+LFxuICBbYW55LCBhbnldW11cbj4gPSB7XG4gIGlkOiBgJHtuYW1lc3BhY2V9L21hcEFzQXJyYXlgLFxuXG4gIHNlcmlhbGl6ZShtYXAsIHNlcmlhbGl6ZSkge1xuICAgIGlmICghKG1hcCBpbnN0YW5jZW9mIE1hcCkgJiYgIWlzT2JzZXJ2YWJsZU1hcChtYXApKSByZXR1cm4gY2Fubm90U2VyaWFsaXplXG5cbiAgICBjb25zdCBhcnI6IFthbnksIGFueV1bXSA9IFtdXG5cbiAgICBjb25zdCBpdGVyID0gbWFwLmtleXMoKVxuICAgIGxldCBjdXIgPSBpdGVyLm5leHQoKVxuICAgIHdoaWxlICghY3VyLmRvbmUpIHtcbiAgICAgIGNvbnN0IGsgPSBjdXIudmFsdWVcbiAgICAgIGNvbnN0IHYgPSBtYXAuZ2V0KGspXG4gICAgICBhcnIucHVzaChbc2VyaWFsaXplKGspLCBzZXJpYWxpemUodildKVxuICAgICAgY3VyID0gaXRlci5uZXh0KClcbiAgICB9XG5cbiAgICByZXR1cm4gYXJyXG4gIH0sXG5cbiAgZGVzZXJpYWxpemUoYXJyLCBkZXNlcmlhbGl6ZSkge1xuICAgIGNvbnN0IG1hcCA9IG5ldyBNYXAoKVxuXG4gICAgY29uc3QgbGVuID0gYXJyLmxlbmd0aFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGNvbnN0IGsgPSBhcnJbaV1bMF1cbiAgICAgIGNvbnN0IHYgPSBhcnJbaV1bMV1cbiAgICAgIG1hcC5zZXQoZGVzZXJpYWxpemUoayksIGRlc2VyaWFsaXplKHYpKVxuICAgIH1cblxuICAgIHJldHVybiBtYXBcbiAgfSxcbn1cbiIsImltcG9ydCB7IG1vZGVsSWRLZXkgfSBmcm9tIFwiLi4vbW9kZWwvbWV0YWRhdGFcIlxuaW1wb3J0IHsgaXNNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXG5pbXBvcnQgdHlwZSB7IFJvb3RQYXRoIH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoXCJcbmltcG9ydCB0eXBlIHsgUGF0aCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFR5cGVzXCJcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvb3RQYXRoVG9UYXJnZXRQYXRoSWRzKHJvb3RQYXRoOiBSb290UGF0aDxhbnk+KTogKHN0cmluZyB8IG51bGwpW10ge1xuICBjb25zdCB0YXJnZXRQYXRoSWRzOiAoc3RyaW5nIHwgbnVsbClbXSA9IFtdXG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCByb290UGF0aC5wYXRoLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgdGFyZ2V0T2JqID0gcm9vdFBhdGgucGF0aE9iamVjdHNbaSArIDFdIC8vIGZpcnN0IGlzIHJvb3QsIHdlIGRvbid0IGNhcmUgYWJvdXQgaXRzIElEXG4gICAgY29uc3QgdGFyZ2V0T2JqSWQgPSBpc01vZGVsKHRhcmdldE9iaikgPyB0YXJnZXRPYmpbbW9kZWxJZEtleV0gPz8gbnVsbCA6IG51bGxcbiAgICB0YXJnZXRQYXRoSWRzLnB1c2godGFyZ2V0T2JqSWQpXG4gIH1cblxuICByZXR1cm4gdGFyZ2V0UGF0aElkc1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gcGF0aFRvVGFyZ2V0UGF0aElkcyhyb290OiBhbnksIHBhdGg6IFBhdGgpOiAoc3RyaW5nIHwgbnVsbClbXSB7XG4gIGNvbnN0IHRhcmdldFBhdGhJZHM6IChzdHJpbmcgfCBudWxsKVtdID0gW11cbiAgbGV0IGN1cnJlbnQgPSByb290IC8vIHdlIGRvbid0IGNhcmUgYWJvdXQgdGhlIHJvb3QgSURcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICBjdXJyZW50ID0gY3VycmVudFtwYXRoW2ldXVxuICAgIGNvbnN0IHRhcmdldE9iaklkID0gaXNNb2RlbChjdXJyZW50KSA/IGN1cnJlbnRbbW9kZWxJZEtleV0gPz8gbnVsbCA6IG51bGxcbiAgICB0YXJnZXRQYXRoSWRzLnB1c2godGFyZ2V0T2JqSWQpXG4gIH1cblxuICByZXR1cm4gdGFyZ2V0UGF0aElkc1xufVxuIiwiaW1wb3J0IHsgZmFzdEdldFJvb3RQYXRoLCByZXNvbHZlUGF0aENoZWNraW5nSWRzIH0gZnJvbSBcIi4uLy4uL3BhcmVudC9wYXRoXCJcclxuaW1wb3J0IHsgUGF0aCB9IGZyb20gXCIuLi8uLi9wYXJlbnQvcGF0aFR5cGVzXCJcclxuaW1wb3J0IHsgaXNUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uLy4uL3R3ZWFrZXIvY29yZVwiXHJcbmltcG9ydCB7IGZhaWx1cmUsIG5hbWVzcGFjZSB9IGZyb20gXCIuLi8uLi91dGlsc1wiXHJcbmltcG9ydCB7IHJvb3RQYXRoVG9UYXJnZXRQYXRoSWRzIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplciwgY2Fubm90U2VyaWFsaXplIH0gZnJvbSBcIi4vY29yZVwiXHJcblxyXG5pbnRlcmZhY2UgT2JqZWN0UGF0aCB7XHJcbiAgdGFyZ2V0UGF0aDogUGF0aFxyXG4gIHRhcmdldFBhdGhJZHM6IChzdHJpbmcgfCBudWxsKVtdXHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBvYmplY3RQYXRoU2VyaWFsaXplcjogQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcjxvYmplY3QsIE9iamVjdFBhdGg+ID0ge1xyXG4gIGlkOiBgJHtuYW1lc3BhY2V9L29iamVjdFBhdGhgLFxyXG5cclxuICBzZXJpYWxpemUodmFsdWUsIF8sIHRhcmdldFJvb3QpIHtcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIgfHwgdmFsdWUgPT09IG51bGwgfHwgIWlzVHdlYWtlZE9iamVjdCh2YWx1ZSwgZmFsc2UpKVxyXG4gICAgICByZXR1cm4gY2Fubm90U2VyaWFsaXplXHJcblxyXG4gICAgLy8gdHJ5IHRvIHNlcmlhbGl6ZSBhIHJlZiB0byBpdHMgcGF0aCBpZiBwb3NzaWJsZSBpbnN0ZWFkXHJcbiAgICBpZiAodGFyZ2V0Um9vdCkge1xyXG4gICAgICBjb25zdCByb290UGF0aCA9IGZhc3RHZXRSb290UGF0aCh2YWx1ZSlcclxuICAgICAgaWYgKHJvb3RQYXRoLnJvb3QgPT09IHRhcmdldFJvb3QpIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgdGFyZ2V0UGF0aDogcm9vdFBhdGgucGF0aCxcclxuICAgICAgICAgIHRhcmdldFBhdGhJZHM6IHJvb3RQYXRoVG9UYXJnZXRQYXRoSWRzKHJvb3RQYXRoKSxcclxuICAgICAgICB9IGFzIE9iamVjdFBhdGhcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBjYW5ub3RTZXJpYWxpemVcclxuICB9LFxyXG5cclxuICBkZXNlcmlhbGl6ZShyZWYsIF8sIHRhcmdldFJvb3QpIHtcclxuICAgIC8vIHRyeSB0byByZXNvbHZlIHRoZSBub2RlIGJhY2tcclxuICAgIGlmICh0YXJnZXRSb290KSB7XHJcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHJlc29sdmVQYXRoQ2hlY2tpbmdJZHModGFyZ2V0Um9vdCwgcmVmLnRhcmdldFBhdGgsIHJlZi50YXJnZXRQYXRoSWRzKVxyXG4gICAgICBpZiAocmVzdWx0LnJlc29sdmVkKSB7XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdC52YWx1ZVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhyb3cgZmFpbHVyZShcclxuICAgICAgYG9iamVjdCBhdCBwYXRoICR7SlNPTi5zdHJpbmdpZnkocmVmLnRhcmdldFBhdGgpfSB3aXRoIGlkcyAke0pTT04uc3RyaW5naWZ5KFxyXG4gICAgICAgIHJlZi50YXJnZXRQYXRoSWRzXHJcbiAgICAgICl9IGNvdWxkIG5vdCBiZSByZXNvbHZlZGBcclxuICAgIClcclxuICB9LFxyXG59XHJcbiIsImltcG9ydCB7IGZyb21TbmFwc2hvdCB9IGZyb20gXCIuLi8uLi9zbmFwc2hvdC9mcm9tU25hcHNob3RcIlxuaW1wb3J0IHsgZ2V0U25hcHNob3QgfSBmcm9tIFwiLi4vLi4vc25hcHNob3QvZ2V0U25hcHNob3RcIlxuaW1wb3J0IHsgaXNUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uLy4uL3R3ZWFrZXIvY29yZVwiXG5pbXBvcnQgeyBuYW1lc3BhY2UgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIlxuaW1wb3J0IHsgQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplciwgY2Fubm90U2VyaWFsaXplIH0gZnJvbSBcIi4vY29yZVwiXG5cbmV4cG9ydCBjb25zdCBvYmplY3RTbmFwc2hvdFNlcmlhbGl6ZXI6IEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXI8b2JqZWN0LCBvYmplY3Q+ID0ge1xuICBpZDogYCR7bmFtZXNwYWNlfS9vYmplY3RTbmFwc2hvdGAsXG5cbiAgc2VyaWFsaXplKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIiB8fCB2YWx1ZSA9PT0gbnVsbCB8fCAhaXNUd2Vha2VkT2JqZWN0KHZhbHVlLCBmYWxzZSkpXG4gICAgICByZXR1cm4gY2Fubm90U2VyaWFsaXplXG5cbiAgICByZXR1cm4gZ2V0U25hcHNob3QodmFsdWUpXG4gIH0sXG5cbiAgZGVzZXJpYWxpemUoc25hcHNob3QpIHtcbiAgICByZXR1cm4gZnJvbVNuYXBzaG90KHNuYXBzaG90KVxuICB9LFxufVxuIiwiaW1wb3J0IHsgaXNPYnNlcnZhYmxlT2JqZWN0IH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgaXNQbGFpbk9iamVjdCwgbmFtZXNwYWNlIH0gZnJvbSBcIi4uLy4uL3V0aWxzXCJcbmltcG9ydCB7IEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXIsIGNhbm5vdFNlcmlhbGl6ZSB9IGZyb20gXCIuL2NvcmVcIlxuXG5leHBvcnQgY29uc3QgcGxhaW5PYmplY3RTZXJpYWxpemVyOiBBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVyPG9iamVjdCwgb2JqZWN0PiA9IHtcbiAgaWQ6IGAke25hbWVzcGFjZX0vcGxhaW5PYmplY3RgLFxuXG4gIHNlcmlhbGl6ZSh2YWx1ZSwgc2VyaWFsaXplKSB7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KHZhbHVlKSAmJiAhaXNPYnNlcnZhYmxlT2JqZWN0KHZhbHVlKSkgcmV0dXJuIGNhbm5vdFNlcmlhbGl6ZVxuXG4gICAgLy8gdGhpcyB3aWxsIG1ha2Ugb2JzZXJ2YWJsZSBvYmplY3RzIG5vbi1vYnNlcnZhYmxlIG9uZXNcbiAgICByZXR1cm4gbWFwT2JqZWN0RmllbGRzKHZhbHVlLCBzZXJpYWxpemUpXG4gIH0sXG5cbiAgZGVzZXJpYWxpemUob2JqLCBzZXJpYWxpemUpIHtcbiAgICByZXR1cm4gbWFwT2JqZWN0RmllbGRzKG9iaiwgc2VyaWFsaXplKVxuICB9LFxufVxuXG5mdW5jdGlvbiBtYXBPYmplY3RGaWVsZHMob3JpZ2luYWxPYmo6IGFueSwgbWFwRm46ICh4OiBhbnkpID0+IGFueSk6IGFueSB7XG4gIGNvbnN0IG9iajogYW55ID0ge31cbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9yaWdpbmFsT2JqKVxuICBjb25zdCBsZW4gPSBrZXlzLmxlbmd0aFxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgY29uc3QgayA9IGtleXNbaV1cbiAgICBjb25zdCB2ID0gb3JpZ2luYWxPYmpba11cbiAgICBvYmpba10gPSBtYXBGbih2KVxuICB9XG4gIHJldHVybiBvYmpcbn1cbiIsImltcG9ydCB7IG5hbWVzcGFjZSB9IGZyb20gXCIuLi8uLi91dGlsc1wiXG5pbXBvcnQgeyBBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVyLCBjYW5ub3RTZXJpYWxpemUgfSBmcm9tIFwiLi9jb3JlXCJcblxuZXhwb3J0IGNvbnN0IHByaW1pdGl2ZVNlcmlhbGl6ZXI6IEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXI8XG4gIG51bWJlciB8IGJpZ2ludCB8IHVuZGVmaW5lZCxcbiAgc3RyaW5nXG4+ID0ge1xuICBpZDogYCR7bmFtZXNwYWNlfS9wcmltaXRpdmVBc1N0cmluZ2AsXG5cbiAgc2VyaWFsaXplKHZhbHVlKSB7XG4gICAgLy8gbnVtYmVyXG4gICAgaWYgKE51bWJlci5pc05hTih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBcIm5hblwiXG4gICAgfVxuICAgIHN3aXRjaCAodmFsdWUpIHtcbiAgICAgIGNhc2UgK0luZmluaXR5OlxuICAgICAgICByZXR1cm4gXCIraW5mXCJcbiAgICAgIGNhc2UgLUluZmluaXR5OlxuICAgICAgICByZXR1cm4gXCItaW5mXCJcbiAgICB9XG5cbiAgICAvLyBiaWdpbnRcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcImJpZ2ludFwiKSB7XG4gICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKVxuICAgIH1cblxuICAgIC8vIHVuZGVmaW5lZFxuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gXCJ1bmRlZmluZWRcIlxuICAgIH1cblxuICAgIHJldHVybiBjYW5ub3RTZXJpYWxpemVcbiAgfSxcblxuICBkZXNlcmlhbGl6ZShzdHIpIHtcbiAgICBzd2l0Y2ggKHN0cikge1xuICAgICAgY2FzZSBcIm5hblwiOlxuICAgICAgICByZXR1cm4gTmFOXG4gICAgICBjYXNlIFwiK2luZlwiOlxuICAgICAgICByZXR1cm4gK0luZmluaXR5XG4gICAgICBjYXNlIFwiLWluZlwiOlxuICAgICAgICByZXR1cm4gLUluZmluaXR5XG4gICAgICBjYXNlIFwidW5kZWZpbmVkXCI6XG4gICAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBCaWdJbnQoc3RyKVxuICAgIH1cbiAgfSxcbn1cbiIsImltcG9ydCB0eXBlIHsgT2JzZXJ2YWJsZVNldCB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IG5hbWVzcGFjZSB9IGZyb20gXCIuLi8uLi91dGlsc1wiXG5pbXBvcnQgeyBBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVyLCBjYW5ub3RTZXJpYWxpemUgfSBmcm9tIFwiLi9jb3JlXCJcblxuZXhwb3J0IGNvbnN0IHNldFNlcmlhbGl6ZXI6IEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXI8U2V0PGFueT4gfCBPYnNlcnZhYmxlU2V0PGFueT4sIGFueVtdPiA9IHtcbiAgaWQ6IGAke25hbWVzcGFjZX0vc2V0QXNBcnJheWAsXG5cbiAgc2VyaWFsaXplKHNldCwgc2VyaWFsaXplKSB7XG4gICAgaWYgKCEoc2V0IGluc3RhbmNlb2YgU2V0KSkgcmV0dXJuIGNhbm5vdFNlcmlhbGl6ZVxuXG4gICAgY29uc3QgYXJyOiBhbnlbXSA9IFtdXG5cbiAgICBjb25zdCBpdGVyID0gc2V0LmtleXMoKVxuICAgIGxldCBjdXIgPSBpdGVyLm5leHQoKVxuICAgIHdoaWxlICghY3VyLmRvbmUpIHtcbiAgICAgIGNvbnN0IGsgPSBjdXIudmFsdWVcbiAgICAgIGFyci5wdXNoKHNlcmlhbGl6ZShrKSlcbiAgICAgIGN1ciA9IGl0ZXIubmV4dCgpXG4gICAgfVxuXG4gICAgcmV0dXJuIGFyclxuICB9LFxuXG4gIGRlc2VyaWFsaXplKGFyciwgZGVzZXJpYWxpemUpIHtcbiAgICBjb25zdCBzZXQgPSBuZXcgU2V0KClcblxuICAgIGNvbnN0IGxlbiA9IGFyci5sZW5ndGhcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBjb25zdCBrID0gYXJyW2ldXG4gICAgICBzZXQuYWRkKGRlc2VyaWFsaXplKGspKVxuICAgIH1cblxuICAgIHJldHVybiBzZXRcbiAgfSxcbn1cbiIsImltcG9ydCB0eXBlIHsgTyB9IGZyb20gXCJ0cy10b29sYmVsdFwiXG5pbXBvcnQgdHlwZSB7IEFjdGlvbkNhbGwgfSBmcm9tIFwiLi4vLi4vYWN0aW9uL2FwcGx5QWN0aW9uXCJcbmltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vLi4vdHdlYWtlci9jb3JlXCJcbmltcG9ydCB7IGZhaWx1cmUsIGlzSlNPTlByaW1pdGl2ZSwgaXNQbGFpbk9iamVjdCB9IGZyb20gXCIuLi8uLi91dGlsc1wiXG5pbXBvcnQgdHlwZSB7IEpTT05QcmltaXRpdmVWYWx1ZSB9IGZyb20gXCIuLi8uLi91dGlscy90eXBlc1wiXG5pbXBvcnQgeyBhcnJheVNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9hcnJheVNlcmlhbGl6ZXJcIlxuaW1wb3J0IHsgQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplciwgY2Fubm90U2VyaWFsaXplIH0gZnJvbSBcIi4vY29yZVwiXG5pbXBvcnQgeyBkYXRlU2VyaWFsaXplciB9IGZyb20gXCIuL2RhdGVTZXJpYWxpemVyXCJcbmltcG9ydCB7IG1hcFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9tYXBTZXJpYWxpemVyXCJcbmltcG9ydCB7IG9iamVjdFBhdGhTZXJpYWxpemVyIH0gZnJvbSBcIi4vb2JqZWN0UGF0aFNlcmlhbGl6ZXJcIlxuaW1wb3J0IHsgb2JqZWN0U25hcHNob3RTZXJpYWxpemVyIH0gZnJvbSBcIi4vb2JqZWN0U25hcHNob3RTZXJpYWxpemVyXCJcbmltcG9ydCB7IHBsYWluT2JqZWN0U2VyaWFsaXplciB9IGZyb20gXCIuL3BsYWluT2JqZWN0U2VyaWFsaXplclwiXG5pbXBvcnQgeyBwcmltaXRpdmVTZXJpYWxpemVyIH0gZnJvbSBcIi4vcHJpbWl0aXZlU2VyaWFsaXplclwiXG5pbXBvcnQgeyBzZXRTZXJpYWxpemVyIH0gZnJvbSBcIi4vc2V0U2VyaWFsaXplclwiXG5cbmNvbnN0IHNlcmlhbGl6ZXJzQXJyYXk6IEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXI8YW55LCBhbnk+W10gPSBbXVxuY29uc3Qgc2VyaWFsaXplcnNNYXAgPSBuZXcgTWFwPHN0cmluZywgQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcjxhbnksIGFueT4+KClcblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBuZXcgYWN0aW9uIGNhbGwgYXJndW1lbnQgc2VyaWFsaXplcnMuXG4gKiBTZXJpYWxpemVycyBhcmUgY2FsbGVkIGluIHRoZSBpbnZlcnNlIG9yZGVyIHRoZXkgYXJlIHJlZ2lzdGVyZWQsIG1lYW5pbmcgdGhlXG4gKiBsYXRlc3Qgb25lIHJlZ2lzdGVyZWQgd2lsbCBiZSBjYWxsZWQgZmlyc3QuXG4gKlxuICogQHBhcmFtIHNlcmlhbGl6ZXIgU2VyaWFsaXplciB0byByZWdpc3Rlci5cbiAqIEByZXR1cm5zIEEgZGlzcG9zZXIgdG8gdW5yZWdpc3RlciB0aGUgc2VyaWFsaXplci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcihcbiAgc2VyaWFsaXplcjogQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcjxhbnksIGFueT5cbik6ICgpID0+IHZvaWQge1xuICByZWdpc3RlckRlZmF1bHRBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVycygpXG5cbiAgaWYgKHNlcmlhbGl6ZXJzQXJyYXkuaW5jbHVkZXMoc2VyaWFsaXplcikpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFwiYWN0aW9uIGNhbGwgYXJndW1lbnQgc2VyaWFsaXplciBhbHJlYWR5IHJlZ2lzdGVyZWRcIilcbiAgfVxuICBpZiAoc2VyaWFsaXplcnNNYXAuaGFzKHNlcmlhbGl6ZXIuaWQpKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgYWN0aW9uIGNhbGwgYXJndW1lbnQgc2VyaWFsaXplciB3aXRoIGlkICcke3NlcmlhbGl6ZXIuaWR9JyBhbHJlYWR5IHJlZ2lzdGVyZWRgKVxuICB9XG5cbiAgc2VyaWFsaXplcnNBcnJheS51bnNoaWZ0KHNlcmlhbGl6ZXIpXG4gIHNlcmlhbGl6ZXJzTWFwLnNldChzZXJpYWxpemVyLmlkLCBzZXJpYWxpemVyKVxuXG4gIHJldHVybiAoKSA9PiB7XG4gICAgY29uc3QgaW5kZXggPSBzZXJpYWxpemVyc0FycmF5LmluZGV4T2Yoc2VyaWFsaXplcilcbiAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgc2VyaWFsaXplcnNBcnJheS5zcGxpY2UoaW5kZXgsIDEpXG4gICAgfVxuICAgIHNlcmlhbGl6ZXJzTWFwLmRlbGV0ZShzZXJpYWxpemVyLmlkKVxuICB9XG59XG5cbi8qKlxuICogU2VyaWFsaXplZCBhY3Rpb24gY2FsbCBhcmd1bWVudC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZXJpYWxpemVkQWN0aW9uQ2FsbEFyZ3VtZW50IHtcbiAgLyoqXG4gICAqIFNlcmlhbGl6ZXIgaWQuXG4gICAqL1xuICByZWFkb25seSAkbW9ieEtleXN0b25lU2VyaWFsaXplcjogc3RyaW5nXG4gIC8qKlxuICAgKiBTZXJpYWxpemVkIHZhbHVlLlxuICAgKi9cbiAgcmVhZG9ubHkgdmFsdWU6IGFueVxufVxuXG4vKipcbiAqIEEgc2VyaWFsaXplZCBhY3Rpb24gY2FsbC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZXJpYWxpemVkQWN0aW9uQ2FsbCBleHRlbmRzIE9taXQ8QWN0aW9uQ2FsbCwgXCJzZXJpYWxpemVkXCI+IHtcbiAgLyoqXG4gICAqIFNlcmlhbGl6ZWQgYWN0aW9uIGFyZ3VtZW50cy5cbiAgICovXG4gIHJlYWRvbmx5IGFyZ3M6IFJlYWRvbmx5QXJyYXk8U2VyaWFsaXplZEFjdGlvbkNhbGxBcmd1bWVudCB8IEpTT05QcmltaXRpdmVWYWx1ZT5cblxuICAvKipcbiAgICogTWFya3MgdGhpcyBhY3Rpb24gY2FsbCBhcyBzZXJpYWxpemVkLlxuICAgKi9cbiAgc2VyaWFsaXplZDogdHJ1ZVxufVxuXG4vKipcbiAqIFRyYW5zZm9ybXMgYW4gYWN0aW9uIGNhbGwgYXJndW1lbnQgYnkgcmV0dXJuaW5nIGEgYFNlcmlhbGl6ZWRBY3Rpb25DYWxsQXJndW1lbnRgLlxuICogVGhlIGZvbGxvd2luZyBhcmUgc3VwcG9ydGVkIG91dCBvZiB0aGUgYm94OlxuICogLSBQcmltaXRpdmVzLlxuICogLSBOb2RlcyB0aGF0IGFyZSB1bmRlciB0aGUgc2FtZSByb290IG5vZGUgYXMgdGhlIHRhcmdldCByb290ICh3aGVuIHByb3ZpZGVkKSB3aWxsIGJlIHNlcmlhbGl6ZWRcbiAqICAgYXMgYSBwYXRoLlxuICogLSBOb2RlcyB0aGF0IGFyZSBub3QgdW5kZXIgdGhlIHNhbWUgcm9vdCBub2RlIGFzIHRoZSB0YXJnZXQgcm9vdCB3aWxsIGJlIHNlcmlhbGl6ZWQgYXMgdGhlaXIgc25hcHNob3QuXG4gKiAtIEFycmF5cyAob2JzZXJ2YWJsZSBvciBub3QpLlxuICogLSBEYXRlcy5cbiAqIC0gTWFwcyAob2JzZXJ2YWJsZSBvciBub3QpLlxuICogLSBTZXRzIChvYnNlcnZhYmxlIG9yIG5vdCkuXG4gKiAtIFBsYWluIG9iamVjdHMgKG9ic2VydmFibGUgb3Igbm90KS5cbiAqXG4gKiBJZiB0aGUgdmFsdWUgY2Fubm90IGJlIHNlcmlhbGl6ZWQgaXQgd2lsbCB0aHJvdyBhbiBleGNlcHRpb24uXG4gKlxuICogQHBhcmFtIGFyZ1ZhbHVlIEFyZ3VtZW50IHZhbHVlIHRvIGJlIHRyYW5zZm9ybWVkIGludG8gaXRzIHNlcmlhbGl6YWJsZSBmb3JtLlxuICogQHBhcmFtIFt0YXJnZXRSb290XSBUYXJnZXQgcm9vdCBub2RlIG9mIHRoZSBtb2RlbCB3aGVyZSB0aGlzIGFjdGlvbiBpcyBiZWluZyBwZXJmb3JtZWQuXG4gKiBAcmV0dXJucyBUaGUgc2VyaWFsaXphYmxlIGZvcm0gb2YgdGhlIHBhc3NlZCB2YWx1ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlcmlhbGl6ZUFjdGlvbkNhbGxBcmd1bWVudChcbiAgYXJnVmFsdWU6IGFueSxcbiAgdGFyZ2V0Um9vdD86IG9iamVjdFxuKTogU2VyaWFsaXplZEFjdGlvbkNhbGxBcmd1bWVudCB8IEpTT05QcmltaXRpdmVWYWx1ZSB7XG4gIHJlZ2lzdGVyRGVmYXVsdEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXJzKClcblxuICBpZiAoaXNKU09OUHJpbWl0aXZlKGFyZ1ZhbHVlKSkge1xuICAgIHJldHVybiBhcmdWYWx1ZVxuICB9XG5cbiAgY29uc3Qgb3JpZ1ZhbHVlID0gYXJnVmFsdWVcblxuICBjb25zdCBzZXJpYWxpemUgPSAodjogYW55KSA9PiBzZXJpYWxpemVBY3Rpb25DYWxsQXJndW1lbnQodiwgdGFyZ2V0Um9vdClcblxuICAvLyB0cnkgc2VyaWFsaXplcnNcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZXJpYWxpemVyc0FycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3Qgc2VyaWFsaXplciA9IHNlcmlhbGl6ZXJzQXJyYXlbaV1cbiAgICBjb25zdCBzZXJpYWxpemVkVmFsdWUgPSBzZXJpYWxpemVyLnNlcmlhbGl6ZShhcmdWYWx1ZSwgc2VyaWFsaXplLCB0YXJnZXRSb290KVxuICAgIGlmIChzZXJpYWxpemVkVmFsdWUgIT09IGNhbm5vdFNlcmlhbGl6ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgJG1vYnhLZXlzdG9uZVNlcmlhbGl6ZXI6IHNlcmlhbGl6ZXIuaWQsXG4gICAgICAgIHZhbHVlOiBzZXJpYWxpemVkVmFsdWUsXG4gICAgICB9IGFzIFNlcmlhbGl6ZWRBY3Rpb25DYWxsQXJndW1lbnRcbiAgICB9XG4gIH1cblxuICB0aHJvdyBmYWlsdXJlKGBzZXJpYWxpemVBY3Rpb25DYWxsQXJndW1lbnQgY291bGQgbm90IHNlcmlhbGl6ZSB0aGUgZ2l2ZW4gdmFsdWU6ICR7b3JpZ1ZhbHVlfWApXG59XG5cbi8qKlxuICogRW5zdXJlcyB0aGF0IGFuIGFjdGlvbiBjYWxsIGlzIHNlcmlhbGl6YWJsZSBieSBtYXBwaW5nIHRoZSBhY3Rpb24gYXJndW1lbnRzIGludG8gaXRzXG4gKiBzZXJpYWxpemFibGUgdmVyc2lvbiBieSB1c2luZyBgc2VyaWFsaXplQWN0aW9uQ2FsbEFyZ3VtZW50YC5cbiAqXG4gKiBAcGFyYW0gYWN0aW9uQ2FsbCBBY3Rpb24gY2FsbCB0byBjb252ZXJ0LlxuICogQHBhcmFtIFt0YXJnZXRSb290XSBUYXJnZXQgcm9vdCBub2RlIG9mIHRoZSBtb2RlbCB3aGVyZSB0aGlzIGFjdGlvbiBpcyBiZWluZyBwZXJmb3JtZWQuXG4gKiBAcmV0dXJucyBUaGUgc2VyaWFsaXphYmxlIGFjdGlvbiBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplQWN0aW9uQ2FsbChcbiAgYWN0aW9uQ2FsbDogQWN0aW9uQ2FsbCxcbiAgdGFyZ2V0Um9vdD86IG9iamVjdFxuKTogU2VyaWFsaXplZEFjdGlvbkNhbGwge1xuICBpZiAoYWN0aW9uQ2FsbC5zZXJpYWxpemVkKSB7XG4gICAgdGhyb3cgZmFpbHVyZShcImNhbm5vdCBzZXJpYWxpemUgYW4gYWxyZWFkeSBzZXJpYWxpemVkIGFjdGlvbiBjYWxsXCIpXG4gIH1cblxuICBpZiAodGFyZ2V0Um9vdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgYXNzZXJ0VHdlYWtlZE9iamVjdCh0YXJnZXRSb290LCBcInRhcmdldFJvb3RcIilcbiAgfVxuXG4gIGNvbnN0IHNlcmlhbGl6ZSA9ICh2OiBhbnkpID0+IHNlcmlhbGl6ZUFjdGlvbkNhbGxBcmd1bWVudCh2LCB0YXJnZXRSb290KVxuXG4gIHJldHVybiB7XG4gICAgLi4uYWN0aW9uQ2FsbCxcbiAgICBzZXJpYWxpemVkOiB0cnVlLFxuICAgIGFyZ3M6IGFjdGlvbkNhbGwuYXJncy5tYXAoc2VyaWFsaXplKSxcbiAgfVxufVxuXG4vKipcbiAqIFRyYW5zZm9ybXMgYW4gYWN0aW9uIGNhbGwgYXJndW1lbnQgYnkgcmV0dXJuaW5nIGl0cyBkZXNlcmlhbGl6ZWQgZXF1aXZhbGVudC5cbiAqXG4gKiBAcGFyYW0gYXJnVmFsdWUgQXJndW1lbnQgdmFsdWUgdG8gYmUgdHJhbnNmb3JtZWQgaW50byBpdHMgZGVzZXJpYWxpemVkIGZvcm0uXG4gKiBAcGFyYW0gW3RhcmdldFJvb3RdIFRhcmdldCByb290IG5vZGUgb2YgdGhlIG1vZGVsIHdoZXJlIHRoaXMgYWN0aW9uIGlzIGJlaW5nIHBlcmZvcm1lZC5cbiAqIEByZXR1cm5zIFRoZSBkZXNlcmlhbGl6ZWQgZm9ybSBvZiB0aGUgcGFzc2VkIHZhbHVlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVzZXJpYWxpemVBY3Rpb25DYWxsQXJndW1lbnQoXG4gIGFyZ1ZhbHVlOiBTZXJpYWxpemVkQWN0aW9uQ2FsbEFyZ3VtZW50IHwgSlNPTlByaW1pdGl2ZVZhbHVlLFxuICB0YXJnZXRSb290Pzogb2JqZWN0XG4pOiBhbnkge1xuICByZWdpc3RlckRlZmF1bHRBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVycygpXG5cbiAgaWYgKGlzSlNPTlByaW1pdGl2ZShhcmdWYWx1ZSkpIHtcbiAgICByZXR1cm4gYXJnVmFsdWVcbiAgfVxuXG4gIGlmICghaXNQbGFpbk9iamVjdChhcmdWYWx1ZSkgfHwgdHlwZW9mIGFyZ1ZhbHVlLiRtb2J4S2V5c3RvbmVTZXJpYWxpemVyICE9PSBcInN0cmluZ1wiKSB7XG4gICAgdGhyb3cgZmFpbHVyZShcImludmFsaWQgc2VyaWFsaXplZCBhY3Rpb24gY2FsbCBhcmd1bWVudFwiKVxuICB9XG5cbiAgY29uc3Qgc2VyaWFsaXplcklkID0gYXJnVmFsdWUuJG1vYnhLZXlzdG9uZVNlcmlhbGl6ZXJcbiAgY29uc3Qgc2VyaWFsaXplciA9IHNlcmlhbGl6ZXJzTWFwLmdldChzZXJpYWxpemVySWQpXG5cbiAgaWYgKCFzZXJpYWxpemVyKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgYSBzZXJpYWxpemVyIHdpdGggaWQgJyR7c2VyaWFsaXplcklkfScgY291bGQgbm90IGJlIGZvdW5kYClcbiAgfVxuXG4gIGNvbnN0IHNlcmlhbGl6ZWRWYWx1ZSA9IGFyZ1ZhbHVlIGFzIFNlcmlhbGl6ZWRBY3Rpb25DYWxsQXJndW1lbnRcblxuICBjb25zdCBkZXNlcmlhbGl6ZSA9ICh2OiBhbnkpID0+IGRlc2VyaWFsaXplQWN0aW9uQ2FsbEFyZ3VtZW50KHYsIHRhcmdldFJvb3QpXG4gIHJldHVybiBzZXJpYWxpemVyLmRlc2VyaWFsaXplKHNlcmlhbGl6ZWRWYWx1ZS52YWx1ZSwgZGVzZXJpYWxpemUsIHRhcmdldFJvb3QpXG59XG5cbi8qKlxuICogRW5zdXJlcyB0aGF0IGFuIGFjdGlvbiBjYWxsIGlzIGRlc2VyaWFsaXplZCBieSBtYXBwaW5nIHRoZSBhY3Rpb24gYXJndW1lbnRzIGludG8gaXRzXG4gKiBkZXNlcmlhbGl6ZWQgdmVyc2lvbiBieSB1c2luZyBgZGVzZXJpYWxpemVBY3Rpb25DYWxsQXJndW1lbnRgLlxuICpcbiAqIEBwYXJhbSBhY3Rpb25DYWxsIEFjdGlvbiBjYWxsIHRvIGNvbnZlcnQuXG4gKiBAcGFyYW0gW3RhcmdldFJvb3RdIFRhcmdldCByb290IG5vZGUgb2YgdGhlIG1vZGVsIHdoZXJlIHRoaXMgYWN0aW9uIGlzIGJlaW5nIHBlcmZvcm1lZC5cbiAqIEByZXR1cm5zIFRoZSBkZXNlcmlhbGl6ZWQgYWN0aW9uIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXNlcmlhbGl6ZUFjdGlvbkNhbGwoXG4gIGFjdGlvbkNhbGw6IFNlcmlhbGl6ZWRBY3Rpb25DYWxsLFxuICB0YXJnZXRSb290Pzogb2JqZWN0XG4pOiBBY3Rpb25DYWxsIHtcbiAgaWYgKCFhY3Rpb25DYWxsLnNlcmlhbGl6ZWQpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFwiY2Fubm90IGRlc2VyaWFsaXplIGEgbm9uLXNlcmlhbGl6ZWQgYWN0aW9uIGNhbGxcIilcbiAgfVxuXG4gIGlmICh0YXJnZXRSb290ICE9PSB1bmRlZmluZWQpIHtcbiAgICBhc3NlcnRUd2Vha2VkT2JqZWN0KHRhcmdldFJvb3QsIFwidGFyZ2V0Um9vdFwiKVxuICB9XG5cbiAgY29uc3QgZGVzZXJpYWxpemUgPSAodjogYW55KSA9PiBkZXNlcmlhbGl6ZUFjdGlvbkNhbGxBcmd1bWVudCh2LCB0YXJnZXRSb290KVxuICBjb25zdCBkZXNlcmlhbGl6ZWRBY3Rpb25DYWxsOiBBY3Rpb25DYWxsID0ge1xuICAgIC4uLmFjdGlvbkNhbGwsXG4gICAgc2VyaWFsaXplZDogdW5kZWZpbmVkLFxuICAgIGFyZ3M6IGFjdGlvbkNhbGwuYXJncy5tYXAoZGVzZXJpYWxpemUpLFxuICB9XG4gIGRlbGV0ZSAoZGVzZXJpYWxpemVkQWN0aW9uQ2FsbCBhcyBPLldyaXRhYmxlPEFjdGlvbkNhbGw+KS5zZXJpYWxpemVkXG4gIHJldHVybiBkZXNlcmlhbGl6ZWRBY3Rpb25DYWxsXG59XG5cbmxldCBkZWZhdWx0QWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcnNSZWdpc3RlcmVkID0gZmFsc2VcblxuZnVuY3Rpb24gcmVnaXN0ZXJEZWZhdWx0QWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcnMoKSB7XG4gIGlmIChkZWZhdWx0QWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcnNSZWdpc3RlcmVkKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgZGVmYXVsdEFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXJzUmVnaXN0ZXJlZCA9IHRydWVcblxuICAvLyBzZXJpYWxpemVyIHJlZ2lzdHJhdGlvbiAoZnJvbSBsb3cgcHJpb3JpdHkgdG8gaGlnaCBwcmlvcml0eSlcblxuICByZWdpc3RlckFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXIocHJpbWl0aXZlU2VyaWFsaXplcilcbiAgcmVnaXN0ZXJBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVyKHBsYWluT2JqZWN0U2VyaWFsaXplcilcbiAgcmVnaXN0ZXJBY3Rpb25DYWxsQXJndW1lbnRTZXJpYWxpemVyKHNldFNlcmlhbGl6ZXIpXG4gIHJlZ2lzdGVyQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcihtYXBTZXJpYWxpemVyKVxuICByZWdpc3RlckFjdGlvbkNhbGxBcmd1bWVudFNlcmlhbGl6ZXIoZGF0ZVNlcmlhbGl6ZXIpXG4gIHJlZ2lzdGVyQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcihhcnJheVNlcmlhbGl6ZXIpXG4gIHJlZ2lzdGVyQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcihvYmplY3RTbmFwc2hvdFNlcmlhbGl6ZXIpXG4gIHJlZ2lzdGVyQWN0aW9uQ2FsbEFyZ3VtZW50U2VyaWFsaXplcihvYmplY3RQYXRoU2VyaWFsaXplcilcbn1cbiIsImltcG9ydCB7IHJ1bkluQWN0aW9uIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgYXBwbHlBY3Rpb24gfSBmcm9tIFwiLi4vLi4vYWN0aW9uL2FwcGx5QWN0aW9uXCJcbmltcG9ydCB7IGZyb3plbktleSB9IGZyb20gXCIuLi8uLi9mcm96ZW4vRnJvemVuXCJcbmltcG9ydCB7IGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUgfSBmcm9tIFwiLi4vLi4vbW9kZWwvZ2V0TW9kZWxNZXRhZGF0YVwiXG5pbXBvcnQgeyBpc01vZGVsIH0gZnJvbSBcIi4uLy4uL21vZGVsL3V0aWxzXCJcbmltcG9ydCB7IHJlc29sdmVQYXRoIH0gZnJvbSBcIi4uLy4uL3BhcmVudC9wYXRoXCJcbmltcG9ydCB0eXBlIHsgV3JpdGFibGVQYXRoIH0gZnJvbSBcIi4uLy4uL3BhcmVudC9wYXRoVHlwZXNcIlxuaW1wb3J0IHsgYXBwbHlQYXRjaGVzIH0gZnJvbSBcIi4uLy4uL3BhdGNoL2FwcGx5UGF0Y2hlc1wiXG5pbXBvcnQgeyBvblBhdGNoZXMgfSBmcm9tIFwiLi4vLi4vcGF0Y2gvZW1pdFBhdGNoXCJcbmltcG9ydCB0eXBlIHsgUGF0Y2ggfSBmcm9tIFwiLi4vLi4vcGF0Y2gvUGF0Y2hcIlxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi8uLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgZmFpbHVyZSwgaXNPYmplY3QgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIlxuaW1wb3J0IHsgZGVzZXJpYWxpemVBY3Rpb25DYWxsLCBTZXJpYWxpemVkQWN0aW9uQ2FsbCB9IGZyb20gXCIuL2FjdGlvblNlcmlhbGl6YXRpb25cIlxuXG4vKipcbiAqIFNlcmlhbGl6ZWQgYWN0aW9uIGNhbGwgd2l0aCBtb2RlbCBJRCBvdmVycmlkZXMuXG4gKiBDYW4gYmUgZ2VuZXJhdGVkIHdpdGggYGFwcGx5U2VyaWFsaXplZEFjdGlvbkFuZFRyYWNrTmV3TW9kZWxJZHNgLlxuICogVG8gYmUgYXBwbGllZCB3aXRoIGBhcHBseVNlcmlhbGl6ZWRBY3Rpb25BbmRTeW5jTmV3TW9kZWxJZHNgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlcmlhbGl6ZWRBY3Rpb25DYWxsV2l0aE1vZGVsSWRPdmVycmlkZXMgZXh0ZW5kcyBTZXJpYWxpemVkQWN0aW9uQ2FsbCB7XG4gIC8qKlxuICAgKiBNb2RlbCBJZCBvdmVycmlkZXMgdG8gYmUgYXBwbGllZCBhdCB0aGUgZW5kIG9mIGFwcGx5aW5nIHRoZSBhY3Rpb24uXG4gICAqL1xuICByZWFkb25seSBtb2RlbElkT3ZlcnJpZGVzOiBSZWFkb25seUFycmF5PFBhdGNoPlxufVxuXG4vKipcbiAqIEFwcGxpZXMgKHJ1bnMpIGEgc2VyaWFsaXplZCBhY3Rpb24gb3ZlciBhIHRhcmdldCBvYmplY3QuXG4gKiBJbiB0aGlzIG1vZGUgbmV3bHkgZ2VuZXJhdGVkIC8gbW9kaWZpZWQgbW9kZWwgSURzIHdpbGwgYmUgdHJhY2tlZFxuICogc28gdGhleSBjYW4gYmUgbGF0ZXIgc3luY2hyb25pemVkIHdoZW4gYXBwbHlpbmcgaXQgb24gYW5vdGhlciBtYWNoaW5lXG4gKiB2aWEgYGFwcGx5U2VyaWFsaXplZEFjdGlvbkFuZFN5bmNOZXdNb2RlbElkc2AuXG4gKiBUaGlzIG1lYW5zIHRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgdXNlZCBvbiB0aGUgc2VydmVyIHNpZGUuXG4gKlxuICogSWYgeW91IGludGVuZCB0byBhcHBseSBub24tc2VyaWFsaXplZCBhY3Rpb25zIGNoZWNrIGBhcHBseUFjdGlvbmAgaW5zdGVhZC5cbiAqXG4gKiBAcGFyYW0gc3VidHJlZVJvb3QgU3VidHJlZSByb290IHRhcmdldCBvYmplY3QgdG8gcnVuIHRoZSBhY3Rpb24gb3Zlci5cbiAqIEBwYXJhbSBjYWxsIFRoZSBzZXJpYWxpemVkIGFjdGlvbiwgdXN1YWxseSBhcyBjb21pbmcgZnJvbSB0aGUgc2VydmVyL2NsaWVudC5cbiAqIEByZXR1cm5zIFRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGFjdGlvbiwgaWYgYW55LCBwbHVzIGEgbmV3IHNlcmlhbGl6ZWQgYWN0aW9uXG4gKiB3aXRoIG1vZGVsIG92ZXJyaWRlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5U2VyaWFsaXplZEFjdGlvbkFuZFRyYWNrTmV3TW9kZWxJZHM8VFJldCA9IGFueT4oXG4gIHN1YnRyZWVSb290OiBvYmplY3QsXG4gIGNhbGw6IFNlcmlhbGl6ZWRBY3Rpb25DYWxsXG4pOiB7XG4gIHJldHVyblZhbHVlOiBUUmV0XG4gIHNlcmlhbGl6ZWRBY3Rpb25DYWxsOiBTZXJpYWxpemVkQWN0aW9uQ2FsbFdpdGhNb2RlbElkT3ZlcnJpZGVzXG59IHtcbiAgaWYgKCFjYWxsLnNlcmlhbGl6ZWQpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFwiY2Fubm90IGFwcGx5IGEgbm9uLXNlcmlhbGl6ZWQgYWN0aW9uIGNhbGwsIHVzZSAnYXBwbHlBY3Rpb24nIGluc3RlYWRcIilcbiAgfVxuXG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qoc3VidHJlZVJvb3QsIFwic3VidHJlZVJvb3RcIilcblxuICBjb25zdCBkZXNlcmlhbGl6ZWRDYWxsID0gZGVzZXJpYWxpemVBY3Rpb25DYWxsKGNhbGwsIHN1YnRyZWVSb290KVxuXG4gIGNvbnN0IG1vZGVsSWRPdmVycmlkZXM6IFBhdGNoW10gPSBbXVxuXG4gIC8vIHNldCBhIHBhdGNoIGxpc3RlbmVyIHRvIHRyYWNrIGNoYW5nZXMgdG8gbW9kZWwgaWRzXG4gIGNvbnN0IHBhdGNoRGlzcG9zZXIgPSBvblBhdGNoZXMoc3VidHJlZVJvb3QsIChwYXRjaGVzKSA9PiB7XG4gICAgc2NhblBhdGNoZXNGb3JNb2RlbElkQ2hhbmdlcyhzdWJ0cmVlUm9vdCwgbW9kZWxJZE92ZXJyaWRlcywgcGF0Y2hlcylcbiAgfSlcblxuICB0cnkge1xuICAgIGNvbnN0IHJldHVyblZhbHVlID0gYXBwbHlBY3Rpb24oc3VidHJlZVJvb3QsIGRlc2VyaWFsaXplZENhbGwpXG5cbiAgICByZXR1cm4ge1xuICAgICAgcmV0dXJuVmFsdWUsXG4gICAgICBzZXJpYWxpemVkQWN0aW9uQ2FsbDoge1xuICAgICAgICAuLi5jYWxsLFxuICAgICAgICBtb2RlbElkT3ZlcnJpZGVzLFxuICAgICAgfSxcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgcGF0Y2hEaXNwb3NlcigpXG4gIH1cbn1cblxuZnVuY3Rpb24gc2NhblBhdGNoZXNGb3JNb2RlbElkQ2hhbmdlcyhyb290OiBvYmplY3QsIG1vZGVsSWRPdmVycmlkZXM6IFBhdGNoW10sIHBhdGNoZXM6IFBhdGNoW10pIHtcbiAgY29uc3QgbGVuID0gcGF0Y2hlcy5sZW5ndGhcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIGNvbnN0IHBhdGNoID0gcGF0Y2hlc1tpXVxuICAgIGlmIChwYXRjaC5vcCA9PT0gXCJyZXBsYWNlXCIgfHwgcGF0Y2gub3AgPT09IFwiYWRkXCIpIHtcbiAgICAgIGRlZXBTY2FuVmFsdWVGb3JNb2RlbElkQ2hhbmdlcyhcbiAgICAgICAgcm9vdCxcbiAgICAgICAgbW9kZWxJZE92ZXJyaWRlcyxcbiAgICAgICAgcGF0Y2gudmFsdWUsXG4gICAgICAgIHBhdGNoLnBhdGggYXMgV3JpdGFibGVQYXRoXG4gICAgICApXG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGRlZXBTY2FuVmFsdWVGb3JNb2RlbElkQ2hhbmdlcyhcbiAgcm9vdDogb2JqZWN0LFxuICBtb2RlbElkT3ZlcnJpZGVzOiBQYXRjaFtdLFxuICB2YWx1ZTogYW55LFxuICBwYXRoOiBXcml0YWJsZVBhdGhcbikge1xuICBpZiAocGF0aC5sZW5ndGggPj0gMSAmJiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAvLyBlbnN1cmUgdGhlIHBhcmVudCBpcyBhbiBhY3R1YWwgbW9kZWxcbiAgICBjb25zdCBwYXJlbnQgPSByZXNvbHZlUGF0aChyb290LCBwYXRoLnNsaWNlKDAsIHBhdGgubGVuZ3RoIC0gMSkpLnZhbHVlXG5cbiAgICBpZiAoaXNNb2RlbChwYXJlbnQpKSB7XG4gICAgICBjb25zdCBwcm9wZXJ0eU5hbWUgPSBwYXRoW3BhdGgubGVuZ3RoIC0gMV1cbiAgICAgIGlmIChwcm9wZXJ0eU5hbWUgPT09IGdldE1vZGVsSWRQcm9wZXJ0eU5hbWUocGFyZW50LmNvbnN0cnVjdG9yIGFzIGFueSkpIHtcbiAgICAgICAgLy8gZm91bmQgb25lXG4gICAgICAgIG1vZGVsSWRPdmVycmlkZXMucHVzaCh7XG4gICAgICAgICAgb3A6IFwicmVwbGFjZVwiLFxuICAgICAgICAgIHBhdGg6IHBhdGguc2xpY2UoKSxcbiAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgY29uc3QgbGVuID0gdmFsdWUubGVuZ3RoXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgcGF0aC5wdXNoKGkpXG4gICAgICBkZWVwU2NhblZhbHVlRm9yTW9kZWxJZENoYW5nZXMocm9vdCwgbW9kZWxJZE92ZXJyaWRlcywgdmFsdWVbaV0sIHBhdGgpXG4gICAgICBwYXRoLnBvcCgpXG4gICAgfVxuICB9IGVsc2UgaWYgKGlzT2JqZWN0KHZhbHVlKSkge1xuICAgIC8vIHNraXAgZnJvemVuIHZhbHVlc1xuICAgIGlmICghdmFsdWVbZnJvemVuS2V5XSkge1xuICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHZhbHVlKVxuICAgICAgY29uc3QgbGVuID0ga2V5cy5sZW5ndGhcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgY29uc3QgcHJvcE5hbWUgPSBrZXlzW2ldXG4gICAgICAgIGNvbnN0IHByb3BWYWx1ZSA9IHZhbHVlW3Byb3BOYW1lXVxuXG4gICAgICAgIHBhdGgucHVzaChwcm9wTmFtZSlcbiAgICAgICAgZGVlcFNjYW5WYWx1ZUZvck1vZGVsSWRDaGFuZ2VzKHJvb3QsIG1vZGVsSWRPdmVycmlkZXMsIHByb3BWYWx1ZSwgcGF0aClcbiAgICAgICAgcGF0aC5wb3AoKVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEFwcGxpZXMgKHJ1bnMpIGEgc2VyaWFsaXplZCBhY3Rpb24gb3ZlciBhIHRhcmdldCBvYmplY3QuXG4gKiBJbiB0aGlzIG1vZGUgbmV3bHkgZ2VuZXJhdGVkIC8gbW9kaWZpZWQgbW9kZWwgSURzIHByZXZpb3VzbHkgdHJhY2tlZFxuICogYnkgYGFwcGx5U2VyaWFsaXplZEFjdGlvbkFuZFRyYWNrTmV3TW9kZWxJZHNgIHdpbGwgYmUgc3luY2hyb25pemVkIGFmdGVyXG4gKiB0aGUgYWN0aW9uIGlzIGFwcGxpZWQuXG4gKiBUaGlzIG1lYW5zIHRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgdXNlZCBvbiB0aGUgY2xpZW50IHNpZGUuXG4gKlxuICogSWYgeW91IGludGVuZCB0byBhcHBseSBub24tc2VyaWFsaXplZCBhY3Rpb25zIGNoZWNrIGBhcHBseUFjdGlvbmAgaW5zdGVhZC5cbiAqXG4gKiBAcGFyYW0gc3VidHJlZVJvb3QgU3VidHJlZSByb290IHRhcmdldCBvYmplY3QgdG8gcnVuIHRoZSBhY3Rpb24gb3Zlci5cbiAqIEBwYXJhbSBjYWxsIFRoZSBzZXJpYWxpemVkIGFjdGlvbiwgdXN1YWxseSBhcyBjb21pbmcgZnJvbSB0aGUgc2VydmVyL2NsaWVudC5cbiAqIEByZXR1cm5zIFRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGFjdGlvbiwgaWYgYW55LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlTZXJpYWxpemVkQWN0aW9uQW5kU3luY05ld01vZGVsSWRzPFRSZXQgPSBhbnk+KFxuICBzdWJ0cmVlUm9vdDogb2JqZWN0LFxuICBjYWxsOiBTZXJpYWxpemVkQWN0aW9uQ2FsbFdpdGhNb2RlbElkT3ZlcnJpZGVzXG4pOiBUUmV0IHtcbiAgaWYgKCFjYWxsLnNlcmlhbGl6ZWQpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFwiY2Fubm90IGFwcGx5IGEgbm9uLXNlcmlhbGl6ZWQgYWN0aW9uIGNhbGwsIHVzZSAnYXBwbHlBY3Rpb24nIGluc3RlYWRcIilcbiAgfVxuXG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qoc3VidHJlZVJvb3QsIFwic3VidHJlZVJvb3RcIilcblxuICBjb25zdCBkZXNlcmlhbGl6ZWRDYWxsID0gZGVzZXJpYWxpemVBY3Rpb25DYWxsKGNhbGwsIHN1YnRyZWVSb290KVxuXG4gIGxldCByZXR1cm5WYWx1ZTogYW55XG4gIHJ1bkluQWN0aW9uKCgpID0+IHtcbiAgICByZXR1cm5WYWx1ZSA9IGFwcGx5QWN0aW9uKHN1YnRyZWVSb290LCBkZXNlcmlhbGl6ZWRDYWxsKVxuXG4gICAgLy8gYXBwbHkgbW9kZWwgaWQgb3ZlcnJpZGVzXG4gICAgYXBwbHlQYXRjaGVzKHN1YnRyZWVSb290LCBjYWxsLm1vZGVsSWRPdmVycmlkZXMpXG4gIH0pXG5cbiAgcmV0dXJuIHJldHVyblZhbHVlXG59XG4iLCJpbXBvcnQge1xuICBBY3Rpb25Db250ZXh0LFxuICBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZSxcbiAgQWN0aW9uQ29udGV4dEFzeW5jU3RlcFR5cGUsXG59IGZyb20gXCIuLi9hY3Rpb24vY29udGV4dFwiXG5pbXBvcnQge1xuICBBY3Rpb25NaWRkbGV3YXJlLFxuICBBY3Rpb25NaWRkbGV3YXJlRGlzcG9zZXIsXG4gIGFkZEFjdGlvbk1pZGRsZXdhcmUsXG59IGZyb20gXCIuLi9hY3Rpb24vbWlkZGxld2FyZVwiXG5pbXBvcnQgdHlwZSB7IEZsb3dGaW5pc2hlciB9IGZyb20gXCIuLi9hY3Rpb24vbW9kZWxGbG93XCJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcbmltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxuXG4vKipcbiAqIFNpbXBsaWZpZWQgdmVyc2lvbiBvZiBhY3Rpb24gY29udGV4dC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaW1wbGVBY3Rpb25Db250ZXh0IHtcbiAgLyoqXG4gICAqIEFjdGlvbiBuYW1lXG4gICAqL1xuICByZWFkb25seSBhY3Rpb25OYW1lOiBzdHJpbmdcbiAgLyoqXG4gICAqIEFjdGlvbiB0eXBlLCBzeW5jIG9yIGFzeW5jLlxuICAgKi9cbiAgcmVhZG9ubHkgdHlwZTogQWN0aW9uQ29udGV4dEFjdGlvblR5cGVcbiAgLyoqXG4gICAqIEFjdGlvbiB0YXJnZXQgbW9kZWwgaW5zdGFuY2UuXG4gICAqL1xuICByZWFkb25seSB0YXJnZXQ6IEFueU1vZGVsXG4gIC8qKlxuICAgKiBBcnJheSBvZiBhY3Rpb24gYXJndW1lbnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgYXJnczogUmVhZG9ubHlBcnJheTxhbnk+XG4gIC8qKlxuICAgKiBQYXJlbnQgYWN0aW9uIGNvbnRleHQsIGlmIGFueS5cbiAgICovXG4gIHJlYWRvbmx5IHBhcmVudENvbnRleHQ/OiBTaW1wbGVBY3Rpb25Db250ZXh0XG4gIC8qKlxuICAgKiBSb290IGFjdGlvbiBjb250ZXh0LCBvciBpdHNlbGYgaWYgdGhlIHJvb3QuXG4gICAqL1xuICByZWFkb25seSByb290Q29udGV4dDogU2ltcGxlQWN0aW9uQ29udGV4dFxuICAvKipcbiAgICogQ3VzdG9tIGRhdGEgZm9yIHRoZSBhY3Rpb24gY29udGV4dCB0byBiZSBzZXQgYnkgbWlkZGxld2FyZXMsIGFuIG9iamVjdC5cbiAgICogU3ltYm9scyBtdXN0IGJlIHVzZWQgYXMga2V5cyB0byBhdm9pZCBuYW1lIGNsYXNoaW5nIGJldHdlZW4gbWlkZGxld2FyZXMuXG4gICAqL1xuICByZWFkb25seSBkYXRhOiBSZWNvcmQ8c3ltYm9sLCBhbnk+XG59XG5cbi8qKlxuICogQWN0aW9uIHRyYWNraW5nIG1pZGRsZXdhcmUgZmluaXNoIHJlc3VsdC5cbiAqL1xuZXhwb3J0IGVudW0gQWN0aW9uVHJhY2tpbmdSZXN1bHQge1xuICAvKipcbiAgICogVGhlIGFjdGlvbiByZXR1cm5lZCBub3JtYWxseSAod2l0aG91dCB0aHJvd2luZykuXG4gICAqL1xuICBSZXR1cm4gPSBcInJldHVyblwiLFxuICAvKipcbiAgICogVGhlIGFjdGlvbiB0aHJldyBhbiBlcnJvci5cbiAgICovXG4gIFRocm93ID0gXCJ0aHJvd1wiLFxufVxuXG4vKipcbiAqIEFjdGlvbiB0cmFja2luZyBtaWRkbGV3YXJlIGhvb2tzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFjdGlvblRyYWNraW5nTWlkZGxld2FyZSB7XG4gIC8qKlxuICAgKiBGaWx0ZXIgZnVuY3Rpb24gY2FsbGVkIHdoZW5ldmVyIGVhY2ggYWN0aW9uIHN0YXJ0cywgYW5kIG9ubHkgdGhlbi5cbiAgICpcbiAgICogSWYgdGhlIGFjdGlvbiBpcyBhY2NlcHRlZCB0aGVuIGBvblN0YXJ0YCwgYG9uUmVzdW1lYCwgYG9uU3VzcGVuZGAgYW5kIGBvbkZpbmlzaGBcbiAgICogZm9yIHRoYXQgcGFydGljdWxhciBhY3Rpb24gd2lsbCBiZSBjYWxsZWQuXG4gICAqXG4gICAqIEFsbCBhY3Rpb25zIGFyZSBhY2NlcHRlZCBieSBkZWZhdWx0IGlmIG5vIGZpbHRlciBmdW5jdGlvbiBpcyBwcmVzZW50LlxuICAgKlxuICAgKiBAcGFyYW0gY3R4IFNpbXBsaWZpZWQgYWN0aW9uIGNvbnRleHQuXG4gICAqIEByZXR1cm5zIHRydWUgdG8gYWNjZXB0IHRoZSBhY3Rpb24sIGZhbHNlIHRvIHNraXAgaXQuXG4gICAqL1xuICBmaWx0ZXI/KGN0eDogU2ltcGxlQWN0aW9uQ29udGV4dCk6IGJvb2xlYW5cblxuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gYW4gYWN0aW9uIGp1c3Qgc3RhcnRlZC5cbiAgICpcbiAgICogQHBhcmFtIGN0eCBTaW1wbGlmaWVkIGFjdGlvbiBjb250ZXh0LlxuICAgKiBAcmV0dXJucyBDYW4gb3B0aW9uYWxseSByZXR1cm4gYSByZXN1bHQgdGhhdCB3aWxsIGNhbmNlbCB0aGUgb3JpZ2luYWwgYWN0aW9uIGFuZCBmaW5pc2ggaXRcbiAgICogd2l0aCB0aGUgcmV0dXJuZWQgdmFsdWUgLyBlcnJvciB0byBiZSB0aHJvd24uIEluIGVpdGhlciBjYXNlIGNhc2UgcmVzdW1lIC8gc3VzcGVuZCAvIGZpbmlzaCB3aWxsXG4gICAqIHN0aWxsIGJlIGNhbGxlZCBub3JtYWxseS5cbiAgICovXG4gIG9uU3RhcnQ/KGN0eDogU2ltcGxlQWN0aW9uQ29udGV4dCk6IHZvaWQgfCBBY3Rpb25UcmFja2luZ1JldHVyblxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiBhbiBhY3Rpb24ganVzdCByZXN1bWVkIGEgc3luY2hyb25vdXMgcGllY2Ugb2YgY29kZSBleGVjdXRpb24uXG4gICAqIEdldHMgY2FsbGVkIG9uY2UgZm9yIHN5bmMgYWN0aW9ucyBhbmQgbXVsdGlwbGUgdGltZXMgZm9yIGZsb3dzLlxuICAgKlxuICAgKiBAcGFyYW0gY3R4IFNpbXBsaWZpZWQgYWN0aW9uIGNvbnRleHQuXG4gICAqL1xuICBvblJlc3VtZT8oY3R4OiBTaW1wbGVBY3Rpb25Db250ZXh0KTogdm9pZFxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiBhbiBhY3Rpb24ganVzdCBmaW5pc2hlZCBhIHN5bmNocm9ub3VzIHBpY2Ugb2YgY29kZSBleGVjdXRpb24uXG4gICAqIE5vdGUgdGhhdCB0aGlzIGRvZXNuJ3QgbmVjZXNzYXJpbHkgbWVhbiB0aGUgYWN0aW9uIGlzIGZpbmlzaGVkLlxuICAgKiBHZXRzIGNhbGxlZCBvbmNlIGZvciBzeW5jIGFjdGlvbnMgYW5kIG11bHRpcGxlIHRpbWVzIGZvciBmbG93cy5cbiAgICpcbiAgICogQHBhcmFtIGN0eCBTaW1wbGlmaWVkIGFjdGlvbiBjb250ZXh0LlxuICAgKi9cbiAgb25TdXNwZW5kPyhjdHg6IFNpbXBsZUFjdGlvbkNvbnRleHQpOiB2b2lkXG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIGFuIGFjdGlvbiBqdXN0IGZpbmlzaGVkLCBlaXRoZXIgYnkgcmV0dXJuaW5nIG5vcm1hbGx5IG9yIGJ5IHRocm93aW5nIGFuIGVycm9yLlxuICAgKlxuICAgKiBAcGFyYW0gY3R4IFNpbXBsaWZpZWQgYWN0aW9uIGNvbnRleHQuXG4gICAqIEBwYXJhbSByZXQgQWN0aW9uIHJldHVybiByZXN1bHQuXG4gICAqIEByZXR1cm5zIENhbiBvcHRpb25hbGx5IHJldHVybiBhIG5ldyByZXN1bHQgdGhhdCB3aWxsIG92ZXJyaWRlIHRoZSBvcmlnaW5hbCBvbmUuXG4gICAqL1xuICBvbkZpbmlzaD8oY3R4OiBTaW1wbGVBY3Rpb25Db250ZXh0LCByZXQ6IEFjdGlvblRyYWNraW5nUmV0dXJuKTogdm9pZCB8IEFjdGlvblRyYWNraW5nUmV0dXJuXG59XG5cbi8qKlxuICogUmV0dXJuIHJlc3VsdCBvZiBhbiBhY3Rpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uVHJhY2tpbmdSZXR1cm4ge1xuICByZXN1bHQ6IEFjdGlvblRyYWNraW5nUmVzdWx0XG4gIHZhbHVlOiBhbnlcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIGFjdGlvbiB0cmFja2luZyBtaWRkbGV3YXJlLCB3aGljaCBpcyBhIHNpbXBsaWZpZWQgdmVyc2lvblxuICogb2YgdGhlIHN0YW5kYXJkIGFjdGlvbiBtaWRkbGV3YXJlLlxuICpcbiAqIEBwYXJhbSBzdWJ0cmVlUm9vdCBTdWJ0cmVlIHJvb3QgdGFyZ2V0IG9iamVjdC5cbiAqIEBwYXJhbSBob29rcyBNaWRkbGV3YXJlIGhvb2tzLlxuICogQHJldHVybnMgVGhlIG1pZGRsZXdhcmUgZGlzcG9zZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhY3Rpb25UcmFja2luZ01pZGRsZXdhcmUoXG4gIHN1YnRyZWVSb290OiBvYmplY3QsXG4gIGhvb2tzOiBBY3Rpb25UcmFja2luZ01pZGRsZXdhcmVcbik6IEFjdGlvbk1pZGRsZXdhcmVEaXNwb3NlciB7XG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qoc3VidHJlZVJvb3QsIFwic3VidHJlZVJvb3RcIilcblxuICBjb25zdCBkYXRhU3ltYm9sID0gU3ltYm9sKFwiYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlRGF0YVwiKVxuXG4gIGVudW0gU3RhdGUge1xuICAgIElkbGUgPSBcImlkbGVcIixcbiAgICBTdGFydGVkID0gXCJzdGFydGVkXCIsXG4gICAgUmVhbFJlc3VtZWQgPSBcInJlYWxSZXN1bWVkXCIsXG4gICAgRmFrZVJlc3VtZWQgPSBcImZha2VSZXN1bWVkXCIsXG4gICAgU3VzcGVuZGVkID0gXCJzdXNwZW5kZWRcIixcbiAgICBGaW5pc2hlZCA9IFwiZmluaXNoZWRcIixcbiAgfVxuXG4gIGludGVyZmFjZSBEYXRhIHtcbiAgICBzdGFydEFjY2VwdGVkOiBib29sZWFuXG4gICAgc3RhdGU6IFN0YXRlXG4gIH1cblxuICBmdW5jdGlvbiBnZXRDdHhEYXRhKGN0eDogQWN0aW9uQ29udGV4dCB8IFNpbXBsZUFjdGlvbkNvbnRleHQpOiBEYXRhIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gY3R4LmRhdGFbZGF0YVN5bWJvbF1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldEN0eERhdGEoY3R4OiBBY3Rpb25Db250ZXh0IHwgU2ltcGxlQWN0aW9uQ29udGV4dCwgcGFydGlhbERhdGE6IFBhcnRpYWw8RGF0YT4pIHtcbiAgICBsZXQgY3VycmVudERhdGEgPSBjdHguZGF0YVtkYXRhU3ltYm9sXVxuICAgIGlmICghY3VycmVudERhdGEpIHtcbiAgICAgIGN0eC5kYXRhW2RhdGFTeW1ib2xdID0gcGFydGlhbERhdGFcbiAgICB9IGVsc2Uge1xuICAgICAgT2JqZWN0LmFzc2lnbihjdXJyZW50RGF0YSwgcGFydGlhbERhdGEpXG4gICAgfVxuICB9XG5cbiAgY29uc3QgdXNlckZpbHRlcjogQWN0aW9uTWlkZGxld2FyZVtcImZpbHRlclwiXSA9IChjdHgpID0+IHtcbiAgICBpZiAoaG9va3MuZmlsdGVyKSB7XG4gICAgICByZXR1cm4gaG9va3MuZmlsdGVyKHNpbXBsaWZ5QWN0aW9uQ29udGV4dChjdHgpKVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICBjb25zdCByZXN1bWVTdXNwZW5kU3VwcG9ydCA9ICEhaG9va3Mub25SZXN1bWUgfHwgISFob29rcy5vblN1c3BlbmRcblxuICBjb25zdCBmaWx0ZXI6IEFjdGlvbk1pZGRsZXdhcmVbXCJmaWx0ZXJcIl0gPSAoY3R4KSA9PiB7XG4gICAgaWYgKGN0eC50eXBlID09PSBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZS5TeW5jKSB7XG4gICAgICAvLyBzdGFydCBhbmQgZmluaXNoIGlzIG9uIHRoZSBzYW1lIGNvbnRleHRcbiAgICAgIGNvbnN0IGFjY2VwdGVkID0gdXNlckZpbHRlcihjdHgpXG4gICAgICBpZiAoYWNjZXB0ZWQpIHtcbiAgICAgICAgc2V0Q3R4RGF0YShjdHgsIHtcbiAgICAgICAgICBzdGFydEFjY2VwdGVkOiB0cnVlLFxuICAgICAgICAgIHN0YXRlOiBTdGF0ZS5JZGxlLFxuICAgICAgICB9KVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY2VwdGVkXG4gICAgfSBlbHNlIHtcbiAgICAgIHN3aXRjaCAoY3R4LmFzeW5jU3RlcFR5cGUpIHtcbiAgICAgICAgY2FzZSBBY3Rpb25Db250ZXh0QXN5bmNTdGVwVHlwZS5TcGF3bjpcbiAgICAgICAgICBjb25zdCBhY2NlcHRlZCA9IHVzZXJGaWx0ZXIoY3R4KVxuICAgICAgICAgIGlmIChhY2NlcHRlZCkge1xuICAgICAgICAgICAgc2V0Q3R4RGF0YShjdHgsIHtcbiAgICAgICAgICAgICAgc3RhcnRBY2NlcHRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgc3RhdGU6IFN0YXRlLklkbGUsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYWNjZXB0ZWRcblxuICAgICAgICBjYXNlIEFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlLlJldHVybjpcbiAgICAgICAgY2FzZSBBY3Rpb25Db250ZXh0QXN5bmNTdGVwVHlwZS5UaHJvdzpcbiAgICAgICAgICAvLyBkZXBlbmRzIGlmIHRoZSBzcGF3biBvbmUgd2FzIGFjY2VwdGVkIG9yIG5vdFxuICAgICAgICAgIGNvbnN0IGRhdGEgPSBnZXRDdHhEYXRhKGN0eC5zcGF3bkFzeW5jU3RlcENvbnRleHQhKVxuICAgICAgICAgIHJldHVybiBkYXRhID8gZGF0YS5zdGFydEFjY2VwdGVkIDogZmFsc2VcblxuICAgICAgICBjYXNlIEFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlLlJlc3VtZTpcbiAgICAgICAgY2FzZSBBY3Rpb25Db250ZXh0QXN5bmNTdGVwVHlwZS5SZXN1bWVFcnJvcjpcbiAgICAgICAgICBpZiAoIXJlc3VtZVN1c3BlbmRTdXBwb3J0KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZGVwZW5kcyBpZiB0aGUgc3Bhd24gb25lIHdhcyBhY2NlcHRlZCBvciBub3RcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBnZXRDdHhEYXRhKGN0eC5zcGF3bkFzeW5jU3RlcENvbnRleHQhKVxuICAgICAgICAgICAgcmV0dXJuIGRhdGEgPyBkYXRhLnN0YXJ0QWNjZXB0ZWQgOiBmYWxzZVxuICAgICAgICAgIH1cblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHN0YXJ0ID0gKHNpbXBsZUN0eDogU2ltcGxlQWN0aW9uQ29udGV4dCk6IEFjdGlvblRyYWNraW5nUmV0dXJuIHwgdW5kZWZpbmVkID0+IHtcbiAgICBzZXRDdHhEYXRhKHNpbXBsZUN0eCwge1xuICAgICAgc3RhdGU6IFN0YXRlLlN0YXJ0ZWQsXG4gICAgfSlcbiAgICBpZiAoaG9va3Mub25TdGFydCkge1xuICAgICAgcmV0dXJuIGhvb2tzLm9uU3RhcnQoc2ltcGxlQ3R4KSB8fCB1bmRlZmluZWRcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9XG5cbiAgY29uc3QgZmluaXNoID0gKFxuICAgIHNpbXBsZUN0eDogU2ltcGxlQWN0aW9uQ29udGV4dCxcbiAgICByZXQ6IEFjdGlvblRyYWNraW5nUmV0dXJuXG4gICk6IEFjdGlvblRyYWNraW5nUmV0dXJuID0+IHtcbiAgICAvLyBmYWtlbHkgcmVzdW1lIGFuZCBzdXNwZW5kIHRoZSBwYXJlbnQgaWYgbmVlZGVkXG4gICAgY29uc3QgcGFyZW50Q3R4ID0gc2ltcGxlQ3R4LnBhcmVudENvbnRleHRcbiAgICBsZXQgcGFyZW50UmVzdW1lZCA9IGZhbHNlXG4gICAgaWYgKHBhcmVudEN0eCkge1xuICAgICAgY29uc3QgcGFyZW50RGF0YSA9IGdldEN0eERhdGEocGFyZW50Q3R4KVxuICAgICAgaWYgKHBhcmVudERhdGEgJiYgcGFyZW50RGF0YS5zdGFydEFjY2VwdGVkICYmIHBhcmVudERhdGEuc3RhdGUgPT09IFN0YXRlLlN1c3BlbmRlZCkge1xuICAgICAgICBwYXJlbnRSZXN1bWVkID0gdHJ1ZVxuICAgICAgICByZXN1bWUocGFyZW50Q3R4LCBmYWxzZSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRDdHhEYXRhKHNpbXBsZUN0eCwge1xuICAgICAgc3RhdGU6IFN0YXRlLkZpbmlzaGVkLFxuICAgIH0pXG5cbiAgICBpZiAoaG9va3Mub25GaW5pc2gpIHtcbiAgICAgIHJldCA9IGhvb2tzLm9uRmluaXNoKHNpbXBsZUN0eCwgcmV0KSB8fCByZXRcbiAgICB9XG5cbiAgICBpZiAocGFyZW50UmVzdW1lZCkge1xuICAgICAgc3VzcGVuZChwYXJlbnRDdHghKVxuICAgIH1cblxuICAgIHJldHVybiByZXRcbiAgfVxuXG4gIGNvbnN0IHJlc3VtZSA9IChzaW1wbGVDdHg6IFNpbXBsZUFjdGlvbkNvbnRleHQsIHJlYWw6IGJvb2xlYW4pID0+IHtcbiAgICAvLyBlbnN1cmUgcGFyZW50cyBhcmUgcmVzdW1lZFxuICAgIGNvbnN0IHBhcmVudEN0eCA9IHNpbXBsZUN0eC5wYXJlbnRDb250ZXh0XG4gICAgaWYgKHBhcmVudEN0eCkge1xuICAgICAgY29uc3QgcGFyZW50RGF0YSA9IGdldEN0eERhdGEocGFyZW50Q3R4KVxuICAgICAgaWYgKHBhcmVudERhdGEgJiYgcGFyZW50RGF0YS5zdGFydEFjY2VwdGVkICYmIHBhcmVudERhdGEuc3RhdGUgPT09IFN0YXRlLlN1c3BlbmRlZCkge1xuICAgICAgICByZXN1bWUocGFyZW50Q3R4LCBmYWxzZSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRDdHhEYXRhKHNpbXBsZUN0eCwge1xuICAgICAgc3RhdGU6IHJlYWwgPyBTdGF0ZS5SZWFsUmVzdW1lZCA6IFN0YXRlLkZha2VSZXN1bWVkLFxuICAgIH0pXG4gICAgaWYgKGhvb2tzLm9uUmVzdW1lKSB7XG4gICAgICBob29rcy5vblJlc3VtZShzaW1wbGVDdHgpXG4gICAgfVxuICB9XG5cbiAgY29uc3Qgc3VzcGVuZCA9IChzaW1wbGVDdHg6IFNpbXBsZUFjdGlvbkNvbnRleHQpID0+IHtcbiAgICBzZXRDdHhEYXRhKHNpbXBsZUN0eCwge1xuICAgICAgc3RhdGU6IFN0YXRlLlN1c3BlbmRlZCxcbiAgICB9KVxuICAgIGlmIChob29rcy5vblN1c3BlbmQpIHtcbiAgICAgIGhvb2tzLm9uU3VzcGVuZChzaW1wbGVDdHgpXG4gICAgfVxuXG4gICAgLy8gZW5zdXJlIHBhcmVudHMgYXJlIHN1c3BlbmRlZCBpZiB0aGV5IHdlcmUgZmFrZWx5IHJlc3VtZWRcbiAgICBjb25zdCBwYXJlbnRDdHggPSBzaW1wbGVDdHgucGFyZW50Q29udGV4dFxuICAgIGlmIChwYXJlbnRDdHgpIHtcbiAgICAgIGNvbnN0IHBhcmVudERhdGEgPSBnZXRDdHhEYXRhKHBhcmVudEN0eClcbiAgICAgIGlmIChwYXJlbnREYXRhICYmIHBhcmVudERhdGEuc3RhcnRBY2NlcHRlZCAmJiBwYXJlbnREYXRhLnN0YXRlID09PSBTdGF0ZS5GYWtlUmVzdW1lZCkge1xuICAgICAgICBzdXNwZW5kKHBhcmVudEN0eClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBtd2FyZTogQWN0aW9uTWlkZGxld2FyZVtcIm1pZGRsZXdhcmVcIl0gPSAoY3R4LCBuZXh0KSA9PiB7XG4gICAgY29uc3Qgc2ltcGxlQ3R4ID0gc2ltcGxpZnlBY3Rpb25Db250ZXh0KGN0eClcblxuICAgIGNvbnN0IG9yaWdOZXh0ID0gbmV4dFxuICAgIG5leHQgPSAoKSA9PiB7XG4gICAgICByZXN1bWUoc2ltcGxlQ3R4LCB0cnVlKVxuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIG9yaWdOZXh0KClcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHN1c3BlbmQoc2ltcGxlQ3R4KVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjdHgudHlwZSA9PT0gQWN0aW9uQ29udGV4dEFjdGlvblR5cGUuU3luYykge1xuICAgICAgbGV0IHJldE9iaiA9IHN0YXJ0KHNpbXBsZUN0eClcblxuICAgICAgaWYgKHJldE9iaikge1xuICAgICAgICAvLyBhY3Rpb24gY2FuY2VsZWQgLyBvdmVycmlkZGVuIGJ5IG9uU3RhcnRcbiAgICAgICAgcmVzdW1lKHNpbXBsZUN0eCwgdHJ1ZSlcbiAgICAgICAgc3VzcGVuZChzaW1wbGVDdHgpXG4gICAgICAgIHJldE9iaiA9IGZpbmlzaChzaW1wbGVDdHgsIHJldE9iailcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0T2JqID0gZmluaXNoKHNpbXBsZUN0eCwgeyByZXN1bHQ6IEFjdGlvblRyYWNraW5nUmVzdWx0LlJldHVybiwgdmFsdWU6IG5leHQoKSB9KVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICByZXRPYmogPSBmaW5pc2goc2ltcGxlQ3R4LCB7IHJlc3VsdDogQWN0aW9uVHJhY2tpbmdSZXN1bHQuVGhyb3csIHZhbHVlOiBlcnIgfSlcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmV0dXJuT3JUaHJvd0FjdGlvblRyYWNraW5nUmV0dXJuKHJldE9iailcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gYXN5bmNcblxuICAgICAgc3dpdGNoIChjdHguYXN5bmNTdGVwVHlwZSkge1xuICAgICAgICBjYXNlIEFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlLlNwYXduOiB7XG4gICAgICAgICAgbGV0IHJldE9iaiA9IHN0YXJ0KHNpbXBsZUN0eClcbiAgICAgICAgICBpZiAocmV0T2JqKSB7XG4gICAgICAgICAgICAvLyBhY3Rpb24gY2FuY2VsZWQgLyBvdmVycmlkZGVuIGJ5IG9uU3RhcnRcbiAgICAgICAgICAgIHJlc3VtZShzaW1wbGVDdHgsIHRydWUpXG4gICAgICAgICAgICBzdXNwZW5kKHNpbXBsZUN0eClcbiAgICAgICAgICAgIHJldE9iaiA9IGZpbmlzaChzaW1wbGVDdHgsIHJldE9iailcbiAgICAgICAgICAgIHJldHVybiByZXR1cm5PclRocm93QWN0aW9uVHJhY2tpbmdSZXR1cm4ocmV0T2JqKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbmV4dCgpXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSBBY3Rpb25Db250ZXh0QXN5bmNTdGVwVHlwZS5SZXR1cm46IHtcbiAgICAgICAgICBjb25zdCBmbG93RmluaXNoZXI6IEZsb3dGaW5pc2hlciA9IG5leHQoKVxuICAgICAgICAgIGNvbnN0IHJldE9iaiA9IGZpbmlzaChzaW1wbGVDdHgsIHtcbiAgICAgICAgICAgIHJlc3VsdDogQWN0aW9uVHJhY2tpbmdSZXN1bHQuUmV0dXJuLFxuICAgICAgICAgICAgdmFsdWU6IGZsb3dGaW5pc2hlci52YWx1ZSxcbiAgICAgICAgICB9KVxuICAgICAgICAgIGZsb3dGaW5pc2hlci5yZXNvbHV0aW9uID1cbiAgICAgICAgICAgIHJldE9iai5yZXN1bHQgPT09IEFjdGlvblRyYWNraW5nUmVzdWx0LlJldHVybiA/IFwiYWNjZXB0XCIgOiBcInJlamVjdFwiXG4gICAgICAgICAgZmxvd0ZpbmlzaGVyLnZhbHVlID0gcmV0T2JqLnZhbHVlXG4gICAgICAgICAgcmV0dXJuIGZsb3dGaW5pc2hlclxuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSBBY3Rpb25Db250ZXh0QXN5bmNTdGVwVHlwZS5UaHJvdzoge1xuICAgICAgICAgIGNvbnN0IGZsb3dGaW5pc2hlcjogRmxvd0ZpbmlzaGVyID0gbmV4dCgpXG4gICAgICAgICAgY29uc3QgcmV0T2JqID0gZmluaXNoKHNpbXBsZUN0eCwge1xuICAgICAgICAgICAgcmVzdWx0OiBBY3Rpb25UcmFja2luZ1Jlc3VsdC5UaHJvdyxcbiAgICAgICAgICAgIHZhbHVlOiBmbG93RmluaXNoZXIudmFsdWUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICBmbG93RmluaXNoZXIucmVzb2x1dGlvbiA9XG4gICAgICAgICAgICByZXRPYmoucmVzdWx0ID09PSBBY3Rpb25UcmFja2luZ1Jlc3VsdC5SZXR1cm4gPyBcImFjY2VwdFwiIDogXCJyZWplY3RcIlxuICAgICAgICAgIGZsb3dGaW5pc2hlci52YWx1ZSA9IHJldE9iai52YWx1ZVxuICAgICAgICAgIHJldHVybiBmbG93RmluaXNoZXJcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgQWN0aW9uQ29udGV4dEFzeW5jU3RlcFR5cGUuUmVzdW1lOlxuICAgICAgICBjYXNlIEFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlLlJlc3VtZUVycm9yOlxuICAgICAgICAgIGlmIChyZXN1bWVTdXNwZW5kU3VwcG9ydCkge1xuICAgICAgICAgICAgcmV0dXJuIG5leHQoKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBmYWlsdXJlKFxuICAgICAgICAgICAgICBgYXNzZXJ0aW9uIGVycm9yOiBhc3luYyBzdGVwIHNob3VsZCBoYXZlIGJlZW4gZmlsdGVyZWQgb3V0IC0gJHtjdHguYXN5bmNTdGVwVHlwZX1gXG4gICAgICAgICAgICApXG4gICAgICAgICAgfVxuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgZmFpbHVyZShcbiAgICAgICAgICAgIGBhc3NlcnRpb24gZXJyb3I6IGFzeW5jIHN0ZXAgc2hvdWxkIGhhdmUgYmVlbiBmaWx0ZXJlZCBvdXQgLSAke2N0eC5hc3luY1N0ZXBUeXBlfWBcbiAgICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGFkZEFjdGlvbk1pZGRsZXdhcmUoeyBtaWRkbGV3YXJlOiBtd2FyZSwgZmlsdGVyLCBzdWJ0cmVlUm9vdDogc3VidHJlZVJvb3QgfSlcbn1cblxuZnVuY3Rpb24gcmV0dXJuT3JUaHJvd0FjdGlvblRyYWNraW5nUmV0dXJuKHJldE9iajogQWN0aW9uVHJhY2tpbmdSZXR1cm4pIHtcbiAgaWYgKHJldE9iai5yZXN1bHQgPT09IEFjdGlvblRyYWNraW5nUmVzdWx0LlJldHVybikge1xuICAgIHJldHVybiByZXRPYmoudmFsdWVcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyByZXRPYmoudmFsdWVcbiAgfVxufVxuXG5jb25zdCBzaW1wbGVEYXRhQ29udGV4dFN5bWJvbCA9IFN5bWJvbChcInNpbXBsZURhdGFDb250ZXh0XCIpXG5cbi8qKlxuICogU2ltcGxpZmllcyBhbiBhY3Rpb24gY29udGV4dCBieSBjb252ZXJ0aW5nIGFuIGFzeW5jIGNhbGwgaGllcmFyY2h5IGludG8gYSBzaW1wbGVyIG9uZS5cbiAqXG4gKiBAcGFyYW0gY3R4IEFjdGlvbiBjb250ZXh0IHRvIGNvbnZlcnQuXG4gKiBAcmV0dXJucyBTaW1wbGlmaWVkIGFjdGlvbiBjb250ZXh0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2ltcGxpZnlBY3Rpb25Db250ZXh0KGN0eDogQWN0aW9uQ29udGV4dCk6IFNpbXBsZUFjdGlvbkNvbnRleHQge1xuICB3aGlsZSAoY3R4LnByZXZpb3VzQXN5bmNTdGVwQ29udGV4dCkge1xuICAgIGN0eCA9IGN0eC5wcmV2aW91c0FzeW5jU3RlcENvbnRleHRcbiAgfVxuXG4gIGxldCBzaW1wbGVDdHggPSBjdHguZGF0YVtzaW1wbGVEYXRhQ29udGV4dFN5bWJvbF1cbiAgaWYgKCFzaW1wbGVDdHgpIHtcbiAgICBjb25zdCBwYXJlbnRDb250ZXh0ID0gY3R4LnBhcmVudENvbnRleHQgPyBzaW1wbGlmeUFjdGlvbkNvbnRleHQoY3R4LnBhcmVudENvbnRleHQpIDogdW5kZWZpbmVkXG5cbiAgICBzaW1wbGVDdHggPSB7XG4gICAgICBhY3Rpb25OYW1lOiBjdHguYWN0aW9uTmFtZSxcbiAgICAgIHR5cGU6IGN0eC50eXBlLFxuICAgICAgdGFyZ2V0OiBjdHgudGFyZ2V0LFxuICAgICAgYXJnczogY3R4LmFyZ3MsXG4gICAgICBkYXRhOiBjdHguZGF0YSxcbiAgICAgIHBhcmVudENvbnRleHQsXG4gICAgfVxuICAgIHNpbXBsZUN0eC5yb290Q29udGV4dCA9IHBhcmVudENvbnRleHQgPyBwYXJlbnRDb250ZXh0LnJvb3RDb250ZXh0IDogc2ltcGxlQ3R4XG5cbiAgICBjdHguZGF0YVtzaW1wbGVEYXRhQ29udGV4dFN5bWJvbF0gPSBzaW1wbGVDdHhcbiAgfVxuICByZXR1cm4gc2ltcGxlQ3R4XG59XG4iLCJpbXBvcnQgdHlwZSB7IEFjdGlvbkNhbGwgfSBmcm9tIFwiLi4vYWN0aW9uL2FwcGx5QWN0aW9uXCJcclxuaW1wb3J0IHsgaXNIb29rQWN0aW9uIH0gZnJvbSBcIi4uL2FjdGlvbi9ob29rQWN0aW9uc1wiXHJcbmltcG9ydCB0eXBlIHsgQWN0aW9uTWlkZGxld2FyZURpc3Bvc2VyIH0gZnJvbSBcIi4uL2FjdGlvbi9taWRkbGV3YXJlXCJcclxuaW1wb3J0IHsgZmFzdEdldFJvb3RQYXRoIH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoXCJcclxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxyXG5pbXBvcnQgeyBhc3NlcnRJc09iamVjdCB9IGZyb20gXCIuLi91dGlsc1wiXHJcbmltcG9ydCB7XHJcbiAgYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlLFxyXG4gIEFjdGlvblRyYWNraW5nUmV0dXJuLFxyXG4gIFNpbXBsZUFjdGlvbkNvbnRleHQsXHJcbn0gZnJvbSBcIi4vYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlXCJcclxuaW1wb3J0IHsgcm9vdFBhdGhUb1RhcmdldFBhdGhJZHMgfSBmcm9tIFwiLi91dGlsc1wiXHJcblxyXG4vKipcclxuICogQXR0YWNoZXMgYW4gYWN0aW9uIG1pZGRsZXdhcmUgdGhhdCBpbnZva2VzIGEgbGlzdGVuZXIgZm9yIGFsbCBhY3Rpb25zIG9mIGEgZ2l2ZW4gdHJlZS5cclxuICogTm90ZSB0aGF0IHRoZSBsaXN0ZW5lciB3aWxsIG9ubHkgYmUgaW52b2tlZCBmb3IgdGhlIHRvcG1vc3QgbGV2ZWwgYWN0aW9ucywgc28gaXQgd29uJ3QgcnVuIGZvciBjaGlsZCBhY3Rpb25zIG9yIGludGVybWVkaWFyeSBmbG93IHN0ZXBzLlxyXG4gKiBBbHNvIGl0IHdvbid0IHRyaWdnZXIgdGhlIGxpc3RlbmVyIGZvciBjYWxscyB0byBob29rcyBzdWNoIGFzIGBvbkF0dGFjaGVkVG9Sb290U3RvcmVgIG9yIGl0cyByZXR1cm5lZCBkaXNwb3Nlci5cclxuICpcclxuICogSXRzIG1haW4gdXNlIGlzIHRvIGtlZXAgdHJhY2sgb2YgdG9wIGxldmVsIGFjdGlvbnMgdGhhdCBjYW4gYmUgbGF0ZXIgcmVwbGljYXRlZCB2aWEgYGFwcGx5QWN0aW9uYCBzb21ld2hlcmUgZWxzZSAoYW5vdGhlciBtYWNoaW5lLCBldGMuKS5cclxuICpcclxuICogVGhlcmUgYXJlIHR3byBraW5kIG9mIHBvc3NpYmxlIGxpc3RlbmVycywgYG9uU3RhcnRgIGFuZCBgb25GaW5pc2hgIGxpc3RlbmVycy5cclxuICogYG9uU3RhcnRgIGxpc3RlbmVycyBhcmUgY2FsbGVkIGJlZm9yZSB0aGUgYWN0aW9uIGV4ZWN1dGVzIGFuZCBhbGxvdyBjYW5jZWxsYXRpb24gYnkgcmV0dXJuaW5nIGEgbmV3IHJldHVybiB2YWx1ZSAod2hpY2ggbWlnaHQgYmUgYSByZXR1cm4gb3IgYSB0aHJvdykuXHJcbiAqIGBvbkZpbmlzaGAgbGlzdGVuZXJzIGFyZSBjYWxsZWQgYWZ0ZXIgdGhlIGFjdGlvbiBleGVjdXRlcywgaGF2ZSBhY2Nlc3MgdG8gdGhlIGFjdGlvbiBhY3R1YWwgcmV0dXJuIHZhbHVlIGFuZCBhbGxvdyBvdmVycmlkaW5nIGJ5IHJldHVybmluZyBhXHJcbiAqIG5ldyByZXR1cm4gdmFsdWUgKHdoaWNoIG1pZ2h0IGJlIGEgcmV0dXJuIG9yIGEgdGhyb3cpLlxyXG4gKlxyXG4gKiBJZiB5b3Ugd2FudCB0byBlbnN1cmUgdGhhdCB0aGUgYWN0dWFsIGFjdGlvbiBjYWxscyBhcmUgc2VyaWFsaXphYmxlIHlvdSBzaG91bGQgdXNlIGVpdGhlciBgc2VyaWFsaXplQWN0aW9uQ2FsbEFyZ3VtZW50YCBvdmVyIHRoZSBhcmd1bWVudHNcclxuICogb3IgYHNlcmlhbGl6ZUFjdGlvbkNhbGxgIG92ZXIgdGhlIHdob2xlIGFjdGlvbiBiZWZvcmUgc2VuZGluZyB0aGUgYWN0aW9uIGNhbGwgb3ZlciB0aGUgd2lyZSAvIHN0b3JpbmcgdGhlbSAuXHJcbiAqXHJcbiAqIEBwYXJhbSBzdWJ0cmVlUm9vdCBTdWJ0cmVlIHJvb3QgdGFyZ2V0IG9iamVjdC5cclxuICogQHBhcmFtIGxpc3RlbmVycyBMaXN0ZW5lciBmdW5jdGlvbnMgdGhhdCB3aWxsIGJlIGludm9rZWQgZXZlcnl0aW1lIGEgdG9wbW9zdCBhY3Rpb24gaXMgaW52b2tlZCBvbiB0aGUgbW9kZWwgb3IgYW55IGNoaWxkcmVuLlxyXG4gKiBAcmV0dXJucyBUaGUgbWlkZGxld2FyZSBkaXNwb3Nlci5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBvbkFjdGlvbk1pZGRsZXdhcmUoXHJcbiAgc3VidHJlZVJvb3Q6IG9iamVjdCxcclxuICBsaXN0ZW5lcnM6IHtcclxuICAgIG9uU3RhcnQ/OiAoXHJcbiAgICAgIGFjdGlvbkNhbGw6IEFjdGlvbkNhbGwsXHJcbiAgICAgIGFjdGlvbkNvbnRleHQ6IFNpbXBsZUFjdGlvbkNvbnRleHRcclxuICAgICkgPT4gdm9pZCB8IEFjdGlvblRyYWNraW5nUmV0dXJuXHJcbiAgICBvbkZpbmlzaD86IChcclxuICAgICAgYWN0aW9uQ2FsbDogQWN0aW9uQ2FsbCxcclxuICAgICAgYWN0aW9uQ29udGV4dDogU2ltcGxlQWN0aW9uQ29udGV4dCxcclxuICAgICAgcmV0OiBBY3Rpb25UcmFja2luZ1JldHVyblxyXG4gICAgKSA9PiB2b2lkIHwgQWN0aW9uVHJhY2tpbmdSZXR1cm5cclxuICB9XHJcbik6IEFjdGlvbk1pZGRsZXdhcmVEaXNwb3NlciB7XHJcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdChzdWJ0cmVlUm9vdCwgXCJzdWJ0cmVlUm9vdFwiKVxyXG4gIGFzc2VydElzT2JqZWN0KGxpc3RlbmVycywgXCJsaXN0ZW5lcnNcIilcclxuXHJcbiAgcmV0dXJuIGFjdGlvblRyYWNraW5nTWlkZGxld2FyZShzdWJ0cmVlUm9vdCwge1xyXG4gICAgZmlsdGVyKGN0eCkge1xyXG4gICAgICBpZiAoY3R4LnBhcmVudENvbnRleHQpIHtcclxuICAgICAgICAvLyBzdWItYWN0aW9uLCBkbyBub3RoaW5nXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIHNraXAgaG9va3NcclxuICAgICAgaWYgKGlzSG9va0FjdGlvbihjdHguYWN0aW9uTmFtZSkpIHtcclxuICAgICAgICByZXR1cm4gZmFsc2VcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIHRydWVcclxuICAgIH0sXHJcblxyXG4gICAgb25TdGFydChjdHgpIHtcclxuICAgICAgaWYgKGxpc3RlbmVycy5vblN0YXJ0KSB7XHJcbiAgICAgICAgY29uc3QgYWN0aW9uQ2FsbCA9IGFjdGlvbkNvbnRleHRUb0FjdGlvbkNhbGwoY3R4KVxyXG4gICAgICAgIHJldHVybiBsaXN0ZW5lcnMub25TdGFydChhY3Rpb25DYWxsLCBjdHgpXHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgb25GaW5pc2goY3R4LCByZXQpIHtcclxuICAgICAgaWYgKGxpc3RlbmVycy5vbkZpbmlzaCkge1xyXG4gICAgICAgIGNvbnN0IGFjdGlvbkNhbGwgPSBhY3Rpb25Db250ZXh0VG9BY3Rpb25DYWxsKGN0eClcclxuICAgICAgICByZXR1cm4gbGlzdGVuZXJzLm9uRmluaXNoKGFjdGlvbkNhbGwsIGN0eCwgcmV0KVxyXG4gICAgICB9XHJcbiAgICB9LFxyXG4gIH0pXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGFjdGlvbkNvbnRleHRUb0FjdGlvbkNhbGwoY3R4OiBTaW1wbGVBY3Rpb25Db250ZXh0KTogQWN0aW9uQ2FsbCB7XHJcbiAgY29uc3Qgcm9vdFBhdGggPSBmYXN0R2V0Um9vdFBhdGgoY3R4LnRhcmdldClcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIGFjdGlvbk5hbWU6IGN0eC5hY3Rpb25OYW1lLFxyXG4gICAgYXJnczogY3R4LmFyZ3MsXHJcbiAgICB0YXJnZXRQYXRoOiByb290UGF0aC5wYXRoLFxyXG4gICAgdGFyZ2V0UGF0aElkczogcm9vdFBhdGhUb1RhcmdldFBhdGhJZHMocm9vdFBhdGgpLFxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBpc0hvb2tBY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9uL2hvb2tBY3Rpb25zXCJcbmltcG9ydCB0eXBlIHsgQWN0aW9uTWlkZGxld2FyZURpc3Bvc2VyIH0gZnJvbSBcIi4uL2FjdGlvbi9taWRkbGV3YXJlXCJcbmltcG9ydCB7IGFzc2VydFR3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxuaW1wb3J0IHtcbiAgYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlLFxuICBBY3Rpb25UcmFja2luZ1Jlc3VsdCxcbiAgU2ltcGxlQWN0aW9uQ29udGV4dCxcbn0gZnJvbSBcIi4vYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlXCJcblxuLyoqXG4gKiBSZXR1cm4gdHlwZSBmb3IgcmVhZG9ubHkgbWlkZGxld2FyZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWFkb25seU1pZGRsZXdhcmVSZXR1cm4ge1xuICBhbGxvd1dyaXRlPFI+KGZuOiAoKSA9PiBSKTogUlxuXG4gIGRpc3Bvc2U6IEFjdGlvbk1pZGRsZXdhcmVEaXNwb3NlclxufVxuXG4vKipcbiAqIEF0dGFjaGVzIGFuIGFjdGlvbiBtaWRkbGV3YXJlIHRoYXQgd2lsbCB0aHJvdyB3aGVuIGFueSBhY3Rpb24gaXMgc3RhcnRlZFxuICogb3ZlciB0aGUgbm9kZSBvciBhbnkgb2YgdGhlIGNoaWxkIG5vZGVzLCB0aHVzIGVmZmVjdGl2ZWx5IG1ha2luZyB0aGUgc3VidHJlZVxuICogcmVhZG9ubHkuXG4gKlxuICogSXQgd2lsbCByZXR1cm4gYW4gb2JqZWN0IHdpdGggYSBgZGlzcG9zZWAgZnVuY3Rpb24gdG8gcmVtb3ZlIHRoZSBtaWRkbGV3YXJlIGFuZCBhIGBhbGxvd1dyaXRlYCBmdW5jdGlvblxuICogdGhhdCB3aWxsIGFsbG93IGFjdGlvbnMgdG8gYmUgc3RhcnRlZCBpbnNpZGUgdGhlIHByb3ZpZGVkIGNvZGUgYmxvY2suXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYHRzXG4gKiAvLyBnaXZlbiBhIG1vZGVsIGluc3RhbmNlIG5hbWVkIHRvZG9cbiAqIGNvbnN0IHsgZGlzcG9zZSwgYWxsb3dXcml0ZSB9ID0gcmVhZG9ubHlNaWRkbGV3YXJlKHRvZG8pXG4gKlxuICogLy8gdGhpcyB3aWxsIHRocm93XG4gKiB0b2RvLnNldERvbmUoZmFsc2UpXG4gKiBhd2FpdCB0b2RvLnNldERvbmVBc3luYyhmYWxzZSlcbiAqXG4gKiAvLyB0aGlzIHdpbGwgd29ya1xuICogYWxsb3dXcml0ZSgoKSA9PiB0b2RvLnNldERvbmUoZmFsc2UpKVxuICogLy8gbm90ZTogZm9yIGFzeW5jIGFsd2F5cyB1c2Ugb25lIGFjdGlvbiBpbnZvY2F0aW9uIHBlciBhbGxvd1dyaXRlIVxuICogYXdhaXQgYWxsb3dXcml0ZSgoKSA9PiB0b2RvLnNldERvbmVBc3luYyhmYWxzZSkpXG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gc3VidHJlZVJvb3QgU3VidHJlZSByb290IHRhcmdldCBvYmplY3QuXG4gKiBAcmV0dXJucyBBbiBvYmplY3Qgd2l0aCB0aGUgbWlkZGxld2FyZSBkaXNwb3NlciAoYGRpc3Bvc2VgKSBhbmQgYSBgYWxsb3dXcml0ZWAgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkb25seU1pZGRsZXdhcmUoc3VidHJlZVJvb3Q6IG9iamVjdCk6IFJlYWRvbmx5TWlkZGxld2FyZVJldHVybiB7XG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qoc3VidHJlZVJvb3QsIFwic3VidHJlZVJvb3RcIilcblxuICBsZXQgd3JpdGFibGUgPSBmYWxzZVxuICBjb25zdCB3cml0YWJsZVN5bWJvbCA9IFN5bWJvbChcIndyaXRhYmxlXCIpXG5cbiAgY29uc3QgZGlzcG9zZXIgPSBhY3Rpb25UcmFja2luZ01pZGRsZXdhcmUoc3VidHJlZVJvb3QsIHtcbiAgICBmaWx0ZXIoY3R4KSB7XG4gICAgICAvLyBza2lwIGhvb2tzXG4gICAgICBpZiAoaXNIb29rQWN0aW9uKGN0eC5hY3Rpb25OYW1lKSkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIH1cblxuICAgICAgLy8gaWYgd2UgYXJlIGluc2lkZSBhbGxvd1dyaXRlIGl0IGlzIHdyaXRhYmxlXG4gICAgICBsZXQgY3VycmVudGx5V3JpdGFibGUgPSB3cml0YWJsZVxuXG4gICAgICBpZiAoIWN1cnJlbnRseVdyaXRhYmxlKSB7XG4gICAgICAgIC8vIGlmIGEgcGFyZW50IGNvbnRleHQgd2FzIHdyaXRhYmxlIHRoZW4gdGhlIGNoaWxkIHNob3VsZCBiZSBhcyB3ZWxsXG4gICAgICAgIGxldCBjdXJyZW50Q3R4OiBTaW1wbGVBY3Rpb25Db250ZXh0IHwgdW5kZWZpbmVkID0gY3R4XG4gICAgICAgIHdoaWxlIChjdXJyZW50Q3R4ICYmICFjdXJyZW50bHlXcml0YWJsZSkge1xuICAgICAgICAgIGN1cnJlbnRseVdyaXRhYmxlID0gISFjdXJyZW50Q3R4LmRhdGFbd3JpdGFibGVTeW1ib2xdXG4gICAgICAgICAgY3VycmVudEN0eCA9IGN1cnJlbnRDdHgucGFyZW50Q29udGV4dFxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjdXJyZW50bHlXcml0YWJsZSkge1xuICAgICAgICBjdHguZGF0YVt3cml0YWJsZVN5bWJvbF0gPSB0cnVlXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0sXG5cbiAgICBvblN0YXJ0KGN0eCkge1xuICAgICAgLy8gaWYgd2UgZ2V0IGhlcmUgKHdhc24ndCBmaWx0ZXJlZCBvdXQpIGl0IGlzIG5vdCB3cml0YWJsZVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVzdWx0OiBBY3Rpb25UcmFja2luZ1Jlc3VsdC5UaHJvdyxcbiAgICAgICAgdmFsdWU6IGZhaWx1cmUoYHRyaWVkIHRvIGludm9rZSBhY3Rpb24gJyR7Y3R4LmFjdGlvbk5hbWV9JyBvdmVyIGEgcmVhZG9ubHkgbm9kZWApLFxuICAgICAgfVxuICAgIH0sXG4gIH0pXG5cbiAgcmV0dXJuIHtcbiAgICBkaXNwb3NlOiBkaXNwb3NlcixcbiAgICBhbGxvd1dyaXRlKGZuKSB7XG4gICAgICBjb25zdCBvbGRXcml0YWJsZSA9IHdyaXRhYmxlXG4gICAgICB3cml0YWJsZSA9IHRydWVcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBmbigpXG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB3cml0YWJsZSA9IG9sZFdyaXRhYmxlXG4gICAgICB9XG4gICAgfSxcbiAgfVxufVxuIiwiaW1wb3J0IHR5cGUgeyBQYXRoIH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoVHlwZXNcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXG5pbXBvcnQgdHlwZSB7IFBhdGNoIH0gZnJvbSBcIi4vUGF0Y2hcIlxuXG5leHBvcnQgdHlwZSBKc29uUGF0Y2ggPVxuICB8IEpzb25QYXRjaEFkZE9wZXJhdGlvbjxhbnk+XG4gIHwgSnNvblBhdGNoUmVtb3ZlT3BlcmF0aW9uXG4gIHwgSnNvblBhdGNoUmVwbGFjZU9wZXJhdGlvbjxhbnk+XG5cbmV4cG9ydCBpbnRlcmZhY2UgSnNvblBhdGNoQmFzZU9wZXJhdGlvbiB7XG4gIHBhdGg6IHN0cmluZ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEpzb25QYXRjaEFkZE9wZXJhdGlvbjxUPiBleHRlbmRzIEpzb25QYXRjaEJhc2VPcGVyYXRpb24ge1xuICBvcDogXCJhZGRcIlxuICB2YWx1ZTogVFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEpzb25QYXRjaFJlbW92ZU9wZXJhdGlvbiBleHRlbmRzIEpzb25QYXRjaEJhc2VPcGVyYXRpb24ge1xuICBvcDogXCJyZW1vdmVcIlxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEpzb25QYXRjaFJlcGxhY2VPcGVyYXRpb248VD4gZXh0ZW5kcyBKc29uUGF0Y2hCYXNlT3BlcmF0aW9uIHtcbiAgb3A6IFwicmVwbGFjZVwiXG4gIHZhbHVlOiBUXG59XG5cbi8qKlxuICogRXNjYXBlcyBhIGpzb24gcG9pbnRlciBwYXRoLlxuICpcbiAqIEBwYXJhbSBwYXRoIFRoZSByYXcgcG9pbnRlclxuICogQHJldHVybiB0aGUgRXNjYXBlZCBwYXRoXG4gKi9cbmZ1bmN0aW9uIGVzY2FwZVBhdGhDb21wb25lbnQocGF0aDogc3RyaW5nIHwgbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiBwYXRoID09PSBcIm51bWJlclwiKSB7XG4gICAgcmV0dXJuIFwiXCIgKyBwYXRoXG4gIH1cbiAgaWYgKHBhdGguaW5kZXhPZihcIi9cIikgPT09IC0xICYmIHBhdGguaW5kZXhPZihcIn5cIikgPT09IC0xKSB7XG4gICAgcmV0dXJuIHBhdGhcbiAgfVxuICByZXR1cm4gcGF0aC5yZXBsYWNlKC9+L2csIFwifjBcIikucmVwbGFjZSgvXFwvL2csIFwifjFcIilcbn1cblxuLyoqXG4gKiBVbmVzY2FwZXMgYSBqc29uIHBvaW50ZXIgcGF0aC5cbiAqXG4gKiBAcGFyYW0gcGF0aCBUaGUgZXNjYXBlZCBwb2ludGVyXG4gKiBAcmV0dXJuIFRoZSB1bmVzY2FwZWQgcGF0aFxuICovXG5mdW5jdGlvbiB1bmVzY2FwZVBhdGhDb21wb25lbnQocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGgucmVwbGFjZSgvfjEvZywgXCIvXCIpLnJlcGxhY2UoL34wL2csIFwiflwiKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgcGF0aCBpbnRvIGEgSlNPTiBwb2ludGVyLlxuICpcbiAqIEBwYXJhbSBwYXRoIFBhdGggdG8gY29udmVydC5cbiAqIEByZXR1cm5zIENvbnZlcnRlZCBKU09OIHBvaW50ZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXRoVG9Kc29uUG9pbnRlcihwYXRoOiBQYXRoKTogc3RyaW5nIHtcbiAgaWYgKHBhdGgubGVuZ3RoIDw9IDApIHtcbiAgICByZXR1cm4gXCJcIlxuICB9XG4gIHJldHVybiBcIi9cIiArIHBhdGgubWFwKGVzY2FwZVBhdGhDb21wb25lbnQpLmpvaW4oXCIvXCIpXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBKU09OIHBvaW50ZXIgaW50byBhIHBhdGguXG4gKlxuICogQHBhcmFtIGpzb25Qb2ludGVyIEpTT04gcG9pbnRlciB0byBjb252ZXJ0LlxuICogQHJldHVybnMgQ29udmVydGVkIHBhdGguXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBqc29uUG9pbnRlclRvUGF0aChqc29uUG9pbnRlcjogc3RyaW5nKTogUGF0aCB7XG4gIGlmIChqc29uUG9pbnRlciA9PT0gXCJcIikge1xuICAgIHJldHVybiBbXVxuICB9XG4gIGlmICghanNvblBvaW50ZXIuc3RhcnRzV2l0aChcIi9cIikpIHtcbiAgICB0aHJvdyBmYWlsdXJlKFwiYSBKU09OIHBvaW50ZXIgbXVzdCBzdGFydCB3aXRoICcvJyBvciBiZSBlbXB0eVwiKVxuICB9XG4gIGpzb25Qb2ludGVyID0ganNvblBvaW50ZXIuc2xpY2UoMSlcbiAgcmV0dXJuIGpzb25Qb2ludGVyLnNwbGl0KFwiL1wiKS5tYXAodW5lc2NhcGVQYXRoQ29tcG9uZW50KVxufVxuXG4vKipcbiAqIENvbnZlcnQgYSBwYXRjaCBpbnRvIGEgSlNPTiBwYXRjaC5cbiAqXG4gKiBAcGFyYW0gcGF0Y2ggQSBwYXRjaC5cbiAqIEByZXR1cm5zIEEgSlNPTiBwYXRjaC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhdGNoVG9Kc29uUGF0Y2gocGF0Y2g6IFBhdGNoKTogSnNvblBhdGNoIHtcbiAgcmV0dXJuIHtcbiAgICAuLi5wYXRjaCxcbiAgICBwYXRoOiBwYXRoVG9Kc29uUG9pbnRlcihwYXRjaC5wYXRoKSxcbiAgfVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgSlNPTiBwYXRjaCBpbnRvIGEgcGF0Y2guXG4gKlxuICogQHBhcmFtIGpzb25QYXRjaCBBIEpTT04gcGF0Y2guXG4gKiBAcmV0dXJucyBBIHBhdGNoLlxuICovXG5leHBvcnQgZnVuY3Rpb24ganNvblBhdGNoVG9QYXRjaChqc29uUGF0Y2g6IEpzb25QYXRjaCk6IFBhdGNoIHtcbiAgcmV0dXJuIHtcbiAgICAuLi5qc29uUGF0Y2gsXG4gICAgcGF0aDoganNvblBvaW50ZXJUb1BhdGgoanNvblBhdGNoLnBhdGgpLFxuICB9XG59XG4iLCJpbXBvcnQgeyBvYnNlcnZhYmxlIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgb25HbG9iYWxQYXRjaGVzLCBvblBhdGNoZXMsIE9uUGF0Y2hlc0Rpc3Bvc2VyLCBPblBhdGNoZXNMaXN0ZW5lciB9IGZyb20gXCIuL2VtaXRQYXRjaFwiXG5pbXBvcnQgdHlwZSB7IFBhdGNoIH0gZnJvbSBcIi4vUGF0Y2hcIlxuXG4vKipcbiAqIFBhdGNoIHJlY29yZGVyIGV2ZW50LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBhdGNoUmVjb3JkZXJFdmVudCB7XG4gIC8qKlxuICAgKiBUYXJnZXQgb2JqZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0OiBvYmplY3RcbiAgLyoqXG4gICAqIFJlY29yZGVkIHBhdGNoZXMuXG4gICAqL1xuICByZWFkb25seSBwYXRjaGVzOiBQYXRjaFtdXG4gIC8qKlxuICAgKiBSZWNvcmRlZCBpbnZlcnNlIHBhdGNoZXMuXG4gICAqL1xuICByZWFkb25seSBpbnZlcnNlUGF0Y2hlczogUGF0Y2hbXVxufVxuXG4vKipcbiAqIFBhdGNoIHJlY29yZGVyIGludGVyZmFjZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQYXRjaFJlY29yZGVyIHtcbiAgLyoqXG4gICAqIEdldHMvc2V0cyBpZiB0aGUgcGF0Y2ggcmVjb3JkZXIgaXMgY3VycmVudGx5IHJlY29yZGluZy5cbiAgICovXG4gIHJlY29yZGluZzogYm9vbGVhblxuXG4gIC8qKlxuICAgKiBPYnNlcnZhYmxlIGFycmF5IG9mIHBhdGNoaW5nIGV2ZW50cy5cbiAgICovXG4gIHJlYWRvbmx5IGV2ZW50czogUGF0Y2hSZWNvcmRlckV2ZW50W11cblxuICAvKipcbiAgICogRGlzcG9zZSBvZiB0aGUgcGF0Y2ggcmVjb3JkZXIuXG4gICAqL1xuICBkaXNwb3NlKCk6IHZvaWRcbn1cblxuLyoqXG4gKiBQYXRjaCByZWNvcmRlciBvcHRpb25zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBhdGNoUmVjb3JkZXJPcHRpb25zIHtcbiAgLyoqXG4gICAqIElmIHRoZSBwYXRjaCByZWNvcmRlciBpcyBpbml0aWFsbHkgcmVjb3JkaW5nIHdoZW4gY3JlYXRlZC5cbiAgICovXG4gIHJlY29yZGluZz86IGJvb2xlYW5cblxuICAvKipcbiAgICogQW4gb3B0aW9uYWwgY2FsbGJhY2sgZmlsdGVyIHRvIHNlbGVjdCB3aWNoIHBhdGNoZXMgdG8gcmVjb3JkL3NraXAuXG4gICAqIEl0IHdpbGwgYmUgZXhlY3V0ZWQgYmVmb3JlIHRoZSBldmVudCBpcyBhZGRlZCB0byB0aGUgZXZlbnRzIGxpc3QuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRjaGVzIFBhdGNoZXMgYWJvdXQgdG8gYmUgcmVjb3JkZWQuXG4gICAqIEBwYXJhbSBpbnZlcnNlUGF0Y2hlcyBJbnZlcnNlIHBhdGNoZXMgYWJvdXQgdG8gYmUgcmVjb3JkZWQuXG4gICAqIEByZXR1cm5zIGB0cnVlYCB0byByZWNvcmQgdGhlIHBhdGNoLCBgZmFsc2VgIHRvIHNraXAgaXQuXG4gICAqL1xuICBmaWx0ZXI/KHBhdGNoZXM6IFBhdGNoW10sIGludmVyc2VQYXRjaGVzOiBQYXRjaFtdKTogYm9vbGVhblxuXG4gIC8qKlxuICAgKiBBbiBvcHRpb25hbCBjYWxsYmFjayBydW4gb25jZSBhIHBhdGNoIGlzIHJlY29yZGVkLlxuICAgKiBJdCB3aWxsIGJlIGV4ZWN1dGVkIGFmdGVyIHRoZSBldmVudCBpcyBhZGRlZCB0byB0aGUgZXZlbnRzIGxpc3QuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRjaGVzIFBhdGNoZXMganVzdCByZWNvcmRlZC5cbiAgICogQHBhcmFtIGludmVyc2VQYXRjaGVzIEludmVyc2UgcGF0Y2hlcyBqdXN0IHJlY29yZGVkLlxuICAgKi9cbiAgb25QYXRjaGVzPzogT25QYXRjaGVzTGlzdGVuZXJcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgcGF0Y2ggcmVjb3JkZXIuXG4gKlxuICogQHBhcmFtIHN1YnRyZWVSb290XG4gKiBAcGFyYW0gW29wdHNdXG4gKiBAcmV0dXJucyBUaGUgcGF0Y2ggcmVjb3JkZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXRjaFJlY29yZGVyKHN1YnRyZWVSb290OiBvYmplY3QsIG9wdHM/OiBQYXRjaFJlY29yZGVyT3B0aW9ucyk6IFBhdGNoUmVjb3JkZXIge1xuICBhc3NlcnRUd2Vha2VkT2JqZWN0KHN1YnRyZWVSb290LCBcInN1YnRyZWVSb290XCIpXG5cbiAgcmV0dXJuIGludGVybmFsUGF0Y2hSZWNvcmRlcihzdWJ0cmVlUm9vdCwgb3B0cylcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqXG4gKiBDcmVhdGVzIGEgZ2xvYmFsIG9yIGxvY2FsIHBhdGNoIHJlY29yZGVyLlxuICpcbiAqIEBwYXJhbSBzdWJ0cmVlUm9vdFxuICogQHBhcmFtIFtvcHRzXVxuICogQHJldHVybnMgVGhlIHBhdGNoIHJlY29yZGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJuYWxQYXRjaFJlY29yZGVyKFxuICBzdWJ0cmVlUm9vdDogb2JqZWN0IHwgdW5kZWZpbmVkLFxuICBvcHRzPzogUGF0Y2hSZWNvcmRlck9wdGlvbnNcbik6IFBhdGNoUmVjb3JkZXIge1xuICBsZXQgeyByZWNvcmRpbmcsIGZpbHRlciB9ID0ge1xuICAgIHJlY29yZGluZzogdHJ1ZSxcbiAgICBmaWx0ZXI6IGFsd2F5c0FjY2VwdEZpbHRlcixcbiAgICAuLi5vcHRzLFxuICB9XG5cbiAgY29uc3QgZXZlbnRzID0gb2JzZXJ2YWJsZS5hcnJheTxQYXRjaFJlY29yZGVyRXZlbnQ+KFtdLCB7XG4gICAgZGVlcDogZmFsc2UsXG4gIH0pXG5cbiAgbGV0IG9uUGF0Y2hlc0Rpc3Bvc2VyOiBPblBhdGNoZXNEaXNwb3NlclxuXG4gIGlmIChzdWJ0cmVlUm9vdCkge1xuICAgIG9uUGF0Y2hlc0Rpc3Bvc2VyID0gb25QYXRjaGVzKHN1YnRyZWVSb290LCAocCwgaW52UCkgPT4ge1xuICAgICAgaWYgKHJlY29yZGluZyAmJiBmaWx0ZXIocCwgaW52UCkpIHtcbiAgICAgICAgZXZlbnRzLnB1c2goe1xuICAgICAgICAgIHRhcmdldDogc3VidHJlZVJvb3QsXG4gICAgICAgICAgcGF0Y2hlczogcCxcbiAgICAgICAgICBpbnZlcnNlUGF0Y2hlczogaW52UCxcbiAgICAgICAgfSlcbiAgICAgICAgb3B0cz8ub25QYXRjaGVzPy4ocCwgaW52UClcbiAgICAgIH1cbiAgICB9KVxuICB9IGVsc2Uge1xuICAgIG9uUGF0Y2hlc0Rpc3Bvc2VyID0gb25HbG9iYWxQYXRjaGVzKCh0YXJnZXQsIHAsIGludlApID0+IHtcbiAgICAgIGlmIChyZWNvcmRpbmcgJiYgZmlsdGVyKHAsIGludlApKSB7XG4gICAgICAgIGV2ZW50cy5wdXNoKHtcbiAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgcGF0Y2hlczogcCxcbiAgICAgICAgICBpbnZlcnNlUGF0Y2hlczogaW52UCxcbiAgICAgICAgfSlcbiAgICAgICAgb3B0cz8ub25QYXRjaGVzPy4ocCwgaW52UClcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBnZXQgcmVjb3JkaW5nKCkge1xuICAgICAgcmV0dXJuIHJlY29yZGluZ1xuICAgIH0sXG4gICAgc2V0IHJlY29yZGluZyhlbmFibGVkOiBib29sZWFuKSB7XG4gICAgICByZWNvcmRpbmcgPSBlbmFibGVkXG4gICAgfSxcbiAgICBnZXQgZXZlbnRzKCkge1xuICAgICAgcmV0dXJuIGV2ZW50c1xuICAgIH0sXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgIG9uUGF0Y2hlc0Rpc3Bvc2VyKClcbiAgICB9LFxuICB9XG59XG5cbmNvbnN0IGFsd2F5c0FjY2VwdEZpbHRlciA9ICgpID0+IHRydWVcbiIsImltcG9ydCB7IGNoZWNrRGVjb3JhdG9yQ29udGV4dCB9IGZyb20gXCIuLi91dGlscy9kZWNvcmF0b3JzXCJcclxuaW1wb3J0IHR5cGUgeyBBY3Rpb25NaWRkbGV3YXJlRGlzcG9zZXIgfSBmcm9tIFwiLi4vYWN0aW9uL21pZGRsZXdhcmVcIlxyXG5pbXBvcnQgdHlwZSB7IEFueU1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Jhc2VNb2RlbFwiXHJcbmltcG9ydCB7IGFzc2VydElzTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvdXRpbHNcIlxyXG5pbXBvcnQgeyBhZGRNb2RlbENsYXNzSW5pdGlhbGl6ZXIgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxDbGFzc0luaXRpYWxpemVyXCJcclxuaW1wb3J0IHsgYXBwbHlQYXRjaGVzIH0gZnJvbSBcIi4uL3BhdGNoXCJcclxuaW1wb3J0IHsgaW50ZXJuYWxQYXRjaFJlY29yZGVyLCBQYXRjaFJlY29yZGVyIH0gZnJvbSBcIi4uL3BhdGNoL3BhdGNoUmVjb3JkZXJcIlxyXG5pbXBvcnQgeyBhc3NlcnRJc09iamVjdCwgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXHJcbmltcG9ydCB7XHJcbiAgYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlLFxyXG4gIEFjdGlvblRyYWNraW5nUmVzdWx0LFxyXG4gIFNpbXBsZUFjdGlvbkNvbnRleHQsXHJcbn0gZnJvbSBcIi4vYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlXCJcclxuXHJcbi8qKlxyXG4gKiBDcmVhdGVzIGEgdHJhbnNhY3Rpb24gbWlkZGxld2FyZSwgd2hpY2ggcmV2ZXJ0cyBjaGFuZ2VzIG1hZGUgYnkgYW4gYWN0aW9uIC8gY2hpbGRcclxuICogYWN0aW9ucyB3aGVuIHRoZSByb290IGFjdGlvbiB0aHJvd3MgYW4gZXhjZXB0aW9uIGJ5IGFwcGx5aW5nIGludmVyc2UgcGF0Y2hlcy5cclxuICpcclxuICogQHR5cGVwYXJhbSBNIE1vZGVsXHJcbiAqIEBwYXJhbSB0YXJnZXQgT2JqZWN0IHdpdGggdGhlIHJvb3QgdGFyZ2V0IG1vZGVsIG9iamVjdCAoYG1vZGVsYCkgYW5kIHJvb3QgYWN0aW9uIG5hbWUgKGBhY3Rpb25OYW1lYCkuXHJcbiAqIEByZXR1cm5zIFRoZSBtaWRkbGV3YXJlIGRpc3Bvc2VyLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zYWN0aW9uTWlkZGxld2FyZTxNIGV4dGVuZHMgQW55TW9kZWw+KHRhcmdldDoge1xyXG4gIG1vZGVsOiBNXHJcbiAgYWN0aW9uTmFtZToga2V5b2YgTVxyXG59KTogQWN0aW9uTWlkZGxld2FyZURpc3Bvc2VyIHtcclxuICBhc3NlcnRJc09iamVjdCh0YXJnZXQsIFwidGFyZ2V0XCIpXHJcblxyXG4gIGNvbnN0IHsgbW9kZWwsIGFjdGlvbk5hbWUgfSA9IHRhcmdldFxyXG5cclxuICBhc3NlcnRJc01vZGVsKG1vZGVsLCBcInRhcmdldC5tb2RlbFwiKVxyXG5cclxuICBpZiAodHlwZW9mIGFjdGlvbk5hbWUgIT09IFwic3RyaW5nXCIpIHtcclxuICAgIHRocm93IGZhaWx1cmUoXCJ0YXJnZXQuYWN0aW9uTmFtZSBtdXN0IGJlIGEgc3RyaW5nXCIpXHJcbiAgfVxyXG5cclxuICBjb25zdCBwYXRjaFJlY29yZGVyU3ltYm9sID0gU3ltYm9sKFwicGF0Y2hSZWNvcmRlclwiKVxyXG4gIGZ1bmN0aW9uIGluaXRQYXRjaFJlY29yZGVyKGN0eDogU2ltcGxlQWN0aW9uQ29udGV4dCkge1xyXG4gICAgY3R4LnJvb3RDb250ZXh0LmRhdGFbcGF0Y2hSZWNvcmRlclN5bWJvbF0gPSBpbnRlcm5hbFBhdGNoUmVjb3JkZXIodW5kZWZpbmVkLCB7XHJcbiAgICAgIHJlY29yZGluZzogZmFsc2UsXHJcbiAgICB9KVxyXG4gIH1cclxuICBmdW5jdGlvbiBnZXRQYXRjaFJlY29yZGVyKGN0eDogU2ltcGxlQWN0aW9uQ29udGV4dCk6IFBhdGNoUmVjb3JkZXIge1xyXG4gICAgcmV0dXJuIGN0eC5yb290Q29udGV4dC5kYXRhW3BhdGNoUmVjb3JkZXJTeW1ib2xdXHJcbiAgfVxyXG5cclxuICByZXR1cm4gYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlKG1vZGVsLCB7XHJcbiAgICBmaWx0ZXIoY3R4KSB7XHJcbiAgICAgIC8vIHRoZSBwcmltYXJ5IGFjdGlvbiBtdXN0IGJlIG9uIHRoZSByb290IG9iamVjdFxyXG4gICAgICBjb25zdCByb290Q29udGV4dCA9IGN0eC5yb290Q29udGV4dFxyXG4gICAgICByZXR1cm4gcm9vdENvbnRleHQudGFyZ2V0ID09PSBtb2RlbCAmJiByb290Q29udGV4dC5hY3Rpb25OYW1lID09PSBhY3Rpb25OYW1lXHJcbiAgICB9LFxyXG4gICAgb25TdGFydChjdHgpIHtcclxuICAgICAgaWYgKGN0eCA9PT0gY3R4LnJvb3RDb250ZXh0KSB7XHJcbiAgICAgICAgaW5pdFBhdGNoUmVjb3JkZXIoY3R4KVxyXG4gICAgICB9XHJcbiAgICB9LFxyXG4gICAgb25SZXN1bWUoY3R4KSB7XHJcbiAgICAgIGdldFBhdGNoUmVjb3JkZXIoY3R4KS5yZWNvcmRpbmcgPSB0cnVlXHJcbiAgICB9LFxyXG4gICAgb25TdXNwZW5kKGN0eCkge1xyXG4gICAgICBnZXRQYXRjaFJlY29yZGVyKGN0eCkucmVjb3JkaW5nID0gZmFsc2VcclxuICAgIH0sXHJcbiAgICBvbkZpbmlzaChjdHgsIHJldCkge1xyXG4gICAgICBpZiAoY3R4ID09PSBjdHgucm9vdENvbnRleHQpIHtcclxuICAgICAgICBjb25zdCBwYXRjaFJlY29yZGVyID0gZ2V0UGF0Y2hSZWNvcmRlcihjdHgpXHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICBpZiAocmV0LnJlc3VsdCA9PT0gQWN0aW9uVHJhY2tpbmdSZXN1bHQuVGhyb3cpIHtcclxuICAgICAgICAgICAgLy8gdW5kbyBjaGFuZ2VzIChiYWNrd2FyZHMgZm9yIGludmVyc2UgcGF0Y2hlcylcclxuICAgICAgICAgICAgY29uc3QgeyBldmVudHMgfSA9IHBhdGNoUmVjb3JkZXJcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGV2ZW50cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gZXZlbnRzW2ldXHJcbiAgICAgICAgICAgICAgYXBwbHlQYXRjaGVzKGV2ZW50LnRhcmdldCwgZXZlbnQuaW52ZXJzZVBhdGNoZXMsIHRydWUpXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGZpbmFsbHkge1xyXG4gICAgICAgICAgcGF0Y2hSZWNvcmRlci5kaXNwb3NlKClcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0sXHJcbiAgfSlcclxufVxyXG5cclxuLyoqXHJcbiAqIFRyYW5zYWN0aW9uIG1pZGRsZXdhcmUgYXMgYSBkZWNvcmF0b3IuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNhY3Rpb24oLi4uYXJnczogYW55W10pOiB2b2lkIHtcclxuICBpZiAodHlwZW9mIGFyZ3NbMV0gPT09IFwib2JqZWN0XCIpIHtcclxuICAgIC8vIHN0YW5kYXJkIGRlY29yYXRvcnNcclxuICAgIGNvbnN0IGN0eCA9IGFyZ3NbMV0gYXMgQ2xhc3NNZXRob2REZWNvcmF0b3JDb250ZXh0IHwgQ2xhc3NGaWVsZERlY29yYXRvckNvbnRleHRcclxuXHJcbiAgICBjaGVja0RlY29yYXRvckNvbnRleHQoXCJ0cmFuc2FjdGlvblwiLCBjdHgubmFtZSwgY3R4LnN0YXRpYylcclxuICAgIGlmIChjdHgua2luZCAhPT0gXCJtZXRob2RcIiAmJiBjdHgua2luZCAhPT0gXCJmaWVsZFwiKSB7XHJcbiAgICAgIHRocm93IGZhaWx1cmUoYEB0cmFuc2FjdGlvbiBjYW4gb25seSBiZSB1c2VkIG9uIGZpZWxkcyBvciBtZXRob2RzfWApXHJcbiAgICB9XHJcblxyXG4gICAgY3R4LmFkZEluaXRpYWxpemVyKGZ1bmN0aW9uICh0aGlzOiBhbnkpIHtcclxuICAgICAgY29uc3QgbW9kZWxJbnN0YW5jZSA9IHRoaXNcclxuICAgICAgdHJhbnNhY3Rpb25NaWRkbGV3YXJlKHtcclxuICAgICAgICBtb2RlbDogbW9kZWxJbnN0YW5jZSBhcyBBbnlNb2RlbCxcclxuICAgICAgICBhY3Rpb25OYW1lOiBjdHgubmFtZSBhcyBhbnksXHJcbiAgICAgIH0pXHJcbiAgICB9KVxyXG4gIH0gZWxzZSB7XHJcbiAgICAvLyBub24tc3RhbmRhcmQgZGVjb3JhdG9yc1xyXG4gICAgY29uc3QgdGFyZ2V0ID0gYXJnc1swXVxyXG4gICAgY29uc3QgcHJvcGVydHlLZXk6IHN0cmluZyB8IHN5bWJvbCA9IGFyZ3NbMV1cclxuXHJcbiAgICBjaGVja0RlY29yYXRvckNvbnRleHQoXCJ0cmFuc2FjdGlvblwiLCBwcm9wZXJ0eUtleSwgZmFsc2UpXHJcblxyXG4gICAgYWRkTW9kZWxDbGFzc0luaXRpYWxpemVyKHRhcmdldC5jb25zdHJ1Y3RvciwgKG1vZGVsSW5zdGFuY2UpID0+IHtcclxuICAgICAgdHJhbnNhY3Rpb25NaWRkbGV3YXJlKHtcclxuICAgICAgICBtb2RlbDogbW9kZWxJbnN0YW5jZSBhcyBBbnlNb2RlbCxcclxuICAgICAgICBhY3Rpb25OYW1lOiBwcm9wZXJ0eUtleSBhcyBhbnksXHJcbiAgICAgIH0pXHJcbiAgICB9KVxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgdHlwZSB7IE8gfSBmcm9tIFwidHMtdG9vbGJlbHRcIlxuaW1wb3J0IHsgRnJvemVuIH0gZnJvbSBcIi4uLy4uL2Zyb3plbi9Gcm96ZW5cIlxuaW1wb3J0IHsgYXNzZXJ0SXNGdW5jdGlvbiwgYXNzZXJ0SXNPYmplY3QsIGlzT2JqZWN0LCBsYXp5IH0gZnJvbSBcIi4uLy4uL3V0aWxzXCJcbmltcG9ydCB7IGdldFR5cGVJbmZvIH0gZnJvbSBcIi4uL2dldFR5cGVJbmZvXCJcbmltcG9ydCB7IHJlc29sdmVTdGFuZGFyZFR5cGUsIHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuLi9yZXNvbHZlVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHR5cGUge1xuICBBbnlTdGFuZGFyZFR5cGUsXG4gIEFueVR5cGUsXG4gIE1vZGVsVHlwZSxcbiAgT2JqZWN0VHlwZUZ1bmN0aW9uLFxuICBUeXBlVG9EYXRhLFxufSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQge1xuICBsYXRlVHlwZUNoZWNrZXIsXG4gIExhdGVUeXBlQ2hlY2tlcixcbiAgVHlwZUNoZWNrZXIsXG4gIFR5cGVDaGVja2VyQmFzZVR5cGUsXG4gIFR5cGVJbmZvLFxuICBUeXBlSW5mb0dlbixcbn0gZnJvbSBcIi4uL1R5cGVDaGVja2VyXCJcbmltcG9ydCB7IFR5cGVDaGVja0Vycm9yIH0gZnJvbSBcIi4uL1R5cGVDaGVja0Vycm9yXCJcblxuZnVuY3Rpb24gdHlwZXNPYmplY3RIZWxwZXI8Uz4ob2JqRm46IFMsIGZyb3plbjogYm9vbGVhbiwgdHlwZUluZm9HZW46IFR5cGVJbmZvR2VuKTogUyB7XG4gIGFzc2VydElzRnVuY3Rpb24ob2JqRm4sIFwib2JqRm5cIilcblxuICByZXR1cm4gbGF0ZVR5cGVDaGVja2VyKCgpID0+IHtcbiAgICBjb25zdCBvYmplY3RTY2hlbWE6IHtcbiAgICAgIFtrOiBzdHJpbmddOiBUeXBlQ2hlY2tlciB8IExhdGVUeXBlQ2hlY2tlclxuICAgIH0gPSAob2JqRm4gYXMgYW55KSgpXG4gICAgYXNzZXJ0SXNPYmplY3Qob2JqZWN0U2NoZW1hLCBcIm9iamVjdFNjaGVtYVwiKVxuXG4gICAgY29uc3Qgc2NoZW1hRW50cmllcyA9IE9iamVjdC5lbnRyaWVzKG9iamVjdFNjaGVtYSlcblxuICAgIGNvbnN0IGdldFR5cGVOYW1lID0gKC4uLnJlY3Vyc2l2ZVR5cGVDaGVja2VyczogVHlwZUNoZWNrZXJbXSkgPT4ge1xuICAgICAgY29uc3QgcHJvcHNNc2c6IHN0cmluZ1tdID0gW11cbiAgICAgIGZvciAoY29uc3QgW2ssIHVucmVzb2x2ZWRUY10gb2Ygc2NoZW1hRW50cmllcykge1xuICAgICAgICBjb25zdCB0YyA9IHJlc29sdmVUeXBlQ2hlY2tlcih1bnJlc29sdmVkVGMpXG4gICAgICAgIGxldCBwcm9wVHlwZW5hbWUgPSBcIi4uLlwiXG4gICAgICAgIGlmICghcmVjdXJzaXZlVHlwZUNoZWNrZXJzLmluY2x1ZGVzKHRjKSkge1xuICAgICAgICAgIHByb3BUeXBlbmFtZSA9IHRjLmdldFR5cGVOYW1lKC4uLnJlY3Vyc2l2ZVR5cGVDaGVja2VycywgdGMpXG4gICAgICAgIH1cbiAgICAgICAgcHJvcHNNc2cucHVzaChgJHtrfTogJHtwcm9wVHlwZW5hbWV9O2ApXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBgeyAke3Byb3BzTXNnLmpvaW4oXCIgXCIpfSB9YFxuICAgIH1cblxuICAgIGNvbnN0IGFwcGx5U25hcHNob3RQcm9jZXNzb3IgPSAob2JqOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgbW9kZTogXCJmcm9tXCIgfCBcInRvXCIpID0+IHtcbiAgICAgIGNvbnN0IG5ld09iajogdHlwZW9mIG9iaiA9IHt9XG5cbiAgICAgIC8vIG5vdGU6IHdlIGFsbG93IGV4Y2VzcyBwcm9wZXJ0aWVzIHdoZW4gY2hlY2tpbmcgb2JqZWN0c1xuICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iailcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBrID0ga2V5c1tpXVxuICAgICAgICBjb25zdCB1bnJlc29sdmVkVGMgPSBvYmplY3RTY2hlbWFba11cbiAgICAgICAgaWYgKHVucmVzb2x2ZWRUYykge1xuICAgICAgICAgIGNvbnN0IHRjID0gcmVzb2x2ZVR5cGVDaGVja2VyKHVucmVzb2x2ZWRUYylcbiAgICAgICAgICBuZXdPYmpba10gPVxuICAgICAgICAgICAgbW9kZSA9PT0gXCJmcm9tXCIgPyB0Yy5mcm9tU25hcHNob3RQcm9jZXNzb3Iob2JqW2tdKSA6IHRjLnRvU25hcHNob3RQcm9jZXNzb3Iob2JqW2tdKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIHVua25vd24gcHJvcCwgY29weSBhcyBpc1xuICAgICAgICAgIG5ld09ialtrXSA9IG9ialtrXVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXdPYmpcbiAgICB9XG5cbiAgICBjb25zdCB0aGlzVGM6IFR5cGVDaGVja2VyID0gbmV3IFR5cGVDaGVja2VyKFxuICAgICAgVHlwZUNoZWNrZXJCYXNlVHlwZS5PYmplY3QsXG5cbiAgICAgIChvYmosIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+IHtcbiAgICAgICAgaWYgKCFpc09iamVjdChvYmopIHx8IChmcm96ZW4gJiYgIShvYmogaW5zdGFuY2VvZiBGcm96ZW4pKSkge1xuICAgICAgICAgIHJldHVybiBuZXcgVHlwZUNoZWNrRXJyb3IocGF0aCwgZ2V0VHlwZU5hbWUodGhpc1RjKSwgb2JqLCB0eXBlQ2hlY2tlZFZhbHVlKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gbm90ZTogd2UgYWxsb3cgZXhjZXNzIHByb3BlcnRpZXMgd2hlbiBjaGVja2luZyBvYmplY3RzXG4gICAgICAgIGZvciAoY29uc3QgW2ssIHVucmVzb2x2ZWRUY10gb2Ygc2NoZW1hRW50cmllcykge1xuICAgICAgICAgIGNvbnN0IHRjID0gcmVzb2x2ZVR5cGVDaGVja2VyKHVucmVzb2x2ZWRUYylcbiAgICAgICAgICBjb25zdCBvYmpWYWwgPSBvYmpba11cblxuICAgICAgICAgIGNvbnN0IHZhbHVlRXJyb3IgPSB0Yy5jaGVjayhvYmpWYWwsIFsuLi5wYXRoLCBrXSwgdHlwZUNoZWNrZWRWYWx1ZSlcbiAgICAgICAgICBpZiAodmFsdWVFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlRXJyb3JcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgfSxcblxuICAgICAgZ2V0VHlwZU5hbWUsXG4gICAgICB0eXBlSW5mb0dlbixcblxuICAgICAgKG9iaikgPT4ge1xuICAgICAgICBpZiAoIWlzT2JqZWN0KG9iaikpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgLy8gbm90ZTogd2UgYWxsb3cgZXhjZXNzIHByb3BlcnRpZXMgd2hlbiBjaGVja2luZyBvYmplY3RzXG4gICAgICAgIGZvciAoY29uc3QgW2ssIHVucmVzb2x2ZWRUY10gb2Ygc2NoZW1hRW50cmllcykge1xuICAgICAgICAgIGNvbnN0IHRjID0gcmVzb2x2ZVR5cGVDaGVja2VyKHVucmVzb2x2ZWRUYylcbiAgICAgICAgICBjb25zdCBvYmpWYWwgPSBvYmpba11cblxuICAgICAgICAgIGNvbnN0IHZhbHVlQWN0dWFsQ2hlY2tlciA9IHRjLnNuYXBzaG90VHlwZShvYmpWYWwpXG4gICAgICAgICAgaWYgKCF2YWx1ZUFjdHVhbENoZWNrZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXNUY1xuICAgICAgfSxcblxuICAgICAgKG9iajogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHtcbiAgICAgICAgcmV0dXJuIGFwcGx5U25hcHNob3RQcm9jZXNzb3Iob2JqLCBcImZyb21cIilcbiAgICAgIH0sXG5cbiAgICAgIChvYmo6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB7XG4gICAgICAgIHJldHVybiBhcHBseVNuYXBzaG90UHJvY2Vzc29yKG9iaiwgXCJ0b1wiKVxuICAgICAgfVxuICAgIClcblxuICAgIHJldHVybiB0aGlzVGNcbiAgfSwgdHlwZUluZm9HZW4pIGFzIGFueVxufVxuXG4vKipcbiAqIEEgdHlwZSB0aGF0IHJlcHJlc2VudHMgYSBwbGFpbiBvYmplY3QuXG4gKiBOb3RlIHRoYXQgdGhlIHBhcmFtZXRlciBtdXN0IGJlIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGFuIG9iamVjdC4gVGhpcyBpcyBkb25lIHNvIG9iamVjdHMgY2FuIHN1cHBvcnQgc2VsZiAvIGNyb3NzIHR5cGVzLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogLy8gbm90aWNlIHRoZSAoeyAuLi4gfSksIG5vdCBqdXN0IHsgLi4uIH1cbiAqIGNvbnN0IHBvaW50VHlwZSA9IHR5cGVzLm9iamVjdCgoKSA9PiAoe1xuICogICB4OiB0eXBlcy5udW1iZXIsXG4gKiAgIHk6IHR5cGVzLm51bWJlclxuICogfSkpXG4gKiBgYGBcbiAqXG4gKiBAdHlwZXBhcmFtIFQgVHlwZS5cbiAqIEBwYXJhbSBvYmplY3RGdW5jdGlvbiBGdW5jdGlvbiB0aGF0IGdlbmVyYXRlcyBhbiBvYmplY3Qgd2l0aCB0eXBlcy5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc09iamVjdDxUPihvYmplY3RGdW5jdGlvbjogVCk6IFQge1xuICAvLyB3ZSBjYW4ndCB0eXBlIHRoaXMgZnVuY3Rpb24gb3IgZWxzZSB3ZSB3b24ndCBiZSBhYmxlIHRvIG1ha2UgaXQgd29yayByZWN1cnNpdmVseVxuICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT4gbmV3IE9iamVjdFR5cGVJbmZvKHQsIG9iamVjdEZ1bmN0aW9uIGFzIGFueSlcblxuICByZXR1cm4gdHlwZXNPYmplY3RIZWxwZXIob2JqZWN0RnVuY3Rpb24sIGZhbHNlLCB0eXBlSW5mb0dlbikgYXMgYW55XG59XG5cbi8qKlxuICogYHR5cGVzLm9iamVjdGAgdHlwZSBpbmZvIGZvciBhbiBvYmplY3QgcHJvcHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT2JqZWN0VHlwZUluZm9Qcm9wcyB7XG4gIHJlYWRvbmx5IFtwcm9wTmFtZTogc3RyaW5nXTogUmVhZG9ubHk8e1xuICAgIHR5cGU6IEFueVN0YW5kYXJkVHlwZVxuICAgIHR5cGVJbmZvOiBUeXBlSW5mb1xuICB9PlxufVxuXG4vKipcbiAqIGB0eXBlcy5vYmplY3RgIHR5cGUgaW5mby5cbiAqL1xuZXhwb3J0IGNsYXNzIE9iamVjdFR5cGVJbmZvIGV4dGVuZHMgVHlwZUluZm8ge1xuICAvLyBtZW1vaXplIHRvIGFsd2F5cyByZXR1cm4gdGhlIHNhbWUgb2JqZWN0XG4gIHByaXZhdGUgX3Byb3BzID0gbGF6eSgoKSA9PiB7XG4gICAgY29uc3Qgb2JqU2NoZW1hID0gdGhpcy5fb2JqVHlwZUZuKClcblxuICAgIGNvbnN0IHByb3BUeXBlczogTy5Xcml0YWJsZTxPYmplY3RUeXBlSW5mb1Byb3BzPiA9IHt9XG4gICAgT2JqZWN0LmtleXMob2JqU2NoZW1hKS5mb3JFYWNoKChwcm9wTmFtZSkgPT4ge1xuICAgICAgY29uc3QgdHlwZSA9IHJlc29sdmVTdGFuZGFyZFR5cGUob2JqU2NoZW1hW3Byb3BOYW1lXSlcbiAgICAgIHByb3BUeXBlc1twcm9wTmFtZV0gPSB7IHR5cGUsIHR5cGVJbmZvOiBnZXRUeXBlSW5mbyh0eXBlKSB9XG4gICAgfSlcbiAgICByZXR1cm4gcHJvcFR5cGVzXG4gIH0pXG5cbiAgZ2V0IHByb3BzKCk6IE9iamVjdFR5cGVJbmZvUHJvcHMge1xuICAgIHJldHVybiB0aGlzLl9wcm9wcygpXG4gIH1cblxuICBjb25zdHJ1Y3Rvcih0aGlzVHlwZTogQW55U3RhbmRhcmRUeXBlLCBwcml2YXRlIF9vYmpUeXBlRm46IE9iamVjdFR5cGVGdW5jdGlvbikge1xuICAgIHN1cGVyKHRoaXNUeXBlKVxuICB9XG59XG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBmcm96ZW4gZGF0YS5cbiAqXG4gKiBFeGFtcGxlOlxuICogYGBgdHNcbiAqIGNvbnN0IGZyb3plbk51bWJlclR5cGUgPSB0eXBlcy5mcm96ZW4odHlwZXMubnVtYmVyKVxuICogY29uc3QgZnJvemVuQW55VHlwZSA9IHR5cGVzLmZyb3plbih0eXBlcy51bmNoZWNrZWQ8YW55PigpKVxuICogY29uc3QgZnJvemVuTnVtYmVyQXJyYXlUeXBlID0gdHlwZXMuZnJvemVuKHR5cGVzLmFycmF5KHR5cGVzLm51bWJlcikpXG4gKiBjb25zdCBmcm96ZW5VbmNoZWNrZWROdW1iZXJBcnJheVR5cGUgPSB0eXBlcy5mcm96ZW4odHlwZXMudW5jaGVja2VkPG51bWJlcltdPigpKVxuICogYGBgXG4gKlxuICogQHR5cGVwYXJhbSBUIFR5cGUuXG4gKiBAcGFyYW0gZGF0YVR5cGUgVHlwZSBvZiB0aGUgZnJvemVuIGRhdGEuXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHlwZXNGcm96ZW48VCBleHRlbmRzIEFueVR5cGU+KGRhdGFUeXBlOiBUKTogTW9kZWxUeXBlPEZyb3plbjxUeXBlVG9EYXRhPFQ+Pj4ge1xuICByZXR1cm4gdHlwZXNPYmplY3RIZWxwZXIoXG4gICAgKCkgPT4gKHtcbiAgICAgIGRhdGE6IGRhdGFUeXBlLFxuICAgIH0pLFxuICAgIHRydWUsXG4gICAgKHQpID0+IG5ldyBGcm96ZW5UeXBlSW5mbyh0LCByZXNvbHZlU3RhbmRhcmRUeXBlKGRhdGFUeXBlKSlcbiAgKSBhcyBhbnlcbn1cblxuLyoqXG4gKiBgdHlwZXMuZnJvemVuYCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBGcm96ZW5UeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHtcbiAgZ2V0IGRhdGFUeXBlSW5mbygpOiBUeXBlSW5mbyB7XG4gICAgcmV0dXJuIGdldFR5cGVJbmZvKHRoaXMuZGF0YVR5cGUpXG4gIH1cblxuICBjb25zdHJ1Y3Rvcih0aGlzVHlwZTogQW55U3RhbmRhcmRUeXBlLCByZWFkb25seSBkYXRhVHlwZTogQW55U3RhbmRhcmRUeXBlKSB7XG4gICAgc3VwZXIodGhpc1R5cGUpXG4gIH1cbn1cbiIsImltcG9ydCB7IGlkZW50aXR5Rm4gfSBmcm9tIFwiLi4vLi4vdXRpbHNcIlxuaW1wb3J0IHR5cGUgeyBJZGVudGl0eVR5cGUgfSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQgeyBUeXBlQ2hlY2tlciwgVHlwZUNoZWNrZXJCYXNlVHlwZSwgVHlwZUluZm8gfSBmcm9tIFwiLi4vVHlwZUNoZWNrZXJcIlxuXG5jb25zdCB1bmNoZWNrZWQ6IElkZW50aXR5VHlwZTxhbnk+ID0gbmV3IFR5cGVDaGVja2VyKFxuICBUeXBlQ2hlY2tlckJhc2VUeXBlLkFueSxcbiAgbnVsbCxcbiAgKCkgPT4gXCJhbnlcIixcbiAgKHQpID0+IG5ldyBVbmNoZWNrZWRUeXBlSW5mbyh0KSxcblxuICAoKSA9PiB1bmNoZWNrZWQgYXMgYW55LFxuXG4gIGlkZW50aXR5Rm4sXG4gIGlkZW50aXR5Rm5cbikgYXMgYW55XG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBhIGdpdmVuIHZhbHVlIHRoYXQgd29uJ3QgYmUgdHlwZSBjaGVja2VkLlxuICogVGhpcyBpcyBiYXNpY2FsbHkgYSB3YXkgdG8gYmFpbCBvdXQgb2YgdGhlIHJ1bnRpbWUgdHlwZSBjaGVja2luZyBzeXN0ZW0uXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYHRzXG4gKiBjb25zdCB1bmNoZWNrZWRTb21lTW9kZWwgPSB0eXBlcy51bmNoZWNrZWQ8U29tZU1vZGVsPigpXG4gKiBjb25zdCBhbnlUeXBlID0gdHlwZXMudW5jaGVja2VkPGFueT4oKVxuICogY29uc3QgY3VzdG9tVW5jaGVja2VkVHlwZSA9IHR5cGVzLnVuY2hlY2tlZDwoQSAmIEIpIHwgQz4oKVxuICogYGBgXG4gKlxuICogQHR5cGVwYXJhbSBUIFR5cGUgb2YgdGhlIHZhbHVlLCBvciB1bmtvd24gaWYgbm90IGdpdmVuLlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGVzVW5jaGVja2VkPFQgPSBuZXZlcj4oKTogSWRlbnRpdHlUeXBlPFQ+IHtcbiAgcmV0dXJuIHVuY2hlY2tlZFxufVxuXG4vKipcbiAqIGB0eXBlcy51bmNoZWNrZWRgIHR5cGUgaW5mby5cbiAqL1xuZXhwb3J0IGNsYXNzIFVuY2hlY2tlZFR5cGVJbmZvIGV4dGVuZHMgVHlwZUluZm8ge31cbiIsImltcG9ydCB7IGZhaWx1cmUsIGxhenkgfSBmcm9tIFwiLi4vLi4vdXRpbHNcIlxuaW1wb3J0IHsgZ2V0VHlwZUluZm8gfSBmcm9tIFwiLi4vZ2V0VHlwZUluZm9cIlxuaW1wb3J0IHtcbiAgcmVzb2x2ZVN0YW5kYXJkVHlwZSxcbiAgcmVzb2x2ZVN0YW5kYXJkVHlwZU5vVGhyb3csXG4gIHJlc29sdmVUeXBlQ2hlY2tlcixcbn0gZnJvbSBcIi4uL3Jlc29sdmVUeXBlQ2hlY2tlclwiXG5pbXBvcnQgdHlwZSB7IEFueVN0YW5kYXJkVHlwZSwgQW55VHlwZSB9IGZyb20gXCIuLi9zY2hlbWFzXCJcbmltcG9ydCB7XG4gIGdldFR5cGVDaGVja2VyQmFzZVR5cGVGcm9tVmFsdWUsXG4gIGxhdGVUeXBlQ2hlY2tlcixcbiAgVHlwZUNoZWNrZXIsXG4gIFR5cGVDaGVja2VyQmFzZVR5cGUsXG4gIFR5cGVJbmZvLFxuICBUeXBlSW5mb0dlbixcbn0gZnJvbSBcIi4uL1R5cGVDaGVja2VyXCJcbmltcG9ydCB7IFR5cGVDaGVja0Vycm9yIH0gZnJvbSBcIi4uL1R5cGVDaGVja0Vycm9yXCJcbmltcG9ydCB7IHR5cGVzVW5jaGVja2VkIH0gZnJvbSBcIi4vdHlwZXNVbmNoZWNrZWRcIlxuXG4vKipcbiAqIEEgdHlwZSB0aGF0IHJlcHJlc2VudHMgdGhlIHVuaW9uIG9mIHNldmVyYWwgb3RoZXIgdHlwZXMgKGEgfCBiIHwgYyB8IC4uLikuXG4gKiBBY2NlcHRzIGEgZGlzcGF0Y2hlciB0aGF0LCBnaXZlbiBhIHNuYXBzaG90LCByZXR1cm5zIHRoZSB0eXBlXG4gKiB0aGF0IHNuYXBzaG90IGlzLlxuICpcbiAqIEB0eXBlcGFyYW0gVCBUeXBlLlxuICogQHBhcmFtIGRpc3BhdGNoZXIgRnVuY3Rpb24gdGhhdCBnaXZlbiBhIHNuYXBzaG90IHJldHVybnMgdGhlIHR5cGUuXG4gKiBAcGFyYW0gb3JUeXBlcyBQb3NzaWJsZSB0eXBlcy5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc09yPFQgZXh0ZW5kcyBBbnlUeXBlW10+KFxuICBkaXNwYXRjaGVyOiAoc246IGFueSkgPT4gVFtudW1iZXJdLFxuICAuLi5vclR5cGVzOiBUXG4pOiBUW251bWJlcl1cblxuLyoqXG4gKiBBIHR5cGUgdGhhdCByZXByZXNlbnRzIHRoZSB1bmlvbiBvZiBzZXZlcmFsIG90aGVyIHR5cGVzIChhIHwgYiB8IGMgfCAuLi4pLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogY29uc3QgYm9vbGVhbk9yTnVtYmVyVHlwZSA9IHR5cGVzLm9yKHR5cGVzLmJvb2xlYW4sIHR5cGVzLm51bWJlcilcbiAqIGBgYFxuICpcbiAqIEB0eXBlcGFyYW0gVCBUeXBlLlxuICogQHBhcmFtIG9yVHlwZXMgUG9zc2libGUgdHlwZXMuXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHlwZXNPcjxUIGV4dGVuZHMgQW55VHlwZVtdPiguLi5vclR5cGVzOiBUKTogVFtudW1iZXJdXG5cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc09yKFxuICBkaXNwYXRjaGVyT3JUeXBlOiAoKHNuOiBhbnkpID0+IEFueVR5cGUpIHwgQW55VHlwZSxcbiAgLi4ubW9yZU9yVHlwZXM6IEFueVR5cGVbXVxuKTogQW55VHlwZSB7XG4gIGNvbnN0IG9yVHlwZXMgPSBtb3JlT3JUeXBlcy5zbGljZSgpXG4gIGxldCBmaW5hbERpc3BhdGNoZXI6ICgoc246IGFueSkgPT4gVHlwZUNoZWNrZXIpIHwgdW5kZWZpbmVkXG5cbiAgY29uc3QgZmlyc3RUeXBlQ2hlY2tlciA9IHJlc29sdmVTdGFuZGFyZFR5cGVOb1Rocm93KGRpc3BhdGNoZXJPclR5cGUgYXMgQW55VHlwZSlcblxuICBpZiAoZmlyc3RUeXBlQ2hlY2tlcikge1xuICAgIG9yVHlwZXMudW5zaGlmdChmaXJzdFR5cGVDaGVja2VyKVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IGRpc3BhdGNoZXIgPSBkaXNwYXRjaGVyT3JUeXBlIGFzIChzbjogYW55KSA9PiBBbnlUeXBlXG4gICAgZmluYWxEaXNwYXRjaGVyID0gKHNuOiBhbnkpID0+IHtcbiAgICAgIGNvbnN0IHR5cGUgPSBkaXNwYXRjaGVyKHNuKVxuICAgICAgY29uc3QgdHlwZUNoZWNrZXIgPSByZXNvbHZlVHlwZUNoZWNrZXIodHlwZSlcbiAgICAgIHJldHVybiB0eXBlQ2hlY2tlclxuICAgIH1cbiAgfVxuXG4gIGlmIChvclR5cGVzLmxlbmd0aCA8PSAwKSB7XG4gICAgdGhyb3cgZmFpbHVyZShcIm9yIHR5cGUgbXVzdCBoYXZlIGF0IGxlYXN0IDEgcG9zc2libGUgdHlwZVwiKVxuICB9XG5cbiAgY29uc3QgdHlwZUluZm9HZW46IFR5cGVJbmZvR2VuID0gKHQpID0+IG5ldyBPclR5cGVJbmZvKHQsIG9yVHlwZXMubWFwKHJlc29sdmVTdGFuZGFyZFR5cGUpKVxuXG4gIHJldHVybiBsYXRlVHlwZUNoZWNrZXIoKCkgPT4ge1xuICAgIGNvbnN0IGNoZWNrZXJzID0gb3JUeXBlcy5tYXAocmVzb2x2ZVR5cGVDaGVja2VyKVxuXG4gICAgLy8gaWYgdGhlIG9yIGluY2x1ZGVzIHVuY2hlY2tlZCB0aGVuIGl0IGlzIHVuY2hlY2tlZFxuICAgIGlmIChjaGVja2Vycy5zb21lKCh0YykgPT4gdGMudW5jaGVja2VkKSkge1xuICAgICAgcmV0dXJuIHR5cGVzVW5jaGVja2VkKCkgYXMgYW55XG4gICAgfVxuXG4gICAgY29uc3QgZ2V0VHlwZU5hbWUgPSAoLi4ucmVjdXJzaXZlVHlwZUNoZWNrZXJzOiBUeXBlQ2hlY2tlcltdKSA9PiB7XG4gICAgICBjb25zdCB0eXBlTmFtZXMgPSBjaGVja2Vycy5tYXAoKHRjKSA9PiB7XG4gICAgICAgIGlmIChyZWN1cnNpdmVUeXBlQ2hlY2tlcnMuaW5jbHVkZXModGMpKSB7XG4gICAgICAgICAgcmV0dXJuIFwiLi4uXCJcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGMuZ2V0VHlwZU5hbWUoLi4ucmVjdXJzaXZlVHlwZUNoZWNrZXJzLCB0YylcbiAgICAgIH0pXG5cbiAgICAgIHJldHVybiB0eXBlTmFtZXMuam9pbihcIiB8IFwiKVxuICAgIH1cblxuICAgIGxldCB0aGlzVGNCYXNlVHlwZTogVHlwZUNoZWNrZXJCYXNlVHlwZVxuICAgIGlmIChjaGVja2Vycy5zb21lKChjKSA9PiBjLmJhc2VUeXBlICE9PSBjaGVja2Vyc1swXS5iYXNlVHlwZSkpIHtcbiAgICAgIHRoaXNUY0Jhc2VUeXBlID0gVHlwZUNoZWNrZXJCYXNlVHlwZS5BbnlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpc1RjQmFzZVR5cGUgPSBjaGVja2Vyc1swXS5iYXNlVHlwZVxuICAgIH1cblxuICAgIGNvbnN0IHRoaXNUYzogVHlwZUNoZWNrZXIgPSBuZXcgVHlwZUNoZWNrZXIoXG4gICAgICB0aGlzVGNCYXNlVHlwZSxcblxuICAgICAgKHZhbHVlLCBwYXRoLCB0eXBlQ2hlY2tlZFZhbHVlKSA9PiB7XG4gICAgICAgIGNvbnN0IHNvbWVNYXRjaGluZ1R5cGUgPSBjaGVja2Vycy5zb21lKCh0YykgPT4gIXRjLmNoZWNrKHZhbHVlLCBwYXRoLCB0eXBlQ2hlY2tlZFZhbHVlKSlcbiAgICAgICAgaWYgKHNvbWVNYXRjaGluZ1R5cGUpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBuZXcgVHlwZUNoZWNrRXJyb3IocGF0aCwgZ2V0VHlwZU5hbWUodGhpc1RjKSwgdmFsdWUsIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICAgIH1cbiAgICAgIH0sXG5cbiAgICAgIGdldFR5cGVOYW1lLFxuICAgICAgdHlwZUluZm9HZW4sXG5cbiAgICAgICh2YWx1ZSkgPT4ge1xuICAgICAgICBjb25zdCB2YWx1ZUJhc2VUeXBlID0gZ2V0VHlwZUNoZWNrZXJCYXNlVHlwZUZyb21WYWx1ZSh2YWx1ZSlcblxuICAgICAgICBjb25zdCBjaGVja2VyRm9yQmFzZVR5cGUgPSBjaGVja2Vycy5maWx0ZXIoXG4gICAgICAgICAgKGMpID0+IGMuYmFzZVR5cGUgPT09IHZhbHVlQmFzZVR5cGUgfHwgYy5iYXNlVHlwZSA9PT0gVHlwZUNoZWNrZXJCYXNlVHlwZS5BbnlcbiAgICAgICAgKVxuXG4gICAgICAgIGlmIChjaGVja2VyRm9yQmFzZVR5cGUubGVuZ3RoID09PSAxICYmIGNoZWNrZXJGb3JCYXNlVHlwZVswXS5iYXNlVHlwZSA9PT0gdmFsdWVCYXNlVHlwZSkge1xuICAgICAgICAgIC8vIHdoZW4gdGhlcmUgaXMgb25seSBvbmUgdmFsaWQgb3B0aW9uIGFjY2VwdCBpdCB3aXRob3V0IGFza2luZ1xuICAgICAgICAgIC8vIHRoaXMgaXMgZG9uZSBiZWNhdXNlOlxuICAgICAgICAgIC8vIDEpIHBlcmZvcm1hbmNlIChhdm9pZCBjaGVja2luZyBzdHJ1Y3R1cmUgaWYgbm90IG5lZWRlZClcbiAgICAgICAgICAvLyAyKSBzbyB3ZSBjYW4gYWNjZXB0IHVudHlwZWQgbW9kZWxzIHdoZW4gcGFpcmVkIHdpdGggdW5kZWZpbmVkIHwgbnVsbFxuICAgICAgICAgIHJldHVybiBjaGVja2VyRm9yQmFzZVR5cGVbMF1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hlY2tlckZvckJhc2VUeXBlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY29uc3QgbWF0Y2hpbmdUeXBlID0gY2hlY2tlckZvckJhc2VUeXBlW2ldLnNuYXBzaG90VHlwZSh2YWx1ZSlcbiAgICAgICAgICBpZiAobWF0Y2hpbmdUeXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hpbmdUeXBlXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgIH0sXG5cbiAgICAgIChzbikgPT4ge1xuICAgICAgICBjb25zdCB0eXBlID0gZmluYWxEaXNwYXRjaGVyID8gZmluYWxEaXNwYXRjaGVyKHNuKSA6IHRoaXNUYy5zbmFwc2hvdFR5cGUoc24pXG4gICAgICAgIGlmICghdHlwZSkge1xuICAgICAgICAgIHRocm93IGZhaWx1cmUoXG4gICAgICAgICAgICBgc25hcHNob3QgJyR7SlNPTi5zdHJpbmdpZnkoc24pfScgZG9lcyBub3QgbWF0Y2ggdGhlIGZvbGxvd2luZyB0eXBlOiAke2dldFR5cGVOYW1lKFxuICAgICAgICAgICAgICB0aGlzVGNcbiAgICAgICAgICAgICl9YFxuICAgICAgICAgIClcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0eXBlLmZyb21TbmFwc2hvdFByb2Nlc3NvcihzbilcbiAgICAgIH0sXG5cbiAgICAgIChzbikgPT4ge1xuICAgICAgICBjb25zdCB0eXBlID0gZmluYWxEaXNwYXRjaGVyID8gZmluYWxEaXNwYXRjaGVyKHNuKSA6IHRoaXNUYy5zbmFwc2hvdFR5cGUoc24pXG4gICAgICAgIGlmICghdHlwZSkge1xuICAgICAgICAgIHRocm93IGZhaWx1cmUoXG4gICAgICAgICAgICBgc25hcHNob3QgJyR7SlNPTi5zdHJpbmdpZnkoc24pfScgZG9lcyBub3QgbWF0Y2ggdGhlIGZvbGxvd2luZyB0eXBlOiAke2dldFR5cGVOYW1lKFxuICAgICAgICAgICAgICB0aGlzVGNcbiAgICAgICAgICAgICl9YFxuICAgICAgICAgIClcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0eXBlLnRvU25hcHNob3RQcm9jZXNzb3Ioc24pXG4gICAgICB9XG4gICAgKVxuXG4gICAgcmV0dXJuIHRoaXNUY1xuICB9LCB0eXBlSW5mb0dlbikgYXMgYW55XG59XG5cbi8qKlxuICogYHR5cGVzLm9yYCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBPclR5cGVJbmZvIGV4dGVuZHMgVHlwZUluZm8ge1xuICAvLyBtZW1vaXplIHRvIGFsd2F5cyByZXR1cm4gdGhlIHNhbWUgYXJyYXkgb24gdGhlIGdldHRlclxuICBwcml2YXRlIF9vclR5cGVJbmZvcyA9IGxhenkoKCkgPT4gdGhpcy5vclR5cGVzLm1hcChnZXRUeXBlSW5mbykpXG5cbiAgZ2V0IG9yVHlwZUluZm9zKCk6IFJlYWRvbmx5QXJyYXk8VHlwZUluZm8+IHtcbiAgICByZXR1cm4gdGhpcy5fb3JUeXBlSW5mb3MoKVxuICB9XG5cbiAgY29uc3RydWN0b3IodGhpc1R5cGU6IEFueVN0YW5kYXJkVHlwZSwgcmVhZG9ubHkgb3JUeXBlczogUmVhZG9ubHlBcnJheTxBbnlTdGFuZGFyZFR5cGU+KSB7XG4gICAgc3VwZXIodGhpc1R5cGUpXG4gIH1cbn1cbiIsImltcG9ydCB7IEFueU1vZGVsUHJvcCwgTWF5YmVPcHRpb25hbE1vZGVsUHJvcCwgT3B0aW9uYWxNb2RlbFByb3AsIHByb3AgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvcHJvcFwiXHJcbmltcG9ydCB7XHJcbiAgdHlwZXNCb29sZWFuLFxyXG4gIHR5cGVzTnVsbCxcclxuICB0eXBlc051bWJlcixcclxuICB0eXBlc1N0cmluZyxcclxuICB0eXBlc1VuZGVmaW5lZCxcclxufSBmcm9tIFwiLi9wcmltaXRpdmVCYXNlZC90eXBlc1ByaW1pdGl2ZVwiXHJcbmltcG9ydCB7IHJlc29sdmVTdGFuZGFyZFR5cGUsIHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuL3Jlc29sdmVUeXBlQ2hlY2tlclwiXHJcbmltcG9ydCB0eXBlIHsgQW55VHlwZSwgVHlwZVRvRGF0YSB9IGZyb20gXCIuL3NjaGVtYXNcIlxyXG5pbXBvcnQgeyBMYXRlVHlwZUNoZWNrZXIsIFR5cGVDaGVja2VyIH0gZnJvbSBcIi4vVHlwZUNoZWNrZXJcIlxyXG5pbXBvcnQgeyB0eXBlc09yIH0gZnJvbSBcIi4vdXRpbGl0eS90eXBlc09yXCJcclxuXHJcbmNvbnN0IG5vRGVmYXVsdFZhbHVlU3ltYm9sID0gU3ltYm9sKFwibm9EZWZhdWx0VmFsdWVcIilcclxuXHJcbmNvbnN0IHRQcm9wQ2FjaGUgPSBuZXcgV2Vha01hcDxUeXBlQ2hlY2tlciB8IExhdGVUeXBlQ2hlY2tlciwgTWFwPHVua25vd24sIEFueU1vZGVsUHJvcD4+KClcclxuXHJcbmZ1bmN0aW9uIGdldE9yQ3JlYXRlVFByb3AoXHJcbiAgdHlwZTogVHlwZUNoZWNrZXIgfCBMYXRlVHlwZUNoZWNrZXIsXHJcbiAgZGVmS2V5OiB1bmtub3duLFxyXG4gIGNyZWF0ZVRQcm9wOiAoKSA9PiBBbnlNb2RlbFByb3BcclxuKTogQW55TW9kZWxQcm9wIHtcclxuICBsZXQgZGVmVmFsdWVDYWNoZSA9IHRQcm9wQ2FjaGUuZ2V0KHR5cGUpXHJcbiAgaWYgKCFkZWZWYWx1ZUNhY2hlKSB7XHJcbiAgICBkZWZWYWx1ZUNhY2hlID0gbmV3IE1hcCgpXHJcbiAgICB0UHJvcENhY2hlLnNldCh0eXBlLCBkZWZWYWx1ZUNhY2hlKVxyXG4gIH1cclxuXHJcbiAgbGV0IHByb3AgPSBkZWZWYWx1ZUNhY2hlLmdldChkZWZLZXkpXHJcbiAgaWYgKCFwcm9wKSB7XHJcbiAgICBwcm9wID0gY3JlYXRlVFByb3AoKVxyXG4gICAgZGVmVmFsdWVDYWNoZS5zZXQoZGVmS2V5LCBwcm9wKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHByb3BcclxufVxyXG5cclxuLyoqXHJcbiAqIERlZmluZXMgYSBzdHJpbmcgbW9kZWwgcHJvcGVydHkgd2l0aCBhIGRlZmF1bHQgdmFsdWUuXHJcbiAqIEVxdWl2YWxlbnQgdG8gYHRQcm9wKHR5cGVzLnN0cmluZywgZGVmYXVsdFZhbHVlKWAuXHJcbiAqXHJcbiAqIEV4YW1wbGU6XHJcbiAqIGBgYHRzXHJcbiAqIHg6IHRQcm9wKFwiZm9vXCIpIC8vIGFuIG9wdGlvbmFsIHN0cmluZyB0aGF0IHdpbGwgdGFrZSB0aGUgdmFsdWUgYFwiZm9vXCJgIHdoZW4gdW5kZWZpbmVkLlxyXG4gKiBgYGBcclxuICpcclxuICogQHBhcmFtIGRlZmF1bHRWYWx1ZSBEZWZhdWx0IHZhbHVlLlxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHRQcm9wKGRlZmF1bHRWYWx1ZTogc3RyaW5nKTogT3B0aW9uYWxNb2RlbFByb3A8c3RyaW5nPlxyXG5cclxuLyoqXHJcbiAqIERlZmluZXMgYSBudW1iZXIgbW9kZWwgcHJvcGVydHkgd2l0aCBhIGRlZmF1bHQgdmFsdWUuXHJcbiAqIEVxdWl2YWxlbnQgdG8gYHRQcm9wKHR5cGVzLm51bWJlciwgZGVmYXVsdFZhbHVlKWAuXHJcbiAqXHJcbiAqIEV4YW1wbGU6XHJcbiAqIGBgYHRzXHJcbiAqIHg6IHRQcm9wKDQyKSAvLyBhbiBvcHRpb25hbCBudW1iZXIgdGhhdCB3aWxsIHRha2UgdGhlIHZhbHVlIGA0MmAgd2hlbiB1bmRlZmluZWQuXHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAcGFyYW0gZGVmYXVsdFZhbHVlIERlZmF1bHQgdmFsdWUuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdFByb3AoZGVmYXVsdFZhbHVlOiBudW1iZXIpOiBPcHRpb25hbE1vZGVsUHJvcDxudW1iZXI+XHJcblxyXG4vKipcclxuICogRGVmaW5lcyBhIGJvb2xlYW4gbW9kZWwgcHJvcGVydHkgd2l0aCBhIGRlZmF1bHQgdmFsdWUuXHJcbiAqIEVxdWl2YWxlbnQgdG8gYHRQcm9wKHR5cGVzLmJvb2xlYW4sIGRlZmF1bHRWYWx1ZSlgLlxyXG4gKlxyXG4gKiBFeGFtcGxlOlxyXG4gKiBgYGB0c1xyXG4gKiB4OiB0UHJvcCh0cnVlKSAvLyBhbiBvcHRpb25hbCBib29sZWFuIHRoYXQgd2lsbCB0YWtlIHRoZSB2YWx1ZSBgdHJ1ZWAgd2hlbiB1bmRlZmluZWQuXHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAcGFyYW0gZGVmYXVsdFZhbHVlIERlZmF1bHQgdmFsdWUuXHJcbiAqIEBwYXJhbSBvcHRpb25zIE1vZGVsIHByb3BlcnR5IG9wdGlvbnMuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdFByb3AoZGVmYXVsdFZhbHVlOiBib29sZWFuKTogT3B0aW9uYWxNb2RlbFByb3A8Ym9vbGVhbj5cclxuXHJcbi8qKlxyXG4gKiBEZWZpbmVzIGEgbW9kZWwgcHJvcGVydHksIHdpdGggYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZ2VuZXJhdGUgYSBkZWZhdWx0IHZhbHVlXHJcbiAqIGlmIHRoZSBpbnB1dCBzbmFwc2hvdCAvIG1vZGVsIGNyZWF0aW9uIGRhdGEgaXMgYG51bGxgIG9yIGB1bmRlZmluZWRgIGFuZCB3aXRoIGFuIGFzc29jaWF0ZWQgdHlwZSBjaGVja2VyLlxyXG4gKlxyXG4gKiBFeGFtcGxlOlxyXG4gKiBgYGB0c1xyXG4gKiB4OiB0UHJvcCh0eXBlcy5udW1iZXIsICgpID0+IDEwKSAvLyBhbiBvcHRpb25hbCBudW1iZXIsIHdpdGggYSBkZWZhdWx0IHZhbHVlIG9mIDEwXHJcbiAqIHg6IHRQcm9wKHR5cGVzLmFycmF5KHR5cGVzLm51bWJlciksICgpID0+IFtdKSAvLyBhbiBvcHRpb25hbCBudW1iZXIgYXJyYXksIHdpdGggYSBkZWZhdWx0IGVtcHR5IGFycmF5XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFRUeXBlIFR5cGUgY2hlY2tlciB0eXBlLlxyXG4gKlxyXG4gKiBAcGFyYW0gdHlwZSBUeXBlIGNoZWNrZXIuXHJcbiAqIEBwYXJhbSBkZWZhdWx0Rm4gRGVmYXVsdCB2YWx1ZSBnZW5lcmF0b3IgZnVuY3Rpb24uXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdFByb3A8VFR5cGUgZXh0ZW5kcyBBbnlUeXBlPihcclxuICB0eXBlOiBUVHlwZSxcclxuICBkZWZhdWx0Rm46ICgpID0+IFR5cGVUb0RhdGE8VFR5cGU+XHJcbik6IE9wdGlvbmFsTW9kZWxQcm9wPFR5cGVUb0RhdGE8VFR5cGU+PlxyXG5cclxuLyoqXHJcbiAqIERlZmluZXMgYSBtb2RlbCBwcm9wZXJ0eSwgd2l0aCBhbiBvcHRpb25hbCBkZWZhdWx0IHZhbHVlXHJcbiAqIGlmIHRoZSBpbnB1dCBzbmFwc2hvdCAvIG1vZGVsIGNyZWF0aW9uIGRhdGEgaXMgYG51bGxgIG9yIGB1bmRlZmluZWRgIGFuZCB3aXRoIGFuIGFzc29jaWF0ZWQgdHlwZSBjaGVja2VyLlxyXG4gKiBZb3Ugc2hvdWxkIG9ubHkgdXNlIHRoaXMgd2l0aCBwcmltaXRpdmUgdmFsdWVzIGFuZCBuZXZlciB3aXRoIG9iamVjdCB2YWx1ZXNcclxuICogKGFycmF5LCBtb2RlbCwgb2JqZWN0LCBldGMpLlxyXG4gKlxyXG4gKiBFeGFtcGxlOlxyXG4gKiBgYGB0c1xyXG4gKiB4OiB0UHJvcCh0eXBlcy5udW1iZXIsIDEwKSAvLyBhbiBvcHRpb25hbCBudW1iZXIsIHdpdGggYSBkZWZhdWx0IHZhbHVlIG9mIDEwXHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFRUeXBlIFR5cGUgY2hlY2tlciB0eXBlLlxyXG4gKlxyXG4gKiBAcGFyYW0gdHlwZSBUeXBlIGNoZWNrZXIuXHJcbiAqIEBwYXJhbSBkZWZhdWx0VmFsdWUgRGVmYXVsdCB2YWx1ZSBnZW5lcmF0b3IgZnVuY3Rpb24uXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdFByb3A8VFR5cGUgZXh0ZW5kcyBBbnlUeXBlPihcclxuICB0eXBlOiBUVHlwZSxcclxuICBkZWZhdWx0VmFsdWU6IFR5cGVUb0RhdGE8VFR5cGU+XHJcbik6IE9wdGlvbmFsTW9kZWxQcm9wPFR5cGVUb0RhdGE8VFR5cGU+PlxyXG5cclxuLyoqXHJcbiAqIERlZmluZXMgYSBtb2RlbCBwcm9wZXJ0eSB3aXRoIG5vIGRlZmF1bHQgdmFsdWUgYW5kIGFuIGFzc29jaWF0ZWQgdHlwZSBjaGVja2VyLlxyXG4gKlxyXG4gKiBFeGFtcGxlOlxyXG4gKiBgYGB0c1xyXG4gKiB4OiB0UHJvcCh0eXBlcy5udW1iZXIpIC8vIGEgcmVxdWlyZWQgbnVtYmVyXHJcbiAqIHg6IHRQcm9wKHR5cGVzLm1heWJlKHR5cGVzLm51bWJlcikpIC8vIGFuIG9wdGlvbmFsIG51bWJlciwgd2hpY2ggZGVmYXVsdHMgdG8gdW5kZWZpbmVkXHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFRUeXBlIFR5cGUgY2hlY2tlciB0eXBlLlxyXG4gKlxyXG4gKiBAcGFyYW0gdHlwZSBUeXBlIGNoZWNrZXIuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdFByb3A8VFR5cGUgZXh0ZW5kcyBBbnlUeXBlPih0eXBlOiBUVHlwZSk6IE1heWJlT3B0aW9uYWxNb2RlbFByb3A8VHlwZVRvRGF0YTxUVHlwZT4+XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gdFByb3AodHlwZU9yRGVmYXVsdFZhbHVlOiBhbnksIGRlZj86IGFueSk6IEFueU1vZGVsUHJvcCB7XHJcbiAgc3dpdGNoICh0eXBlb2YgdHlwZU9yRGVmYXVsdFZhbHVlKSB7XHJcbiAgICBjYXNlIFwic3RyaW5nXCI6XHJcbiAgICAgIHJldHVybiB0UHJvcCh0eXBlc1N0cmluZywgdHlwZU9yRGVmYXVsdFZhbHVlKVxyXG4gICAgY2FzZSBcIm51bWJlclwiOlxyXG4gICAgICByZXR1cm4gdFByb3AodHlwZXNOdW1iZXIsIHR5cGVPckRlZmF1bHRWYWx1ZSlcclxuICAgIGNhc2UgXCJib29sZWFuXCI6XHJcbiAgICAgIHJldHVybiB0UHJvcCh0eXBlc0Jvb2xlYW4sIHR5cGVPckRlZmF1bHRWYWx1ZSlcclxuICB9XHJcblxyXG4gIGNvbnN0IGhhc0RlZmF1bHRWYWx1ZSA9IGFyZ3VtZW50cy5sZW5ndGggPj0gMlxyXG5cclxuICBjb25zdCB0eXBlQ2hlY2tlciA9IHJlc29sdmVTdGFuZGFyZFR5cGUodHlwZU9yRGVmYXVsdFZhbHVlKSBhcyB1bmtub3duIGFzXHJcbiAgICB8IFR5cGVDaGVja2VyXHJcbiAgICB8IExhdGVUeXBlQ2hlY2tlclxyXG5cclxuICByZXR1cm4gZ2V0T3JDcmVhdGVUUHJvcCh0eXBlQ2hlY2tlciwgaGFzRGVmYXVsdFZhbHVlID8gZGVmIDogbm9EZWZhdWx0VmFsdWVTeW1ib2wsICgpID0+IHtcclxuICAgIGNvbnN0IGZyb21TbmFwc2hvdFR5cGVDaGVja2VyID0gaGFzRGVmYXVsdFZhbHVlXHJcbiAgICAgID8gdHlwZXNPcih0eXBlQ2hlY2tlciBhcyB1bmtub3duIGFzIEFueVR5cGUsIHR5cGVzVW5kZWZpbmVkLCB0eXBlc051bGwpXHJcbiAgICAgIDogdHlwZUNoZWNrZXJcclxuXHJcbiAgICAvLyB3ZSB1c2UgT2JqZWN0LmNyZWF0ZSB0byBhdm9pZCBtZXNzaW5nIHVwIHdpdGggdGhlIHByb3AgY2FjaGVcclxuICAgIGNvbnN0IG5ld1Byb3AgPSBPYmplY3QuY3JlYXRlKGhhc0RlZmF1bHRWYWx1ZSA/IHByb3AoZGVmKSA6IHByb3AoKSlcclxuXHJcbiAgICBPYmplY3QuYXNzaWduKG5ld1Byb3AsIHtcclxuICAgICAgX3R5cGVDaGVja2VyOiB0eXBlQ2hlY2tlcixcclxuXHJcbiAgICAgIF9mcm9tU25hcHNob3RQcm9jZXNzb3I6IHRQcm9wRnJvbVNuYXBzaG90UHJvY2Vzc29yLmJpbmQodW5kZWZpbmVkLCBmcm9tU25hcHNob3RUeXBlQ2hlY2tlciksXHJcblxyXG4gICAgICBfdG9TbmFwc2hvdFByb2Nlc3NvcjogdFByb3BUb1NuYXBzaG90UHJvY2Vzc29yLmJpbmQodW5kZWZpbmVkLCB0eXBlQ2hlY2tlciksXHJcbiAgICB9IHNhdGlzZmllcyBQYXJ0aWFsPEFueU1vZGVsUHJvcD4pXHJcblxyXG4gICAgcmV0dXJuIG5ld1Byb3BcclxuICB9KVxyXG59XHJcblxyXG5mdW5jdGlvbiB0UHJvcEZyb21TbmFwc2hvdFByb2Nlc3NvcihcclxuICBmcm9tU25hcHNob3RUeXBlQ2hlY2tlcjogQW55VHlwZSB8IFR5cGVDaGVja2VyIHwgTGF0ZVR5cGVDaGVja2VyLFxyXG4gIHNuOiB1bmtub3duXHJcbik6IHVua25vd24ge1xyXG4gIGNvbnN0IGZzbnAgPSByZXNvbHZlVHlwZUNoZWNrZXIoZnJvbVNuYXBzaG90VHlwZUNoZWNrZXIpLmZyb21TbmFwc2hvdFByb2Nlc3NvclxyXG4gIHJldHVybiBmc25wID8gZnNucChzbikgOiBzblxyXG59XHJcblxyXG5mdW5jdGlvbiB0UHJvcFRvU25hcHNob3RQcm9jZXNzb3IoXHJcbiAgdHlwZUNoZWNrZXI6IEFueVR5cGUgfCBUeXBlQ2hlY2tlciB8IExhdGVUeXBlQ2hlY2tlcixcclxuICBzbjogdW5rbm93blxyXG4pOiB1bmtub3duIHtcclxuICBjb25zdCB0c25wID0gcmVzb2x2ZVR5cGVDaGVja2VyKHR5cGVDaGVja2VyKS50b1NuYXBzaG90UHJvY2Vzc29yXHJcbiAgcmV0dXJuIHRzbnAgPyB0c25wKHNuKSA6IHNuXHJcbn1cclxuIiwiZXhwb3J0IGZ1bmN0aW9uIGNoYWluRm5zPEYgZXh0ZW5kcyBGdW5jdGlvbj4oLi4uZm5zOiAoRiB8IHVuZGVmaW5lZClbXSk6IEYgfCB1bmRlZmluZWQge1xuICBjb25zdCBkZWZpbmVkRm5zID0gZm5zLmZpbHRlcigoZm4pID0+ICEhZm4pXG4gIGlmIChkZWZpbmVkRm5zLmxlbmd0aCA8PSAwKSByZXR1cm4gdW5kZWZpbmVkXG5cbiAgY29uc3QgY2hhaW5lZEZuID0gKHY6IGFueSwgLi4uYXJnczogYW55W10pID0+IHtcbiAgICBsZXQgcmV0ID0gdlxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkZWZpbmVkRm5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICByZXQgPSBkZWZpbmVkRm5zW2ldIShyZXQsIC4uLmFyZ3MpXG4gICAgfVxuXG4gICAgcmV0dXJuIHJldFxuICB9XG5cbiAgcmV0dXJuIGNoYWluZWRGbiBhcyB1bmtub3duIGFzIEZcbn1cbiIsImltcG9ydCB0eXBlIHsgQW55RGF0YU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9CYXNlRGF0YU1vZGVsXCJcbmltcG9ydCB7IGlzRGF0YU1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vZGF0YU1vZGVsL3V0aWxzXCJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcbmltcG9ydCB7IGlzTW9kZWxDbGFzcyB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXG5pbXBvcnQgeyBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB0eXBlIHsgTW9kZWxDbGFzcyB9IGZyb20gXCIuL0Jhc2VNb2RlbFNoYXJlZFwiXG5cbi8qKlxuICogQGludGVybmFsXG4gKlxuICogQXNzZXJ0cyBzb21ldGhpbmcgaXMgYWN0dWFsbHkgYSBjbGFzcyBvciBkYXRhIG1vZGVsLlxuICpcbiAqIEBwYXJhbSBtb2RlbFxuICogQHBhcmFtIGFyZ05hbWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydElzQ2xhc3NPckRhdGFNb2RlbENsYXNzKFxuICBtb2RlbDogdW5rbm93bixcbiAgYXJnTmFtZTogc3RyaW5nLFxuICBjdXN0b21FcnJNc2cgPSBcIm11c3QgYmUgYSBjbGFzcyBvciBkYXRhIG1vZGVsIGNsYXNzXCJcbik6IGFzc2VydHMgbW9kZWwgaXMgTW9kZWxDbGFzczxBbnlNb2RlbD4gfCBNb2RlbENsYXNzPEFueURhdGFNb2RlbD4ge1xuICBpZiAoIWlzTW9kZWxDbGFzcyhtb2RlbCkgJiYgIWlzRGF0YU1vZGVsQ2xhc3MobW9kZWwpKSB7XG4gICAgdGhyb3cgZmFpbHVyZShgJHthcmdOYW1lfSAke2N1c3RvbUVyck1zZ31gKVxuICB9XG59XG4iLCJpbXBvcnQgeyBhcHBseVNldCB9IGZyb20gXCIuLi9hY3Rpb24vYXBwbHlTZXRcIlxyXG5pbXBvcnQgeyBnZXRDdXJyZW50QWN0aW9uQ29udGV4dCB9IGZyb20gXCIuLi9hY3Rpb24vY29udGV4dFwiXHJcbmltcG9ydCB7IG1vZGVsQWN0aW9uIH0gZnJvbSBcIi4uL2FjdGlvbi9tb2RlbEFjdGlvblwiXHJcbmltcG9ydCB7IEFueURhdGFNb2RlbCwgQmFzZURhdGFNb2RlbCwgYmFzZURhdGFNb2RlbFByb3BOYW1lcyB9IGZyb20gXCIuLi9kYXRhTW9kZWwvQmFzZURhdGFNb2RlbFwiXHJcbmltcG9ydCB0eXBlIHsgRGF0YU1vZGVsQ29uc3RydWN0b3JPcHRpb25zIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9EYXRhTW9kZWxDb25zdHJ1Y3Rvck9wdGlvbnNcIlxyXG5pbXBvcnQgdHlwZSB7IERhdGFNb2RlbE1ldGFkYXRhIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC9nZXREYXRhTW9kZWxNZXRhZGF0YVwiXHJcbmltcG9ydCB7IGdldEdsb2JhbENvbmZpZyB9IGZyb20gXCIuLi9nbG9iYWxDb25maWcvZ2xvYmFsQ29uZmlnXCJcclxuaW1wb3J0IHsgQW55TW9kZWwsIEJhc2VNb2RlbCwgYmFzZU1vZGVsUHJvcE5hbWVzIH0gZnJvbSBcIi4uL21vZGVsL0Jhc2VNb2RlbFwiXHJcbmltcG9ydCB0eXBlIHsgTW9kZWxNZXRhZGF0YSB9IGZyb20gXCIuLi9tb2RlbC9nZXRNb2RlbE1ldGFkYXRhXCJcclxuaW1wb3J0IHsgbW9kZWxUeXBlS2V5IH0gZnJvbSBcIi4uL21vZGVsL21ldGFkYXRhXCJcclxuaW1wb3J0IHR5cGUgeyBNb2RlbENvbnN0cnVjdG9yT3B0aW9ucyB9IGZyb20gXCIuLi9tb2RlbC9Nb2RlbENvbnN0cnVjdG9yT3B0aW9uc1wiXHJcbmltcG9ydCB7IHR5cGVzT2JqZWN0IH0gZnJvbSBcIi4uL3R5cGVzL29iamVjdEJhc2VkL3R5cGVzT2JqZWN0XCJcclxuaW1wb3J0IHsgdHlwZXNTdHJpbmcgfSBmcm9tIFwiLi4vdHlwZXMvcHJpbWl0aXZlQmFzZWQvdHlwZXNQcmltaXRpdmVcIlxyXG5pbXBvcnQgdHlwZSB7IEFueVR5cGUgfSBmcm9tIFwiLi4vdHlwZXMvc2NoZW1hc1wiXHJcbmltcG9ydCB7IHRQcm9wIH0gZnJvbSBcIi4uL3R5cGVzL3RQcm9wXCJcclxuaW1wb3J0IHR5cGUgeyBMYXRlVHlwZUNoZWNrZXIgfSBmcm9tIFwiLi4vdHlwZXMvVHlwZUNoZWNrZXJcIlxyXG5pbXBvcnQgeyB0eXBlc1VuY2hlY2tlZCB9IGZyb20gXCIuLi90eXBlcy91dGlsaXR5L3R5cGVzVW5jaGVja2VkXCJcclxuaW1wb3J0IHsgYXNzZXJ0SXNPYmplY3QsIGZhaWx1cmUsIHByb3BOYW1lVG9TZXR0ZXJOYW1lIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgY2hhaW5GbnMgfSBmcm9tIFwiLi4vdXRpbHMvY2hhaW5GbnNcIlxyXG5pbXBvcnQgeyBNb2RlbENsYXNzLCBtb2RlbEluaXRpYWxpemVkU3ltYm9sIH0gZnJvbSBcIi4vQmFzZU1vZGVsU2hhcmVkXCJcclxuaW1wb3J0IHsgbW9kZWxJbml0aWFsaXplcnNTeW1ib2wgfSBmcm9tIFwiLi9tb2RlbENsYXNzSW5pdGlhbGl6ZXJcIlxyXG5pbXBvcnQgeyBnZXRJbnRlcm5hbE1vZGVsQ2xhc3NQcm9wc0luZm8sIHNldEludGVybmFsTW9kZWxDbGFzc1Byb3BzSW5mbyB9IGZyb20gXCIuL21vZGVsUHJvcHNJbmZvXCJcclxuaW1wb3J0IHsgbW9kZWxNZXRhZGF0YVN5bWJvbCwgbW9kZWxVbndyYXBwZWRDbGFzc1N5bWJvbCB9IGZyb20gXCIuL21vZGVsU3ltYm9sc1wiXHJcbmltcG9ydCB7IEFueU1vZGVsUHJvcCwgZ2V0TW9kZWxQcm9wRGVmYXVsdFZhbHVlLCBNb2RlbFByb3BzLCBub0RlZmF1bHRWYWx1ZSwgcHJvcCB9IGZyb20gXCIuL3Byb3BcIlxyXG5pbXBvcnQgeyBhc3NlcnRJc0NsYXNzT3JEYXRhTW9kZWxDbGFzcyB9IGZyb20gXCIuL3V0aWxzXCJcclxuXHJcbmZ1bmN0aW9uIGdldE1vZGVsSW5zdGFuY2VEYXRhRmllbGQ8TSBleHRlbmRzIEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPihcclxuICBtb2RlbDogTSxcclxuICBtb2RlbFByb3A6IEFueU1vZGVsUHJvcCxcclxuICBtb2RlbFByb3BOYW1lOiBzdHJpbmdcclxuKTogYW55IHtcclxuICAvLyBubyBuZWVkIHRvIHVzZSBnZXQgc2luY2UgdGhlc2UgdmFycyBhbHdheXMgZ2V0IG9uIHRoZSBpbml0aWFsICRcclxuICBjb25zdCB2YWx1ZSA9IG1vZGVsLiRbbW9kZWxQcm9wTmFtZV1cclxuXHJcbiAgaWYgKCFtb2RlbFByb3AuX3RyYW5zZm9ybSkge1xyXG4gICAgcmV0dXJuIHZhbHVlXHJcbiAgfVxyXG5cclxuICByZXR1cm4gbW9kZWxQcm9wLl90cmFuc2Zvcm0udHJhbnNmb3JtKHZhbHVlLCBtb2RlbCwgbW9kZWxQcm9wTmFtZSwgKG5ld1ZhbHVlKSA9PiB7XHJcbiAgICAvLyB1c2UgYXBwbHkgc2V0IGluc3RlYWQgdG8gd3JhcCBpdCBpbiBhbiBhY3Rpb25cclxuICAgIC8vIHNldCB0aGUgJCBvYmplY3QgdG8gc2V0IHRoZSBvcmlnaW5hbCB2YWx1ZSBkaXJlY3RseVxyXG4gICAgYXBwbHlTZXQobW9kZWwuJCwgbW9kZWxQcm9wTmFtZSwgbmV3VmFsdWUpXHJcbiAgfSkgYXMgYW55XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHNldE1vZGVsSW5zdGFuY2VEYXRhRmllbGQ8TSBleHRlbmRzIEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPihcclxuICBtb2RlbDogTSxcclxuICBtb2RlbFByb3A6IEFueU1vZGVsUHJvcCxcclxuICBtb2RlbFByb3BOYW1lOiBzdHJpbmcsXHJcbiAgdmFsdWU6IGFueVxyXG4pOiB2b2lkIHtcclxuICAvLyBoYWNrIHRvIG9ubHkgcGVybWl0IHNldHRpbmcgdGhlc2UgdmFsdWVzIG9uY2UgZnVsbHkgY29uc3RydWN0ZWRcclxuICAvLyB0aGlzIGlzIHRvIGlnbm9yZSBhYnN0cmFjdCBwcm9wZXJ0aWVzIGJlaW5nIHNldCBieSBiYWJlbFxyXG4gIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20veGF2aWVyZ29uei9tb2J4LWtleXN0b25lL2lzc3Vlcy8xOFxyXG4gIGlmICghKG1vZGVsSW5pdGlhbGl6ZWRTeW1ib2wgaW4gbW9kZWwpKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIGlmIChtb2RlbFByb3AuX3NldHRlciA9PT0gXCJhc3NpZ25cIiAmJiAhZ2V0Q3VycmVudEFjdGlvbkNvbnRleHQoKSkge1xyXG4gICAgLy8gdXNlIGFwcGx5IHNldCBpbnN0ZWFkIHRvIHdyYXAgaXQgaW4gYW4gYWN0aW9uXHJcbiAgICBhcHBseVNldChtb2RlbCwgbW9kZWxQcm9wTmFtZSBhcyBhbnksIHZhbHVlKVxyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG5cclxuICBsZXQgdW50cmFuc2Zvcm1lZFZhbHVlID0gbW9kZWxQcm9wLl90cmFuc2Zvcm1cclxuICAgID8gbW9kZWxQcm9wLl90cmFuc2Zvcm0udW50cmFuc2Zvcm0odmFsdWUsIG1vZGVsLCBtb2RlbFByb3BOYW1lKVxyXG4gICAgOiB2YWx1ZVxyXG5cclxuICAvLyBhcHBseSBkZWZhdWx0IHZhbHVlIGlmIGFwcGxpY2FibGVcclxuICBpZiAodW50cmFuc2Zvcm1lZFZhbHVlID09IG51bGwpIHtcclxuICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IGdldE1vZGVsUHJvcERlZmF1bHRWYWx1ZShtb2RlbFByb3ApXHJcbiAgICBpZiAoZGVmYXVsdFZhbHVlICE9PSBub0RlZmF1bHRWYWx1ZSkge1xyXG4gICAgICB1bnRyYW5zZm9ybWVkVmFsdWUgPSBkZWZhdWx0VmFsdWVcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIG5vIG5lZWQgdG8gdXNlIHNldCBzaW5jZSB0aGVzZSB2YXJzIGFsd2F5cyBnZXQgb24gdGhlIGluaXRpYWwgJFxyXG4gIG1vZGVsLiRbbW9kZWxQcm9wTmFtZV0gPSB1bnRyYW5zZm9ybWVkVmFsdWVcclxufVxyXG5cclxuY29uc3QgaWRHZW5lcmF0b3IgPSAoKSA9PiBnZXRHbG9iYWxDb25maWcoKS5tb2RlbElkR2VuZXJhdG9yKClcclxuY29uc3QgdFByb3BGb3JJZCA9IHRQcm9wKHR5cGVzU3RyaW5nLCBpZEdlbmVyYXRvcilcclxudFByb3BGb3JJZC5faXNJZCA9IHRydWVcclxuY29uc3QgcHJvcEZvcklkID0gcHJvcChpZEdlbmVyYXRvcilcclxucHJvcEZvcklkLl9pc0lkID0gdHJ1ZVxyXG5cclxudHlwZSBGcm9tU25hcHNob3RQcm9jZXNzb3JGbiA9IChzbjogYW55KSA9PiBhbnlcclxudHlwZSBUb1NuYXBzaG90UHJvY2Vzc29yRm4gPSAoc246IGFueSwgaW5zdGFuY2U6IGFueSkgPT4gYW55XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gc2hhcmVkSW50ZXJuYWxNb2RlbDxcclxuICBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLFxyXG4gIFRCYXNlTW9kZWwgZXh0ZW5kcyBBbnlNb2RlbCB8IEFueURhdGFNb2RlbFxyXG4+KHtcclxuICBtb2RlbFByb3BzLFxyXG4gIGJhc2VNb2RlbCxcclxuICB0eXBlLFxyXG4gIHZhbHVlVHlwZSxcclxuICBmcm9tU25hcHNob3RQcm9jZXNzb3IsXHJcbiAgdG9TbmFwc2hvdFByb2Nlc3NvcixcclxufToge1xyXG4gIG1vZGVsUHJvcHM6IFRQcm9wc1xyXG4gIGJhc2VNb2RlbDogTW9kZWxDbGFzczxUQmFzZU1vZGVsPiB8IHVuZGVmaW5lZFxyXG4gIHR5cGU6IFwiY2xhc3NcIiB8IFwiZGF0YVwiXHJcbiAgdmFsdWVUeXBlOiBib29sZWFuXHJcbiAgZnJvbVNuYXBzaG90UHJvY2Vzc29yOiBGcm9tU25hcHNob3RQcm9jZXNzb3JGbiB8IHVuZGVmaW5lZFxyXG4gIHRvU25hcHNob3RQcm9jZXNzb3I6IFRvU25hcHNob3RQcm9jZXNzb3JGbiB8IHVuZGVmaW5lZFxyXG59KTogYW55IHtcclxuICBhc3NlcnRJc09iamVjdChtb2RlbFByb3BzLCBcIm1vZGVsUHJvcHNcIilcclxuXHJcbiAgLy8gbWFrZSBzdXJlIHdlIGF2b2lkIHByb3RvdHlwZSBwb2xsdXRpb25cclxuICBtb2RlbFByb3BzID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG51bGwpLCBtb2RlbFByb3BzKVxyXG5cclxuICBpZiAoYmFzZU1vZGVsKSB7XHJcbiAgICBhc3NlcnRJc0NsYXNzT3JEYXRhTW9kZWxDbGFzcyhiYXNlTW9kZWwsIFwiYmFzZU1vZGVsXCIpXHJcblxyXG4gICAgLy8gaWYgdGhlIGJhc2VNb2RlbCBpcyB3cmFwcGVkIHdpdGggdGhlIG1vZGVsIGRlY29yYXRvciBnZXQgdGhlIG9yaWdpbmFsIG9uZVxyXG4gICAgY29uc3QgdW53cmFwcGVkQ2xhc3MgPSAoYmFzZU1vZGVsIGFzIGFueSlbbW9kZWxVbndyYXBwZWRDbGFzc1N5bWJvbF1cclxuICAgIGlmICh1bndyYXBwZWRDbGFzcykge1xyXG4gICAgICBiYXNlTW9kZWwgPSB1bndyYXBwZWRDbGFzc1xyXG4gICAgICBhc3NlcnRJc0NsYXNzT3JEYXRhTW9kZWxDbGFzcyhiYXNlTW9kZWwsIFwiYmFzZU1vZGVsXCIpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb25zdCBjb21wb3NlZE1vZGVsUHJvcHM6IE1vZGVsUHJvcHMgPSBtb2RlbFByb3BzXHJcbiAgaWYgKGJhc2VNb2RlbCkge1xyXG4gICAgY29uc3Qgb2xkTW9kZWxQcm9wcyA9IGdldEludGVybmFsTW9kZWxDbGFzc1Byb3BzSW5mbyhiYXNlTW9kZWwpXHJcbiAgICBmb3IgKGNvbnN0IG9sZE1vZGVsUHJvcEtleSBvZiBPYmplY3Qua2V5cyhvbGRNb2RlbFByb3BzKSkge1xyXG4gICAgICBpZiAoIW1vZGVsUHJvcHNbb2xkTW9kZWxQcm9wS2V5XSkge1xyXG4gICAgICAgIGNvbXBvc2VkTW9kZWxQcm9wc1tvbGRNb2RlbFByb3BLZXldID0gb2xkTW9kZWxQcm9wc1tvbGRNb2RlbFByb3BLZXldXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIGxvb2sgZm9yIGlkIGtleXNcclxuICBjb25zdCBpZEtleXMgPSBPYmplY3Qua2V5cyhjb21wb3NlZE1vZGVsUHJvcHMpLmZpbHRlcigoaykgPT4ge1xyXG4gICAgY29uc3QgcCA9IGNvbXBvc2VkTW9kZWxQcm9wc1trXVxyXG4gICAgcmV0dXJuIHAuX2lzSWRcclxuICB9KVxyXG4gIGlmICh0eXBlID09PSBcImNsYXNzXCIpIHtcclxuICAgIGlmIChpZEtleXMubGVuZ3RoID4gMSkge1xyXG4gICAgICB0aHJvdyBmYWlsdXJlKGBleHBlY3RlZCBhdCBtb3N0IG9uZSBpZFByb3AgYnV0IGdvdCBtYW55OiAke0pTT04uc3RyaW5naWZ5KGlkS2V5cyl9YClcclxuICAgIH1cclxuICB9IGVsc2Uge1xyXG4gICAgaWYgKGlkS2V5cy5sZW5ndGggPj0gMSkge1xyXG4gICAgICB0aHJvdyBmYWlsdXJlKGBleHBlY3RlZCBubyBpZFByb3AgYnV0IGdvdCBzb21lOiAke0pTT04uc3RyaW5naWZ5KGlkS2V5cyl9YClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IG5lZWRzVHlwZUNoZWNrZXIgPSBPYmplY3QudmFsdWVzKGNvbXBvc2VkTW9kZWxQcm9wcykuc29tZSgobXApID0+ICEhbXAuX3R5cGVDaGVja2VyKVxyXG5cclxuICAvLyB0cmFuc2Zvcm0gaWQga2V5cyAob25seSBvbmUgcmVhbGx5KVxyXG4gIGxldCBpZEtleTogc3RyaW5nIHwgdW5kZWZpbmVkXHJcbiAgaWYgKGlkS2V5cy5sZW5ndGggPj0gMSkge1xyXG4gICAgaWRLZXkgPSBpZEtleXNbMF1cclxuICAgIGNvbnN0IGlkUHJvcCA9IGNvbXBvc2VkTW9kZWxQcm9wc1tpZEtleV1cclxuICAgIGxldCBiYXNlUHJvcDogQW55TW9kZWxQcm9wID0gbmVlZHNUeXBlQ2hlY2tlciA/IHRQcm9wRm9ySWQgOiBwcm9wRm9ySWRcclxuICAgIHN3aXRjaCAoaWRQcm9wPy5fc2V0dGVyKSB7XHJcbiAgICAgIGNhc2UgdHJ1ZTpcclxuICAgICAgICBiYXNlUHJvcCA9IGJhc2VQcm9wLndpdGhTZXR0ZXIoKVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgXCJhc3NpZ25cIjpcclxuICAgICAgICBiYXNlUHJvcCA9IGJhc2VQcm9wLndpdGhTZXR0ZXIoXCJhc3NpZ25cIilcclxuICAgICAgICBicmVha1xyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIGJyZWFrXHJcbiAgICB9XHJcbiAgICBjb21wb3NlZE1vZGVsUHJvcHNbaWRLZXldID0gYmFzZVByb3BcclxuICB9XHJcblxyXG4gIC8vIGNyZWF0ZSB0eXBlIGNoZWNrZXIgaWYgbmVlZGVkXHJcbiAgbGV0IGRhdGFUeXBlQ2hlY2tlcjogTGF0ZVR5cGVDaGVja2VyIHwgdW5kZWZpbmVkXHJcbiAgaWYgKG5lZWRzVHlwZUNoZWNrZXIpIHtcclxuICAgIGNvbnN0IHR5cGVDaGVja2VyT2JqOiB7XHJcbiAgICAgIFtrOiBzdHJpbmddOiBhbnlcclxuICAgIH0gPSB7fVxyXG4gICAgZm9yIChjb25zdCBbaywgbXBdIG9mIE9iamVjdC5lbnRyaWVzKGNvbXBvc2VkTW9kZWxQcm9wcykpIHtcclxuICAgICAgdHlwZUNoZWNrZXJPYmpba10gPSAhbXAuX3R5cGVDaGVja2VyID8gdHlwZXNVbmNoZWNrZWQoKSA6IG1wLl90eXBlQ2hlY2tlclxyXG4gICAgfVxyXG4gICAgZGF0YVR5cGVDaGVja2VyID0gdHlwZXNPYmplY3QoKCkgPT4gdHlwZUNoZWNrZXJPYmopIGFzIGFueVxyXG4gIH1cclxuXHJcbiAgY29uc3QgYmFzZTogYW55ID0gYmFzZU1vZGVsID8/ICh0eXBlID09PSBcImNsYXNzXCIgPyBCYXNlTW9kZWwgOiBCYXNlRGF0YU1vZGVsKVxyXG4gIGNvbnN0IGJhc2VQcm9wTmFtZXMgPSB0eXBlID09PSBcImNsYXNzXCIgPyBiYXNlTW9kZWxQcm9wTmFtZXMgOiBiYXNlRGF0YU1vZGVsUHJvcE5hbWVzXHJcblxyXG4gIGxldCBwcm9wc1RvRGVsZXRlRnJvbUJhc2U6IHN0cmluZ1tdIHwgdW5kZWZpbmVkXHJcblxyXG4gIC8vIHdlIHVzZSB0aGlzIHdlaXJkIGhhY2sgcmF0aGVyIHRoYW4ganVzdCBjbGFzcyBDdXN0b21CYXNlTW9kZWwgZXh0ZW5kcyBiYXNlIHt9XHJcbiAgLy8gaW4gb3JkZXIgdG8gd29yayBhcm91bmQgcHJvYmxlbXMgd2l0aCBFUzUgY2xhc3NlcyBleHRlbmRpbmcgRVM2IGNsYXNzZXNcclxuICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3hhdmllcmdvbnovbW9ieC1rZXlzdG9uZS9pc3N1ZXMvMTVcclxuICBmdW5jdGlvbiBUaGlzTW9kZWwoXHJcbiAgICB0aGlzOiBhbnksXHJcbiAgICBpbml0aWFsRGF0YTogYW55LFxyXG4gICAgY29uc3RydWN0b3JPcHRpb25zPzogTW9kZWxDb25zdHJ1Y3Rvck9wdGlvbnMgfCBEYXRhTW9kZWxDb25zdHJ1Y3Rvck9wdGlvbnNcclxuICApIHtcclxuICAgIGNvbnN0IG1vZGVsQ2xhc3MgPSBjb25zdHJ1Y3Rvck9wdGlvbnM/Lm1vZGVsQ2xhc3MgPz8gdGhpcy5jb25zdHJ1Y3RvclxyXG4gICAgY29uc3QgYmFzZU1vZGVsID0gbmV3IGJhc2UoaW5pdGlhbERhdGEsIHtcclxuICAgICAgLi4uY29uc3RydWN0b3JPcHRpb25zLFxyXG4gICAgICBtb2RlbENsYXNzLFxyXG4gICAgfSBhcyBNb2RlbENvbnN0cnVjdG9yT3B0aW9ucyAmIERhdGFNb2RlbENvbnN0cnVjdG9yT3B0aW9ucylcclxuXHJcbiAgICAvLyBtYWtlIHN1cmUgYWJzdHJhY3QgY2xhc3NlcyBkbyBub3Qgb3ZlcnJpZGUgcHJvdG90eXBlIHByb3BzXHJcbiAgICBpZiAoIXByb3BzVG9EZWxldGVGcm9tQmFzZSkge1xyXG4gICAgICBwcm9wc1RvRGVsZXRlRnJvbUJhc2UgPSBPYmplY3Qua2V5cyhjb21wb3NlZE1vZGVsUHJvcHMpLmZpbHRlcihcclxuICAgICAgICAocCkgPT4gIWJhc2VQcm9wTmFtZXMuaGFzKHAgYXMgYW55KSAmJiBPYmplY3QuaGFzT3duKGJhc2VNb2RlbCwgcClcclxuICAgICAgKVxyXG4gICAgfVxyXG5cclxuICAgIHByb3BzVG9EZWxldGVGcm9tQmFzZS5mb3JFYWNoKChwcm9wKSA9PiBkZWxldGUgYmFzZU1vZGVsW3Byb3BdKVxyXG5cclxuICAgIHJldHVybiBiYXNlTW9kZWxcclxuICB9XHJcblxyXG4gIC8vIGNvcHkgc3RhdGljIHByb3BzIGZyb20gYmFzZVxyXG4gIE9iamVjdC5hc3NpZ24oVGhpc01vZGVsLCBiYXNlKVxyXG5cclxuICBjb25zdCBpbml0aWFsaXplcnMgPSBiYXNlW21vZGVsSW5pdGlhbGl6ZXJzU3ltYm9sXVxyXG4gIGlmIChpbml0aWFsaXplcnMpIHtcclxuICAgIFRoaXNNb2RlbFttb2RlbEluaXRpYWxpemVyc1N5bWJvbF0gPSBpbml0aWFsaXplcnMuc2xpY2UoKVxyXG4gIH1cclxuXHJcbiAgc2V0SW50ZXJuYWxNb2RlbENsYXNzUHJvcHNJbmZvKFRoaXNNb2RlbCBhcyBhbnksIGNvbXBvc2VkTW9kZWxQcm9wcylcclxuXHJcbiAgaWYgKHR5cGUgPT09IFwiY2xhc3NcIikge1xyXG4gICAgY29uc3QgbWV0YWRhdGE6IE1vZGVsTWV0YWRhdGEgPSB7XHJcbiAgICAgIGRhdGFUeXBlOiBkYXRhVHlwZUNoZWNrZXIgYXMgdW5rbm93biBhcyBBbnlUeXBlIHwgdW5kZWZpbmVkLFxyXG4gICAgICBtb2RlbElkUHJvcGVydHk6IGlkS2V5LFxyXG4gICAgICB2YWx1ZVR5cGUsXHJcbiAgICB9XHJcbiAgICBUaGlzTW9kZWxbbW9kZWxNZXRhZGF0YVN5bWJvbF0gPSBtZXRhZGF0YVxyXG4gIH0gZWxzZSB7XHJcbiAgICBjb25zdCBtZXRhZGF0YTogRGF0YU1vZGVsTWV0YWRhdGEgPSB7XHJcbiAgICAgIGRhdGFUeXBlOiBkYXRhVHlwZUNoZWNrZXIgYXMgdW5rbm93biBhcyBBbnlUeXBlIHwgdW5kZWZpbmVkLFxyXG4gICAgfVxyXG4gICAgVGhpc01vZGVsW21vZGVsTWV0YWRhdGFTeW1ib2xdID0gbWV0YWRhdGFcclxuICB9XHJcblxyXG4gIGNvbnN0IG5ld1Byb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoYmFzZS5wcm90b3R5cGUpXHJcblxyXG4gIFRoaXNNb2RlbC5wcm90b3R5cGUgPSBuZXcgUHJveHkobmV3UHJvdG90eXBlLCB7XHJcbiAgICBnZXQodGFyZ2V0LCBwLCByZWNlaXZlcikge1xyXG4gICAgICBpZiAocmVjZWl2ZXIgPT09IFRoaXNNb2RlbC5wcm90b3R5cGUpIHtcclxuICAgICAgICByZXR1cm4gdGFyZ2V0W3BdXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IG1vZGVsUHJvcCA9ICFiYXNlUHJvcE5hbWVzLmhhcyhwIGFzIGFueSkgJiYgY29tcG9zZWRNb2RlbFByb3BzW3AgYXMgc3RyaW5nXVxyXG4gICAgICByZXR1cm4gbW9kZWxQcm9wXHJcbiAgICAgICAgPyBnZXRNb2RlbEluc3RhbmNlRGF0YUZpZWxkKHJlY2VpdmVyLCBtb2RlbFByb3AsIHAgYXMgc3RyaW5nKVxyXG4gICAgICAgIDogUmVmbGVjdC5nZXQodGFyZ2V0LCBwLCByZWNlaXZlcilcclxuICAgIH0sXHJcblxyXG4gICAgc2V0KHRhcmdldCwgcCwgdiwgcmVjZWl2ZXIpIHtcclxuICAgICAgaWYgKHJlY2VpdmVyID09PSBUaGlzTW9kZWwucHJvdG90eXBlKSB7XHJcbiAgICAgICAgdGFyZ2V0W3BdID0gdlxyXG4gICAgICAgIHJldHVybiB0cnVlXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IG1vZGVsUHJvcCA9ICFiYXNlUHJvcE5hbWVzLmhhcyhwIGFzIGFueSkgJiYgY29tcG9zZWRNb2RlbFByb3BzW3AgYXMgc3RyaW5nXVxyXG4gICAgICBpZiAobW9kZWxQcm9wKSB7XHJcbiAgICAgICAgc2V0TW9kZWxJbnN0YW5jZURhdGFGaWVsZChyZWNlaXZlciwgbW9kZWxQcm9wLCBwIGFzIHN0cmluZywgdilcclxuICAgICAgICByZXR1cm4gdHJ1ZVxyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBSZWZsZWN0LnNldCh0YXJnZXQsIHAsIHYsIHJlY2VpdmVyKVxyXG4gICAgfSxcclxuXHJcbiAgICBoYXModGFyZ2V0LCBwKSB7XHJcbiAgICAgIGNvbnN0IG1vZGVsUHJvcCA9ICFiYXNlUHJvcE5hbWVzLmhhcyhwIGFzIGFueSkgJiYgY29tcG9zZWRNb2RlbFByb3BzW3AgYXMgc3RyaW5nXVxyXG4gICAgICByZXR1cm4gISFtb2RlbFByb3AgfHwgUmVmbGVjdC5oYXModGFyZ2V0LCBwKVxyXG4gICAgfSxcclxuICB9KVxyXG5cclxuICBuZXdQcm90b3R5cGUuY29uc3RydWN0b3IgPSBUaGlzTW9kZWxcclxuXHJcbiAgLy8gYWRkIHNldHRlciBhY3Rpb25zIHRvIHByb3RvdHlwZVxyXG4gIGZvciAoY29uc3QgW3Byb3BOYW1lLCBwcm9wRGF0YV0gb2YgT2JqZWN0LmVudHJpZXMobW9kZWxQcm9wcykpIHtcclxuICAgIGlmIChwcm9wRGF0YS5fc2V0dGVyID09PSB0cnVlKSB7XHJcbiAgICAgIGNvbnN0IHNldHRlck5hbWUgPSBwcm9wTmFtZVRvU2V0dGVyTmFtZShwcm9wTmFtZSlcclxuXHJcbiAgICAgIGNvbnN0IG5ld1Byb3BEZXNjcmlwdG9yOiBhbnkgPSBtb2RlbEFjdGlvbihuZXdQcm90b3R5cGUsIHNldHRlck5hbWUsIHtcclxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gKHRoaXM6IGFueSwgdmFsdWU6IGFueSkge1xyXG4gICAgICAgICAgdGhpc1twcm9wTmFtZV0gPSB2YWx1ZVxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXHJcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXHJcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxyXG4gICAgICB9KVxyXG5cclxuICAgICAgLy8gd2UgdXNlIGRlZmluZSBwcm9wZXJ0eSB0byBhdm9pZCB0aGUgYmFzZSBwcm94eVxyXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobmV3UHJvdG90eXBlLCBzZXR0ZXJOYW1lLCBuZXdQcm9wRGVzY3JpcHRvcilcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IG1vZGVsUHJvcHNGcm9tU25hcHNob3RQcm9jZXNzb3IgPSBnZXRNb2RlbFByb3BzRnJvbVNuYXBzaG90UHJvY2Vzc29yKGNvbXBvc2VkTW9kZWxQcm9wcylcclxuXHJcbiAgY29uc3QgbW9kZWxQcm9wc1RvU25hcHNob3RQcm9jZXNzb3IgPSBnZXRNb2RlbFByb3BzVG9TbmFwc2hvdFByb2Nlc3Nvcihjb21wb3NlZE1vZGVsUHJvcHMpXHJcblxyXG4gIGlmIChmcm9tU25hcHNob3RQcm9jZXNzb3IpIHtcclxuICAgIGNvbnN0IGZuID0gZnJvbVNuYXBzaG90UHJvY2Vzc29yXHJcbiAgICBmcm9tU25hcHNob3RQcm9jZXNzb3IgPSAoc24pID0+IHtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICAuLi5mbihzbiksXHJcbiAgICAgICAgW21vZGVsVHlwZUtleV06IHNuW21vZGVsVHlwZUtleV0sXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlmICh0b1NuYXBzaG90UHJvY2Vzc29yKSB7XHJcbiAgICBjb25zdCBmbiA9IHRvU25hcHNob3RQcm9jZXNzb3JcclxuICAgIHRvU25hcHNob3RQcm9jZXNzb3IgPSAoc24sIG1vZGVsSW5zdGFuY2UpID0+IHtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICAuLi5mbihzbiwgbW9kZWxJbnN0YW5jZSksXHJcbiAgICAgICAgW21vZGVsVHlwZUtleV06IHNuW21vZGVsVHlwZUtleV0sXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIFRoaXNNb2RlbC5mcm9tU25hcHNob3RQcm9jZXNzb3IgPSBjaGFpbkZucyhmcm9tU25hcHNob3RQcm9jZXNzb3IsIG1vZGVsUHJvcHNGcm9tU25hcHNob3RQcm9jZXNzb3IpXHJcbiAgVGhpc01vZGVsLnRvU25hcHNob3RQcm9jZXNzb3IgPSBjaGFpbkZucyhtb2RlbFByb3BzVG9TbmFwc2hvdFByb2Nlc3NvciwgdG9TbmFwc2hvdFByb2Nlc3NvcilcclxuXHJcbiAgcmV0dXJuIFRoaXNNb2RlbFxyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRNb2RlbFByb3BzRnJvbVNuYXBzaG90UHJvY2Vzc29yKFxyXG4gIGNvbXBvc2VkTW9kZWxQcm9wczogTW9kZWxQcm9wc1xyXG4pOiBGcm9tU25hcHNob3RQcm9jZXNzb3JGbiB8IHVuZGVmaW5lZCB7XHJcbiAgY29uc3QgcHJvcHNXaXRoRnJvbVNuYXBzaG90UHJvY2Vzc29yID0gT2JqZWN0LmVudHJpZXMoY29tcG9zZWRNb2RlbFByb3BzKS5maWx0ZXIoXHJcbiAgICAoW19wcm9wTmFtZSwgcHJvcERhdGFdKSA9PiBwcm9wRGF0YS5fZnJvbVNuYXBzaG90UHJvY2Vzc29yXHJcbiAgKVxyXG4gIGlmIChwcm9wc1dpdGhGcm9tU25hcHNob3RQcm9jZXNzb3IubGVuZ3RoIDw9IDApIHtcclxuICAgIHJldHVybiB1bmRlZmluZWRcclxuICB9XHJcblxyXG4gIHJldHVybiAoc24pID0+IHtcclxuICAgIGNvbnN0IG5ld1NuID0geyAuLi5zbiB9XHJcbiAgICBmb3IgKGNvbnN0IFtwcm9wTmFtZSwgcHJvcERhdGFdIG9mIHByb3BzV2l0aEZyb21TbmFwc2hvdFByb2Nlc3Nvcikge1xyXG4gICAgICBpZiAocHJvcERhdGEuX2Zyb21TbmFwc2hvdFByb2Nlc3Nvcikge1xyXG4gICAgICAgIG5ld1NuW3Byb3BOYW1lXSA9IHByb3BEYXRhLl9mcm9tU25hcHNob3RQcm9jZXNzb3Ioc25bcHJvcE5hbWVdKVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbmV3U25cclxuICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldE1vZGVsUHJvcHNUb1NuYXBzaG90UHJvY2Vzc29yKFxyXG4gIGNvbXBvc2VkTW9kZWxQcm9wczogTW9kZWxQcm9wc1xyXG4pOiBUb1NuYXBzaG90UHJvY2Vzc29yRm4gfCB1bmRlZmluZWQge1xyXG4gIGNvbnN0IHByb3BzV2l0aFRvU25hcHNob3RQcm9jZXNzb3IgPSBPYmplY3QuZW50cmllcyhjb21wb3NlZE1vZGVsUHJvcHMpLmZpbHRlcihcclxuICAgIChbX3Byb3BOYW1lLCBwcm9wRGF0YV0pID0+IHByb3BEYXRhLl90b1NuYXBzaG90UHJvY2Vzc29yXHJcbiAgKVxyXG5cclxuICBpZiAocHJvcHNXaXRoVG9TbmFwc2hvdFByb2Nlc3Nvci5sZW5ndGggPD0gMCkge1xyXG4gICAgcmV0dXJuIHVuZGVmaW5lZFxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIChzbikgPT4ge1xyXG4gICAgY29uc3QgbmV3U24gPSB7IC4uLnNuIH1cclxuICAgIGZvciAoY29uc3QgW3Byb3BOYW1lLCBwcm9wRGF0YV0gb2YgcHJvcHNXaXRoVG9TbmFwc2hvdFByb2Nlc3Nvcikge1xyXG4gICAgICBpZiAocHJvcERhdGEuX3RvU25hcHNob3RQcm9jZXNzb3IpIHtcclxuICAgICAgICBuZXdTbltwcm9wTmFtZV0gPSBwcm9wRGF0YS5fdG9TbmFwc2hvdFByb2Nlc3Nvcihzbltwcm9wTmFtZV0pXHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBuZXdTblxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgdHlwZSB7XHJcbiAgQWJzdHJhY3RNb2RlbENsYXNzLFxyXG4gIE1vZGVsQ2xhc3MsXHJcbiAgTW9kZWxDcmVhdGlvbkRhdGEsXHJcbn0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL0Jhc2VNb2RlbFNoYXJlZFwiXHJcbmltcG9ydCB0eXBlIHtcclxuICBNb2RlbFByb3BzLFxyXG4gIE1vZGVsUHJvcHNUb1NldHRlcixcclxuICBNb2RlbFByb3BzVG9TbmFwc2hvdENyZWF0aW9uRGF0YSxcclxuICBNb2RlbFByb3BzVG9TbmFwc2hvdERhdGEsXHJcbiAgTW9kZWxQcm9wc1RvVHJhbnNmb3JtZWRDcmVhdGlvbkRhdGEsXHJcbiAgTW9kZWxQcm9wc1RvVHJhbnNmb3JtZWREYXRhLFxyXG59IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9wcm9wXCJcclxuaW1wb3J0IHsgc2hhcmVkSW50ZXJuYWxNb2RlbCB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9zaGFyZWRJbnRlcm5hbE1vZGVsXCJcclxuaW1wb3J0IHR5cGUgeyBBbnlNb2RlbCwgQmFzZU1vZGVsLCBCYXNlTW9kZWxLZXlzLCBNb2RlbElkUHJvcGVydHlOYW1lIH0gZnJvbSBcIi4vQmFzZU1vZGVsXCJcclxuaW1wb3J0IHsgYXNzZXJ0SXNNb2RlbENsYXNzLCBpc01vZGVsQ2xhc3MgfSBmcm9tIFwiLi91dGlsc1wiXHJcblxyXG5leHBvcnQgdHlwZSBfQ29tcG9zZWRDcmVhdGlvbkRhdGE8XHJcbiAgU3VwZXJNb2RlbCxcclxuICBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzXHJcbj4gPSBTdXBlck1vZGVsIGV4dGVuZHMgQW55TW9kZWxcclxuICA/IE1vZGVsUHJvcHNUb1RyYW5zZm9ybWVkQ3JlYXRpb25EYXRhPFRQcm9wcz4gJiBNb2RlbENyZWF0aW9uRGF0YTxTdXBlck1vZGVsPlxyXG4gIDogTW9kZWxQcm9wc1RvVHJhbnNmb3JtZWRDcmVhdGlvbkRhdGE8VFByb3BzPlxyXG5cclxuLyoqXHJcbiAqIFRoZSBkZWZhdWx0IHR5cGUgdXNlZCBieSBmcm9tU25hcHNob3QgYmVmb3JlIHByb2Nlc3NvcnMgYXJlIGFwcGxpZWQuXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBGcm9tU25hcHNob3REZWZhdWx0VHlwZTxUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzPiA9XHJcbiAgTW9kZWxQcm9wc1RvU25hcHNob3RDcmVhdGlvbkRhdGE8VFByb3BzPlxyXG5cclxuLyoqXHJcbiAqIFRoZSBkZWZhdWx0IHR5cGUgdXNlZCBieSBnZXRTbmFwc2hvdCBiZWZvcmUgcHJvY2Vzc29ycyBhcmUgYXBwbGllZC5cclxuICovXHJcbmV4cG9ydCB0eXBlIFRvU25hcHNob3REZWZhdWx0VHlwZTxUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzPiA9IE1vZGVsUHJvcHNUb1NuYXBzaG90RGF0YTxUUHJvcHM+XHJcblxyXG5leHBvcnQgdHlwZSBfTW9kZWxJZDxTdXBlck1vZGVsLCBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzPiA9IFN1cGVyTW9kZWwgZXh0ZW5kcyBBbnlNb2RlbFxyXG4gID8gTW9kZWxJZFByb3BlcnR5TmFtZTxTdXBlck1vZGVsPlxyXG4gIDogRXh0cmFjdE1vZGVsSWRQcm9wPFRQcm9wcz4gJiBzdHJpbmdcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgX01vZGVsPFxyXG4gIFN1cGVyTW9kZWwsXHJcbiAgVFByb3BzIGV4dGVuZHMgTW9kZWxQcm9wcyxcclxuICBGcm9tU25hcHNob3RPdmVycmlkZSBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4sXHJcbiAgVG9TbmFwc2hvdE92ZXJyaWRlIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PlxyXG4+IHtcclxuICBuZXcgKGRhdGE6IF9Db21wb3NlZENyZWF0aW9uRGF0YTxTdXBlck1vZGVsLCBUUHJvcHM+KTogU3VwZXJNb2RlbCAmXHJcbiAgICBCYXNlTW9kZWw8VFByb3BzLCBGcm9tU25hcHNob3RPdmVycmlkZSwgVG9TbmFwc2hvdE92ZXJyaWRlLCBfTW9kZWxJZDxTdXBlck1vZGVsLCBUUHJvcHM+PiAmXHJcbiAgICBPbWl0PE1vZGVsUHJvcHNUb1RyYW5zZm9ybWVkRGF0YTxUUHJvcHM+LCBCYXNlTW9kZWxLZXlzPiAmXHJcbiAgICBNb2RlbFByb3BzVG9TZXR0ZXI8VFByb3BzPlxyXG59XHJcblxyXG4vKipcclxuICogRXh0cmFjdCB0aGUgbW9kZWwgaWQgcHJvcGVydHkgZnJvbSB0aGUgbW9kZWwgcHJvcHMuXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBFeHRyYWN0TW9kZWxJZFByb3A8VFByb3BzIGV4dGVuZHMgTW9kZWxQcm9wcz4gPSB7XHJcbiAgW0sgaW4ga2V5b2YgVFByb3BzXTogVFByb3BzW0tdW1wiJGlzSWRcIl0gZXh0ZW5kcyB0cnVlID8gSyA6IG5ldmVyXHJcbn1ba2V5b2YgVFByb3BzXVxyXG5cclxuLyoqXHJcbiAqIEJhc2UgYWJzdHJhY3QgY2xhc3MgZm9yIG1vZGVscyB0aGF0IGV4dGVuZHMgYW5vdGhlciBtb2RlbC5cclxuICpcclxuICogQHR5cGVwYXJhbSBUUHJvcHMgTmV3IG1vZGVsIHByb3BlcnRpZXMgdHlwZS5cclxuICogQHR5cGVwYXJhbSBUTW9kZWxDbGFzcyBNb2RlbCBjbGFzcyB0eXBlLlxyXG4gKiBAcGFyYW0gZ2VuRm4gRnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBiYXNlIG1vZGVsIGFuZCBtb2RlbCBwcm9wZXJ0aWVzLlxyXG4gKiBAcGFyYW0gbW9kZWxPcHRpb25zIE1vZGVsIG9wdGlvbnMuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXh0ZW5kZWRNb2RlbDxcclxuICBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLFxyXG4gIFRNb2RlbENsYXNzIGV4dGVuZHMgQWJzdHJhY3RNb2RlbENsYXNzPEFueU1vZGVsPixcclxuICBBIGV4dGVuZHMgW10sXHJcbiAgRlMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbmV2ZXIsXHJcbiAgVFMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbmV2ZXJcclxuPihcclxuICBnZW5GbjogKC4uLmFyZ3M6IEEpID0+IHtcclxuICAgIGJhc2VNb2RlbDogVE1vZGVsQ2xhc3NcclxuICAgIHByb3BzOiBUUHJvcHNcclxuICB9LFxyXG4gIG1vZGVsT3B0aW9ucz86IE1vZGVsT3B0aW9uczxUUHJvcHMsIEZTLCBUUz5cclxuKTogX01vZGVsPEluc3RhbmNlVHlwZTxUTW9kZWxDbGFzcz4sIFRQcm9wcywgRlMsIFRTPlxyXG5cclxuLyoqXHJcbiAqIEJhc2UgYWJzdHJhY3QgY2xhc3MgZm9yIG1vZGVscyB0aGF0IGV4dGVuZHMgYW5vdGhlciBtb2RlbC5cclxuICpcclxuICogQHR5cGVwYXJhbSBUUHJvcHMgTmV3IG1vZGVsIHByb3BlcnRpZXMgdHlwZS5cclxuICogQHR5cGVwYXJhbSBUTW9kZWxDbGFzcyBNb2RlbCBjbGFzcyB0eXBlLlxyXG4gKiBAcGFyYW0gYmFzZU1vZGVsIEJhc2UgbW9kZWwgdHlwZS5cclxuICogQHBhcmFtIG1vZGVsUHJvcHMgTW9kZWwgcHJvcGVydGllcy5cclxuICogQHBhcmFtIG1vZGVsT3B0aW9ucyBNb2RlbCBvcHRpb25zLlxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEV4dGVuZGVkTW9kZWw8XHJcbiAgVFByb3BzIGV4dGVuZHMgTW9kZWxQcm9wcyxcclxuICBUTW9kZWxDbGFzcyBleHRlbmRzIEFic3RyYWN0TW9kZWxDbGFzczxBbnlNb2RlbD4sXHJcbiAgRlMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbmV2ZXIsXHJcbiAgVFMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbmV2ZXJcclxuPihcclxuICBiYXNlTW9kZWw6IFRNb2RlbENsYXNzLFxyXG4gIG1vZGVsUHJvcHM6IFRQcm9wcyxcclxuICBtb2RlbE9wdGlvbnM/OiBNb2RlbE9wdGlvbnM8VFByb3BzLCBGUywgVFM+XHJcbik6IF9Nb2RlbDxJbnN0YW5jZVR5cGU8VE1vZGVsQ2xhc3M+LCBUUHJvcHMsIEZTLCBUUz4gJiBPbWl0PFRNb2RlbENsYXNzLCBcInByb3RvdHlwZVwiPlxyXG5cclxuLy8gYmFzZVxyXG5leHBvcnQgZnVuY3Rpb24gRXh0ZW5kZWRNb2RlbDxcclxuICBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLFxyXG4gIFRNb2RlbENsYXNzIGV4dGVuZHMgQWJzdHJhY3RNb2RlbENsYXNzPEFueU1vZGVsPixcclxuICBGUyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBuZXZlcixcclxuICBUUyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBuZXZlclxyXG4+KC4uLmFyZ3M6IGFueVtdKTogX01vZGVsPEluc3RhbmNlVHlwZTxUTW9kZWxDbGFzcz4sIFRQcm9wcywgRlMsIFRTPiB7XHJcbiAgbGV0IGJhc2VNb2RlbFxyXG4gIGxldCBtb2RlbFByb3BzXHJcbiAgbGV0IG1vZGVsT3B0aW9uc1xyXG4gIGlmIChpc01vZGVsQ2xhc3MoYXJnc1swXSkpIHtcclxuICAgIGJhc2VNb2RlbCA9IGFyZ3NbMF1cclxuICAgIG1vZGVsUHJvcHMgPSBhcmdzWzFdXHJcbiAgICBtb2RlbE9wdGlvbnMgPSBhcmdzWzJdXHJcbiAgfSBlbHNlIHtcclxuICAgIGNvbnN0IGdlbiA9IGFyZ3NbMF0oKVxyXG5cclxuICAgIGJhc2VNb2RlbCA9IGdlbi5iYXNlTW9kZWxcclxuICAgIG1vZGVsUHJvcHMgPSBnZW4ucHJvcHNcclxuICAgIG1vZGVsT3B0aW9ucyA9IGFyZ3NbMV1cclxuICB9XHJcblxyXG4gIGFzc2VydElzTW9kZWxDbGFzcyhiYXNlTW9kZWwsIFwiYmFzZU1vZGVsXCIpXHJcblxyXG4gIHJldHVybiBpbnRlcm5hbE1vZGVsKG1vZGVsUHJvcHMsIGJhc2VNb2RlbCBhcyBhbnksIG1vZGVsT3B0aW9ucylcclxufVxyXG5cclxuLyoqXHJcbiAqIEJhc2UgYWJzdHJhY3QgY2xhc3MgZm9yIG1vZGVscy5cclxuICpcclxuICogTmV2ZXIgb3ZlcnJpZGUgdGhlIGNvbnN0cnVjdG9yLCB1c2UgYG9uSW5pdGAgb3IgYG9uQXR0YWNoZWRUb1Jvb3RTdG9yZWAgaW5zdGVhZC5cclxuICpcclxuICogQHR5cGVwYXJhbSBUUHJvcHMgTW9kZWwgcHJvcGVydGllcyB0eXBlLlxyXG4gKiBAcGFyYW0gZm5Nb2RlbFByb3BzIEZ1bmN0aW9uIHRoYXQgZ2VuZXJhdGVzIG1vZGVsIHByb3BlcnRpZXMuXHJcbiAqIEBwYXJhbSBtb2RlbE9wdGlvbnMgTW9kZWwgb3B0aW9ucy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBNb2RlbDxcclxuICBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLFxyXG4gIEEgZXh0ZW5kcyBbXSxcclxuICBGUyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBuZXZlcixcclxuICBUUyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBuZXZlclxyXG4+KFxyXG4gIGZuTW9kZWxQcm9wczogKC4uLmFyZ3M6IEEpID0+IFRQcm9wcyxcclxuICBtb2RlbE9wdGlvbnM/OiBNb2RlbE9wdGlvbnM8VFByb3BzLCBGUywgVFM+XHJcbik6IF9Nb2RlbDx1bmtub3duLCBUUHJvcHMsIEZTLCBUUz5cclxuXHJcbi8qKlxyXG4gKiBCYXNlIGFic3RyYWN0IGNsYXNzIGZvciBtb2RlbHMuXHJcbiAqXHJcbiAqIE5ldmVyIG92ZXJyaWRlIHRoZSBjb25zdHJ1Y3RvciwgdXNlIGBvbkluaXRgIG9yIGBvbkF0dGFjaGVkVG9Sb290U3RvcmVgIGluc3RlYWQuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVFByb3BzIE1vZGVsIHByb3BlcnRpZXMgdHlwZS5cclxuICogQHBhcmFtIG1vZGVsUHJvcHMgTW9kZWwgcHJvcGVydGllcy5cclxuICogQHBhcmFtIG1vZGVsT3B0aW9ucyBNb2RlbCBvcHRpb25zLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIE1vZGVsPFxyXG4gIFRQcm9wcyBleHRlbmRzIE1vZGVsUHJvcHMsXHJcbiAgRlMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbmV2ZXIsXHJcbiAgVFMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbmV2ZXJcclxuPihtb2RlbFByb3BzOiBUUHJvcHMsIG1vZGVsT3B0aW9ucz86IE1vZGVsT3B0aW9uczxUUHJvcHMsIEZTLCBUUz4pOiBfTW9kZWw8dW5rbm93biwgVFByb3BzLCBGUywgVFM+XHJcblxyXG4vLyBiYXNlXHJcbmV4cG9ydCBmdW5jdGlvbiBNb2RlbDxcclxuICBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLFxyXG4gIEZTIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IG5ldmVyLFxyXG4gIFRTIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IG5ldmVyXHJcbj4oXHJcbiAgZm5Nb2RlbFByb3BzT3JNb2RlbFByb3BzOiAoKCkgPT4gVFByb3BzKSB8IFRQcm9wcyxcclxuICBtb2RlbE9wdGlvbnM/OiBNb2RlbE9wdGlvbnM8VFByb3BzLCBGUywgVFM+XHJcbik6IF9Nb2RlbDx1bmtub3duLCBUUHJvcHMsIEZTLCBUUz4ge1xyXG4gIGNvbnN0IG1vZGVsUHJvcHMgPVxyXG4gICAgdHlwZW9mIGZuTW9kZWxQcm9wc09yTW9kZWxQcm9wcyA9PT0gXCJmdW5jdGlvblwiXHJcbiAgICAgID8gZm5Nb2RlbFByb3BzT3JNb2RlbFByb3BzKClcclxuICAgICAgOiBmbk1vZGVsUHJvcHNPck1vZGVsUHJvcHNcclxuICByZXR1cm4gaW50ZXJuYWxNb2RlbChtb2RlbFByb3BzLCB1bmRlZmluZWQsIG1vZGVsT3B0aW9ucylcclxufVxyXG5cclxuZnVuY3Rpb24gaW50ZXJuYWxNb2RlbDxcclxuICBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLFxyXG4gIFRCYXNlTW9kZWwgZXh0ZW5kcyBBbnlNb2RlbCxcclxuICBGUyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBuZXZlcixcclxuICBUUyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBuZXZlclxyXG4+KFxyXG4gIG1vZGVsUHJvcHM6IFRQcm9wcyxcclxuICBiYXNlTW9kZWw6IE1vZGVsQ2xhc3M8VEJhc2VNb2RlbD4gfCB1bmRlZmluZWQsXHJcbiAgbW9kZWxPcHRpb25zPzogTW9kZWxPcHRpb25zPFRQcm9wcywgRlMsIFRTPlxyXG4pOiBfTW9kZWw8VEJhc2VNb2RlbCwgVFByb3BzLCBGUywgVFM+IHtcclxuICByZXR1cm4gc2hhcmVkSW50ZXJuYWxNb2RlbCh7XHJcbiAgICBtb2RlbFByb3BzLFxyXG4gICAgYmFzZU1vZGVsLFxyXG4gICAgdHlwZTogXCJjbGFzc1wiLFxyXG4gICAgdmFsdWVUeXBlOiBtb2RlbE9wdGlvbnM/LnZhbHVlVHlwZSA/PyBmYWxzZSxcclxuICAgIGZyb21TbmFwc2hvdFByb2Nlc3NvcjogbW9kZWxPcHRpb25zPy5mcm9tU25hcHNob3RQcm9jZXNzb3IsXHJcbiAgICB0b1NuYXBzaG90UHJvY2Vzc29yOiBtb2RlbE9wdGlvbnM/LnRvU25hcHNob3RQcm9jZXNzb3IsXHJcbiAgfSlcclxufVxyXG5cclxuLyoqXHJcbiAqIE1vZGVsIG9wdGlvbnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIE1vZGVsT3B0aW9uczxUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLCBGUywgVFM+IHtcclxuICAvKipcclxuICAgKiBBIHZhbHVlIHR5cGUgd2lsbCBiZSBjbG9uZWQgYXV0b21hdGljYWxseSB3aGVuIGJlaW5nIGF0dGFjaGVkIHRvIGEgbmV3IHRyZWUuXHJcbiAgICogVGhlIGRlZmF1bHQgaXMgYGZhbHNlYC5cclxuICAgKi9cclxuICB2YWx1ZVR5cGU/OiBib29sZWFuXHJcblxyXG4gIC8qKlxyXG4gICAqIE9wdGlvbmFsIHRyYW5zZm9ybWF0aW9uIHRoYXQgd2lsbCBiZSBydW4gd2hlbiBjb252ZXJ0aW5nIGZyb20gYSBzbmFwc2hvdCB0byB0aGUgZGF0YSBwYXJ0IG9mIHRoZSBtb2RlbC5cclxuICAgKiBVc2VmdWwgZm9yIGV4YW1wbGUgdG8gZG8gdmVyc2lvbmluZyBhbmQga2VlcCB0aGUgZGF0YSBwYXJ0IHVwIHRvIGRhdGUgd2l0aCB0aGUgbGF0ZXN0IHZlcnNpb24gb2YgdGhlIG1vZGVsLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHNuIFRoZSBjdXN0b20gaW5wdXQgc25hcHNob3QuXHJcbiAgICogQHJldHVybnMgQW4gaW5wdXQgc25hcHNob3QgdGhhdCBtdXN0IG1hdGNoIHRoZSBleHBlY3RlZCBtb2RlbCBpbnB1dCBzbmFwc2hvdC5cclxuICAgKi9cclxuICBmcm9tU25hcHNob3RQcm9jZXNzb3I/KHNuOiBGUyk6IEZyb21TbmFwc2hvdERlZmF1bHRUeXBlPFRQcm9wcz5cclxuXHJcbiAgLyoqXHJcbiAgICogT3B0aW9uYWwgdHJhbnNmb3JtYXRpb24gdGhhdCB3aWxsIGJlIHJ1biB3aGVuIGNvbnZlcnRpbmcgdGhlIGRhdGEgcGFydCBvZiB0aGUgbW9kZWwgaW50byBhIHNuYXBzaG90LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHNuIFRoZSBvdXRwdXQgc25hcHNob3QuXHJcbiAgICogQHBhcmFtIG1vZGVsSW5zdGFuY2UgVGhlIG1vZGVsIGluc3RhbmNlLlxyXG4gICAqIEByZXR1cm5zICBhIGN1c3RvbSBvdXRwdXQgc25hcHNob3QuXHJcbiAgICovXHJcbiAgdG9TbmFwc2hvdFByb2Nlc3Nvcj8oc246IFRvU25hcHNob3REZWZhdWx0VHlwZTxUUHJvcHM+LCBtb2RlbEluc3RhbmNlOiBhbnkpOiBUU1xyXG59XHJcbiIsImltcG9ydCB7IEhvb2tBY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9uL2hvb2tBY3Rpb25zXCJcbmltcG9ydCB7IHdyYXBNb2RlbE1ldGhvZEluQWN0aW9uSWZOZWVkZWQgfSBmcm9tIFwiLi4vYWN0aW9uL3dyYXBJbkFjdGlvblwiXG5pbXBvcnQgdHlwZSB7IEFueURhdGFNb2RlbCB9IGZyb20gXCIuLi9kYXRhTW9kZWwvQmFzZURhdGFNb2RlbFwiXG5pbXBvcnQgeyBpc0RhdGFNb2RlbENsYXNzIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC91dGlsc1wiXG5pbXBvcnQgeyBnZXRHbG9iYWxDb25maWcgfSBmcm9tIFwiLi4vZ2xvYmFsQ29uZmlnXCJcbmltcG9ydCB0eXBlIHsgQW55TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQmFzZU1vZGVsXCJcbmltcG9ydCB7IG1vZGVsVHlwZUtleSB9IGZyb20gXCIuLi9tb2RlbC9tZXRhZGF0YVwiXG5pbXBvcnQgeyBpc01vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWwvdXRpbHNcIlxuaW1wb3J0IHsgTW9kZWxDbGFzcywgbW9kZWxJbml0aWFsaXplZFN5bWJvbCB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9CYXNlTW9kZWxTaGFyZWRcIlxuaW1wb3J0IHsgbW9kZWxJbmZvQnlDbGFzcywgbW9kZWxJbmZvQnlOYW1lIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL21vZGVsSW5mb1wiXG5pbXBvcnQge1xuICBtb2RlbFVud3JhcHBlZENsYXNzU3ltYm9sLFxuICBydW5BZnRlck1vZGVsRGVjb3JhdG9yU3ltYm9sLFxufSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxTeW1ib2xzXCJcbmltcG9ydCB7XG4gIGFkZEhpZGRlblByb3AsXG4gIGZhaWx1cmUsXG4gIGdldE1vYnhWZXJzaW9uLFxuICBsb2dXYXJuaW5nLFxuICBtb2J4NixcbiAgcnVuQWZ0ZXJOZXdTeW1ib2wsXG4gIHJ1bkJlZm9yZU9uSW5pdFN5bWJvbCxcbiAgcnVuTGF0ZUluaXRpYWxpemF0aW9uRnVuY3Rpb25zLFxufSBmcm9tIFwiLi4vdXRpbHNcIlxuXG4vKipcbiAqIERlY29yYXRvciB0aGF0IG1hcmtzIHRoaXMgY2xhc3MgKHdoaWNoIE1VU1QgaW5oZXJpdCBmcm9tIHRoZSBgTW9kZWxgIG9yIGBEYXRhTW9kZWxgIGFic3RyYWN0IGNsYXNzZXMpXG4gKiBhcyBhIG1vZGVsLlxuICpcbiAqIEBwYXJhbSBuYW1lIFVuaXF1ZSBuYW1lIGZvciB0aGUgbW9kZWwgdHlwZS4gTm90ZSB0aGF0IHRoaXMgbmFtZSBtdXN0IGJlIHVuaXF1ZSBmb3IgeW91ciB3aG9sZVxuICogYXBwbGljYXRpb24sIHNvIGl0IGlzIHVzdWFsbHkgYSBnb29kIGlkZWEgdG8gdXNlIHNvbWUgcHJlZml4IHVuaXF1ZSB0byB5b3VyIGFwcGxpY2F0aW9uIGRvbWFpbi5cbiAqL1xuZXhwb3J0IGNvbnN0IG1vZGVsID1cbiAgKG5hbWU6IHN0cmluZykgPT5cbiAgPE1DIGV4dGVuZHMgTW9kZWxDbGFzczxBbnlNb2RlbCB8IEFueURhdGFNb2RlbD4+KGNsYXp6OiBNQywgLi4uYXJnczogYW55W10pOiBNQyA9PiB7XG4gICAgY29uc3QgY3R4ID0gdHlwZW9mIGFyZ3NbMV0gPT09IFwib2JqZWN0XCIgPyAoYXJnc1sxXSBhcyBDbGFzc0RlY29yYXRvckNvbnRleHQpIDogdW5kZWZpbmVkXG5cbiAgICByZXR1cm4gaW50ZXJuYWxNb2RlbChuYW1lLCBjbGF6eiwgY3R4Py5hZGRJbml0aWFsaXplcikgYXMgYW55XG4gIH1cblxuY29uc3QgYWZ0ZXJDbGFzc0luaXRpYWxpemF0aW9uRGF0YSA9IG5ldyBXZWFrTWFwPFxuICBNb2RlbENsYXNzPEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPixcbiAge1xuICAgIG1ha2VPYnNlcnZhYmxlRmFpbGVkOiBib29sZWFuXG4gICAgdHlwZTogXCJjbGFzc1wiIHwgXCJkYXRhXCJcbiAgfVxuPigpXG5cbmNvbnN0IHJ1bkFmdGVyQ2xhc3NJbml0aWFsaXphdGlvbiA9IChcbiAgdGFyZ2V0OiBNb2RlbENsYXNzPEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPixcbiAgaW5zdGFuY2U6IGFueVxuKSA9PiB7XG4gIHJ1bkxhdGVJbml0aWFsaXphdGlvbkZ1bmN0aW9ucyhpbnN0YW5jZSwgcnVuQWZ0ZXJOZXdTeW1ib2wpXG5cbiAgLy8gY29tcGF0aWJpbGl0eSB3aXRoIG1vYnggNlxuICBjb25zdCB0YWcgPSBhZnRlckNsYXNzSW5pdGlhbGl6YXRpb25EYXRhLmdldCh0YXJnZXQpIVxuICBpZiAoIXRhZy5tYWtlT2JzZXJ2YWJsZUZhaWxlZCAmJiBnZXRNb2J4VmVyc2lvbigpID49IDYpIHtcbiAgICB0cnkge1xuICAgICAgbW9ieDYubWFrZU9ic2VydmFibGUoaW5zdGFuY2UpXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gc2FkbHkgd2UgbmVlZCB0byB1c2UgdGhpcyBoYWNrIHNpbmNlIHRoZSBQUiB0byBkbyB0aGlzIHRoZSBwcm9wZXIgd2F5XG4gICAgICAvLyB3YXMgcmVqZWN0ZWQgb24gdGhlIG1vYnggc2lkZVxuICAgICAgdGFnLm1ha2VPYnNlcnZhYmxlRmFpbGVkID0gdHJ1ZVxuXG4gICAgICBjb25zdCBlcnIgPSBlIGFzIEVycm9yXG4gICAgICBpZiAoXG4gICAgICAgIGVyci5tZXNzYWdlICE9PVxuICAgICAgICAgIFwiW01vYlhdIE5vIGFubm90YXRpb25zIHdlcmUgcGFzc2VkIHRvIG1ha2VPYnNlcnZhYmxlLCBidXQgbm8gZGVjb3JhdG9yIG1lbWJlcnMgaGF2ZSBiZWVuIGZvdW5kIGVpdGhlclwiICYmXG4gICAgICAgIGVyci5tZXNzYWdlICE9PVxuICAgICAgICAgIFwiW01vYlhdIE5vIGFubm90YXRpb25zIHdlcmUgcGFzc2VkIHRvIG1ha2VPYnNlcnZhYmxlLCBidXQgbm8gZGVjb3JhdGVkIG1lbWJlcnMgaGF2ZSBiZWVuIGZvdW5kIGVpdGhlclwiXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgZXJyXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gdGhlIG9iamVjdCBpcyByZWFkeVxuICBhZGRIaWRkZW5Qcm9wKGluc3RhbmNlLCBtb2RlbEluaXRpYWxpemVkU3ltYm9sLCB0cnVlLCBmYWxzZSlcblxuICBydW5MYXRlSW5pdGlhbGl6YXRpb25GdW5jdGlvbnMoaW5zdGFuY2UsIHJ1bkJlZm9yZU9uSW5pdFN5bWJvbClcblxuICBpZiAodGFnLnR5cGUgPT09IFwiY2xhc3NcIiAmJiBpbnN0YW5jZS5vbkluaXQpIHtcbiAgICB3cmFwTW9kZWxNZXRob2RJbkFjdGlvbklmTmVlZGVkKGluc3RhbmNlLCBcIm9uSW5pdFwiLCBIb29rQWN0aW9uLk9uSW5pdClcblxuICAgIGluc3RhbmNlLm9uSW5pdCgpXG4gIH1cblxuICBpZiAodGFnLnR5cGUgPT09IFwiZGF0YVwiICYmIGluc3RhbmNlLm9uTGF6eUluaXQpIHtcbiAgICB3cmFwTW9kZWxNZXRob2RJbkFjdGlvbklmTmVlZGVkKGluc3RhbmNlLCBcIm9uTGF6eUluaXRcIiwgSG9va0FjdGlvbi5PbkxhenlJbml0KVxuXG4gICAgaW5zdGFuY2Uub25MYXp5SW5pdCgpXG4gIH1cbn1cblxuY29uc3QgcHJveHlDbGFzc0hhbmRsZXI6IFByb3h5SGFuZGxlcjxNb2RlbENsYXNzPEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPj4gPSB7XG4gIGNvbnN0cnVjdChjbGF6eiwgYXJncykge1xuICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IChjbGF6eiBhcyBhbnkpKC4uLmFyZ3MpXG5cbiAgICBydW5BZnRlckNsYXNzSW5pdGlhbGl6YXRpb24oY2xhenosIGluc3RhbmNlKVxuXG4gICAgcmV0dXJuIGluc3RhbmNlXG4gIH0sXG59XG5cbmNvbnN0IGludGVybmFsTW9kZWwgPSA8TUMgZXh0ZW5kcyBNb2RlbENsYXNzPEFueU1vZGVsIHwgQW55RGF0YU1vZGVsPj4oXG4gIG5hbWU6IHN0cmluZyxcbiAgY2xheno6IE1DLFxuICBhZGRJbml0aWFsaXplcjogKChpbml0aWFsaXplcjogKHRoaXM6IGFueSkgPT4gdm9pZCkgPT4gdm9pZCkgfCB1bmRlZmluZWRcbik6IE1DIHwgdm9pZCA9PiB7XG4gIGNvbnN0IHR5cGUgPSBpc01vZGVsQ2xhc3MoY2xhenopID8gXCJjbGFzc1wiIDogaXNEYXRhTW9kZWxDbGFzcyhjbGF6eikgPyBcImRhdGFcIiA6IHVuZGVmaW5lZFxuICBpZiAoIXR5cGUpIHtcbiAgICB0aHJvdyBmYWlsdXJlKGBjbGF6eiBtdXN0IGJlIGEgY2xhc3MgdGhhdCBleHRlbmRzIGZyb20gTW9kZWwvRGF0YU1vZGVsYClcbiAgfVxuXG4gIGlmIChtb2RlbEluZm9CeU5hbWVbbmFtZV0pIHtcbiAgICBpZiAoZ2V0R2xvYmFsQ29uZmlnKCkuc2hvd0R1cGxpY2F0ZU1vZGVsTmFtZVdhcm5pbmdzKSB7XG4gICAgICBsb2dXYXJuaW5nKFxuICAgICAgICBcIndhcm5cIixcbiAgICAgICAgYGEgbW9kZWwgd2l0aCBuYW1lIFwiJHtuYW1lfVwiIGFscmVhZHkgZXhpc3RzIChpZiB5b3UgYXJlIHVzaW5nIGhvdC1yZWxvYWRpbmcgeW91IG1heSBzYWZlbHkgaWdub3JlIHRoaXMgd2FybmluZylgLFxuICAgICAgICBgZHVwbGljYXRlTW9kZWxOYW1lIC0gJHtuYW1lfWBcbiAgICAgIClcbiAgICB9XG4gIH1cblxuICBpZiAobW9kZWxVbndyYXBwZWRDbGFzc1N5bWJvbCBpbiBjbGF6eiAmJiBjbGF6elttb2RlbFVud3JhcHBlZENsYXNzU3ltYm9sXSA9PT0gY2xhenopIHtcbiAgICB0aHJvdyBmYWlsdXJlKFwiYSBjbGFzcyBhbHJlYWR5IGRlY29yYXRlZCB3aXRoIGBAbW9kZWxgIGNhbm5vdCBiZSByZS1kZWNvcmF0ZWRcIilcbiAgfVxuXG4gIGNsYXp6LnRvU3RyaW5nID0gKCkgPT4gYGNsYXNzICR7Y2xhenoubmFtZX0jJHtuYW1lfWBcbiAgaWYgKHR5cGUgPT09IFwiY2xhc3NcIikge1xuICAgIDsoY2xhenogYXMgYW55KVttb2RlbFR5cGVLZXldID0gbmFtZVxuICB9XG5cbiAgLy8gdHJhY2sgaWYgd2UgZmFpbCBzbyB3ZSBvbmx5IHRyeSBpdCBvbmNlIHBlciBjbGFzc1xuICBhZnRlckNsYXNzSW5pdGlhbGl6YXRpb25EYXRhLnNldChjbGF6eiwgeyBtYWtlT2JzZXJ2YWJsZUZhaWxlZDogZmFsc2UsIHR5cGUgfSlcblxuICBpZiAoYWRkSW5pdGlhbGl6ZXIpIHtcbiAgICAvLyBzdGFuZGFyZCBkZWNvcmF0b3IgQVBJLCBhdm9pZCBwcm94aWVzXG4gICAgYWRkSW5pdGlhbGl6ZXIoZnVuY3Rpb24gKHRoaXM6IGFueSkge1xuICAgICAgcnVuQWZ0ZXJDbGFzc0luaXRpYWxpemF0aW9uKGNsYXp6LCB0aGlzKVxuICAgIH0pXG5cbiAgICBjb25zdCBtb2RlbEluZm8gPSB7XG4gICAgICBuYW1lLFxuICAgICAgY2xhc3M6IGNsYXp6LFxuICAgIH1cblxuICAgIG1vZGVsSW5mb0J5TmFtZVtuYW1lXSA9IG1vZGVsSW5mb1xuXG4gICAgbW9kZWxJbmZvQnlDbGFzcy5zZXQoY2xhenosIG1vZGVsSW5mbylcblxuICAgIHJ1bkxhdGVJbml0aWFsaXphdGlvbkZ1bmN0aW9ucyhjbGF6eiwgcnVuQWZ0ZXJNb2RlbERlY29yYXRvclN5bWJvbClcblxuICAgIHJldHVybiB1bmRlZmluZWQgLy8gdXNlIHNhbWUgY2xhc3NcbiAgfSBlbHNlIHtcbiAgICAvLyBub24tc3RhbmRhcmQgZGVjb3JhdG9yIEFQSSwgdXNlIHByb3hpZXNcblxuICAgIC8vIHRyaWNrIHNvIHBsYWluIG5ldyB3b3Jrc1xuICAgIGNvbnN0IHByb3h5Q2xhc3MgPSBuZXcgUHJveHk8TUM+KGNsYXp6LCBwcm94eUNsYXNzSGFuZGxlcilcblxuICAgIC8vIHNldCBvciBlbHNlIGl0IHBvaW50cyB0byB0aGUgdW5kZWNvcmF0ZWQgY2xhc3NcbiAgICBwcm94eUNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IHByb3h5Q2xhc3NcbiAgICA7KHByb3h5Q2xhc3MgYXMgYW55KVttb2RlbFVud3JhcHBlZENsYXNzU3ltYm9sXSA9IGNsYXp6XG5cbiAgICBjb25zdCBtb2RlbEluZm8gPSB7XG4gICAgICBuYW1lLFxuICAgICAgY2xhc3M6IHByb3h5Q2xhc3MsXG4gICAgfVxuXG4gICAgbW9kZWxJbmZvQnlOYW1lW25hbWVdID0gbW9kZWxJbmZvXG5cbiAgICBtb2RlbEluZm9CeUNsYXNzLnNldChwcm94eUNsYXNzLCBtb2RlbEluZm8pXG4gICAgbW9kZWxJbmZvQnlDbGFzcy5zZXQoY2xhenosIG1vZGVsSW5mbylcblxuICAgIHJ1bkxhdGVJbml0aWFsaXphdGlvbkZ1bmN0aW9ucyhjbGF6eiwgcnVuQWZ0ZXJNb2RlbERlY29yYXRvclN5bWJvbClcblxuICAgIHJldHVybiBwcm94eUNsYXNzXG4gIH1cbn1cblxuLy8gYmFzaWNhbGx5IHRha2VuIGZyb20gVFNcbmZ1bmN0aW9uIHRzRGVjb3JhdGUoZGVjb3JhdG9yczogYW55LCB0YXJnZXQ6IGFueSwga2V5OiBhbnksIGRlc2M6IGFueSkge1xuICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgciA9XG4gICAgICBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyAoZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpKSA6IGRlc2MsXG4gICAgZFxuICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIChSZWZsZWN0IGFzIGFueSkuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIilcbiAgICByID0gKFJlZmxlY3QgYXMgYW55KS5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYylcbiAgZWxzZVxuICAgIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKVxuICAgICAgaWYgKChkID0gZGVjb3JhdG9yc1tpXSkpIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZXF1ZW5jZXNcbiAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgclxufVxuXG4vKipcbiAqIE1hcmtzIGEgY2xhc3MgKHdoaWNoIE1VU1QgaW5oZXJpdCBmcm9tIHRoZSBgTW9kZWxgIGFic3RyYWN0IGNsYXNzKVxuICogYXMgYSBtb2RlbCBhbmQgZGVjb3JhdGVzIHNvbWUgb2YgaXRzIG1ldGhvZHMvcHJvcGVydGllcy5cbiAqXG4gKiBAcGFyYW0gbmFtZSBVbmlxdWUgbmFtZSBmb3IgdGhlIG1vZGVsIHR5cGUuIE5vdGUgdGhhdCB0aGlzIG5hbWUgbXVzdCBiZSB1bmlxdWUgZm9yIHlvdXIgd2hvbGVcbiAqIGFwcGxpY2F0aW9uLCBzbyBpdCBpcyB1c3VhbGx5IGEgZ29vZCBpZGVhIHRvIHVzZSBzb21lIHByZWZpeCB1bmlxdWUgdG8geW91ciBhcHBsaWNhdGlvbiBkb21haW4uXG4gKiBJZiB5b3UgZG9uJ3Qgd2FudCB0byBhc3NpZ24gYSBuYW1lIHlldCAoZS5nLiBmb3IgYSBiYXNlIG1vZGVsKSBwYXNzIGB1bmRlZmluZWRgLlxuICogQHBhcmFtIGNsYXp6IE1vZGVsIGNsYXNzLlxuICogQHBhcmFtIGRlY29yYXRvcnMgRGVjb3JhdG9ycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29yYXRlZE1vZGVsPE0sIE1DIGV4dGVuZHMgYWJzdHJhY3QgbmV3ICguLi5hZ3M6IGFueSkgPT4gTT4oXG4gIG5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgY2xheno6IE1DLFxuICBkZWNvcmF0b3JzOiB7XG4gICAgW2sgaW4ga2V5b2YgTV0/OiAoKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnkpIHwgUmVhZG9ubHlBcnJheTwoLi4uYXJnczogYW55W10pID0+IGFueT5cbiAgfVxuKTogTUMge1xuICAvLyBkZWNvcmF0ZSBjbGFzcyBtZW1iZXJzXG4gIGZvciAoY29uc3QgW2ssIGRlY29yYXRvcl0gb2YgT2JqZWN0LmVudHJpZXMoZGVjb3JhdG9ycykpIHtcbiAgICBjb25zdCBwcm90b3R5cGVWYWx1ZURlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGNsYXp6LnByb3RvdHlwZSwgaylcbiAgICAvLyBUUyBzZWVtcyB0byBzZW5kIG51bGwgZm9yIG1ldGhvZHMgaW4gdGhlIHByb3RvdHlwZVxuICAgIC8vICh3aGljaCB3ZSBzdWJzdGl0dXRlIGZvciB0aGUgZGVzY3JpcHRvciB0byBhdm9pZCBhIGRvdWJsZSBsb29rLXVwKSBhbmQgdm9pZCAwICh1bmRlZmluZWQpIGZvciBwcm9wc1xuICAgIHRzRGVjb3JhdGUoXG4gICAgICBBcnJheS5pc0FycmF5KGRlY29yYXRvcikgPyBkZWNvcmF0b3IgOiBbZGVjb3JhdG9yXSxcbiAgICAgIGNsYXp6LnByb3RvdHlwZSxcbiAgICAgIGssXG4gICAgICBwcm90b3R5cGVWYWx1ZURlc2MgPyBwcm90b3R5cGVWYWx1ZURlc2MgOiB2b2lkIDBcbiAgICApXG4gIH1cblxuICByZXR1cm4gKG5hbWUgPyBtb2RlbChuYW1lKShjbGF6eiBhcyB1bmtub3duIGFzIE1vZGVsQ2xhc3M8QW55TW9kZWw+KSA6IGNsYXp6KSBhcyBNQ1xufVxuIiwiaW1wb3J0IHsgaXNBcnJheSB9IGZyb20gXCIuLi8uLi91dGlsc1wiXG5pbXBvcnQgeyBnZXRUeXBlSW5mbyB9IGZyb20gXCIuLi9nZXRUeXBlSW5mb1wiXG5pbXBvcnQgeyByZXNvbHZlU3RhbmRhcmRUeXBlLCByZXNvbHZlVHlwZUNoZWNrZXIgfSBmcm9tIFwiLi4vcmVzb2x2ZVR5cGVDaGVja2VyXCJcbmltcG9ydCB0eXBlIHsgQW55U3RhbmRhcmRUeXBlLCBBbnlUeXBlLCBBcnJheVR5cGUgfSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQge1xuICBsYXRlVHlwZUNoZWNrZXIsXG4gIFR5cGVDaGVja2VyLFxuICBUeXBlQ2hlY2tlckJhc2VUeXBlLFxuICBUeXBlSW5mbyxcbiAgVHlwZUluZm9HZW4sXG59IGZyb20gXCIuLi9UeXBlQ2hlY2tlclwiXG5pbXBvcnQgeyBUeXBlQ2hlY2tFcnJvciB9IGZyb20gXCIuLi9UeXBlQ2hlY2tFcnJvclwiXG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBhbiBhcnJheSBvZiB2YWx1ZXMgb2YgYSBnaXZlbiB0eXBlLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogY29uc3QgbnVtYmVyQXJyYXlUeXBlID0gdHlwZXMuYXJyYXkodHlwZXMubnVtYmVyKVxuICogYGBgXG4gKlxuICogQHR5cGVwYXJhbSBUIEl0ZW0gdHlwZS5cbiAqIEBwYXJhbSBpdGVtVHlwZSBUeXBlIG9mIGlubmVyIGl0ZW1zLlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGVzQXJyYXk8VCBleHRlbmRzIEFueVR5cGU+KGl0ZW1UeXBlOiBUKTogQXJyYXlUeXBlPFRbXT4ge1xuICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT4gbmV3IEFycmF5VHlwZUluZm8odCwgcmVzb2x2ZVN0YW5kYXJkVHlwZShpdGVtVHlwZSkpXG5cbiAgcmV0dXJuIGxhdGVUeXBlQ2hlY2tlcigoKSA9PiB7XG4gICAgY29uc3QgaXRlbUNoZWNrZXIgPSByZXNvbHZlVHlwZUNoZWNrZXIoaXRlbVR5cGUpXG5cbiAgICBjb25zdCBnZXRUeXBlTmFtZSA9ICguLi5yZWN1cnNpdmVUeXBlQ2hlY2tlcnM6IFR5cGVDaGVja2VyW10pID0+XG4gICAgICBgQXJyYXk8JHtpdGVtQ2hlY2tlci5nZXRUeXBlTmFtZSguLi5yZWN1cnNpdmVUeXBlQ2hlY2tlcnMsIGl0ZW1DaGVja2VyKX0+YFxuXG4gICAgY29uc3QgdGhpc1RjOiBUeXBlQ2hlY2tlciA9IG5ldyBUeXBlQ2hlY2tlcihcbiAgICAgIFR5cGVDaGVja2VyQmFzZVR5cGUuQXJyYXksXG5cbiAgICAgIChhcnJheSwgcGF0aCwgdHlwZUNoZWNrZWRWYWx1ZSkgPT4ge1xuICAgICAgICBpZiAoIWlzQXJyYXkoYXJyYXkpKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCBnZXRUeXBlTmFtZSh0aGlzVGMpLCBhcnJheSwgdHlwZUNoZWNrZWRWYWx1ZSlcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXRlbUNoZWNrZXIudW5jaGVja2VkKSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgaXRlbUVycm9yID0gaXRlbUNoZWNrZXIuY2hlY2soYXJyYXlbaV0sIFsuLi5wYXRoLCBpXSwgdHlwZUNoZWNrZWRWYWx1ZSlcbiAgICAgICAgICAgIGlmIChpdGVtRXJyb3IpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGl0ZW1FcnJvclxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsXG4gICAgICB9LFxuICAgICAgZ2V0VHlwZU5hbWUsXG4gICAgICB0eXBlSW5mb0dlbixcblxuICAgICAgKGFycmF5KSA9PiB7XG4gICAgICAgIGlmICghaXNBcnJheShhcnJheSkpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpdGVtQ2hlY2tlci51bmNoZWNrZWQpIHtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBpdGVtQWN0dWFsQ2hlY2tlciA9IGl0ZW1DaGVja2VyLnNuYXBzaG90VHlwZShhcnJheVtpXSlcbiAgICAgICAgICAgIGlmICghaXRlbUFjdHVhbENoZWNrZXIpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpc1RjXG4gICAgICB9LFxuXG4gICAgICAoc246IHVua25vd25bXSkgPT4ge1xuICAgICAgICBpZiAoaXRlbUNoZWNrZXIudW5jaGVja2VkKSB7XG4gICAgICAgICAgcmV0dXJuIHNuXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc24ubWFwKChpdGVtKSA9PiBpdGVtQ2hlY2tlci5mcm9tU25hcHNob3RQcm9jZXNzb3IoaXRlbSkpXG4gICAgICB9LFxuXG4gICAgICAoc246IHVua25vd25bXSkgPT4ge1xuICAgICAgICBpZiAoaXRlbUNoZWNrZXIudW5jaGVja2VkKSB7XG4gICAgICAgICAgcmV0dXJuIHNuXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc24ubWFwKChpdGVtKSA9PiBpdGVtQ2hlY2tlci50b1NuYXBzaG90UHJvY2Vzc29yKGl0ZW0pKVxuICAgICAgfVxuICAgIClcblxuICAgIHJldHVybiB0aGlzVGNcbiAgfSwgdHlwZUluZm9HZW4pIGFzIGFueVxufVxuXG4vKipcbiAqIGB0eXBlcy5hcnJheWAgdHlwZSBpbmZvLlxuICovXG5leHBvcnQgY2xhc3MgQXJyYXlUeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHtcbiAgZ2V0IGl0ZW1UeXBlSW5mbygpOiBUeXBlSW5mbyB7XG4gICAgcmV0dXJuIGdldFR5cGVJbmZvKHRoaXMuaXRlbVR5cGUpXG4gIH1cblxuICBjb25zdHJ1Y3Rvcih0aGlzVHlwZTogQW55U3RhbmRhcmRUeXBlLCByZWFkb25seSBpdGVtVHlwZTogQW55U3RhbmRhcmRUeXBlKSB7XG4gICAgc3VwZXIodGhpc1R5cGUpXG4gIH1cbn1cbiIsImltcG9ydCB7IGFjdGlvbiwgY29tcHV0ZWQgfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgdHlwZSB7IEFjdGlvbk1pZGRsZXdhcmVEaXNwb3NlciB9IGZyb20gXCIuLi9hY3Rpb24vbWlkZGxld2FyZVwiXG5pbXBvcnQgeyBtb2RlbEFjdGlvbiB9IGZyb20gXCIuLi9hY3Rpb24vbW9kZWxBY3Rpb25cIlxuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvTW9kZWxcIlxuaW1wb3J0IHsgbW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxEZWNvcmF0b3JcIlxuaW1wb3J0IHsgZmFzdEdldFJvb3RQYXRoIH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoXCJcbmltcG9ydCB0eXBlIHsgUGF0aCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFR5cGVzXCJcbmltcG9ydCB7IFBhdGNoLCBQYXRjaFJlY29yZGVyLCBhcHBseVBhdGNoZXMsIHBhdGNoUmVjb3JkZXIgfSBmcm9tIFwiLi4vcGF0Y2hcIlxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgdHlwZXNBcnJheSB9IGZyb20gXCIuLi90eXBlcy9hcnJheUJhc2VkL3R5cGVzQXJyYXlcIlxuaW1wb3J0IHsgdFByb3AgfSBmcm9tIFwiLi4vdHlwZXMvdFByb3BcIlxuaW1wb3J0IHsgdHlwZXNVbmNoZWNrZWQgfSBmcm9tIFwiLi4vdHlwZXMvdXRpbGl0eS90eXBlc1VuY2hlY2tlZFwiXG5pbXBvcnQgeyBmYWlsdXJlLCBnZXRNb2J4VmVyc2lvbiwgbW9ieDYsIG5hbWVzcGFjZSB9IGZyb20gXCIuLi91dGlsc1wiXG5pbXBvcnQgeyBTaW1wbGVBY3Rpb25Db250ZXh0LCBhY3Rpb25UcmFja2luZ01pZGRsZXdhcmUgfSBmcm9tIFwiLi9hY3Rpb25UcmFja2luZ01pZGRsZXdhcmVcIlxuXG4vKipcbiAqIEFuIHVuZG8vcmVkbyBldmVudCB3aXRob3V0IGF0dGFjaGVkIHN0YXRlLlxuICovXG5leHBvcnQgdHlwZSBVbmRvRXZlbnRXaXRob3V0QXR0YWNoZWRTdGF0ZSA9IFVuZG9TaW5nbGVFdmVudCB8IFVuZG9FdmVudEdyb3VwXG5cbi8qKlxuICogQW4gdW5kby9yZWRvIGV2ZW50LlxuICovXG5leHBvcnQgdHlwZSBVbmRvRXZlbnQgPSBVbmRvRXZlbnRXaXRob3V0QXR0YWNoZWRTdGF0ZSAmIHtcbiAgLyoqXG4gICAqIFRoZSBzdGF0ZSBzYXZlZCBiZWZvcmUgdGhlIGV2ZW50IGFjdGlvbnMgc3RhcnRlZCAvIGFmdGVyIHRoZSBldmVudCBhY3Rpb25zIGZpbmlzaGVkLlxuICAgKi9cbiAgYXR0YWNoZWRTdGF0ZToge1xuICAgIC8qKlxuICAgICAqIFRoZSBzdGF0ZSBzYXZlZCBiZWZvcmUgdGhlIGV2ZW50IGFjdGlvbnMgc3RhcnRlZC5cbiAgICAgKi9cbiAgICBiZWZvcmVFdmVudD86IHVua25vd25cbiAgICAvKipcbiAgICAgKiBUaGUgc3RhdGUgc2F2ZWQgYWZ0ZXIgdGhlIGV2ZW50IGFjdGlvbnMgZmluaXNoZWQuXG4gICAgICovXG4gICAgYWZ0ZXJFdmVudD86IHVua25vd25cbiAgfVxufVxuXG4vKipcbiAqIFVuZG8gZXZlbnQgdHlwZS5cbiAqL1xuZXhwb3J0IGVudW0gVW5kb0V2ZW50VHlwZSB7XG4gIFNpbmdsZSA9IFwic2luZ2xlXCIsXG4gIEdyb3VwID0gXCJncm91cFwiLFxufVxuXG4vKipcbiAqIEFuIHVuZG8vcmVkbyBzaW5nbGUgZXZlbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVW5kb1NpbmdsZUV2ZW50IHtcbiAgLyoqXG4gICAqIEV4cHJlc3NlcyB0aGlzIGlzIGEgc2luZ2xlIGV2ZW50LlxuICAgKi9cbiAgcmVhZG9ubHkgdHlwZTogVW5kb0V2ZW50VHlwZS5TaW5nbGVcbiAgLyoqXG4gICAqIFBhdGggdG8gdGhlIG9iamVjdCB0aGF0IGludm9rZWQgdGhlIGFjdGlvbiBmcm9tIGl0cyByb290LlxuICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0UGF0aDogUGF0aFxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgYWN0aW9uIHRoYXQgd2FzIGludm9rZWQuXG4gICAqL1xuICByZWFkb25seSBhY3Rpb25OYW1lOiBzdHJpbmdcbiAgLyoqXG4gICAqIFBhdGNoZXMgd2l0aCBjaGFuZ2VzIGRvbmUgaW5zaWRlIHRoZSBhY3Rpb24uXG4gICAqIFVzZSBgcmVkbygpYCBpbiB0aGUgYFVuZG9NYW5hZ2VyYCB0byBhcHBseSB0aGVtLlxuICAgKi9cbiAgcmVhZG9ubHkgcGF0Y2hlczogUmVhZG9ubHlBcnJheTxQYXRjaD5cbiAgLyoqXG4gICAqIFBhdGNoZXMgdG8gdW5kbyB0aGUgY2hhbmdlcyBkb25lIGluc2lkZSB0aGUgYWN0aW9uLlxuICAgKiBVc2UgYHVuZG8oKWAgaW4gdGhlIGBVbmRvTWFuYWdlcmAgdG8gYXBwbHkgdGhlbS5cbiAgICovXG4gIHJlYWRvbmx5IGludmVyc2VQYXRjaGVzOiBSZWFkb25seUFycmF5PFBhdGNoPlxufVxuXG4vKipcbiAqIEFuIHVuZG8vcmVkbyBldmVudCBncm91cC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVbmRvRXZlbnRHcm91cCB7XG4gIC8qKlxuICAgKiBFeHByZXNzZXMgdGhpcyBpcyBhbiBldmVudCBncm91cC5cbiAgICovXG4gIHJlYWRvbmx5IHR5cGU6IFVuZG9FdmVudFR5cGUuR3JvdXBcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIGdyb3VwIChpZiBhbnkpLlxuICAgKi9cbiAgcmVhZG9ubHkgZ3JvdXBOYW1lPzogc3RyaW5nXG4gIC8qKlxuICAgKiBFdmVudHMgdGhhdCBjb25mb3JtIHRoaXMgZ3JvdXAgKG1pZ2h0IGJlIHNpbmdsZSBldmVudHMgb3Igb3RoZXIgbmVzdGVkIGdyb3VwcykuXG4gICAqL1xuICByZWFkb25seSBldmVudHM6IFJlYWRvbmx5QXJyYXk8VW5kb0V2ZW50V2l0aG91dEF0dGFjaGVkU3RhdGU+XG59XG5cbmZ1bmN0aW9uIHRvU2luZ2xlRXZlbnRzKFxuICBldmVudDogVW5kb0V2ZW50V2l0aG91dEF0dGFjaGVkU3RhdGUsXG4gIHJldmVyc2U6IGJvb2xlYW5cbik6IFJlYWRvbmx5QXJyYXk8VW5kb1NpbmdsZUV2ZW50PiB7XG4gIGlmIChldmVudC50eXBlID09PSBVbmRvRXZlbnRUeXBlLlNpbmdsZSkgcmV0dXJuIFtldmVudF1cbiAgZWxzZSB7XG4gICAgY29uc3QgYXJyYXk6IFVuZG9TaW5nbGVFdmVudFtdID0gW11cbiAgICBmb3IgKGNvbnN0IGUgb2YgZXZlbnQuZXZlbnRzKSB7XG4gICAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgICBhcnJheS51bnNoaWZ0KC4uLnRvU2luZ2xlRXZlbnRzKGUsIHRydWUpKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXJyYXkucHVzaCguLi50b1NpbmdsZUV2ZW50cyhlLCBmYWxzZSkpXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhcnJheVxuICB9XG59XG5cbi8qKlxuICogU3RvcmUgbW9kZWwgaW5zdGFuY2UgZm9yIHVuZG8vcmVkbyBhY3Rpb25zLlxuICogRG8gbm90IG1hbmlwdWxhdGUgZGlyZWN0bHksIG90aGVyIHRoYXQgY3JlYXRpbmcgaXQuXG4gKi9cbkBtb2RlbChgJHtuYW1lc3BhY2V9L1VuZG9TdG9yZWApXG5leHBvcnQgY2xhc3MgVW5kb1N0b3JlIGV4dGVuZHMgTW9kZWwoe1xuICAvLyBUT0RPOiBhZGQgcHJvcGVyIHR5cGUgY2hlY2tpbmcgdG8gdW5kbyBzdG9yZVxuICB1bmRvRXZlbnRzOiB0UHJvcCh0eXBlc0FycmF5KHR5cGVzVW5jaGVja2VkPFVuZG9FdmVudD4oKSksICgpID0+IFtdKSxcbiAgcmVkb0V2ZW50czogdFByb3AodHlwZXNBcnJheSh0eXBlc1VuY2hlY2tlZDxVbmRvRXZlbnQ+KCkpLCAoKSA9PiBbXSksXG59KSB7XG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBAbW9kZWxBY3Rpb25cbiAgX2NsZWFyVW5kbygpIHtcbiAgICB3aXRob3V0VW5kbygoKSA9PiB7XG4gICAgICB0aGlzLnVuZG9FdmVudHMubGVuZ3RoID0gMFxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgQG1vZGVsQWN0aW9uXG4gIF9jbGVhclJlZG8oKSB7XG4gICAgd2l0aG91dFVuZG8oKCkgPT4ge1xuICAgICAgdGhpcy5yZWRvRXZlbnRzLmxlbmd0aCA9IDBcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIGVuZm9yY2VNYXhMZXZlbHMoe1xuICAgIG1heFVuZG9MZXZlbHMsXG4gICAgbWF4UmVkb0xldmVscyxcbiAgfToge1xuICAgIG1heFVuZG9MZXZlbHM/OiBudW1iZXJcbiAgICBtYXhSZWRvTGV2ZWxzPzogbnVtYmVyXG4gIH0pIHtcbiAgICBpZiAobWF4VW5kb0xldmVscyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB3aGlsZSAodGhpcy51bmRvRXZlbnRzLmxlbmd0aCA+IG1heFVuZG9MZXZlbHMpIHtcbiAgICAgICAgdGhpcy51bmRvRXZlbnRzLnNoaWZ0KClcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG1heFJlZG9MZXZlbHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgd2hpbGUgKHRoaXMucmVkb0V2ZW50cy5sZW5ndGggPiBtYXhSZWRvTGV2ZWxzKSB7XG4gICAgICAgIHRoaXMucmVkb0V2ZW50cy5zaGlmdCgpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIEBtb2RlbEFjdGlvblxuICBfdW5kbyh7IG1heFJlZG9MZXZlbHMgfTogeyBtYXhSZWRvTGV2ZWxzOiBudW1iZXIgfCB1bmRlZmluZWQgfSkge1xuICAgIHdpdGhvdXRVbmRvKCgpID0+IHtcbiAgICAgIGNvbnN0IGV2ZW50ID0gdGhpcy51bmRvRXZlbnRzLnBvcCgpIVxuICAgICAgdGhpcy5yZWRvRXZlbnRzLnB1c2goZXZlbnQpXG4gICAgICB0aGlzLmVuZm9yY2VNYXhMZXZlbHMoeyBtYXhSZWRvTGV2ZWxzIH0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBAbW9kZWxBY3Rpb25cbiAgX3JlZG8oeyBtYXhVbmRvTGV2ZWxzIH06IHsgbWF4VW5kb0xldmVsczogbnVtYmVyIHwgdW5kZWZpbmVkIH0pIHtcbiAgICB3aXRob3V0VW5kbygoKSA9PiB7XG4gICAgICBjb25zdCBldmVudCA9IHRoaXMucmVkb0V2ZW50cy5wb3AoKSFcbiAgICAgIHRoaXMudW5kb0V2ZW50cy5wdXNoKGV2ZW50KVxuICAgICAgdGhpcy5lbmZvcmNlTWF4TGV2ZWxzKHsgbWF4VW5kb0xldmVscyB9KVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgQG1vZGVsQWN0aW9uXG4gIF9hZGRVbmRvKHsgZXZlbnQsIG1heFVuZG9MZXZlbHMgfTogeyBldmVudDogVW5kb0V2ZW50OyBtYXhVbmRvTGV2ZWxzOiBudW1iZXIgfCB1bmRlZmluZWQgfSkge1xuICAgIHdpdGhvdXRVbmRvKCgpID0+IHtcbiAgICAgIHRoaXMudW5kb0V2ZW50cy5wdXNoKGV2ZW50KVxuICAgICAgLy8gb25jZSBhbiB1bmRvIGV2ZW50IGlzIGFkZGVkIHJlZG8gcXVldWUgaXMgbm8gbG9uZ2VyIHZhbGlkXG4gICAgICB0aGlzLnJlZG9FdmVudHMubGVuZ3RoID0gMFxuICAgICAgdGhpcy5lbmZvcmNlTWF4TGV2ZWxzKHsgbWF4VW5kb0xldmVscyB9KVxuICAgIH0pXG4gIH1cblxuICBwcml2YXRlIF9ncm91cFN0YWNrOiBVbmRvRXZlbnRHcm91cFtdID0gW11cblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgX2FkZFVuZG9Ub1BhcmVudEdyb3VwKHBhcmVudEdyb3VwOiBVbmRvRXZlbnRHcm91cCwgZXZlbnQ6IFVuZG9FdmVudFdpdGhvdXRBdHRhY2hlZFN0YXRlKSB7XG4gICAgOyhwYXJlbnRHcm91cC5ldmVudHMgYXMgVW5kb0V2ZW50V2l0aG91dEF0dGFjaGVkU3RhdGVbXSkucHVzaChldmVudClcbiAgfVxuXG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBnZXQgX2N1cnJlbnRHcm91cCgpOiBVbmRvRXZlbnRHcm91cCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2dyb3VwU3RhY2tbdGhpcy5fZ3JvdXBTdGFjay5sZW5ndGggLSAxXVxuICB9XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIF9zdGFydEdyb3VwKFxuICAgIGdyb3VwTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIHN0YXJ0UnVubmluZzogYm9vbGVhbixcbiAgICBvcHRpb25zOiBVbmRvTWlkZGxld2FyZU9wdGlvbnM8dW5rbm93bj4gfCB1bmRlZmluZWRcbiAgKSB7XG4gICAgbGV0IHJ1bm5pbmcgPSBmYWxzZVxuICAgIGxldCBlbmRlZCA9IGZhbHNlXG4gICAgY29uc3QgcGFyZW50R3JvdXAgPSB0aGlzLl9jdXJyZW50R3JvdXBcblxuICAgIGNvbnN0IGdyb3VwOiBVbmRvRXZlbnRHcm91cCA9IHtcbiAgICAgIHR5cGU6IFVuZG9FdmVudFR5cGUuR3JvdXAsXG4gICAgICBncm91cE5hbWUsXG4gICAgICBldmVudHM6IFtdLFxuICAgIH1cblxuICAgIGNvbnN0IGF0dGFjaGVkU3RhdGVCZWZvcmVFdmVudCA9IHBhcmVudEdyb3VwID8gdW5kZWZpbmVkIDogb3B0aW9ucz8uYXR0YWNoZWRTdGF0ZT8uc2F2ZSgpXG5cbiAgICBjb25zdCBhcGkgPSB7XG4gICAgICBwYXVzZTogKCkgPT4ge1xuICAgICAgICBpZiAoZW5kZWQpIHtcbiAgICAgICAgICB0aHJvdyBmYWlsdXJlKFwiY2Fubm90IHBhdXNlIGEgZ3JvdXAgd2hlbiBpdCBpcyBhbHJlYWR5IGVuZGVkXCIpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFydW5uaW5nKSB7XG4gICAgICAgICAgdGhyb3cgZmFpbHVyZShcImNhbm5vdCBwYXVzZSBhIGdyb3VwIHdoZW4gaXQgaXMgbm90IHJ1bm5pbmdcIilcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fY3VycmVudEdyb3VwICE9PSBncm91cCkge1xuICAgICAgICAgIHRocm93IGZhaWx1cmUoXCJncm91cCBvdXQgb2Ygb3JkZXJcIilcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9ncm91cFN0YWNrLnBvcCgpXG4gICAgICAgIHJ1bm5pbmcgPSBmYWxzZVxuICAgICAgfSxcbiAgICAgIHJlc3VtZTogKCkgPT4ge1xuICAgICAgICBpZiAoZW5kZWQpIHtcbiAgICAgICAgICB0aHJvdyBmYWlsdXJlKFwiY2Fubm90IHJlc3VtZSBhIGdyb3VwIHdoZW4gaXQgaXMgYWxyZWFkeSBlbmRlZFwiKVxuICAgICAgICB9XG4gICAgICAgIGlmIChydW5uaW5nKSB7XG4gICAgICAgICAgdGhyb3cgZmFpbHVyZShcImNhbm5vdCByZXN1bWUgYSBncm91cCB3aGVuIGl0IGlzIGFscmVhZHkgcnVubmluZ1wiKVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2dyb3VwU3RhY2sucHVzaChncm91cClcbiAgICAgICAgcnVubmluZyA9IHRydWVcbiAgICAgIH0sXG4gICAgICBlbmQ6ICgpID0+IHtcbiAgICAgICAgaWYgKHJ1bm5pbmcpIHtcbiAgICAgICAgICBhcGkucGF1c2UoKVxuICAgICAgICB9XG4gICAgICAgIGVuZGVkID0gdHJ1ZVxuICAgICAgICBpZiAocGFyZW50R3JvdXApIHtcbiAgICAgICAgICB0aGlzLl9hZGRVbmRvVG9QYXJlbnRHcm91cChwYXJlbnRHcm91cCwgZ3JvdXApXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fYWRkVW5kbyh7XG4gICAgICAgICAgICBldmVudDoge1xuICAgICAgICAgICAgICAuLi5ncm91cCxcbiAgICAgICAgICAgICAgYXR0YWNoZWRTdGF0ZToge1xuICAgICAgICAgICAgICAgIGJlZm9yZUV2ZW50OiBhdHRhY2hlZFN0YXRlQmVmb3JlRXZlbnQsXG4gICAgICAgICAgICAgICAgYWZ0ZXJFdmVudDogb3B0aW9ucz8uYXR0YWNoZWRTdGF0ZT8uc2F2ZSgpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1heFVuZG9MZXZlbHM6IG9wdGlvbnM/Lm1heFVuZG9MZXZlbHMsXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9XG5cbiAgICBpZiAoc3RhcnRSdW5uaW5nKSB7XG4gICAgICBhcGkucmVzdW1lKClcbiAgICB9XG5cbiAgICByZXR1cm4gYXBpXG4gIH1cbn1cblxuLyoqXG4gKiBNYW5hZ2VyIGNsYXNzIHJldHVybmVkIGJ5IGB1bmRvTWlkZGxld2FyZWAgdGhhdCBhbGxvd3MgeW91IHRvIHBlcmZvcm0gdW5kby9yZWRvIGFjdGlvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBVbmRvTWFuYWdlciB7XG4gIC8qKlxuICAgKiBUaGUgc3RvcmUgY3VycmVudGx5IGJlaW5nIHVzZWQgdG8gc3RvcmUgdW5kby9yZWRvIGFjdGlvbiBldmVudHMuXG4gICAqL1xuICByZWFkb25seSBzdG9yZTogVW5kb1N0b3JlXG5cbiAgLyoqXG4gICAqIFRoZSB1bmRvIHN0YWNrLCB3aGVyZSB0aGUgZmlyc3Qgb3BlcmF0aW9uIHRvIHVuZG8gd2lsbCBiZSB0aGUgbGFzdCBvZiB0aGUgYXJyYXkuXG4gICAqIERvIG5vdCBtYW5pcHVsYXRlIHRoaXMgYXJyYXkgZGlyZWN0bHkuXG4gICAqL1xuICBAY29tcHV0ZWRcbiAgZ2V0IHVuZG9RdWV1ZSgpOiBSZWFkb25seUFycmF5PFVuZG9FdmVudD4ge1xuICAgIHJldHVybiB0aGlzLnN0b3JlLnVuZG9FdmVudHNcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcmVkbyBzdGFjaywgd2hlcmUgdGhlIGZpcnN0IG9wZXJhdGlvbiB0byByZWRvIHdpbGwgYmUgdGhlIGxhc3Qgb2YgdGhlIGFycmF5LlxuICAgKiBEbyBub3QgbWFuaXB1bGF0ZSB0aGlzIGFycmF5IGRpcmVjdGx5LlxuICAgKi9cbiAgQGNvbXB1dGVkXG4gIGdldCByZWRvUXVldWUoKTogUmVhZG9ubHlBcnJheTxVbmRvRXZlbnQ+IHtcbiAgICByZXR1cm4gdGhpcy5zdG9yZS5yZWRvRXZlbnRzXG4gIH1cblxuICAvKipcbiAgICogVGhlIG51bWJlciBvZiB1bmRvIGFjdGlvbnMgYXZhaWxhYmxlLlxuICAgKi9cbiAgQGNvbXB1dGVkXG4gIGdldCB1bmRvTGV2ZWxzKCkge1xuICAgIHJldHVybiB0aGlzLnVuZG9RdWV1ZS5sZW5ndGhcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB1bmRvIGNhbiBiZSBwZXJmb3JtZWQgKGlmIHRoZXJlIGlzIGF0IGxlYXN0IG9uZSB1bmRvIGFjdGlvbiBhdmFpbGFibGUpLlxuICAgKi9cbiAgQGNvbXB1dGVkXG4gIGdldCBjYW5VbmRvKCkge1xuICAgIHJldHVybiB0aGlzLnVuZG9MZXZlbHMgPiAwXG4gIH1cblxuICAvKipcbiAgICogQ2xlYXJzIHRoZSB1bmRvIHF1ZXVlLlxuICAgKi9cbiAgQGFjdGlvblxuICBjbGVhclVuZG8oKSB7XG4gICAgdGhpcy5zdG9yZS5fY2xlYXJVbmRvKClcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIHJlZG8gYWN0aW9ucyBhdmFpbGFibGUuXG4gICAqL1xuICBAY29tcHV0ZWRcbiAgZ2V0IHJlZG9MZXZlbHMoKSB7XG4gICAgcmV0dXJuIHRoaXMucmVkb1F1ZXVlLmxlbmd0aFxuICB9XG5cbiAgLyoqXG4gICAqIElmIHJlZG8gY2FuIGJlIHBlcmZvcm1lZCAoaWYgdGhlcmUgaXMgYXQgbGVhc3Qgb25lIHJlZG8gYWN0aW9uIGF2YWlsYWJsZSlcbiAgICovXG4gIEBjb21wdXRlZFxuICBnZXQgY2FuUmVkbygpIHtcbiAgICByZXR1cm4gdGhpcy5yZWRvTGV2ZWxzID4gMFxuICB9XG5cbiAgLyoqXG4gICAqIENsZWFycyB0aGUgcmVkbyBxdWV1ZS5cbiAgICovXG4gIEBhY3Rpb25cbiAgY2xlYXJSZWRvKCkge1xuICAgIHRoaXMuc3RvcmUuX2NsZWFyUmVkbygpXG4gIH1cblxuICAvKipcbiAgICogVW5kb2VzIHRoZSBsYXN0IGFjdGlvbi5cbiAgICogV2lsbCB0aHJvdyBpZiB0aGVyZSBpcyBubyBhY3Rpb24gdG8gdW5kby5cbiAgICovXG4gIEBhY3Rpb25cbiAgdW5kbygpIHtcbiAgICBpZiAoIXRoaXMuY2FuVW5kbykge1xuICAgICAgdGhyb3cgZmFpbHVyZShcIm5vdGhpbmcgdG8gdW5kb1wiKVxuICAgIH1cbiAgICBjb25zdCBldmVudCA9IHRoaXMudW5kb1F1ZXVlW3RoaXMudW5kb1F1ZXVlLmxlbmd0aCAtIDFdXG5cbiAgICB3aXRob3V0VW5kbygoKSA9PiB7XG4gICAgICB0b1NpbmdsZUV2ZW50cyhldmVudCwgdHJ1ZSkuZm9yRWFjaCgoZSkgPT4ge1xuICAgICAgICBhcHBseVBhdGNoZXModGhpcy5zdWJ0cmVlUm9vdCwgZS5pbnZlcnNlUGF0Y2hlcywgdHJ1ZSlcbiAgICAgIH0pXG5cbiAgICAgIC8vIHJlc3RvcmUgdGhlIGF0dGFjaGVkIHN0YXRlIGJlZm9yZSB0aGUgb3BlcmF0aW9uIHdhcyBtYWRlXG4gICAgICBpZiAoZXZlbnQuYXR0YWNoZWRTdGF0ZT8uYmVmb3JlRXZlbnQpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zPy5hdHRhY2hlZFN0YXRlPy5yZXN0b3JlKGV2ZW50LmF0dGFjaGVkU3RhdGUuYmVmb3JlRXZlbnQpXG4gICAgICB9XG4gICAgfSlcblxuICAgIHRoaXMuc3RvcmUuX3VuZG8oeyBtYXhSZWRvTGV2ZWxzOiB0aGlzLm9wdGlvbnM/Lm1heFJlZG9MZXZlbHMgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWRvZXMgdGhlIHByZXZpb3VzIGFjdGlvbi5cbiAgICogV2lsbCB0aHJvdyBpZiB0aGVyZSBpcyBubyBhY3Rpb24gdG8gcmVkby5cbiAgICovXG4gIEBhY3Rpb25cbiAgcmVkbygpIHtcbiAgICBpZiAoIXRoaXMuY2FuUmVkbykge1xuICAgICAgdGhyb3cgZmFpbHVyZShcIm5vdGhpbmcgdG8gcmVkb1wiKVxuICAgIH1cbiAgICBjb25zdCBldmVudCA9IHRoaXMucmVkb1F1ZXVlW3RoaXMucmVkb1F1ZXVlLmxlbmd0aCAtIDFdXG5cbiAgICB3aXRob3V0VW5kbygoKSA9PiB7XG4gICAgICB0b1NpbmdsZUV2ZW50cyhldmVudCwgZmFsc2UpLmZvckVhY2goKGUpID0+IHtcbiAgICAgICAgYXBwbHlQYXRjaGVzKHRoaXMuc3VidHJlZVJvb3QsIGUucGF0Y2hlcylcbiAgICAgIH0pXG5cbiAgICAgIC8vIHJlc3RvcmUgdGhlIGF0dGFjaGVkIHN0YXRlIGFmdGVyIHRoZSBvcGVyYXRpb24gd2FzIG1hZGVcbiAgICAgIGlmIChldmVudC5hdHRhY2hlZFN0YXRlPy5hZnRlckV2ZW50KSB7XG4gICAgICAgIHRoaXMub3B0aW9ucz8uYXR0YWNoZWRTdGF0ZT8ucmVzdG9yZShldmVudC5hdHRhY2hlZFN0YXRlLmFmdGVyRXZlbnQpXG4gICAgICB9XG4gICAgfSlcblxuICAgIHRoaXMuc3RvcmUuX3JlZG8oeyBtYXhVbmRvTGV2ZWxzOiB0aGlzLm9wdGlvbnM/Lm1heFVuZG9MZXZlbHMgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNwb3NlcyB0aGUgdW5kbyBtaWRkbGV3YXJlLlxuICAgKi9cbiAgZGlzcG9zZSgpIHtcbiAgICB0aGlzLmRpc3Bvc2VyKClcbiAgfVxuXG4gIHByaXZhdGUgX2lzVW5kb1JlY29yZGluZ0Rpc2FibGVkID0gZmFsc2VcblxuICAvKipcbiAgICogUmV0dXJucyBpZiB1bmRvIHJlY29yZGluZyBpcyBjdXJyZW50bHkgZGlzYWJsZWQgb3Igbm90IGZvciB0aGlzIHBhcnRpY3VsYXIgYFVuZG9NYW5hZ2VyYC5cbiAgICovXG4gIGdldCBpc1VuZG9SZWNvcmRpbmdEaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5faXNVbmRvUmVjb3JkaW5nRGlzYWJsZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBTa2lwcyB0aGUgdW5kbyByZWNvcmRpbmcgbWVjaGFuaXNtIGZvciB0aGUgY29kZSBibG9jayB0aGF0IGdldHMgcnVuIHN5bmNocm9ub3VzbHkgaW5zaWRlLlxuICAgKlxuICAgKiBAdHlwZXBhcmFtIFQgQ29kZSBibG9jayByZXR1cm4gdHlwZS5cbiAgICogQHBhcmFtIGZuIENvZGUgYmxvY2sgdG8gcnVuLlxuICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgcmV0dXJuZWQgYnkgdGhlIGNvZGUgYmxvY2suXG4gICAqL1xuICB3aXRob3V0VW5kbzxUPihmbjogKCkgPT4gVCk6IFQge1xuICAgIGNvbnN0IHNhdmVkVW5kb0Rpc2FibGVkID0gdGhpcy5faXNVbmRvUmVjb3JkaW5nRGlzYWJsZWRcbiAgICB0aGlzLl9pc1VuZG9SZWNvcmRpbmdEaXNhYmxlZCA9IHRydWVcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGZuKClcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5faXNVbmRvUmVjb3JkaW5nRGlzYWJsZWQgPSBzYXZlZFVuZG9EaXNhYmxlZFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY3VzdG9tIGdyb3VwIHRoYXQgY2FuIGJlIGNvbnRpbnVlZCBtdWx0aXBsZSB0aW1lcyBhbmQgdGhlbiBlbmRlZC5cbiAgICogQHBhcmFtIGdyb3VwTmFtZSBPcHRpb25hbCBncm91cCBuYW1lLlxuICAgKiBAcmV0dXJucyBBbiBBUEkgdG8gY29udGludWUvZW5kIHRoZSBncm91cC5cbiAgICovXG4gIGNyZWF0ZUdyb3VwKGdyb3VwTmFtZT86IHN0cmluZykge1xuICAgIGNvbnN0IGdyb3VwID0gdGhpcy5zdG9yZS5fc3RhcnRHcm91cChncm91cE5hbWUsIGZhbHNlLCB0aGlzLm9wdGlvbnMpXG5cbiAgICByZXR1cm4ge1xuICAgICAgY29udGludWU8VD4oZm46ICgpID0+IFQpOiBUIHtcbiAgICAgICAgZ3JvdXAucmVzdW1lKClcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gZm4oKVxuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIGdyb3VwLnBhdXNlKClcbiAgICAgICAgfVxuICAgICAgfSxcblxuICAgICAgZW5kKCkge1xuICAgICAgICBncm91cC5lbmQoKVxuICAgICAgfSxcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBhIHN5bmNocm9ub3VzIGNvZGUgYmxvY2sgYXMgYW4gdW5kbyBncm91cC5cbiAgICogTm90ZSB0aGF0IG5lc3RlZCBncm91cHMgYXJlIGFsbG93ZWQuXG4gICAqXG4gICAqIEBwYXJhbSBncm91cE5hbWUgR3JvdXAgbmFtZS5cbiAgICogQHBhcmFtIGZuIENvZGUgYmxvY2suXG4gICAqIEByZXR1cm5zIENvZGUgYmxvY2sgcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgd2l0aEdyb3VwPFQ+KGdyb3VwTmFtZTogc3RyaW5nLCBmbjogKCkgPT4gVCk6IFRcblxuICAvKipcbiAgICogUnVucyBhIHN5bmNocm9ub3VzIGNvZGUgYmxvY2sgYXMgYW4gdW5kbyBncm91cC5cbiAgICogTm90ZSB0aGF0IG5lc3RlZCBncm91cHMgYXJlIGFsbG93ZWQuXG4gICAqXG4gICAqIEBwYXJhbSBmbiBDb2RlIGJsb2NrLlxuICAgKiBAcmV0dXJucyBDb2RlIGJsb2NrIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIHdpdGhHcm91cDxUPihmbjogKCkgPT4gVCk6IFRcblxuICB3aXRoR3JvdXA8VD4oYXJnMTogYW55LCBhcmcyPzogYW55KTogVCB7XG4gICAgbGV0IGdyb3VwTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkXG4gICAgbGV0IGZuOiAoKSA9PiBUXG4gICAgaWYgKHR5cGVvZiBhcmcxID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBncm91cE5hbWUgPSBhcmcxXG4gICAgICBmbiA9IGFyZzJcbiAgICB9IGVsc2Uge1xuICAgICAgZm4gPSBhcmcxXG4gICAgfVxuXG4gICAgY29uc3QgZ3JvdXAgPSB0aGlzLnN0b3JlLl9zdGFydEdyb3VwKGdyb3VwTmFtZSwgdHJ1ZSwgdGhpcy5vcHRpb25zKVxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZm4oKVxuICAgIH0gZmluYWxseSB7XG4gICAgICBncm91cC5lbmQoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGFuIGFzeW5jaHJvbm91cyBjb2RlIGJsb2NrIGFzIGFuIHVuZG8gZ3JvdXAuXG4gICAqIE5vdGUgdGhhdCBuZXN0ZWQgZ3JvdXBzIGFyZSBhbGxvd2VkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JvdXBOYW1lIEdyb3VwIG5hbWUuXG4gICAqIEBwYXJhbSBmbiBGbG93IGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBGbG93IGZ1bmN0aW9uIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIHdpdGhHcm91cEZsb3c8Uj4oZ3JvdXBOYW1lOiBzdHJpbmcsIGZuOiAoKSA9PiBHZW5lcmF0b3I8YW55LCBSLCBhbnk+KTogUHJvbWlzZTxSPlxuXG4gIC8qKlxuICAgKiBSdW5zIGFuIGFzeW5jaHJvbm91cyBjb2RlIGJsb2NrIGFzIGFuIHVuZG8gZ3JvdXAuXG4gICAqIE5vdGUgdGhhdCBuZXN0ZWQgZ3JvdXBzIGFyZSBhbGxvd2VkLlxuICAgKlxuICAgKiBAcGFyYW0gZm4gRmxvdyBmdW5jdGlvbi5cbiAgICogQHJldHVybnMgRmxvdyBmdW5jdGlvbiByZXR1cm4gdmFsdWUuXG4gICAqL1xuICB3aXRoR3JvdXBGbG93PFI+KGZuOiAoKSA9PiBHZW5lcmF0b3I8YW55LCBSLCBhbnk+KTogUHJvbWlzZTxSPlxuXG4gIHdpdGhHcm91cEZsb3c8Uj4oYXJnMTogYW55LCBhcmcyPzogYW55KTogUHJvbWlzZTxSPiB7XG4gICAgbGV0IGdyb3VwTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkXG4gICAgbGV0IGZuOiAoKSA9PiBHZW5lcmF0b3I8YW55LCBSLCBhbnk+XG4gICAgaWYgKHR5cGVvZiBhcmcxID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBncm91cE5hbWUgPSBhcmcxXG4gICAgICBmbiA9IGFyZzJcbiAgICB9IGVsc2Uge1xuICAgICAgZm4gPSBhcmcxXG4gICAgfVxuXG4gICAgY29uc3QgZ2VuID0gZm4oKVxuXG4gICAgY29uc3QgZ3JvdXAgPSB0aGlzLnN0b3JlLl9zdGFydEdyb3VwKGdyb3VwTmFtZSwgZmFsc2UsIHRoaXMub3B0aW9ucylcblxuICAgIC8vIHVzZSBib3VuZCBmdW5jdGlvbnMgdG8gZml4IGVzNiBjb21waWxhdGlvblxuICAgIGNvbnN0IGdlbk5leHQgPSBnZW4ubmV4dC5iaW5kKGdlbilcbiAgICBjb25zdCBnZW5UaHJvdyA9IGdlbi50aHJvdyEuYmluZChnZW4pXG5cbiAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2U8Uj4oZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgZnVuY3Rpb24gb25GdWxmaWxsZWQocmVzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgZ3JvdXAucmVzdW1lKClcbiAgICAgICAgbGV0IHJldFxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldCA9IGdlbk5leHQocmVzKVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgZ3JvdXAuZW5kKClcbiAgICAgICAgICByZWplY3QoZSlcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIGdyb3VwLnBhdXNlKClcbiAgICAgICAgbmV4dChyZXQpXG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIG9uUmVqZWN0ZWQoZXJyOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgZ3JvdXAucmVzdW1lKClcbiAgICAgICAgbGV0IHJldFxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldCA9IGdlblRocm93KGVycilcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGdyb3VwLmVuZCgpXG4gICAgICAgICAgcmVqZWN0KGUpXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBncm91cC5wYXVzZSgpXG4gICAgICAgIG5leHQocmV0KVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBuZXh0KHJldDogYW55KTogdm9pZCB7XG4gICAgICAgIGlmIChyZXQgJiYgdHlwZW9mIHJldC50aGVuID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAvLyBhbiBhc3luYyBpdGVyYXRvclxuICAgICAgICAgIHJldC50aGVuKG5leHQsIHJlamVjdClcbiAgICAgICAgfSBlbHNlIGlmIChyZXQuZG9uZSkge1xuICAgICAgICAgIC8vIGRvbmVcbiAgICAgICAgICBncm91cC5lbmQoKVxuICAgICAgICAgIHJlc29sdmUocmV0LnZhbHVlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGNvbnRpbnVlXG4gICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKHJldC52YWx1ZSkudGhlbihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZClcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBvbkZ1bGZpbGxlZCh1bmRlZmluZWQpIC8vIGtpY2sgb2ZmIHRoZSBwcm9jZXNzXG4gICAgfSlcblxuICAgIHJldHVybiBwcm9taXNlXG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBgVW5kb01hbmFnZXJgLlxuICAgKiBEbyBub3QgdXNlIGRpcmVjdGx5LCB1c2UgYHVuZG9NaWRkbGV3YXJlYCBpbnN0ZWFkLlxuICAgKlxuICAgKiBAcGFyYW0gZGlzcG9zZXJcbiAgICogQHBhcmFtIHN1YnRyZWVSb290XG4gICAqIEBwYXJhbSBbc3RvcmVdXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRpc3Bvc2VyOiBBY3Rpb25NaWRkbGV3YXJlRGlzcG9zZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzdWJ0cmVlUm9vdDogb2JqZWN0LFxuICAgIHN0b3JlOiBVbmRvU3RvcmUgfCB1bmRlZmluZWQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBVbmRvTWlkZGxld2FyZU9wdGlvbnM8dW5rbm93bj4gfCB1bmRlZmluZWRcbiAgKSB7XG4gICAgaWYgKGdldE1vYnhWZXJzaW9uKCkgPj0gNikge1xuICAgICAgbW9ieDYubWFrZU9ic2VydmFibGUodGhpcylcbiAgICB9XG5cbiAgICB0aGlzLnN0b3JlID0gc3RvcmUgPz8gbmV3IFVuZG9TdG9yZSh7fSlcbiAgfVxufVxuXG4vKipcbiAqIFVuZG8gbWlkZGxld2FyZSBvcHRpb25zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFVuZG9NaWRkbGV3YXJlT3B0aW9uczxTPiB7XG4gIC8qKlxuICAgKiBNYXggbnVtYmVyIG9mIHVuZG8gbGV2ZWxzIHRvIGtlZXAsIG9yIHVuZGVmaW5lZCBmb3IgaW5maW5pdGUuXG4gICAqL1xuICBtYXhVbmRvTGV2ZWxzPzogbnVtYmVyXG5cbiAgLyoqXG4gICAqIE1heCBudW1iZXIgb2YgcmVkbyBsZXZlbHMgdG8ga2VlcCwgb3IgdW5kZWZpbmVkIGZvciBpbmZpbml0ZS5cbiAgICovXG4gIG1heFJlZG9MZXZlbHM/OiBudW1iZXJcblxuICAvKipcbiAgICogQXR0YWNoZWQgc3RhdGVzIGFyZSBzdGF0ZXMgdGhhdCBhcmUgc2F2ZWQvcmVzdG9yZWQgd2hlbiB1bmRvaW5nL3JlZG9pbmcuXG4gICAqIFVzdWFsbHkgdXNlZCB0byByZXN0b3JlIHN0YXRlIHRoYXQgaXMgbm90IHBhcnQgb2YgdGhlIGRvY3VtZW50IG1vZGVsIHN1Y2ggYXMgZm9jdXMsIHNlbGVjdGlvbiwgc2Nyb2xsIHBvc2l0aW9uLCBldGMuXG4gICAqL1xuICBhdHRhY2hlZFN0YXRlPzoge1xuICAgIC8qKlxuICAgICAqIFNhdmVzIGEgY2VydGFpbiBzdGF0ZSBhbmQgYXNzb2NpYXRlcyBpdCB3aXRoIHRoZSB1bmRvIHN0ZXAuIFRoaXMgc3RhdGUgY2FuIGJlIHJlc3RvcmVkIHdoZW4gdW5kb2luZy9yZWRvaW5nLlxuICAgICAqL1xuICAgIHNhdmUoKTogU1xuICAgIC8qKlxuICAgICAqIFJlc3RvcmVzIGEgY2VydGFpbiBzdGF0ZSBwcmV2aW91c2x5IHNhdmVkLlxuICAgICAqIEBwYXJhbSBzIFN0YXRlIHRvIHJlc3RvcmUuXG4gICAgICovXG4gICAgcmVzdG9yZShzOiBTKTogdm9pZFxuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbiB1bmRvIG1pZGRsZXdhcmUuXG4gKlxuICogQHBhcmFtIHN1YnRyZWVSb290IFN1YnRyZWUgcm9vdCB0YXJnZXQgb2JqZWN0LlxuICogQHBhcmFtIHN0b3JlIE9wdGlvbmFsIGBVbmRvU3RvcmVgIHdoZXJlIHRvIHN0b3JlIHRoZSB1bmRvL3JlZG8gcXVldWVzLiBVc2UgdGhpcyBpZiB5b3Ugd2FudCB0b1xuICogc3RvcmUgc3VjaCBxdWV1ZXMgc29tZXdoZXJlIGluIHlvdXIgbW9kZWxzLiBJZiBub25lIGlzIHByb3ZpZGVkIGl0IHdpbGwgcmVzaWRlIGluIG1lbW9yeS5cbiAqIEBwYXJhbSBvcHRpb25zIEV4dHJhIG9wdGlvbnMsIHN1Y2ggYXMgaG93IHRvIHNhdmUgLyByZXN0b3JlIGNlcnRhaW4gc25hcHNob3Qgb2YgdGhlIHN0YXRlIHRvIGJlIHJlc3RvcmVkIHdoZW4gdW5kb2luZy9yZWRvaW5nLlxuICogQHJldHVybnMgQW4gYFVuZG9NYW5hZ2VyYCB3aGljaCBhbGxvd3MgeW91IHRvIGRvIHRoZSBtYW5hZ2UgdGhlIHVuZG8vcmVkbyBvcGVyYXRpb25zIGFuZCBkaXNwb3NlIG9mIHRoZSBtaWRkbGV3YXJlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5kb01pZGRsZXdhcmU8Uz4oXG4gIHN1YnRyZWVSb290OiBvYmplY3QsXG4gIHN0b3JlPzogVW5kb1N0b3JlLFxuICBvcHRpb25zPzogVW5kb01pZGRsZXdhcmVPcHRpb25zPFM+XG4pOiBVbmRvTWFuYWdlciB7XG4gIGFzc2VydFR3ZWFrZWRPYmplY3Qoc3VidHJlZVJvb3QsIFwic3VidHJlZVJvb3RcIilcblxuICBsZXQgbWFuYWdlcjogVW5kb01hbmFnZXJcblxuICBpbnRlcmZhY2UgUGF0Y2hSZWNvcmRlckRhdGEge1xuICAgIHJlY29yZGVyOiBQYXRjaFJlY29yZGVyXG4gICAgcmVjb3JkZXJTdGFjazogbnVtYmVyXG4gICAgdW5kb1Jvb3RDb250ZXh0OiBTaW1wbGVBY3Rpb25Db250ZXh0XG4gICAgZ3JvdXA6IFVuZG9FdmVudEdyb3VwIHwgdW5kZWZpbmVkXG4gICAgYXR0YWNoZWRTdGF0ZUJlZm9yZUV2ZW50OiBTIHwgdW5kZWZpbmVkXG4gIH1cblxuICBjb25zdCBwYXRjaFJlY29yZGVyU3ltYm9sID0gU3ltYm9sKFwicGF0Y2hSZWNvcmRlclwiKVxuXG4gIGZ1bmN0aW9uIGluaXRQYXRjaFJlY29yZGVyKGN0eDogU2ltcGxlQWN0aW9uQ29udGV4dCkge1xuICAgIGNvbnN0IGdyb3VwID0gbWFuYWdlci5zdG9yZS5fY3VycmVudEdyb3VwXG5cbiAgICBjb25zdCBwYXRjaFJlY29yZGVyRGF0YTogUGF0Y2hSZWNvcmRlckRhdGEgPSB7XG4gICAgICByZWNvcmRlcjogcGF0Y2hSZWNvcmRlcihzdWJ0cmVlUm9vdCwge1xuICAgICAgICByZWNvcmRpbmc6IGZhbHNlLFxuICAgICAgICBmaWx0ZXI6ICgpID0+IHtcbiAgICAgICAgICByZXR1cm4gIV9pc0dsb2JhbFVuZG9SZWNvcmRpbmdEaXNhYmxlZCAmJiAhbWFuYWdlci5pc1VuZG9SZWNvcmRpbmdEaXNhYmxlZFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgICByZWNvcmRlclN0YWNrOiAwLFxuICAgICAgdW5kb1Jvb3RDb250ZXh0OiBjdHgsXG4gICAgICBncm91cCxcblxuICAgICAgYXR0YWNoZWRTdGF0ZUJlZm9yZUV2ZW50OiBvcHRpb25zPy5hdHRhY2hlZFN0YXRlPy5zYXZlKCksXG4gICAgfVxuXG4gICAgY3R4LnJvb3RDb250ZXh0LmRhdGFbcGF0Y2hSZWNvcmRlclN5bWJvbF0gPSBwYXRjaFJlY29yZGVyRGF0YVxuICB9XG5cbiAgZnVuY3Rpb24gZ2V0UGF0Y2hSZWNvcmRlckRhdGEoY3R4OiBTaW1wbGVBY3Rpb25Db250ZXh0KTogUGF0Y2hSZWNvcmRlckRhdGEge1xuICAgIHJldHVybiBjdHgucm9vdENvbnRleHQuZGF0YVtwYXRjaFJlY29yZGVyU3ltYm9sXVxuICB9XG5cbiAgY29uc3QgbWlkZGxld2FyZURpc3Bvc2VyID0gYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlKHN1YnRyZWVSb290LCB7XG4gICAgb25TdGFydChjdHgpIHtcbiAgICAgIGlmICghZ2V0UGF0Y2hSZWNvcmRlckRhdGEoY3R4KSkge1xuICAgICAgICBpbml0UGF0Y2hSZWNvcmRlcihjdHgpXG4gICAgICB9XG4gICAgfSxcbiAgICBvblJlc3VtZShjdHgpIHtcbiAgICAgIGNvbnN0IHBhdGNoUmVjb3JkZXJEYXRhID0gZ2V0UGF0Y2hSZWNvcmRlckRhdGEoY3R4KVxuICAgICAgcGF0Y2hSZWNvcmRlckRhdGEucmVjb3JkZXJTdGFjaysrXG4gICAgICBwYXRjaFJlY29yZGVyRGF0YS5yZWNvcmRlci5yZWNvcmRpbmcgPSBwYXRjaFJlY29yZGVyRGF0YS5yZWNvcmRlclN0YWNrID4gMFxuICAgIH0sXG4gICAgb25TdXNwZW5kKGN0eCkge1xuICAgICAgY29uc3QgcGF0Y2hSZWNvcmRlckRhdGEgPSBnZXRQYXRjaFJlY29yZGVyRGF0YShjdHgpXG4gICAgICBwYXRjaFJlY29yZGVyRGF0YS5yZWNvcmRlclN0YWNrLS1cbiAgICAgIHBhdGNoUmVjb3JkZXJEYXRhLnJlY29yZGVyLnJlY29yZGluZyA9IHBhdGNoUmVjb3JkZXJEYXRhLnJlY29yZGVyU3RhY2sgPiAwXG4gICAgfSxcbiAgICBvbkZpbmlzaChjdHgpIHtcbiAgICAgIGNvbnN0IHBhdGNoUmVjb3JkZXJEYXRhID0gZ2V0UGF0Y2hSZWNvcmRlckRhdGEoY3R4KVxuICAgICAgaWYgKHBhdGNoUmVjb3JkZXJEYXRhICYmIHBhdGNoUmVjb3JkZXJEYXRhLnVuZG9Sb290Q29udGV4dCA9PT0gY3R4KSB7XG4gICAgICAgIGNvbnN0IHBhdGNoUmVjb3JkZXIgPSBwYXRjaFJlY29yZGVyRGF0YS5yZWNvcmRlclxuXG4gICAgICAgIGlmIChwYXRjaFJlY29yZGVyLmV2ZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc3QgcGF0Y2hlczogUGF0Y2hbXSA9IFtdXG4gICAgICAgICAgY29uc3QgaW52ZXJzZVBhdGNoZXM6IFBhdGNoW10gPSBbXVxuXG4gICAgICAgICAgZm9yIChjb25zdCBldmVudCBvZiBwYXRjaFJlY29yZGVyLmV2ZW50cykge1xuICAgICAgICAgICAgcGF0Y2hlcy5wdXNoKC4uLmV2ZW50LnBhdGNoZXMpXG4gICAgICAgICAgICBpbnZlcnNlUGF0Y2hlcy5wdXNoKC4uLmV2ZW50LmludmVyc2VQYXRjaGVzKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogVW5kb0V2ZW50VHlwZS5TaW5nbGUsXG4gICAgICAgICAgICB0YXJnZXRQYXRoOiBmYXN0R2V0Um9vdFBhdGgoY3R4LnRhcmdldCkucGF0aCxcbiAgICAgICAgICAgIGFjdGlvbk5hbWU6IGN0eC5hY3Rpb25OYW1lLFxuICAgICAgICAgICAgcGF0Y2hlcyxcbiAgICAgICAgICAgIGludmVyc2VQYXRjaGVzLFxuICAgICAgICAgIH0gYXMgY29uc3RcblxuICAgICAgICAgIGNvbnN0IHBhcmVudEdyb3VwID0gcGF0Y2hSZWNvcmRlckRhdGEuZ3JvdXBcblxuICAgICAgICAgIGlmIChwYXJlbnRHcm91cCkge1xuICAgICAgICAgICAgbWFuYWdlci5zdG9yZS5fYWRkVW5kb1RvUGFyZW50R3JvdXAocGFyZW50R3JvdXAsIGV2ZW50KVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYW5hZ2VyLnN0b3JlLl9hZGRVbmRvKHtcbiAgICAgICAgICAgICAgZXZlbnQ6IHtcbiAgICAgICAgICAgICAgICAuLi5ldmVudCxcbiAgICAgICAgICAgICAgICBhdHRhY2hlZFN0YXRlOiB7XG4gICAgICAgICAgICAgICAgICBiZWZvcmVFdmVudDogcGF0Y2hSZWNvcmRlckRhdGEuYXR0YWNoZWRTdGF0ZUJlZm9yZUV2ZW50LFxuICAgICAgICAgICAgICAgICAgYWZ0ZXJFdmVudDogb3B0aW9ucz8uYXR0YWNoZWRTdGF0ZT8uc2F2ZSgpLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG1heFVuZG9MZXZlbHM6IG9wdGlvbnM/Lm1heFVuZG9MZXZlbHMsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHBhdGNoUmVjb3JkZXIuZGlzcG9zZSgpXG4gICAgICB9XG4gICAgfSxcbiAgfSlcblxuICBtYW5hZ2VyID0gbmV3IFVuZG9NYW5hZ2VyKG1pZGRsZXdhcmVEaXNwb3Nlciwgc3VidHJlZVJvb3QsIHN0b3JlLCBvcHRpb25zKVxuICByZXR1cm4gbWFuYWdlclxufVxuXG5sZXQgX2lzR2xvYmFsVW5kb1JlY29yZGluZ0Rpc2FibGVkID0gZmFsc2VcblxuLyoqXG4gKiBSZXR1cm5zIGlmIHRoZSB1bmRvIHJlY29yZGluZyBtZWNoYW5pc20gaXMgY3VycmVudGx5IGRpc2FibGVkLlxuICpcbiAqIEByZXR1cm5zIGB0cnVlYCBpZiBpdCBpcyBjdXJyZW50bHkgZGlzYWJsZWQsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNHbG9iYWxVbmRvUmVjb3JkaW5nRGlzYWJsZWQoKSB7XG4gIHJldHVybiBfaXNHbG9iYWxVbmRvUmVjb3JkaW5nRGlzYWJsZWRcbn1cblxuLyoqXG4gKiBHbG9iYWxseSBza2lwcyB0aGUgdW5kbyByZWNvcmRpbmcgbWVjaGFuaXNtIGZvciB0aGUgY29kZSBibG9jayB0aGF0IGdldHMgcnVuIHN5bmNocm9ub3VzbHkgaW5zaWRlLlxuICogQ29uc2lkZXIgdXNpbmcgdGhlIGB3aXRob3V0VW5kb2AgbWV0aG9kIG9mIGEgcGFydGljdWxhciBgVW5kb01hbmFnZXJgIGluc3RlYWQuXG4gKlxuICogQHR5cGVwYXJhbSBUIENvZGUgYmxvY2sgcmV0dXJuIHR5cGUuXG4gKiBAcGFyYW0gZm4gQ29kZSBibG9jayB0byBydW4uXG4gKiBAcmV0dXJucyBUaGUgdmFsdWUgcmV0dXJuZWQgYnkgdGhlIGNvZGUgYmxvY2suXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3aXRob3V0VW5kbzxUPihmbjogKCkgPT4gVCk6IFQge1xuICBjb25zdCBzYXZlZFVuZG9EaXNhYmxlZCA9IF9pc0dsb2JhbFVuZG9SZWNvcmRpbmdEaXNhYmxlZFxuICBfaXNHbG9iYWxVbmRvUmVjb3JkaW5nRGlzYWJsZWQgPSB0cnVlXG4gIHRyeSB7XG4gICAgcmV0dXJuIGZuKClcbiAgfSBmaW5hbGx5IHtcbiAgICBfaXNHbG9iYWxVbmRvUmVjb3JkaW5nRGlzYWJsZWQgPSBzYXZlZFVuZG9EaXNhYmxlZFxuICB9XG59XG4iLCJpbXBvcnQgeyBhY3Rpb24sIGNvbXB1dGVkLCBjcmVhdGVBdG9tLCBJQXRvbSwgSUNvbXB1dGVkVmFsdWUsIG9ic2VydmFibGUgfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7IGZhc3RHZXRQYXJlbnQgfSBmcm9tIFwiLi4vcGFyZW50L3BhdGhcIlxyXG5pbXBvcnQgeyBhc3NlcnRUd2Vha2VkT2JqZWN0LCBpc1R3ZWFrZWRPYmplY3QgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcclxuaW1wb3J0IHsgZ2V0T3JDcmVhdGUgfSBmcm9tIFwiLi4vdXRpbHMvbWFwVXRpbHNcIlxyXG5cclxuLyoqXHJcbiAqIEEgY29udGV4dC5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29udGV4dDxUPiB7XHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgY29udGV4dCBkZWZhdWx0IHZhbHVlLlxyXG4gICAqXHJcbiAgICogQHJldHVybnNcclxuICAgKi9cclxuICBnZXREZWZhdWx0KCk6IFRcclxuXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgY29udGV4dCBkZWZhdWx0IHZhbHVlLlxyXG4gICAqIEBwYXJhbSB2YWx1ZVxyXG4gICAqL1xyXG4gIHNldERlZmF1bHQodmFsdWU6IFQpOiB2b2lkXHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgdGhlIGNvbnRleHQgZGVmYXVsdCB2YWx1ZSByZXNvbHZlci5cclxuICAgKiBAcGFyYW0gdmFsdWVGblxyXG4gICAqL1xyXG4gIHNldERlZmF1bHRDb21wdXRlZCh2YWx1ZUZuOiAoKSA9PiBUKTogdm9pZFxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBjb250ZXh0IHZhbHVlIGZvciBhIGdpdmVuIG5vZGUuXHJcbiAgICogQHBhcmFtIG5vZGVcclxuICAgKi9cclxuICBnZXQobm9kZTogb2JqZWN0KTogVFxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIG5vZGUgdGhhdCB3aWxsIHByb3ZpZGUgdGhlIGNvbnRleHQgdmFsdWUsIG9yIGB1bmRlZmluZWRgXHJcbiAgICogaWYgaXQgY29tZXMgZnJvbSB0aGUgZGVmYXVsdC5cclxuICAgKiBAcGFyYW0gbm9kZVxyXG4gICAqL1xyXG4gIGdldFByb3ZpZGVyTm9kZShub2RlOiBvYmplY3QpOiBvYmplY3QgfCB1bmRlZmluZWRcclxuXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgY29udGV4dCB2YWx1ZSBmb3IgYSBnaXZlbiBub2RlLCBlZmZlY3RpdmVseSBtYWtpbmcgaXQgYSBwcm92aWRlci5cclxuICAgKiBAcGFyYW0gbm9kZVxyXG4gICAqIEBwYXJhbSB2YWx1ZVxyXG4gICAqL1xyXG4gIHNldChub2RlOiBvYmplY3QsIHZhbHVlOiBUKTogdm9pZFxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIHRoZSBjb250ZXh0IHZhbHVlIHJlc29sdmVyIGZvciBhIGdpdmVuIG5vZGUsIGVmZmVjdGl2ZWx5IG1ha2luZyBpdCBhIHByb3ZpZGVyLlxyXG4gICAqIEBwYXJhbSBub2RlXHJcbiAgICogQHBhcmFtIHZhbHVlRm5cclxuICAgKi9cclxuICBzZXRDb21wdXRlZChub2RlOiBvYmplY3QsIHZhbHVlRm46ICgpID0+IFQpOiB2b2lkXHJcblxyXG4gIC8qKlxyXG4gICAqIFVuc2V0cyB0aGUgY29udGV4dCB2YWx1ZSBmb3IgYSBnaXZlbiBub2RlLCB0aGVyZWZvcmUgaXQgd29uJ3QgYmUgYSBwcm92aWRlciBhbnltb3JlLlxyXG4gICAqIEBwYXJhbSBub2RlXHJcbiAgICovXHJcbiAgdW5zZXQobm9kZTogb2JqZWN0KTogdm9pZFxyXG5cclxuICAvKipcclxuICAgKiBBcHBsaWVzIGEgdmFsdWUgb3ZlcnJpZGUgd2hpbGUgdGhlIGdpdmVuIGZ1bmN0aW9uIGlzIHJ1bm5pbmcgYW5kLCBpZiBhIG5vZGUgaXMgcmV0dXJuZWQsXHJcbiAgICogc2V0cyB0aGUgbm9kZSBhcyBhIHByb3ZpZGVyIG9mIHRoZSB2YWx1ZS5cclxuICAgKlxyXG4gICAqIEB0eXBlcGFyYW0gUlxyXG4gICAqIEBwYXJhbSBmbiBGdW5jdGlvbiB0byBydW4uXHJcbiAgICogQHBhcmFtIHZhbHVlIFZhbHVlIHRvIGFwcGx5LlxyXG4gICAqIEByZXR1cm5zIFRoZSB2YWx1ZSByZXR1cm5lZCBmcm9tIHRoZSBmdW5jdGlvbi5cclxuICAgKi9cclxuICBhcHBseTxSPihmbjogKCkgPT4gUiwgdmFsdWU6IFQpOiBSXHJcblxyXG4gIC8qKlxyXG4gICAqIEFwcGxpZXMgYSBjb21wdXRlZCB2YWx1ZSBvdmVycmlkZSB3aGlsZSB0aGUgZ2l2ZW4gZnVuY3Rpb24gaXMgcnVubmluZyBhbmQsIGlmIGEgbm9kZSBpcyByZXR1cm5lZCxcclxuICAgKiBzZXRzIHRoZSBub2RlIGFzIGEgcHJvdmlkZXIgb2YgdGhlIGNvbXB1dGVkIHZhbHVlLlxyXG4gICAqXHJcbiAgICogQHR5cGVwYXJhbSBSXHJcbiAgICogQHBhcmFtIGZuIEZ1bmN0aW9uIHRvIHJ1bi5cclxuICAgKiBAcGFyYW0gdmFsdWUgVmFsdWUgdG8gYXBwbHkuXHJcbiAgICogQHJldHVybnMgVGhlIHZhbHVlIHJldHVybmVkIGZyb20gdGhlIGZ1bmN0aW9uLlxyXG4gICAqL1xyXG4gIGFwcGx5Q29tcHV0ZWQ8Uj4oZm46ICgpID0+IFIsIHZhbHVlRm46ICgpID0+IFQpOiBSXHJcbn1cclxuXHJcbnR5cGUgQ29udGV4dFZhbHVlPFQ+ID1cclxuICB8IHtcclxuICAgICAgdHlwZTogXCJ2YWx1ZVwiXHJcbiAgICAgIHZhbHVlOiBUXHJcbiAgICB9XHJcbiAgfCB7XHJcbiAgICAgIHR5cGU6IFwiY29tcHV0ZWRcIlxyXG4gICAgICB2YWx1ZTogSUNvbXB1dGVkVmFsdWU8VD5cclxuICAgIH1cclxuXHJcbmZ1bmN0aW9uIHJlc29sdmVDb250ZXh0VmFsdWU8VD4oY29udGV4dFZhbHVlOiBDb250ZXh0VmFsdWU8VD4pOiBUIHtcclxuICBpZiAoY29udGV4dFZhbHVlLnR5cGUgPT09IFwidmFsdWVcIikge1xyXG4gICAgcmV0dXJuIGNvbnRleHRWYWx1ZS52YWx1ZVxyXG4gIH0gZWxzZSB7XHJcbiAgICByZXR1cm4gY29udGV4dFZhbHVlLnZhbHVlLmdldCgpXHJcbiAgfVxyXG59XHJcblxyXG5jb25zdCBjcmVhdGVDb250ZXh0VmFsdWVBdG9tID0gKCkgPT4gY3JlYXRlQXRvbShcImNvbnRleHRWYWx1ZVwiKVxyXG5cclxuY2xhc3MgQ29udGV4dENsYXNzPFQ+IGltcGxlbWVudHMgQ29udGV4dDxUPiB7XHJcbiAgcHJpdmF0ZSBkZWZhdWx0Q29udGV4dFZhbHVlID0gb2JzZXJ2YWJsZS5ib3g8Q29udGV4dFZhbHVlPFQ+Pih1bmRlZmluZWQsIHsgZGVlcDogZmFsc2UgfSlcclxuXHJcbiAgcHJpdmF0ZSBvdmVycmlkZUNvbnRleHRWYWx1ZSA9IG9ic2VydmFibGUuYm94PENvbnRleHRWYWx1ZTxUPiB8IHVuZGVmaW5lZD4odW5kZWZpbmVkLCB7XHJcbiAgICBkZWVwOiBmYWxzZSxcclxuICB9KVxyXG5cclxuICBwcml2YXRlIHJlYWRvbmx5IG5vZGVDb250ZXh0VmFsdWUgPSBuZXcgV2Vha01hcDxvYmplY3QsIENvbnRleHRWYWx1ZTxUPj4oKVxyXG4gIHByaXZhdGUgcmVhZG9ubHkgbm9kZUF0b20gPSBuZXcgV2Vha01hcDxvYmplY3QsIElBdG9tPigpXHJcblxyXG4gIHByaXZhdGUgZ2V0Tm9kZUF0b20obm9kZTogb2JqZWN0KSB7XHJcbiAgICByZXR1cm4gZ2V0T3JDcmVhdGUodGhpcy5ub2RlQXRvbSwgbm9kZSwgY3JlYXRlQ29udGV4dFZhbHVlQXRvbSlcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZmFzdEdldChub2RlOiBvYmplY3QpOiBUIHtcclxuICAgIHRoaXMuZ2V0Tm9kZUF0b20obm9kZSkucmVwb3J0T2JzZXJ2ZWQoKVxyXG5cclxuICAgIGNvbnN0IG9ic0Zvck5vZGUgPSB0aGlzLm5vZGVDb250ZXh0VmFsdWUuZ2V0KG5vZGUpXHJcbiAgICBpZiAob2JzRm9yTm9kZSkge1xyXG4gICAgICByZXR1cm4gcmVzb2x2ZUNvbnRleHRWYWx1ZShvYnNGb3JOb2RlKVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHBhcmVudCA9IGZhc3RHZXRQYXJlbnQobm9kZSlcclxuICAgIGlmICghcGFyZW50KSB7XHJcbiAgICAgIGNvbnN0IG92ZXJyaWRlVmFsdWUgPSB0aGlzLm92ZXJyaWRlQ29udGV4dFZhbHVlLmdldCgpXHJcbiAgICAgIGlmIChvdmVycmlkZVZhbHVlKSB7XHJcbiAgICAgICAgcmV0dXJuIHJlc29sdmVDb250ZXh0VmFsdWUob3ZlcnJpZGVWYWx1ZSlcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gdGhpcy5nZXREZWZhdWx0KClcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdGhpcy5mYXN0R2V0KHBhcmVudClcclxuICB9XHJcblxyXG4gIGdldChub2RlOiBvYmplY3QpIHtcclxuICAgIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZSwgXCJub2RlXCIpXHJcblxyXG4gICAgcmV0dXJuIHRoaXMuZmFzdEdldChub2RlKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmYXN0R2V0UHJvdmlkZXJOb2RlKG5vZGU6IG9iamVjdCk6IG9iamVjdCB8IHVuZGVmaW5lZCB7XHJcbiAgICB0aGlzLmdldE5vZGVBdG9tKG5vZGUpLnJlcG9ydE9ic2VydmVkKClcclxuXHJcbiAgICBjb25zdCBvYnNGb3JOb2RlID0gdGhpcy5ub2RlQ29udGV4dFZhbHVlLmdldChub2RlKVxyXG4gICAgaWYgKG9ic0Zvck5vZGUpIHtcclxuICAgICAgcmV0dXJuIG5vZGVcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBwYXJlbnQgPSBmYXN0R2V0UGFyZW50KG5vZGUpXHJcbiAgICBpZiAoIXBhcmVudCkge1xyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkXHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuZmFzdEdldFByb3ZpZGVyTm9kZShwYXJlbnQpXHJcbiAgfVxyXG5cclxuICBnZXRQcm92aWRlck5vZGUobm9kZTogb2JqZWN0KTogb2JqZWN0IHwgdW5kZWZpbmVkIHtcclxuICAgIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZSwgXCJub2RlXCIpXHJcblxyXG4gICAgcmV0dXJuIHRoaXMuZmFzdEdldFByb3ZpZGVyTm9kZShub2RlKVxyXG4gIH1cclxuXHJcbiAgZ2V0RGVmYXVsdCgpOiBUIHtcclxuICAgIHJldHVybiByZXNvbHZlQ29udGV4dFZhbHVlKHRoaXMuZGVmYXVsdENvbnRleHRWYWx1ZS5nZXQoKSEpXHJcbiAgfVxyXG5cclxuICBzZXREZWZhdWx0ID0gYWN0aW9uKCh2YWx1ZTogVCkgPT4ge1xyXG4gICAgdGhpcy5kZWZhdWx0Q29udGV4dFZhbHVlLnNldCh7XHJcbiAgICAgIHR5cGU6IFwidmFsdWVcIixcclxuICAgICAgdmFsdWUsXHJcbiAgICB9KVxyXG4gIH0pXHJcblxyXG4gIHNldERlZmF1bHRDb21wdXRlZCA9IGFjdGlvbigodmFsdWVGbjogKCkgPT4gVCkgPT4ge1xyXG4gICAgdGhpcy5kZWZhdWx0Q29udGV4dFZhbHVlLnNldCh7XHJcbiAgICAgIHR5cGU6IFwiY29tcHV0ZWRcIixcclxuICAgICAgdmFsdWU6IGNvbXB1dGVkKHZhbHVlRm4pLFxyXG4gICAgfSlcclxuICB9KVxyXG5cclxuICBzZXQgPSBhY3Rpb24oKG5vZGU6IG9iamVjdCwgdmFsdWU6IFQpID0+IHtcclxuICAgIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZSwgXCJub2RlXCIpXHJcblxyXG4gICAgdGhpcy5ub2RlQ29udGV4dFZhbHVlLnNldChub2RlLCB7XHJcbiAgICAgIHR5cGU6IFwidmFsdWVcIixcclxuICAgICAgdmFsdWUsXHJcbiAgICB9KVxyXG4gICAgdGhpcy5nZXROb2RlQXRvbShub2RlKS5yZXBvcnRDaGFuZ2VkKClcclxuICB9KVxyXG5cclxuICBwcml2YXRlIF9zZXRDb21wdXRlZChub2RlOiBvYmplY3QsIGNvbXB1dGVkVmFsdWVGbjogSUNvbXB1dGVkVmFsdWU8VD4pIHtcclxuICAgIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZSwgXCJub2RlXCIpXHJcblxyXG4gICAgdGhpcy5ub2RlQ29udGV4dFZhbHVlLnNldChub2RlLCB7IHR5cGU6IFwiY29tcHV0ZWRcIiwgdmFsdWU6IGNvbXB1dGVkVmFsdWVGbiB9KVxyXG4gICAgdGhpcy5nZXROb2RlQXRvbShub2RlKS5yZXBvcnRDaGFuZ2VkKClcclxuICB9XHJcblxyXG4gIHNldENvbXB1dGVkID0gYWN0aW9uKChub2RlOiBvYmplY3QsIHZhbHVlRm46ICgpID0+IFQpID0+IHtcclxuICAgIHRoaXMuX3NldENvbXB1dGVkKG5vZGUsIGNvbXB1dGVkKHZhbHVlRm4pKVxyXG4gIH0pXHJcblxyXG4gIHVuc2V0ID0gYWN0aW9uKChub2RlOiBvYmplY3QpID0+IHtcclxuICAgIGFzc2VydFR3ZWFrZWRPYmplY3Qobm9kZSwgXCJub2RlXCIpXHJcblxyXG4gICAgdGhpcy5ub2RlQ29udGV4dFZhbHVlLmRlbGV0ZShub2RlKVxyXG4gICAgdGhpcy5nZXROb2RlQXRvbShub2RlKS5yZXBvcnRDaGFuZ2VkKClcclxuICB9KVxyXG5cclxuICBhcHBseSA9IGFjdGlvbig8Uj4oZm46ICgpID0+IFIsIHZhbHVlOiBUKTogUiA9PiB7XHJcbiAgICBjb25zdCBvbGQgPSB0aGlzLm92ZXJyaWRlQ29udGV4dFZhbHVlLmdldCgpXHJcbiAgICB0aGlzLm92ZXJyaWRlQ29udGV4dFZhbHVlLnNldCh7XHJcbiAgICAgIHR5cGU6IFwidmFsdWVcIixcclxuICAgICAgdmFsdWUsXHJcbiAgICB9KVxyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHJldCA9IGZuKClcclxuICAgICAgaWYgKGlzVHdlYWtlZE9iamVjdChyZXQsIHRydWUpKSB7XHJcbiAgICAgICAgdGhpcy5zZXQocmV0LCB2YWx1ZSlcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gcmV0XHJcbiAgICB9IGZpbmFsbHkge1xyXG4gICAgICB0aGlzLm92ZXJyaWRlQ29udGV4dFZhbHVlLnNldChvbGQpXHJcbiAgICB9XHJcbiAgfSlcclxuXHJcbiAgYXBwbHlDb21wdXRlZCA9IGFjdGlvbig8Uj4oZm46ICgpID0+IFIsIHZhbHVlRm46ICgpID0+IFQpOiBSID0+IHtcclxuICAgIGNvbnN0IGNvbXB1dGVkVmFsdWVGbiA9IGNvbXB1dGVkKHZhbHVlRm4pXHJcblxyXG4gICAgY29uc3Qgb2xkID0gdGhpcy5vdmVycmlkZUNvbnRleHRWYWx1ZS5nZXQoKVxyXG4gICAgdGhpcy5vdmVycmlkZUNvbnRleHRWYWx1ZS5zZXQoe1xyXG4gICAgICB0eXBlOiBcImNvbXB1dGVkXCIsXHJcbiAgICAgIHZhbHVlOiBjb21wdXRlZFZhbHVlRm4sXHJcbiAgICB9KVxyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHJldCA9IGZuKClcclxuICAgICAgaWYgKGlzVHdlYWtlZE9iamVjdChyZXQsIHRydWUpKSB7XHJcbiAgICAgICAgdGhpcy5fc2V0Q29tcHV0ZWQocmV0LCBjb21wdXRlZFZhbHVlRm4pXHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHJldFxyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgdGhpcy5vdmVycmlkZUNvbnRleHRWYWx1ZS5zZXQob2xkKVxyXG4gICAgfVxyXG4gIH0pXHJcblxyXG4gIGNvbnN0cnVjdG9yKGRlZmF1bHRWYWx1ZT86IFQpIHtcclxuICAgIHRoaXMuc2V0RGVmYXVsdChkZWZhdWx0VmFsdWUgYXMgVClcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDcmVhdGVzIGEgbmV3IGNvbnRleHQgd2l0aCBubyBkZWZhdWx0IHZhbHVlLCB0aHVzIG1ha2luZyBpdHMgZGVmYXVsdCB2YWx1ZSB1bmRlZmluZWQuXHJcbiAqXHJcbiAqIEB0eXBlcGFyYW0gVCBDb250ZXh0IHZhbHVlIHR5cGUuXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29udGV4dDxUPigpOiBDb250ZXh0PFQgfCB1bmRlZmluZWQ+XHJcblxyXG4vKipcclxuICogQ3JlYXRlcyBhIG5ldyBjb250ZXh0IHdpdGggYSBkZWZhdWx0IHZhbHVlLlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgQ29udGV4dCB2YWx1ZSB0eXBlLlxyXG4gKiBAcGFyYW0gZGVmYXVsdFZhbHVlXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29udGV4dDxUPihkZWZhdWx0VmFsdWU6IFQpOiBDb250ZXh0PFQ+XHJcblxyXG4vLyBiYXNlXHJcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb250ZXh0PFQ+KGRlZmF1bHRWYWx1ZT86IFQpOiBDb250ZXh0PFQ+IHtcclxuICByZXR1cm4gbmV3IENvbnRleHRDbGFzcyhkZWZhdWx0VmFsdWUpXHJcbn1cclxuIiwiaW1wb3J0IHsgY29tcHV0ZWQsIElDb21wdXRlZFZhbHVlIH0gZnJvbSBcIm1vYnhcIlxyXG5pbXBvcnQgeyByZWFkb25seU1pZGRsZXdhcmUgfSBmcm9tIFwiLi4vYWN0aW9uTWlkZGxld2FyZXMvcmVhZG9ubHlNaWRkbGV3YXJlXCJcclxuaW1wb3J0IHsgY3JlYXRlQ29udGV4dCB9IGZyb20gXCIuLi9jb250ZXh0L2NvbnRleHRcIlxyXG5pbXBvcnQgeyBpc0RhdGFNb2RlbENsYXNzIH0gZnJvbSBcIi4uL2RhdGFNb2RlbC91dGlsc1wiXHJcbmltcG9ydCB7IGlzTW9kZWxDbGFzcyB9IGZyb20gXCIuLi9tb2RlbC91dGlsc1wiXHJcbmltcG9ydCB7IGlzVHJlZU5vZGUgfSBmcm9tIFwiLi4vdHdlYWtlci9jb3JlXCJcclxuaW1wb3J0IHsgdHdlYWsgfSBmcm9tIFwiLi4vdHdlYWtlci90d2Vha1wiXHJcbmltcG9ydCB7IGFkZExhdGVJbml0aWFsaXphdGlvbkZ1bmN0aW9uLCBmYWlsdXJlLCBydW5CZWZvcmVPbkluaXRTeW1ib2wgfSBmcm9tIFwiLi4vdXRpbHNcIlxyXG5pbXBvcnQgeyBnZXRPckNyZWF0ZSB9IGZyb20gXCIuLi91dGlscy9tYXBVdGlsc1wiXHJcbmltcG9ydCB7IGNoZWNrRGVjb3JhdG9yQ29udGV4dCB9IGZyb20gXCIuLi91dGlscy9kZWNvcmF0b3JzXCJcclxuXHJcbmNvbnN0IGNvbXB1dGVkVHJlZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KGZhbHNlKVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgaWYgYSBnaXZlbiBub2RlIGlzIGEgY29tcHV0ZWQgdHJlZSBub2RlLlxyXG4gKlxyXG4gKiBAcGFyYW0gbm9kZSBOb2RlIHRvIGNoZWNrLlxyXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgaXQgaXMgYSBjb21wdXRlZCB0cmVlIG5vZGUsIGBmYWxzZWAgb3RoZXJ3aXNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzQ29tcHV0ZWRUcmVlTm9kZShub2RlOiBvYmplY3QpOiBib29sZWFuIHtcclxuICByZXR1cm4gY29tcHV0ZWRUcmVlQ29udGV4dC5nZXQobm9kZSlcclxufVxyXG5cclxuY29uc3QgdHdlYWtlZENvbXB1dGVkVHJlZU5vZGVzID0gbmV3IFdlYWtTZXQ8b2JqZWN0PigpXHJcblxyXG5mdW5jdGlvbiB0d2Vha0NvbXB1dGVkVHJlZU5vZGU8VD4obmV3VmFsdWU6IFQsIHBhcmVudDogdW5rbm93biwgcGF0aDogc3RyaW5nKTogVCB7XHJcbiAgY29uc3QgdHdlYWtlZFZhbHVlID0gdHdlYWsobmV3VmFsdWUsIHsgcGFyZW50LCBwYXRoIH0pXHJcbiAgaWYgKGlzVHJlZU5vZGUodHdlYWtlZFZhbHVlKSAmJiAhdHdlYWtlZENvbXB1dGVkVHJlZU5vZGVzLmhhcyh0d2Vha2VkVmFsdWUpKSB7XHJcbiAgICB0d2Vha2VkQ29tcHV0ZWRUcmVlTm9kZXMuYWRkKHR3ZWFrZWRWYWx1ZSlcclxuICAgIHJlYWRvbmx5TWlkZGxld2FyZSh0d2Vha2VkVmFsdWUpXHJcbiAgICBjb21wdXRlZFRyZWVDb250ZXh0LnNldCh0d2Vha2VkVmFsdWUsIHRydWUpXHJcbiAgfVxyXG4gIHJldHVybiB0d2Vha2VkVmFsdWVcclxufVxyXG5cclxuY29uc3QgY29tcHV0ZWRUcmVlTm9kZUluZm8gPSBuZXcgV2Vha01hcDxcclxuICBvYmplY3QsXHJcbiAgTWFwPHN0cmluZywgeyBjb21wdXRlZDogSUNvbXB1dGVkVmFsdWU8dW5rbm93bj47IHZhbHVlOiB1bmtub3duOyB0d2Vha2VkVmFsdWU6IHVua25vd24gfT5cclxuPigpXHJcblxyXG5mdW5jdGlvbiBnZXRPckNyZWF0ZUNvbXB1dGVkVHJlZU5vZGVJbmZvKGluc3RhbmNlOiBvYmplY3QpIHtcclxuICByZXR1cm4gZ2V0T3JDcmVhdGUoY29tcHV0ZWRUcmVlTm9kZUluZm8sIGluc3RhbmNlLCAoKSA9PiBuZXcgTWFwKCkpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEZWNvcmF0b3IgZm9yIHR1cm5pbmcgYSBjb21wdXRlZCBwcm9wZXJ0eSBpbnRvIGEgY29tcHV0ZWQgdHJlZSB3aGljaCBzdXBwb3J0cyB0cmVlIHRyYXZlcnNhbFxyXG4gKiBmdW5jdGlvbnMsIGNvbnRleHRzLCByZWZlcmVuY2VzLCBldGMuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZWRUcmVlKC4uLmFyZ3M6IGFueVtdKTogYW55IHtcclxuICBjb25zdCBjcmVhdGVHZXR0ZXIgPSAocHJvcGVydHlLZXk6IHN0cmluZykgPT5cclxuICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpIHtcclxuICAgICAgY29uc3QgZW50cnkgPSBnZXRPckNyZWF0ZUNvbXB1dGVkVHJlZU5vZGVJbmZvKHRoaXMpLmdldChwcm9wZXJ0eUtleSkhXHJcblxyXG4gICAgICBjb25zdCBvbGRWYWx1ZSA9IGVudHJ5LnZhbHVlXHJcbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gZW50cnkuY29tcHV0ZWQuZ2V0KClcclxuXHJcbiAgICAgIGlmIChvbGRWYWx1ZSA9PT0gbmV3VmFsdWUpIHtcclxuICAgICAgICByZXR1cm4gZW50cnkudHdlYWtlZFZhbHVlXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IG9sZFR3ZWFrZWRWYWx1ZSA9IGVudHJ5LnR3ZWFrZWRWYWx1ZVxyXG4gICAgICB0d2VhayhvbGRUd2Vha2VkVmFsdWUsIHVuZGVmaW5lZClcclxuXHJcbiAgICAgIGNvbnN0IHR3ZWFrZWRWYWx1ZSA9IHR3ZWFrQ29tcHV0ZWRUcmVlTm9kZShuZXdWYWx1ZSwgdGhpcywgcHJvcGVydHlLZXkpXHJcbiAgICAgIGVudHJ5LnZhbHVlID0gbmV3VmFsdWVcclxuICAgICAgZW50cnkudHdlYWtlZFZhbHVlID0gdHdlYWtlZFZhbHVlXHJcbiAgICAgIHJldHVybiB0d2Vha2VkVmFsdWVcclxuICAgIH1cclxuXHJcbiAgY29uc3QgcnVuTGF0ZUluaXQgPSAoaW5zdGFuY2U6IGFueSwgb3JpZ2luYWw6IGFueSwgcHJvcGVydHlLZXk6IHN0cmluZykgPT4ge1xyXG4gICAgY29uc3QgYyA9IGNvbXB1dGVkKCgpID0+IG9yaWdpbmFsLmNhbGwoaW5zdGFuY2UpLCB7IGtlZXBBbGl2ZTogdHJ1ZSB9KVxyXG4gICAgY29uc3QgbmV3VmFsdWUgPSBjLmdldCgpXHJcbiAgICBjb25zdCB0d2Vha2VkVmFsdWUgPSB0d2Vha0NvbXB1dGVkVHJlZU5vZGUobmV3VmFsdWUsIGluc3RhbmNlLCBwcm9wZXJ0eUtleSlcclxuXHJcbiAgICBnZXRPckNyZWF0ZUNvbXB1dGVkVHJlZU5vZGVJbmZvKGluc3RhbmNlKS5zZXQocHJvcGVydHlLZXksIHtcclxuICAgICAgY29tcHV0ZWQ6IGMsXHJcbiAgICAgIHZhbHVlOiBuZXdWYWx1ZSxcclxuICAgICAgdHdlYWtlZFZhbHVlLFxyXG4gICAgfSlcclxuICB9XHJcblxyXG4gIGNvbnN0IGNoZWNrSW5zdGFuY2VDbGFzcyA9IChpbnN0YW5jZTogYW55KSA9PiB7XHJcbiAgICBjb25zdCBpbnN0YW5jZUNsYXNzID0gaW5zdGFuY2UuY29uc3RydWN0b3JcclxuICAgIGlmICghaXNNb2RlbENsYXNzKGluc3RhbmNlQ2xhc3MpICYmICFpc0RhdGFNb2RlbENsYXNzKGluc3RhbmNlQ2xhc3MpKSB7XHJcbiAgICAgIHRocm93IGZhaWx1cmUoXCJAY29tcHV0ZWRUcmVlIGNhbiBvbmx5IGRlY29yYXRlICdnZXQnIGFjY2Vzc29ycyBvZiBjbGFzcyBvciBkYXRhIG1vZGVsc1wiKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgaWYgKHR5cGVvZiBhcmdzWzFdID09PSBcIm9iamVjdFwiKSB7XHJcbiAgICAvLyBzdGFuZGFyZCBkZWNvcmF0b3JzXHJcbiAgICBjb25zdCB2YWx1ZSA9IGFyZ3NbMF1cclxuICAgIGNvbnN0IGN0eCA9IGFyZ3NbMV0gYXMgQ2xhc3NHZXR0ZXJEZWNvcmF0b3JDb250ZXh0XHJcblxyXG4gICAgaWYgKGN0eC5raW5kICE9PSBcImdldHRlclwiKSB7XHJcbiAgICAgIHRocm93IGZhaWx1cmUoXCJAY29tcHV0ZWRUcmVlIHJlcXVpcmVzIGEgJ2dldCcgYWNjZXNzb3JcIilcclxuICAgIH1cclxuXHJcbiAgICBjaGVja0RlY29yYXRvckNvbnRleHQoXCJjb21wdXRlZFRyZWVcIiwgY3R4Lm5hbWUsIGN0eC5zdGF0aWMpXHJcblxyXG4gICAgY29uc3QgcHJvcGVydHlLZXkgPSBjdHgubmFtZSBhcyBzdHJpbmdcclxuICAgIGNvbnN0IG9yaWdpbmFsID0gdmFsdWVcclxuXHJcbiAgICBsZXQgY2xhc3NDaGVja2VkID0gZmFsc2VcclxuXHJcbiAgICBjdHguYWRkSW5pdGlhbGl6ZXIoZnVuY3Rpb24gKHRoaXM6IGFueSkge1xyXG4gICAgICBjb25zdCBpbnN0YW5jZSA9IHRoaXNcclxuXHJcbiAgICAgIGlmICghY2xhc3NDaGVja2VkKSB7XHJcbiAgICAgICAgY2hlY2tJbnN0YW5jZUNsYXNzKGluc3RhbmNlKVxyXG4gICAgICAgIGNsYXNzQ2hlY2tlZCA9IHRydWVcclxuICAgICAgfVxyXG5cclxuICAgICAgcnVuTGF0ZUluaXQoaW5zdGFuY2UsIG9yaWdpbmFsLCBwcm9wZXJ0eUtleSlcclxuICAgIH0pXHJcblxyXG4gICAgcmV0dXJuIGNyZWF0ZUdldHRlcihwcm9wZXJ0eUtleSlcclxuICB9IGVsc2Uge1xyXG4gICAgLy8gbm9uLXN0YW5kYXJkIGRlY29yYXRvcnNcclxuICAgIGNvbnN0IGluc3RhbmNlID0gYXJnc1swXVxyXG4gICAgY29uc3QgcHJvcGVydHlLZXk6IHN0cmluZyA9IGFyZ3NbMV1cclxuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBhcmdzWzJdXHJcblxyXG4gICAgaWYgKCFkZXNjcmlwdG9yLmdldCkge1xyXG4gICAgICB0aHJvdyBmYWlsdXJlKFwiQGNvbXB1dGVkVHJlZSByZXF1aXJlcyBhICdnZXQnIGFjY2Vzc29yXCIpXHJcbiAgICB9XHJcblxyXG4gICAgY2hlY2tEZWNvcmF0b3JDb250ZXh0KFwiY29tcHV0ZWRUcmVlXCIsIHByb3BlcnR5S2V5LCBmYWxzZSlcclxuXHJcbiAgICBjaGVja0luc3RhbmNlQ2xhc3MoaW5zdGFuY2UpXHJcblxyXG4gICAgY29uc3Qgb3JpZ2luYWwgPSBkZXNjcmlwdG9yLmdldFxyXG5cclxuICAgIGRlc2NyaXB0b3IuZ2V0ID0gY3JlYXRlR2V0dGVyKHByb3BlcnR5S2V5KVxyXG5cclxuICAgIGFkZExhdGVJbml0aWFsaXphdGlvbkZ1bmN0aW9uKGluc3RhbmNlLCBydW5CZWZvcmVPbkluaXRTeW1ib2wsIChpbnN0YW5jZSkgPT4ge1xyXG4gICAgICBydW5MYXRlSW5pdChpbnN0YW5jZSwgb3JpZ2luYWwsIHByb3BlcnR5S2V5KVxyXG4gICAgfSlcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHR5cGUge1xuICBBYnN0cmFjdE1vZGVsQ2xhc3MsXG4gIE1vZGVsQ2xhc3MsXG4gIE1vZGVsQ3JlYXRpb25EYXRhLFxuICBNb2RlbFVudHJhbnNmb3JtZWRDcmVhdGlvbkRhdGEsXG59IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9CYXNlTW9kZWxTaGFyZWRcIlxuaW1wb3J0IHR5cGUge1xuICBNb2RlbFByb3BzLFxuICBNb2RlbFByb3BzVG9TZXR0ZXIsXG4gIE1vZGVsUHJvcHNUb1RyYW5zZm9ybWVkQ3JlYXRpb25EYXRhLFxuICBNb2RlbFByb3BzVG9UcmFuc2Zvcm1lZERhdGEsXG4gIE1vZGVsUHJvcHNUb1VudHJhbnNmb3JtZWRDcmVhdGlvbkRhdGEsXG59IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9wcm9wXCJcbmltcG9ydCB7IHNoYXJlZEludGVybmFsTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvc2hhcmVkSW50ZXJuYWxNb2RlbFwiXG5pbXBvcnQgdHlwZSB7IEFueURhdGFNb2RlbCwgQmFzZURhdGFNb2RlbCwgQmFzZURhdGFNb2RlbEtleXMgfSBmcm9tIFwiLi9CYXNlRGF0YU1vZGVsXCJcbmltcG9ydCB7IGFzc2VydElzRGF0YU1vZGVsQ2xhc3MsIGlzRGF0YU1vZGVsQ2xhc3MgfSBmcm9tIFwiLi91dGlsc1wiXG5cbmV4cG9ydCB0eXBlIF9Db21wb3NlZERhdGE8U3VwZXJNb2RlbCwgVFByb3BzIGV4dGVuZHMgTW9kZWxQcm9wcz4gPSBTdXBlck1vZGVsIGV4dGVuZHMgQW55RGF0YU1vZGVsXG4gID9cbiAgICAgIHwgKE1vZGVsUHJvcHNUb1VudHJhbnNmb3JtZWRDcmVhdGlvbkRhdGE8VFByb3BzPiAmIE1vZGVsVW50cmFuc2Zvcm1lZENyZWF0aW9uRGF0YTxTdXBlck1vZGVsPilcbiAgICAgIHwgKE1vZGVsUHJvcHNUb1RyYW5zZm9ybWVkQ3JlYXRpb25EYXRhPFRQcm9wcz4gJiBNb2RlbENyZWF0aW9uRGF0YTxTdXBlck1vZGVsPilcbiAgOiBNb2RlbFByb3BzVG9VbnRyYW5zZm9ybWVkQ3JlYXRpb25EYXRhPFRQcm9wcz4gfCBNb2RlbFByb3BzVG9UcmFuc2Zvcm1lZENyZWF0aW9uRGF0YTxUUHJvcHM+XG5cbmV4cG9ydCBpbnRlcmZhY2UgX0RhdGFNb2RlbDxTdXBlck1vZGVsLCBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzPiB7XG4gIG5ldyAoZGF0YTogX0NvbXBvc2VkRGF0YTxTdXBlck1vZGVsLCBUUHJvcHM+KTogU3VwZXJNb2RlbCAmXG4gICAgQmFzZURhdGFNb2RlbDxUUHJvcHM+ICZcbiAgICBPbWl0PE1vZGVsUHJvcHNUb1RyYW5zZm9ybWVkRGF0YTxUUHJvcHM+LCBCYXNlRGF0YU1vZGVsS2V5cz4gJlxuICAgIE1vZGVsUHJvcHNUb1NldHRlcjxUUHJvcHM+XG59XG5cbi8qKlxuICogQmFzZSBhYnN0cmFjdCBjbGFzcyBmb3IgZGF0YSBtb2RlbHMgdGhhdCBleHRlbmRzIGFub3RoZXIgbW9kZWwuXG4gKlxuICogQHR5cGVwYXJhbSBUUHJvcHMgTmV3IG1vZGVsIHByb3BlcnRpZXMgdHlwZS5cbiAqIEB0eXBlcGFyYW0gVE1vZGVsIE1vZGVsIHR5cGUuXG4gKiBAcGFyYW0gZ2VuRm4gRnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBiYXNlIG1vZGVsIGFuZCBtb2RlbCBwcm9wZXJ0aWVzLlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV4dGVuZGVkRGF0YU1vZGVsPFxuICBUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLFxuICBUTW9kZWwgZXh0ZW5kcyBBbnlEYXRhTW9kZWwsXG4gIEEgZXh0ZW5kcyBbXVxuPihcbiAgZ2VuRm46ICguLi5hcmdzOiBBKSA9PiB7XG4gICAgYmFzZU1vZGVsOiBBYnN0cmFjdE1vZGVsQ2xhc3M8VE1vZGVsPlxuICAgIHByb3BzOiBUUHJvcHNcbiAgfVxuKTogX0RhdGFNb2RlbDxUTW9kZWwsIFRQcm9wcz5cblxuLyoqXG4gKiBCYXNlIGFic3RyYWN0IGNsYXNzIGZvciBkYXRhIG1vZGVscyB0aGF0IGV4dGVuZHMgYW5vdGhlciBtb2RlbC5cbiAqXG4gKiBAdHlwZXBhcmFtIFRQcm9wcyBOZXcgbW9kZWwgcHJvcGVydGllcyB0eXBlLlxuICogQHR5cGVwYXJhbSBUTW9kZWwgTW9kZWwgdHlwZS5cbiAqIEBwYXJhbSBiYXNlTW9kZWwgQmFzZSBtb2RlbCB0eXBlLlxuICogQHBhcmFtIG1vZGVsUHJvcHMgTW9kZWwgcHJvcGVydGllcy5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFeHRlbmRlZERhdGFNb2RlbDxUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLCBUTW9kZWwgZXh0ZW5kcyBBbnlEYXRhTW9kZWw+KFxuICBiYXNlTW9kZWw6IEFic3RyYWN0TW9kZWxDbGFzczxUTW9kZWw+LFxuICBtb2RlbFByb3BzOiBUUHJvcHNcbik6IF9EYXRhTW9kZWw8VE1vZGVsLCBUUHJvcHM+XG5cbi8vIGJhc2VcbmV4cG9ydCBmdW5jdGlvbiBFeHRlbmRlZERhdGFNb2RlbDxUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLCBUTW9kZWwgZXh0ZW5kcyBBbnlEYXRhTW9kZWw+KFxuICAuLi5hcmdzOiBhbnlbXVxuKTogX0RhdGFNb2RlbDxUTW9kZWwsIFRQcm9wcz4ge1xuICBsZXQgYmFzZU1vZGVsXG4gIGxldCBtb2RlbFByb3BzXG4gIGlmIChpc0RhdGFNb2RlbENsYXNzKGFyZ3NbMF0pKSB7XG4gICAgYmFzZU1vZGVsID0gYXJnc1swXVxuICAgIG1vZGVsUHJvcHMgPSBhcmdzWzFdXG4gIH0gZWxzZSB7XG4gICAgY29uc3QgZ2VuID0gYXJnc1swXSgpXG5cbiAgICBiYXNlTW9kZWwgPSBnZW4uYmFzZU1vZGVsXG4gICAgbW9kZWxQcm9wcyA9IGdlbi5wcm9wc1xuICB9XG5cbiAgYXNzZXJ0SXNEYXRhTW9kZWxDbGFzcyhiYXNlTW9kZWwsIFwiYmFzZU1vZGVsXCIpXG5cbiAgcmV0dXJuIGludGVybmFsRGF0YU1vZGVsKG1vZGVsUHJvcHMsIGJhc2VNb2RlbCBhcyBhbnkpXG59XG5cbi8qKlxuICogQmFzZSBhYnN0cmFjdCBjbGFzcyBmb3IgZGF0YSBtb2RlbHMuXG4gKlxuICogTmV2ZXIgb3ZlcnJpZGUgdGhlIGNvbnN0cnVjdG9yLCB1c2UgYG9uTGF6eUluaXRgIG9yIGBvbkxhenlBdHRhY2hlZFRvUm9vdFN0b3JlYCBpbnN0ZWFkLlxuICpcbiAqIEB0eXBlcGFyYW0gVFByb3BzIE1vZGVsIHByb3BlcnRpZXMgdHlwZS5cbiAqIEBwYXJhbSBmbk1vZGVsUHJvcHMgRnVuY3Rpb24gdGhhdCBnZW5lcmF0ZXMgbW9kZWwgcHJvcGVydGllcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIERhdGFNb2RlbDxUUHJvcHMgZXh0ZW5kcyBNb2RlbFByb3BzLCBBIGV4dGVuZHMgW10+KFxuICBmbk1vZGVsUHJvcHM6ICguLi5hcmdzOiBBKSA9PiBUUHJvcHNcbik6IF9EYXRhTW9kZWw8dW5rbm93biwgVFByb3BzPlxuXG4vKipcbiAqIEJhc2UgYWJzdHJhY3QgY2xhc3MgZm9yIGRhdGEgbW9kZWxzLlxuICpcbiAqIE5ldmVyIG92ZXJyaWRlIHRoZSBjb25zdHJ1Y3RvciwgdXNlIGBvbkxhenlJbml0YCBvciBgb25MYXp5QXR0YWNoZWRUb1Jvb3RTdG9yZWAgaW5zdGVhZC5cbiAqXG4gKiBAdHlwZXBhcmFtIFRQcm9wcyBNb2RlbCBwcm9wZXJ0aWVzIHR5cGUuXG4gKiBAcGFyYW0gbW9kZWxQcm9wcyBNb2RlbCBwcm9wZXJ0aWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gRGF0YU1vZGVsPFRQcm9wcyBleHRlbmRzIE1vZGVsUHJvcHM+KFxuICBtb2RlbFByb3BzOiBUUHJvcHNcbik6IF9EYXRhTW9kZWw8dW5rbm93biwgVFByb3BzPlxuXG4vLyBiYXNlXG5leHBvcnQgZnVuY3Rpb24gRGF0YU1vZGVsPFRQcm9wcyBleHRlbmRzIE1vZGVsUHJvcHM+KFxuICBmbk1vZGVsUHJvcHNPck1vZGVsUHJvcHM6ICgoKSA9PiBUUHJvcHMpIHwgVFByb3BzXG4pOiBfRGF0YU1vZGVsPHVua25vd24sIFRQcm9wcz4ge1xuICBjb25zdCBtb2RlbFByb3BzID1cbiAgICB0eXBlb2YgZm5Nb2RlbFByb3BzT3JNb2RlbFByb3BzID09PSBcImZ1bmN0aW9uXCJcbiAgICAgID8gZm5Nb2RlbFByb3BzT3JNb2RlbFByb3BzKClcbiAgICAgIDogZm5Nb2RlbFByb3BzT3JNb2RlbFByb3BzXG4gIHJldHVybiBpbnRlcm5hbERhdGFNb2RlbChtb2RlbFByb3BzLCB1bmRlZmluZWQpXG59XG5cbmZ1bmN0aW9uIGludGVybmFsRGF0YU1vZGVsPFRQcm9wcyBleHRlbmRzIE1vZGVsUHJvcHMsIFRCYXNlTW9kZWwgZXh0ZW5kcyBBbnlEYXRhTW9kZWw+KFxuICBtb2RlbFByb3BzOiBUUHJvcHMsXG4gIGJhc2VNb2RlbDogTW9kZWxDbGFzczxUQmFzZU1vZGVsPiB8IHVuZGVmaW5lZFxuKTogX0RhdGFNb2RlbDxUQmFzZU1vZGVsLCBUUHJvcHM+IHtcbiAgcmV0dXJuIHNoYXJlZEludGVybmFsTW9kZWwoe1xuICAgIG1vZGVsUHJvcHMsXG4gICAgYmFzZU1vZGVsLFxuICAgIHR5cGU6IFwiZGF0YVwiLFxuICAgIHZhbHVlVHlwZTogZmFsc2UsXG4gICAgZnJvbVNuYXBzaG90UHJvY2Vzc29yOiB1bmRlZmluZWQsXG4gICAgdG9TbmFwc2hvdFByb2Nlc3NvcjogdW5kZWZpbmVkLFxuICB9KVxufVxuIiwiaW1wb3J0IHsgQWN0aW9uQ29udGV4dEFjdGlvblR5cGUgfSBmcm9tIFwiLi4vYWN0aW9uXCJcclxuaW1wb3J0IHtcclxuICBhY3Rpb25UcmFja2luZ01pZGRsZXdhcmUsXHJcbiAgQWN0aW9uVHJhY2tpbmdSZXN1bHQsXHJcbiAgU2ltcGxlQWN0aW9uQ29udGV4dCxcclxufSBmcm9tIFwiLi4vYWN0aW9uTWlkZGxld2FyZXNcIlxyXG5pbXBvcnQgeyBmYXN0R2V0Um9vdFBhdGgsIFJvb3RQYXRoIH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoXCJcclxuaW1wb3J0IHsgYXBwbHlTbmFwc2hvdCB9IGZyb20gXCIuLi9zbmFwc2hvdC9hcHBseVNuYXBzaG90XCJcclxuaW1wb3J0IHsgZ2V0U25hcHNob3QgfSBmcm9tIFwiLi4vc25hcHNob3QvZ2V0U25hcHNob3RcIlxyXG5pbXBvcnQgeyBhc3NlcnRUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXHJcblxyXG4vKipcclxuICogQ29ubmVjdHMgYSB0cmVlIG5vZGUgdG8gYSByZWR1eCBkZXYgdG9vbHMgaW5zdGFuY2UuXHJcbiAqXHJcbiAqIEBwYXJhbSByZW1vdGVkZXZQYWNrYWdlIFRoZSByZW1vdGVkZXYgcGFja2FnZSAodXN1YWxseSB0aGUgcmVzdWx0IG9mIGByZXF1aXJlKFwicmVtb3RlRGV2XCIpYCkgKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL3JlbW90ZWRldikuXHJcbiAqIEBwYXJhbSByZW1vdGVkZXZDb25uZWN0aW9uIFRoZSByZXN1bHQgb2YgYSBjb25uZWN0IG1ldGhvZCBmcm9tIHRoZSByZW1vdGVkZXYgcGFja2FnZSAodXN1YWxseSB0aGUgcmVzdWx0IG9mIGByZW1vdGVEZXYuY29ubmVjdFZpYUV4dGVuc2lvbiguLi4pYCkuXHJcbiAqIEBwYXJhbSB0YXJnZXQgT2JqZWN0IHRvIHVzZSBhcyByb290LlxyXG4gKiBAcGFyYW0gc3RvcmVOYW1lIE5hbWUgdG8gYmUgc2hvd24gaW4gdGhlIHJlZHV4IGRldiB0b29scy5cclxuICogQHBhcmFtIFtvcHRpb25zXSBPcHRpb25hbCBvcHRpb25zIG9iamVjdC4gYGxvZ0FyZ3NOZWFyTmFtZWAgaWYgaXQgc2hvdWxkIHNob3cgdGhlIGFyZ3VtZW50cyBuZWFyIHRoZSBhY3Rpb24gbmFtZSAoZGVmYXVsdCBpcyBgdHJ1ZWApLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNvbm5lY3RSZWR1eERldlRvb2xzKFxyXG4gIHJlbW90ZWRldlBhY2thZ2U6IGFueSxcclxuICByZW1vdGVkZXZDb25uZWN0aW9uOiBhbnksXHJcbiAgdGFyZ2V0OiBvYmplY3QsXHJcbiAgb3B0aW9ucz86IHtcclxuICAgIGxvZ0FyZ3NOZWFyTmFtZT86IGJvb2xlYW5cclxuICB9XHJcbikge1xyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3QodGFyZ2V0LCBcInRhcmdldFwiKVxyXG5cclxuICBjb25zdCBvcHRzID0ge1xyXG4gICAgbG9nQXJnc05lYXJOYW1lOiB0cnVlLFxyXG4gICAgLi4ub3B0aW9ucyxcclxuICB9XHJcblxyXG4gIGxldCBoYW5kbGluZ01vbml0b3JBY3Rpb24gPSAwXHJcblxyXG4gIC8vIHN1YnNjcmliZSB0byBjaGFuZ2Ugc3RhdGUgKGlmIG5lZWQgbW9yZSB0aGFuIGp1c3QgbG9nZ2luZylcclxuICByZW1vdGVkZXZDb25uZWN0aW9uLnN1YnNjcmliZSgobWVzc2FnZTogYW55KSA9PiB7XHJcbiAgICBpZiAobWVzc2FnZS50eXBlID09PSBcIkRJU1BBVENIXCIpIHtcclxuICAgICAgaGFuZGxlTW9uaXRvckFjdGlvbnMocmVtb3RlZGV2Q29ubmVjdGlvbiwgdGFyZ2V0LCBtZXNzYWdlKVxyXG4gICAgfVxyXG4gIH0pXHJcblxyXG4gIGNvbnN0IGluaXRpYWxTdGF0ZSA9IGdldFNuYXBzaG90KHRhcmdldClcclxuICByZW1vdGVkZXZDb25uZWN0aW9uLmluaXQoaW5pdGlhbFN0YXRlKVxyXG5cclxuICBsZXQgY3VycmVudEFjdGlvbklkID0gMFxyXG4gIGNvbnN0IGFjdGlvbklkU3ltYm9sID0gU3ltYm9sKFwiYWN0aW9uSWRcIilcclxuXHJcbiAgYWN0aW9uVHJhY2tpbmdNaWRkbGV3YXJlKHRhcmdldCwge1xyXG4gICAgb25TdGFydChjdHgpIHtcclxuICAgICAgY3R4LmRhdGFbYWN0aW9uSWRTeW1ib2xdID0gY3VycmVudEFjdGlvbklkKytcclxuICAgIH0sXHJcbiAgICBvblJlc3VtZShjdHgpIHtcclxuICAgICAgLy8gZ2l2ZSBhIGNoYW5jZSB0byB0aGUgcGFyZW50IHRvIGxvZyBpdHMgb3duIGNoYW5nZXMgYmVmb3JlIHRoZSBjaGlsZCBzdGFydHNcclxuICAgICAgaWYgKGN0eC5wYXJlbnRDb250ZXh0KSB7XHJcbiAgICAgICAgbG9nKGN0eC5wYXJlbnRDb250ZXh0LCB1bmRlZmluZWQpXHJcbiAgICAgIH1cclxuICAgICAgbG9nKGN0eCwgdW5kZWZpbmVkKVxyXG4gICAgfSxcclxuICAgIG9uU3VzcGVuZChjdHgpIHtcclxuICAgICAgbG9nKGN0eCwgdW5kZWZpbmVkKVxyXG4gICAgfSxcclxuICAgIG9uRmluaXNoKGN0eCwgcmV0KSB7XHJcbiAgICAgIGxvZyhjdHgsIHJldC5yZXN1bHQpXHJcbiAgICB9LFxyXG4gIH0pXHJcblxyXG4gIGZ1bmN0aW9uIGhhbmRsZU1vbml0b3JBY3Rpb25zKHJlbW90ZWRldjI6IGFueSwgdGFyZ2V0MjogYW55LCBtZXNzYWdlOiBhbnkpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGhhbmRsaW5nTW9uaXRvckFjdGlvbisrXHJcblxyXG4gICAgICBzd2l0Y2ggKG1lc3NhZ2UucGF5bG9hZC50eXBlKSB7XHJcbiAgICAgICAgY2FzZSBcIlJFU0VUXCI6XHJcbiAgICAgICAgICBhcHBseVNuYXBzaG90KHRhcmdldDIsIGluaXRpYWxTdGF0ZSlcclxuICAgICAgICAgIHJldHVybiByZW1vdGVkZXYyLmluaXQoaW5pdGlhbFN0YXRlKVxyXG4gICAgICAgIGNhc2UgXCJDT01NSVRcIjpcclxuICAgICAgICAgIHJldHVybiByZW1vdGVkZXYyLmluaXQoZ2V0U25hcHNob3QodGFyZ2V0MikpXHJcbiAgICAgICAgY2FzZSBcIlJPTExCQUNLXCI6XHJcbiAgICAgICAgICByZXR1cm4gcmVtb3RlZGV2Mi5pbml0KHJlbW90ZWRldlBhY2thZ2UuZXh0cmFjdFN0YXRlKG1lc3NhZ2UpKVxyXG4gICAgICAgIGNhc2UgXCJKVU1QX1RPX1NUQVRFXCI6XHJcbiAgICAgICAgY2FzZSBcIkpVTVBfVE9fQUNUSU9OXCI6XHJcbiAgICAgICAgICBhcHBseVNuYXBzaG90KHRhcmdldDIsIHJlbW90ZWRldlBhY2thZ2UuZXh0cmFjdFN0YXRlKG1lc3NhZ2UpKVxyXG4gICAgICAgICAgcmV0dXJuXHJcbiAgICAgICAgY2FzZSBcIklNUE9SVF9TVEFURVwiOlxyXG4gICAgICAgICAgY29uc3QgbmV4dExpZnRlZFN0YXRlID0gbWVzc2FnZS5wYXlsb2FkLm5leHRMaWZ0ZWRTdGF0ZVxyXG4gICAgICAgICAgY29uc3QgY29tcHV0ZWRTdGF0ZXMgPSBuZXh0TGlmdGVkU3RhdGUuY29tcHV0ZWRTdGF0ZXNcclxuICAgICAgICAgIGFwcGx5U25hcHNob3QodGFyZ2V0MiwgY29tcHV0ZWRTdGF0ZXNbY29tcHV0ZWRTdGF0ZXMubGVuZ3RoIC0gMV0uc3RhdGUpXHJcbiAgICAgICAgICByZW1vdGVkZXYyLnNlbmQobnVsbCwgbmV4dExpZnRlZFN0YXRlKVxyXG4gICAgICAgICAgcmV0dXJuXHJcbiAgICAgICAgZGVmYXVsdDpcclxuICAgICAgfVxyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgaGFuZGxpbmdNb25pdG9yQWN0aW9uLS1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGxldCBsYXN0TG9nZ2VkU25hcHNob3QgPSBpbml0aWFsU3RhdGVcclxuXHJcbiAgZnVuY3Rpb24gbG9nKGN0eDogU2ltcGxlQWN0aW9uQ29udGV4dCwgcmVzdWx0OiBBY3Rpb25UcmFja2luZ1Jlc3VsdCB8IHVuZGVmaW5lZCkge1xyXG4gICAgaWYgKGhhbmRsaW5nTW9uaXRvckFjdGlvbikge1xyXG4gICAgICByZXR1cm5cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBzbiA9IGdldFNuYXBzaG90KHRhcmdldClcclxuXHJcbiAgICAvLyBpZ25vcmUgYWN0aW9ucyB0aGF0IGRvbid0IGNoYW5nZSBhbnl0aGluZyAodW5sZXNzIGl0IGlzIGEgdGhyb3cpXHJcbiAgICBpZiAoc24gPT09IGxhc3RMb2dnZWRTbmFwc2hvdCAmJiByZXN1bHQgIT09IEFjdGlvblRyYWNraW5nUmVzdWx0LlRocm93KSB7XHJcbiAgICAgIHJldHVyblxyXG4gICAgfVxyXG4gICAgbGFzdExvZ2dlZFNuYXBzaG90ID0gc25cclxuXHJcbiAgICBjb25zdCByb290UGF0aCA9IGZhc3RHZXRSb290UGF0aChjdHgudGFyZ2V0KVxyXG4gICAgY29uc3QgbmFtZSA9IGdldEFjdGlvbkNvbnRleHROYW1lQW5kVHlwZVBhdGgoY3R4LCByb290UGF0aCwgcmVzdWx0KVxyXG5cclxuICAgIGNvbnN0IGNvcHkgPSB7XHJcbiAgICAgIHR5cGU6IG5hbWUsXHJcbiAgICAgIHBhdGg6IHJvb3RQYXRoLnBhdGgsXHJcbiAgICAgIGFyZ3M6IGN0eC5hcmdzLFxyXG4gICAgfVxyXG5cclxuICAgIHJlbW90ZWRldkNvbm5lY3Rpb24uc2VuZChjb3B5LCBzbilcclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uIGdldEFjdGlvbkNvbnRleHROYW1lQW5kVHlwZVBhdGgoXHJcbiAgICBjdHg6IFNpbXBsZUFjdGlvbkNvbnRleHQsXHJcbiAgICByb290UGF0aDogUm9vdFBhdGg8YW55PixcclxuICAgIHJlc3VsdDogQWN0aW9uVHJhY2tpbmdSZXN1bHQgfCB1bmRlZmluZWRcclxuICApIHtcclxuICAgIGNvbnN0IHBhdGhTdHIgPSBcIlsvXCIgKyByb290UGF0aC5wYXRoLmpvaW4oXCIvXCIpICsgXCJdIFwiXHJcbiAgICBsZXQgbmFtZSA9IHBhdGhTdHIgKyBjdHguYWN0aW9uTmFtZVxyXG5cclxuICAgIGlmIChvcHRzLmxvZ0FyZ3NOZWFyTmFtZSkge1xyXG4gICAgICBsZXQgYXJncyA9IGN0eC5hcmdzXHJcbiAgICAgICAgLm1hcCgoYSkgPT4ge1xyXG4gICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGEpXHJcbiAgICAgICAgICB9IGNhdGNoIHtcclxuICAgICAgICAgICAgcmV0dXJuIFwiKip1bnNlcmlhbGl6YWJsZSoqXCJcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG4gICAgICAgIC5qb2luKFwiLCBcIilcclxuXHJcbiAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDY0KSB7XHJcbiAgICAgICAgYXJncyA9IGFyZ3Muc2xpY2UoMCwgNjQpICsgXCIuLi5cIlxyXG4gICAgICB9XHJcblxyXG4gICAgICBuYW1lICs9IGAoJHthcmdzfSlgXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgYWN0aW9uSWQgPSBjdHguZGF0YVthY3Rpb25JZFN5bWJvbF1cclxuXHJcbiAgICBuYW1lICs9IGAgKGlkICR7YWN0aW9uSWQgIT09IHVuZGVmaW5lZCA/IGFjdGlvbklkIDogXCI/XCJ9YFxyXG4gICAgaWYgKGN0eC50eXBlID09PSBBY3Rpb25Db250ZXh0QWN0aW9uVHlwZS5Bc3luYykge1xyXG4gICAgICBuYW1lICs9IFwiLCBhc3luY1wiXHJcbiAgICB9XHJcbiAgICBuYW1lICs9IFwiKVwiXHJcblxyXG4gICAgaWYgKHJlc3VsdCA9PT0gQWN0aW9uVHJhY2tpbmdSZXN1bHQuVGhyb3cpIHtcclxuICAgICAgbmFtZSArPSBcIiAtZXJyb3IgdGhyb3duLVwiXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGN0eC5wYXJlbnRDb250ZXh0KSB7XHJcbiAgICAgIGNvbnN0IHBhcmVudE5hbWUgPSBnZXRBY3Rpb25Db250ZXh0TmFtZUFuZFR5cGVQYXRoKFxyXG4gICAgICAgIGN0eC5wYXJlbnRDb250ZXh0LFxyXG4gICAgICAgIGZhc3RHZXRSb290UGF0aChjdHgucGFyZW50Q29udGV4dC50YXJnZXQpLFxyXG4gICAgICAgIHVuZGVmaW5lZFxyXG4gICAgICApXHJcbiAgICAgIGlmIChwYXJlbnROYW1lKSB7XHJcbiAgICAgICAgbmFtZSA9IGAke3BhcmVudE5hbWV9ID4+PiAke25hbWV9YFxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG5hbWVcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgQWN0aW9uQ2FsbCwgYXBwbHlBY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9uXCJcbmltcG9ydCB7IGdldFNuYXBzaG90IH0gZnJvbSBcIi4uL3NuYXBzaG90L2dldFNuYXBzaG90XCJcbmltcG9ydCB7IG9uU25hcHNob3QsIE9uU25hcHNob3REaXNwb3NlciwgT25TbmFwc2hvdExpc3RlbmVyIH0gZnJvbSBcIi4uL3NuYXBzaG90L29uU25hcHNob3RcIlxuaW1wb3J0IHR5cGUgeyBTbmFwc2hvdE91dE9mIH0gZnJvbSBcIi4uL3NuYXBzaG90L1NuYXBzaG90T2ZcIlxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXG5cbmV4cG9ydCBjb25zdCByZWR1eEFjdGlvblR5cGUgPSBcImFwcGx5QWN0aW9uXCJcblxuLyoqXG4gKiBBIHJlZHV4IGFjdGlvbiBmb3IgbW9ieC1rZXlzdG9uZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWR1eEFjdGlvbiB7XG4gIHJlYWRvbmx5IHR5cGU6IHR5cGVvZiByZWR1eEFjdGlvblR5cGVcbiAgcmVhZG9ubHkgcGF5bG9hZDogQWN0aW9uQ2FsbFxufVxuXG4vKipcbiAqIFRyYW5zZm9ybXMgYW4gYWN0aW9uIGNhbGwgaW50byBhIHJlZHV4IGFjdGlvbi5cbiAqXG4gKiBAcGFyYW0gYWN0aW9uQ2FsbCBBY3Rpb24gY2FsbC5cbiAqIEByZXR1cm5zIEEgcmVkdXggYWN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYWN0aW9uQ2FsbFRvUmVkdXhBY3Rpb24oYWN0aW9uQ2FsbDogQWN0aW9uQ2FsbCk6IFJlZHV4QWN0aW9uIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiByZWR1eEFjdGlvblR5cGUsXG4gICAgcGF5bG9hZDogYWN0aW9uQ2FsbCxcbiAgfVxufVxuXG4vKipcbiAqIEEgcmVkdXggc3RvcmUgZm9yIG1vYngta2V5c3RvbmUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVkdXhTdG9yZTxUPiB7XG4gIGdldFN0YXRlKCk6IFNuYXBzaG90T3V0T2Y8VD5cbiAgZGlzcGF0Y2goYWN0aW9uOiBSZWR1eEFjdGlvbik6IFJlZHV4QWN0aW9uXG4gIHN1YnNjcmliZShsaXN0ZW5lcjogT25TbmFwc2hvdExpc3RlbmVyPFQ+KTogT25TbmFwc2hvdERpc3Bvc2VyXG59XG5cbi8qKlxuICogQSByZWR1eCBydW5uZXIgZm9yIG1vYngta2V5c3RvbmUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVkdXhSdW5uZXI8VD4ge1xuICAobmV4dDogUmVkdXhTdG9yZTxUPltcImRpc3BhdGNoXCJdKTogKGFjdGlvbjogUmVkdXhBY3Rpb24pID0+IFJlZHV4QWN0aW9uXG59XG5cbi8qKlxuICogQSByZWR1eCBtaWRkbGV3YXJlIGZvciBtb2J4LWtleXN0b25lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZHV4TWlkZGxld2FyZTxUPiB7XG4gIChzdG9yZTogUmVkdXhTdG9yZTxUPik6IFJlZHV4UnVubmVyPFQ+XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcmVkdXggY29tcGF0aWJsZSBzdG9yZSBvdXQgb2YgYSBtb2J4LWtleXN0b25lIG9iamVjdC5cbiAqXG4gKiBAdHlwZXBhcmFtIFQgT2JqZWN0IHR5cGUuXG4gKiBAcGFyYW0gdGFyZ2V0IFJvb3Qgb2JqZWN0LlxuICogQHBhcmFtIG1pZGRsZXdhcmVzIE9wdGlvbmFsIGxpc3Qgb2YgcmVkdXggbWlkZGxld2FyZXMuXG4gKiBAcmV0dXJucyBBIHJlZHV4IGNvbXBhdGlibGUgc3RvcmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc1JlZHV4U3RvcmU8VCBleHRlbmRzIG9iamVjdD4oXG4gIHRhcmdldDogVCxcbiAgLi4ubWlkZGxld2FyZXM6IFJlZHV4TWlkZGxld2FyZTxUPltdXG4pOiBSZWR1eFN0b3JlPFQ+IHtcbiAgYXNzZXJ0VHdlYWtlZE9iamVjdCh0YXJnZXQsIFwidGFyZ2V0XCIpXG5cbiAgY29uc3QgZGVmYXVsdERpc3BhdGNoID0gKGFjdGlvbjogUmVkdXhBY3Rpb24pID0+IHtcbiAgICBpZiAoYWN0aW9uLnR5cGUgIT09IHJlZHV4QWN0aW9uVHlwZSkge1xuICAgICAgdGhyb3cgZmFpbHVyZShcbiAgICAgICAgYGFjdGlvbiB0eXBlIHdhcyBleHBlY3RlZCB0byBiZSAnJHtyZWR1eEFjdGlvblR5cGV9JywgYnV0IGl0IHdhcyAnJHthY3Rpb24udHlwZX0nYFxuICAgICAgKVxuICAgIH1cblxuICAgIGFwcGx5QWN0aW9uKHRhcmdldCwgYWN0aW9uLnBheWxvYWQpXG4gICAgcmV0dXJuIGFjdGlvblxuICB9XG5cbiAgbGV0IHN0b3JlOiBSZWR1eFN0b3JlPFQ+ID0ge1xuICAgIGdldFN0YXRlKCkge1xuICAgICAgcmV0dXJuIGdldFNuYXBzaG90KHRhcmdldClcbiAgICB9LFxuICAgIGRpc3BhdGNoKGFjdGlvbikge1xuICAgICAgcmV0dXJuIHJ1bk1pZGRsZXdhcmVzKGFjdGlvbiwgcnVubmVycywgZGVmYXVsdERpc3BhdGNoKVxuICAgIH0sXG4gICAgc3Vic2NyaWJlKGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gb25TbmFwc2hvdCh0YXJnZXQsIGxpc3RlbmVyKVxuICAgIH0sXG4gIH1cblxuICBjb25zdCBydW5uZXJzID0gbWlkZGxld2FyZXMubWFwKChtdykgPT4gbXcoc3RvcmUpKVxuXG4gIHJldHVybiBzdG9yZVxufVxuXG5mdW5jdGlvbiBydW5NaWRkbGV3YXJlczxUPihcbiAgaW5pdGlhbEFjdGlvbjogUmVkdXhBY3Rpb24sXG4gIHJ1bm5lcnM6IFJlYWRvbmx5QXJyYXk8UmVkdXhSdW5uZXI8VD4+LFxuICBuZXh0OiBSZWR1eFN0b3JlPFQ+W1wiZGlzcGF0Y2hcIl1cbik6IFJlZHV4QWN0aW9uIHtcbiAgbGV0IGkgPSAwXG5cbiAgZnVuY3Rpb24gcnVuTmV4dE1pZGRsZXdhcmUoYWN0aW9uOiBSZWR1eEFjdGlvbik6IFJlZHV4QWN0aW9uIHtcbiAgICBjb25zdCBydW5uZXIgPSBydW5uZXJzW2ldXG4gICAgaSsrXG4gICAgaWYgKHJ1bm5lcikge1xuICAgICAgcmV0dXJuIHJ1bm5lcihydW5OZXh0TWlkZGxld2FyZSkoYWN0aW9uKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbmV4dChhY3Rpb24pXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJ1bk5leHRNaWRkbGV3YXJlKGluaXRpYWxBY3Rpb24pXG59XG4iLCJpbXBvcnQgeyBjb21wdXRlZCB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IG1vZGVsVHlwZUtleSB9IGZyb20gXCIuLi9tb2RlbC9tZXRhZGF0YVwiXG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9Nb2RlbFwiXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcbmltcG9ydCB7IHR5cGVzU3RyaW5nIH0gZnJvbSBcIi4uL3R5cGVzL3ByaW1pdGl2ZUJhc2VkL3R5cGVzUHJpbWl0aXZlXCJcbmltcG9ydCB7IHRQcm9wIH0gZnJvbSBcIi4uL3R5cGVzL3RQcm9wXCJcbmltcG9ydCB7IGZhaWx1cmUgfSBmcm9tIFwiLi4vdXRpbHNcIlxuXG4vKipcbiAqIEEgcmVmZXJlbmNlIG1vZGVsIGJhc2UgdHlwZS5cbiAqIFVzZSBgY3VzdG9tUmVmYCB0byBjcmVhdGUgYSBjdXN0b20gcmVmIGNvbnN0cnVjdG9yLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUmVmPFQgZXh0ZW5kcyBvYmplY3Q+IGV4dGVuZHMgTW9kZWwoe1xuICAvKipcbiAgICogUmVmZXJlbmNlIGlkLlxuICAgKi9cbiAgaWQ6IHRQcm9wKHR5cGVzU3RyaW5nKSxcbn0pIHtcbiAgcHJvdGVjdGVkIGFic3RyYWN0IHJlc29sdmUoKTogVCB8IHVuZGVmaW5lZFxuXG4gIC8qKlxuICAgKiBUaGUgb2JqZWN0IHRoaXMgcmVmZXJlbmNlIHBvaW50cyB0bywgb3IgYHVuZGVmaW5lZGAgaWYgdGhlIHJlZmVyZW5jZSBpcyBjdXJyZW50bHkgaW52YWxpZC5cbiAgICovXG4gIEBjb21wdXRlZFxuICBnZXQgbWF5YmVDdXJyZW50KCk6IFQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnJlc29sdmUoKVxuICB9XG5cbiAgLyoqXG4gICAqIElmIHRoZSByZWZlcmVuY2UgaXMgY3VycmVudGx5IHZhbGlkLlxuICAgKi9cbiAgQGNvbXB1dGVkXG4gIGdldCBpc1ZhbGlkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMubWF5YmVDdXJyZW50XG4gIH1cblxuICAvKipcbiAgICogVGhlIG9iamVjdCB0aGlzIHJlZmVyZW5jZSBwb2ludHMgdG8sIG9yIHRocm93cyBpZiBpbnZhbGlkLlxuICAgKi9cbiAgQGNvbXB1dGVkXG4gIGdldCBjdXJyZW50KCk6IFQge1xuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLm1heWJlQ3VycmVudFxuXG4gICAgaWYgKCFjdXJyZW50KSB7XG4gICAgICB0aHJvdyBmYWlsdXJlKFxuICAgICAgICBgYSByZWZlcmVuY2Ugb2YgdHlwZSAnJHt0aGlzW21vZGVsVHlwZUtleV19JyBjb3VsZCBub3QgcmVzb2x2ZSBhbiBvYmplY3Qgd2l0aCBpZCAnJHt0aGlzLmlkfSdgXG4gICAgICApXG4gICAgfVxuXG4gICAgcmV0dXJuIGN1cnJlbnRcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmVzIGJhY2sgcmVmZXJlbmNlcyBmb3IgdGhpcyByZWYgYXJlIHVwIHRvIGRhdGUuXG4gICAqIFRoaXMgb25seSBuZWVkcyB0byBiZSBjYWxsZWQgaWYgeW91IG5lZWQgdG8gZ2V0IHRoZSBtb3N0IHVwIHRvIGRhdGVcbiAgICogYmFjayByZWZlcmVuY2VzIHdoaWxlIGJvdGggc3RpbGwgaW5zaWRlIGFuIGFjdGlvbiBhbmQgd2hpbGUgdGhlIHJlZmVyZW5jZVxuICAgKiBpcyBub3QgYSBjaGlsZCBvZiB0aGUgc2FtZSByb290IHRoYW4gdGhlIHRhcmdldC5cbiAgICovXG4gIGFic3RyYWN0IGZvcmNlVXBkYXRlQmFja1JlZnMoKTogdm9pZFxufVxuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuZXhwb3J0IGRlY2xhcmUgY29uc3QgY3VzdG9tUmVmVHlwZVN5bWJvbDogdW5pcXVlIHN5bWJvbFxuXG4vKiogQSByZWYgY29uc3RydWN0b3IgZm9yIGN1c3RvbSByZWZzICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZkNvbnN0cnVjdG9yPFQgZXh0ZW5kcyBvYmplY3Q+IHtcbiAgPFRFIGV4dGVuZHMgVD4odmFsdWVPcklEOiBURSB8IHN0cmluZyk6IFJlZjxURT5cblxuICByZWZDbGFzczogTW9kZWxDbGFzczxSZWY8VD4+XG5cbiAgW2N1c3RvbVJlZlR5cGVTeW1ib2xdOiBUIC8vIGp1c3QgZm9yIHR5cGluZ3Ncbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSByZWYgb2JqZWN0IGlzIG9mIGEgZ2l2ZW4gcmVmIHR5cGUuXG4gKlxuICogQHR5cGVwYXJhbSBUIFJlZmVyZW5jZWQgb2JqZWN0IHR5cGUuXG4gKiBAcGFyYW0gcmVmIFJlZmVyZW5jZSBvYmplY3QuXG4gKiBAcGFyYW0gcmVmVHlwZSBSZWZlcmVuY2UgdHlwZS5cbiAqIEByZXR1cm5zIGB0cnVlYCBpZiBpdCBpcyBvZiB0aGUgZ2l2ZW4gdHlwZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZWZPZlR5cGU8VCBleHRlbmRzIG9iamVjdD4oXG4gIHJlZjogUmVmPG9iamVjdD4sXG4gIHJlZlR5cGU6IFJlZkNvbnN0cnVjdG9yPFQ+XG4pOiByZWYgaXMgUmVmPFQ+IHtcbiAgcmV0dXJuIHJlZiBpbnN0YW5jZW9mIHJlZlR5cGUucmVmQ2xhc3Ncbn1cbiIsImltcG9ydCB7IGFjdGlvbiwgb2JzZXJ2YWJsZSwgT2JzZXJ2YWJsZVNldCwgcmVhY3Rpb24sIHdoZW4gfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7IGlzTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvdXRpbHNcIlxyXG5pbXBvcnQgdHlwZSB7IE1vZGVsQ2xhc3MgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvQmFzZU1vZGVsU2hhcmVkXCJcclxuaW1wb3J0IHsgbW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxEZWNvcmF0b3JcIlxyXG5pbXBvcnQge1xyXG4gIGdldERlZXBPYmplY3RDaGlsZHJlbixcclxuICByZWdpc3RlckRlZXBPYmplY3RDaGlsZHJlbkV4dGVuc2lvbixcclxufSBmcm9tIFwiLi4vcGFyZW50L2NvcmVPYmplY3RDaGlsZHJlblwiXHJcbmltcG9ydCB7IGZhc3RHZXRSb290IH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoXCJcclxuaW1wb3J0IHsgQ29tcHV0ZWRXYWxrVHJlZUFnZ3JlZ2F0ZSwgY29tcHV0ZWRXYWxrVHJlZUFnZ3JlZ2F0ZSB9IGZyb20gXCIuLi9wYXJlbnQvd2Fsa1RyZWVcIlxyXG5pbXBvcnQgeyBhc3NlcnRUd2Vha2VkT2JqZWN0IH0gZnJvbSBcIi4uL3R3ZWFrZXIvY29yZVwiXHJcbmltcG9ydCB7IGFzc2VydElzT2JqZWN0LCBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuaW1wb3J0IHsgZ2V0T3JDcmVhdGUgfSBmcm9tIFwiLi4vdXRpbHMvbWFwVXRpbHNcIlxyXG5pbXBvcnQgeyBSZWYsIFJlZkNvbnN0cnVjdG9yIH0gZnJvbSBcIi4vUmVmXCJcclxuXHJcbmludGVyZmFjZSBCYWNrUmVmczxUIGV4dGVuZHMgb2JqZWN0PiB7XHJcbiAgYWxsOiBPYnNlcnZhYmxlU2V0PFJlZjxUPj5cclxuICBieVR5cGU6IFdlYWtNYXA8UmVmQ29uc3RydWN0b3I8VD4sIE9ic2VydmFibGVTZXQ8UmVmPFQ+Pj5cclxufVxyXG5cclxuLyoqXHJcbiAqIEJhY2stcmVmZXJlbmNlcyBmcm9tIG9iamVjdCB0byB0aGUgcmVmZXJlbmNlcyB0aGF0IHBvaW50IHRvIGl0LlxyXG4gKi9cclxuY29uc3Qgb2JqZWN0QmFja1JlZnMgPSBuZXcgV2Vha01hcDxvYmplY3QsIEJhY2tSZWZzPGFueT4+KClcclxuXHJcbi8qKlxyXG4gKiBSZWZlcmVuY2UgcmVzb2x2ZXIgdHlwZS5cclxuICovXHJcbmV4cG9ydCB0eXBlIFJlZlJlc29sdmVyPFQgZXh0ZW5kcyBvYmplY3Q+ID0gKHJlZjogUmVmPFQ+KSA9PiBUIHwgdW5kZWZpbmVkXHJcblxyXG4vKipcclxuICogUmVmZXJlbmNlIElEIHJlc29sdmVyIHR5cGUuXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBSZWZJZFJlc29sdmVyID0gKHRhcmdldDogb2JqZWN0KSA9PiBzdHJpbmcgfCB1bmRlZmluZWRcclxuXHJcbi8qKlxyXG4gKiBUeXBlIGZvciB0aGUgY2FsbGJhY2sgY2FsbGVkIHdoZW4gYSByZWZlcmVuY2UgcmVzb2x2ZWQgdmFsdWUgY2hhbmdlcy5cclxuICovXHJcbmV4cG9ydCB0eXBlIFJlZk9uUmVzb2x2ZWRWYWx1ZUNoYW5nZTxUIGV4dGVuZHMgb2JqZWN0PiA9IChcclxuICByZWY6IFJlZjxUPixcclxuICBuZXdWYWx1ZTogVCB8IHVuZGVmaW5lZCxcclxuICBvbGRWYWx1ZTogVCB8IHVuZGVmaW5lZFxyXG4pID0+IHZvaWRcclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpbnRlcm5hbEN1c3RvbVJlZjxUIGV4dGVuZHMgb2JqZWN0PihcclxuICBtb2RlbFR5cGVJZDogc3RyaW5nLFxyXG4gIHJlc29sdmVyR2VuOiAocmVmOiBSZWY8VD4pID0+IFJlZlJlc29sdmVyPFQ+LFxyXG4gIGdldElkOiBSZWZJZFJlc29sdmVyLFxyXG4gIG9uUmVzb2x2ZWRWYWx1ZUNoYW5nZTogUmVmT25SZXNvbHZlZFZhbHVlQ2hhbmdlPFQ+IHwgdW5kZWZpbmVkXHJcbik6IFJlZkNvbnN0cnVjdG9yPFQ+IHtcclxuICBAbW9kZWwobW9kZWxUeXBlSWQpXHJcbiAgY2xhc3MgQ3VzdG9tUmVmIGV4dGVuZHMgUmVmPFQ+IHtcclxuICAgIHByaXZhdGUgcmVzb2x2ZXI/OiBSZWZSZXNvbHZlcjxUPlxyXG5cclxuICAgIHJlc29sdmUoKTogVCB8IHVuZGVmaW5lZCB7XHJcbiAgICAgIGlmICghdGhpcy5yZXNvbHZlcikge1xyXG4gICAgICAgIHRoaXMucmVzb2x2ZXIgPSByZXNvbHZlckdlbih0aGlzKVxyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gdGhpcy5yZXNvbHZlcih0aGlzKVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc2F2ZWRPbGRUYXJnZXQ6IFQgfCB1bmRlZmluZWRcclxuXHJcbiAgICBwcml2YXRlIGludGVybmFsRm9yY2VVcGRhdGVCYWNrUmVmcyhuZXdUYXJnZXQ6IFQgfCB1bmRlZmluZWQpIHtcclxuICAgICAgY29uc3Qgb2xkVGFyZ2V0ID0gdGhpcy5zYXZlZE9sZFRhcmdldFxyXG4gICAgICAvLyB1cGRhdGUgZWFybHkgaW4gY2FzZSBvZiB0aHJvd24gZXhjZXB0aW9uc1xyXG4gICAgICB0aGlzLnNhdmVkT2xkVGFyZ2V0ID0gbmV3VGFyZ2V0XHJcblxyXG4gICAgICB1cGRhdGVCYWNrUmVmcyh0aGlzLCB0aGlzUmVmQ29uc3RydWN0b3IsIG5ld1RhcmdldCwgb2xkVGFyZ2V0KVxyXG4gICAgfVxyXG5cclxuICAgIEBhY3Rpb25cclxuICAgIGZvcmNlVXBkYXRlQmFja1JlZnMoKSB7XHJcbiAgICAgIHRoaXMuaW50ZXJuYWxGb3JjZVVwZGF0ZUJhY2tSZWZzKHRoaXMubWF5YmVDdXJyZW50KVxyXG4gICAgfVxyXG5cclxuICAgIG9uSW5pdCgpIHtcclxuICAgICAgLy8gbGlzdGVuIHRvIGNoYW5nZXNcclxuXHJcbiAgICAgIGxldCBzYXZlZE9sZFRhcmdldDogVCB8IHVuZGVmaW5lZFxyXG4gICAgICBsZXQgc2F2ZWRGaXJzdFRpbWUgPSB0cnVlXHJcblxyXG4gICAgICAvLyBhY2NvcmRpbmcgdG8gbXdlc3RyYXRlIHRoaXMgd29uJ3QgbGVhayBhcyBsb25nIGFzIHdlIGRvbid0IGtlZXAgdGhlIGRpc3Bvc2VyIGFyb3VuZFxyXG4gICAgICByZWFjdGlvbihcclxuICAgICAgICAoKSA9PiB0aGlzLm1heWJlQ3VycmVudCxcclxuICAgICAgICAobmV3VGFyZ2V0KSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmludGVybmFsRm9yY2VVcGRhdGVCYWNrUmVmcyhuZXdUYXJnZXQpXHJcblxyXG4gICAgICAgICAgY29uc3Qgb2xkVGFyZ2V0ID0gc2F2ZWRPbGRUYXJnZXRcclxuICAgICAgICAgIGNvbnN0IGZpcnN0VGltZSA9IHNhdmVkRmlyc3RUaW1lXHJcbiAgICAgICAgICAvLyB1cGRhdGUgZWFybHkgaW4gY2FzZSBvZiB0aHJvd24gZXhjZXB0aW9uc1xyXG4gICAgICAgICAgc2F2ZWRPbGRUYXJnZXQgPSBuZXdUYXJnZXRcclxuICAgICAgICAgIHNhdmVkRmlyc3RUaW1lID0gZmFsc2VcclxuXHJcbiAgICAgICAgICBpZiAoIWZpcnN0VGltZSAmJiBvblJlc29sdmVkVmFsdWVDaGFuZ2UgJiYgbmV3VGFyZ2V0ICE9PSBvbGRUYXJnZXQpIHtcclxuICAgICAgICAgICAgb25SZXNvbHZlZFZhbHVlQ2hhbmdlKHRoaXMsIG5ld1RhcmdldCwgb2xkVGFyZ2V0KVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgeyBmaXJlSW1tZWRpYXRlbHk6IHRydWUgfVxyXG4gICAgICApXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb25zdCBmbiA9ICh0YXJnZXQ6IFQpID0+IHtcclxuICAgIGxldCBpZDogc3RyaW5nIHwgdW5kZWZpbmVkXHJcbiAgICBpZiAodHlwZW9mIHRhcmdldCA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICBpZCA9IHRhcmdldFxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgYXNzZXJ0SXNPYmplY3QodGFyZ2V0LCBcInRhcmdldFwiKVxyXG4gICAgICBpZCA9IGdldElkKHRhcmdldClcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZW9mIGlkICE9PSBcInN0cmluZ1wiKSB7XHJcbiAgICAgIHRocm93IGZhaWx1cmUoXCJyZWYgdGFyZ2V0IG9iamVjdCBtdXN0IGhhdmUgYW4gaWQgb2Ygc3RyaW5nIHR5cGVcIilcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCByZWYgPSBuZXcgQ3VzdG9tUmVmKHtcclxuICAgICAgaWQsXHJcbiAgICB9KVxyXG5cclxuICAgIHJldHVybiByZWZcclxuICB9XHJcbiAgZm4ucmVmQ2xhc3MgPSBDdXN0b21SZWZcclxuXHJcbiAgY29uc3QgdGhpc1JlZkNvbnN0cnVjdG9yID0gZm4gYXMgYW55IGFzIFJlZkNvbnN0cnVjdG9yPFQ+XHJcblxyXG4gIHJldHVybiB0aGlzUmVmQ29uc3RydWN0b3JcclxufVxyXG5cclxuLyoqXHJcbiAqIFVzZXMgYSBtb2RlbCBgZ2V0UmVmSWQoKWAgbWV0aG9kIHdoZW5ldmVyIHBvc3NpYmxlIHRvIGdldCBhIHJlZmVyZW5jZSBJRC5cclxuICogSWYgdGhlIG1vZGVsIGRvZXMgbm90IGhhdmUgYW4gaW1wbGVtZW50YXRpb24gb2YgdGhhdCBtZXRob2QgaXQgcmV0dXJucyBgdW5kZWZpbmVkYC5cclxuICogSWYgdGhlIG1vZGVsIGhhcyBhbiBpbXBsZW1lbnRhdGlvbiwgYnV0IHRoYXQgaW1wbGVtZW50YXRpb24gcmV0dXJucyBhbnl0aGluZyBvdGhlciB0aGFuXHJcbiAqIGEgYHN0cmluZ2AgaXQgd2lsbCB0aHJvdy5cclxuICpcclxuICogQHBhcmFtIHRhcmdldCBUYXJnZXQgb2JqZWN0IHRvIGdldCB0aGUgSUQgZnJvbS5cclxuICogQHJldHVybnMgVGhlIHN0cmluZyBJRCBvciBgdW5kZWZpbmVkYC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRNb2RlbFJlZklkKHRhcmdldDogb2JqZWN0KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcclxuICBpZiAoaXNNb2RlbCh0YXJnZXQpICYmIHRhcmdldC5nZXRSZWZJZCkge1xyXG4gICAgY29uc3QgaWQgPSB0YXJnZXQuZ2V0UmVmSWQoKVxyXG4gICAgaWYgKGlkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGlkICE9PSBcInN0cmluZ1wiKSB7XHJcbiAgICAgIHRocm93IGZhaWx1cmUoXCInZ2V0UmVmSWQoKScgbXVzdCByZXR1cm4gYSBzdHJpbmcgb3IgdW5kZWZpbmVkIHdoZW4gcHJlc2VudFwiKVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGlkXHJcbiAgfVxyXG4gIHJldHVybiB1bmRlZmluZWRcclxufVxyXG5cclxuLy8gb25lIGNvbXB1dGVkIGlkIHRyZWUgcGVyIGlkIGZ1bmN0aW9uXHJcbmNvbnN0IGNvbXB1dGVkSWRUcmVlcyA9IG5ldyBXZWFrTWFwPFxyXG4gIChub2RlOiBvYmplY3QpID0+IHN0cmluZyB8IHVuZGVmaW5lZCxcclxuICBDb21wdXRlZFdhbGtUcmVlQWdncmVnYXRlPHN0cmluZz5cclxuPigpXHJcblxyXG4vKipcclxuICogUmVzb2x2ZXMgYSBub2RlIGdpdmVuIGl0cyBJRC5cclxuICpcclxuICogQHR5cGVwYXJhbSBUIFRhcmdldCBvYmplY3QgdHlwZS5cclxuICogQHBhcmFtIHJvb3QgTm9kZSB3aGVyZSB0byBzdGFydCB0aGUgc2VhcmNoLiBUaGUgc2VhcmNoIHdpbGwgYmUgZG9uZSBvbiBpdCBhbmQgYWxsIGl0cyBjaGlsZHJlbi5cclxuICogQHBhcmFtIGlkIElEIHRvIHNlYXJjaCBmb3IuXHJcbiAqIEBwYXJhbSBnZXRJZCBGdW5jdGlvbiB0aGF0IHdpbGwgYmUgdXNlZCB0byBnZXQgdGhlIElEIGZyb20gYW4gb2JqZWN0IChgZ2V0TW9kZWxSZWZJZGAgYnkgZGVmYXVsdCkuXHJcbiAqIEByZXR1cm5zIFRoZSBub2RlIGZvdW5kIG9yIGB1bmRlZmluZWRgIGlmIG5vbmUuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUlkPFQgZXh0ZW5kcyBvYmplY3Q+KFxyXG4gIHJvb3Q6IG9iamVjdCxcclxuICBpZDogc3RyaW5nLFxyXG4gIGdldElkOiBSZWZJZFJlc29sdmVyID0gZ2V0TW9kZWxSZWZJZFxyXG4pOiBUIHwgdW5kZWZpbmVkIHtcclxuICAvLyBjYWNoZS9yZXVzZSBjb21wdXRlZElkVHJlZXMgZm9yIHNhbWUgZ2V0SWQgZnVuY3Rpb25cclxuICBjb25zdCBjb21wdXRlZElkVHJlZSA9IGdldE9yQ3JlYXRlKGNvbXB1dGVkSWRUcmVlcywgZ2V0SWQsICgpID0+XHJcbiAgICBjb21wdXRlZFdhbGtUcmVlQWdncmVnYXRlPHN0cmluZz4oKG5vZGUpID0+IGdldElkKG5vZGUpKVxyXG4gIClcclxuXHJcbiAgY29uc3QgaWRNYXAgPSBjb21wdXRlZElkVHJlZS53YWxrKHJvb3QpXHJcbiAgcmV0dXJuIGlkTWFwID8gKGlkTWFwLmdldChpZCkgYXMgVCB8IHVuZGVmaW5lZCkgOiB1bmRlZmluZWRcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0QmFja1JlZnM8VCBleHRlbmRzIG9iamVjdD4oXHJcbiAgdGFyZ2V0OiBULFxyXG4gIHJlZlR5cGU/OiBSZWZDb25zdHJ1Y3RvcjxUPlxyXG4pOiBPYnNlcnZhYmxlU2V0PFJlZjxUPj4ge1xyXG4gIGxldCBiYWNrUmVmcyA9IG9iamVjdEJhY2tSZWZzLmdldCh0YXJnZXQpXHJcbiAgaWYgKCFiYWNrUmVmcykge1xyXG4gICAgYmFja1JlZnMgPSB7XHJcbiAgICAgIGFsbDogb2JzZXJ2YWJsZS5zZXQodW5kZWZpbmVkLCB7IGRlZXA6IGZhbHNlIH0pLFxyXG4gICAgICBieVR5cGU6IG5ldyBXZWFrTWFwKCksXHJcbiAgICB9XHJcbiAgICBvYmplY3RCYWNrUmVmcy5zZXQodGFyZ2V0LCBiYWNrUmVmcylcclxuICB9XHJcblxyXG4gIGlmICghcmVmVHlwZSkge1xyXG4gICAgcmV0dXJuIGJhY2tSZWZzLmFsbFxyXG4gIH0gZWxzZSB7XHJcbiAgICBsZXQgYnlUeXBlID0gYmFja1JlZnMuYnlUeXBlLmdldChyZWZUeXBlKVxyXG4gICAgaWYgKCFieVR5cGUpIHtcclxuICAgICAgYnlUeXBlID0gb2JzZXJ2YWJsZS5zZXQodW5kZWZpbmVkLCB7IGRlZXA6IGZhbHNlIH0pXHJcbiAgICAgIGJhY2tSZWZzLmJ5VHlwZS5zZXQocmVmVHlwZSwgYnlUeXBlKVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGJ5VHlwZVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgYWxsIHJlZmVyZW5jZXMgdGhhdCByZXNvbHZlIHRvIGEgZ2l2ZW4gb2JqZWN0LlxyXG4gKlxyXG4gKiBAdHlwZXBhcmFtIFQgUmVmZXJlbmNlZCBvYmplY3QgdHlwZS5cclxuICogQHBhcmFtIHRhcmdldCBOb2RlIHRoZSByZWZlcmVuY2VzIHBvaW50IHRvLlxyXG4gKiBAcGFyYW0gcmVmVHlwZSBQYXNzIGl0IHRvIGZpbHRlciBieSBvbmx5IHJlZmVyZW5jZXMgb2YgYSBnaXZlbiB0eXBlLCBvciBvbWl0IC8gcGFzcyBgdW5kZWZpbmVkYCB0byBnZXQgcmVmZXJlbmNlcyBvZiBhbnkgdHlwZS5cclxuICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucy5cclxuICogQHJldHVybnMgQW4gb2JzZXJ2YWJsZSBzZXQgd2l0aCBhbGwgcmVmZXJlbmNlIG9iamVjdHMgdGhhdCBwb2ludCB0byB0aGUgZ2l2ZW4gb2JqZWN0LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdldFJlZnNSZXNvbHZpbmdUbzxUIGV4dGVuZHMgb2JqZWN0PihcclxuICB0YXJnZXQ6IFQsXHJcbiAgcmVmVHlwZT86IFJlZkNvbnN0cnVjdG9yPFQ+LFxyXG4gIG9wdGlvbnM/OiB7XHJcbiAgICB1cGRhdGVBbGxSZWZzSWZOZWVkZWQ/OiBib29sZWFuXHJcbiAgfVxyXG4pOiBPYnNlcnZhYmxlU2V0PFJlZjxUPj4ge1xyXG4gIGFzc2VydFR3ZWFrZWRPYmplY3QodGFyZ2V0LCBcInRhcmdldFwiKVxyXG5cclxuICBpZiAob3B0aW9ucz8udXBkYXRlQWxsUmVmc0lmTmVlZGVkICYmIGlzUmVhY3Rpb25EZWxheWVkKCkpIHtcclxuICAgIC8vIGluIHRoaXMgY2FzZSB0aGUgcmVmZXJlbmNlIHVwZGF0ZSBtaWdodCBoYXZlIGJlZW4gZGVsYXllZFxyXG4gICAgLy8gc28gd2Ugd2lsbCBtYWtlIGEgYmVzdCBlZmZvcnQgdG8gdXBkYXRlIHRoZW1cclxuICAgIGNvbnN0IHJlZnNDaGVja2VkID0gbmV3IFNldDxSZWY8b2JqZWN0Pj4oKVxyXG4gICAgY29uc3QgdXBkYXRlUmVmID0gKHJlZjogUmVmPGFueT4pID0+IHtcclxuICAgICAgaWYgKCFyZWZzQ2hlY2tlZC5oYXMocmVmKSkge1xyXG4gICAgICAgIGlmICghcmVmVHlwZSB8fCByZWYgaW5zdGFuY2VvZiByZWZUeXBlLnJlZkNsYXNzKSB7XHJcbiAgICAgICAgICByZWYuZm9yY2VVcGRhdGVCYWNrUmVmcygpXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlZnNDaGVja2VkLmFkZChyZWYpXHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBvbGRCYWNrUmVmcyA9IGdldEJhY2tSZWZzKHRhcmdldCwgcmVmVHlwZSlcclxuICAgIG9sZEJhY2tSZWZzLmZvckVhY2godXBkYXRlUmVmKVxyXG5cclxuICAgIGNvbnN0IHJlZnNDaGlsZHJlbk9mUm9vdCA9IGdldERlZXBDaGlsZHJlblJlZnMoZ2V0RGVlcE9iamVjdENoaWxkcmVuKGZhc3RHZXRSb290KHRhcmdldCkpKVxyXG4gICAgbGV0IHJlZnM6IFNldDxSZWY8b2JqZWN0Pj4gfCB1bmRlZmluZWRcclxuICAgIGlmIChyZWZUeXBlKSB7XHJcbiAgICAgIHJlZnMgPSByZWZzQ2hpbGRyZW5PZlJvb3QuYnlUeXBlLmdldChyZWZUeXBlLnJlZkNsYXNzKVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmVmcyA9IHJlZnNDaGlsZHJlbk9mUm9vdC5hbGxcclxuICAgIH1cclxuICAgIHJlZnM/LmZvckVhY2godXBkYXRlUmVmKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGdldEJhY2tSZWZzKHRhcmdldCwgcmVmVHlwZSlcclxufVxyXG5cclxuY29uc3QgdXBkYXRlQmFja1JlZnMgPSBhY3Rpb24oXHJcbiAgXCJ1cGRhdGVCYWNrUmVmc1wiLFxyXG4gIDxUIGV4dGVuZHMgb2JqZWN0PihcclxuICAgIHJlZjogUmVmPFQ+LFxyXG4gICAgcmVmQ2xhc3M6IFJlZkNvbnN0cnVjdG9yPFQ+LFxyXG4gICAgbmV3VGFyZ2V0OiBUIHwgdW5kZWZpbmVkLFxyXG4gICAgb2xkVGFyZ2V0OiBUIHwgdW5kZWZpbmVkXHJcbiAgKSA9PiB7XHJcbiAgICBpZiAobmV3VGFyZ2V0ID09PSBvbGRUYXJnZXQpIHtcclxuICAgICAgcmV0dXJuXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG9sZFRhcmdldCkge1xyXG4gICAgICBnZXRCYWNrUmVmcyhvbGRUYXJnZXQpLmRlbGV0ZShyZWYpXHJcbiAgICAgIGdldEJhY2tSZWZzKG9sZFRhcmdldCwgcmVmQ2xhc3MgYXMgUmVmQ29uc3RydWN0b3I8YW55PikuZGVsZXRlKHJlZilcclxuICAgIH1cclxuICAgIGlmIChuZXdUYXJnZXQpIHtcclxuICAgICAgZ2V0QmFja1JlZnMobmV3VGFyZ2V0KS5hZGQocmVmKVxyXG4gICAgICBnZXRCYWNrUmVmcyhuZXdUYXJnZXQsIHJlZkNsYXNzIGFzIFJlZkNvbnN0cnVjdG9yPGFueT4pLmFkZChyZWYpXHJcbiAgICB9XHJcbiAgfVxyXG4pXHJcblxyXG5mdW5jdGlvbiBpc1JlYWN0aW9uRGVsYXllZCgpIHtcclxuICBsZXQgcmVhY3Rpb25EZWxheWVkID0gdHJ1ZVxyXG4gIGNvbnN0IGRpc3Bvc2UgPSB3aGVuKFxyXG4gICAgKCkgPT4gdHJ1ZSxcclxuICAgICgpID0+IHtcclxuICAgICAgcmVhY3Rpb25EZWxheWVkID0gZmFsc2VcclxuICAgIH1cclxuICApXHJcbiAgZGlzcG9zZSgpXHJcbiAgcmV0dXJuIHJlYWN0aW9uRGVsYXllZFxyXG59XHJcblxyXG5pbnRlcmZhY2UgRGVlcENoaWxkcmVuUmVmcyB7XHJcbiAgYWxsOiBTZXQ8UmVmPGFueT4+XHJcbiAgYnlUeXBlOiBXZWFrTWFwPE1vZGVsQ2xhc3M8UmVmPGFueT4+LCBTZXQ8UmVmPGFueT4+PlxyXG59XHJcblxyXG5jb25zdCBnZXREZWVwQ2hpbGRyZW5SZWZzID0gcmVnaXN0ZXJEZWVwT2JqZWN0Q2hpbGRyZW5FeHRlbnNpb248RGVlcENoaWxkcmVuUmVmcz4oe1xyXG4gIGluaXREYXRhKCkge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgYWxsOiBuZXcgU2V0KCksXHJcbiAgICAgIGJ5VHlwZTogbmV3IFdlYWtNYXAoKSxcclxuICAgIH1cclxuICB9LFxyXG5cclxuICBhZGROb2RlKG5vZGUsIGRhdGEpIHtcclxuICAgIGlmIChub2RlIGluc3RhbmNlb2YgUmVmKSB7XHJcbiAgICAgIGRhdGEuYWxsLmFkZChub2RlKVxyXG4gICAgICBjb25zdCByZWZzQnlUaGlzVHlwZSA9IGdldE9yQ3JlYXRlKGRhdGEuYnlUeXBlLCBub2RlLmNvbnN0cnVjdG9yLCAoKSA9PiBuZXcgU2V0KCkpXHJcbiAgICAgIHJlZnNCeVRoaXNUeXBlLmFkZChub2RlKVxyXG4gICAgfVxyXG4gIH0sXHJcbn0pXHJcbiIsImltcG9ydCB7IGFjdGlvbiB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7XG4gIGdldE1vZGVsUmVmSWQsXG4gIGludGVybmFsQ3VzdG9tUmVmLFxuICBSZWZJZFJlc29sdmVyLFxuICBSZWZPblJlc29sdmVkVmFsdWVDaGFuZ2UsXG4gIFJlZlJlc29sdmVyLFxufSBmcm9tIFwiLi9jb3JlXCJcbmltcG9ydCB0eXBlIHsgUmVmQ29uc3RydWN0b3IgfSBmcm9tIFwiLi9SZWZcIlxuXG4vKipcbiAqIEN1c3RvbSByZWZlcmVuY2Ugb3B0aW9ucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDdXN0b21SZWZPcHRpb25zPFQgZXh0ZW5kcyBvYmplY3Q+IHtcbiAgLyoqXG4gICAqIE11c3QgcmV0dXJuIHRoZSByZXNvbHV0aW9uIGZvciB0aGUgZ2l2ZW4gcmVmZXJlbmNlIG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIHJlZiBSZWZlcmVuY2Ugb2JqZWN0LlxuICAgKiBAcmV0dXJucyBUaGUgcmVzb2x2ZWQgb2JqZWN0IG9yIHVuZGVmaW5lZCBpZiBpdCBjb3VsZCBub3QgYmUgcmVzb2x2ZWQuXG4gICAqL1xuICByZXNvbHZlOiBSZWZSZXNvbHZlcjxUPlxuXG4gIC8qKlxuICAgKiBNdXN0IHJldHVybiB0aGUgSUQgYXNzb2NpYXRlZCB0byB0aGUgZ2l2ZW4gdGFyZ2V0IG9iamVjdCwgb3IgYHVuZGVmaW5lZGAgaWYgaXQgaGFzIG5vIElELlxuICAgKiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCB0cnkgdG8gZ2V0IHRoZSByZWZlcmVuY2UgaWQgZnJvbSB0aGUgbW9kZWwgYGdldFJlZklkKClgIG1ldGhvZC5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldCBUYXJnZXQgb2JqZWN0LlxuICAgKi9cbiAgZ2V0SWQ/OiBSZWZJZFJlc29sdmVyXG5cbiAgLyoqXG4gICAqIFdoYXQgc2hvdWxkIGhhcHBlbiB3aGVuIHRoZSByZXNvbHZlZCB2YWx1ZSBjaGFuZ2VzLlxuICAgKlxuICAgKiBAcGFyYW0gcmVmIFJlZmVyZW5jZSBvYmplY3QuXG4gICAqIEBwYXJhbSBuZXdWYWx1ZSBOZXcgcmVzb2x2ZWQgdmFsdWUuXG4gICAqIEBwYXJhbSBvbGRWYWx1ZSBPbGQgcmVzb2x2ZWQgdmFsdWUuXG4gICAqL1xuICBvblJlc29sdmVkVmFsdWVDaGFuZ2U/OiBSZWZPblJlc29sdmVkVmFsdWVDaGFuZ2U8VD5cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgY3VzdG9tIHJlZiB0byBhbiBvYmplY3QsIHdoaWNoIGluIGl0cyBzbmFwc2hvdCBmb3JtIGhhcyBhbiBpZC5cbiAqXG4gKiBAdHlwZXBhcmFtIFQgVGFyZ2V0IG9iamVjdCB0eXBlLlxuICogQHBhcmFtIG1vZGVsVHlwZUlkIFVuaXF1ZSBtb2RlbCB0eXBlIGlkLlxuICogQHBhcmFtIG9wdGlvbnMgQ3VzdG9tIHJlZmVyZW5jZSBvcHRpb25zLlxuICogQHJldHVybnMgQSBmdW5jdGlvbiB0aGF0IGFsbG93cyB5b3UgdG8gY29uc3RydWN0IHRoYXQgdHlwZSBvZiBjdXN0b20gcmVmZXJlbmNlLlxuICovXG5leHBvcnQgY29uc3QgY3VzdG9tUmVmOiA8VCBleHRlbmRzIG9iamVjdD4oXG4gIG1vZGVsVHlwZUlkOiBzdHJpbmcsXG4gIG9wdGlvbnM6IEN1c3RvbVJlZk9wdGlvbnM8VD5cbikgPT4gUmVmQ29uc3RydWN0b3I8VD4gPSBhY3Rpb24oXCJjdXN0b21SZWZcIiwgKG1vZGVsVHlwZUlkLCBvcHRpb25zKSA9PiB7XG4gIGNvbnN0IGdldElkID0gb3B0aW9ucy5nZXRJZCA/PyBnZXRNb2RlbFJlZklkXG5cbiAgcmV0dXJuIGludGVybmFsQ3VzdG9tUmVmKG1vZGVsVHlwZUlkLCAoKSA9PiBvcHRpb25zLnJlc29sdmUsIGdldElkLCBvcHRpb25zLm9uUmVzb2x2ZWRWYWx1ZUNoYW5nZSlcbn0pXG4iLCJpbXBvcnQgeyBhY3Rpb24gfSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7IGZhc3RHZXRSb290IH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoXCJcclxuaW1wb3J0IHtcclxuICBnZXRNb2RlbFJlZklkLFxyXG4gIGludGVybmFsQ3VzdG9tUmVmLFxyXG4gIFJlZklkUmVzb2x2ZXIsXHJcbiAgUmVmT25SZXNvbHZlZFZhbHVlQ2hhbmdlLFxyXG4gIFJlZlJlc29sdmVyLFxyXG4gIHJlc29sdmVJZCxcclxufSBmcm9tIFwiLi9jb3JlXCJcclxuaW1wb3J0IHR5cGUgeyBSZWYsIFJlZkNvbnN0cnVjdG9yIH0gZnJvbSBcIi4vUmVmXCJcclxuXHJcbi8qKlxyXG4gKiBDdXN0b20gcmVmZXJlbmNlIG9wdGlvbnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFJvb3RSZWZPcHRpb25zPFQgZXh0ZW5kcyBvYmplY3Q+IHtcclxuICAvKipcclxuICAgKiBNdXN0IHJldHVybiB0aGUgSUQgYXNzb2NpYXRlZCB0byB0aGUgZ2l2ZW4gdGFyZ2V0IG9iamVjdCwgb3IgYHVuZGVmaW5lZGAgaWYgaXQgaGFzIG5vIElELlxyXG4gICAqIElmIG5vdCBwcm92aWRlZCBpdCB3aWxsIHRyeSB0byBnZXQgdGhlIHJlZmVyZW5jZSBpZCBmcm9tIHRoZSBtb2RlbCBgZ2V0UmVmSWQoKWAgbWV0aG9kLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHRhcmdldCBUYXJnZXQgb2JqZWN0LlxyXG4gICAqL1xyXG4gIGdldElkPzogUmVmSWRSZXNvbHZlclxyXG5cclxuICAvKipcclxuICAgKiBXaGF0IHNob3VsZCBoYXBwZW4gd2hlbiB0aGUgcmVzb2x2ZWQgdmFsdWUgY2hhbmdlcy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSByZWYgUmVmZXJlbmNlIG9iamVjdC5cclxuICAgKiBAcGFyYW0gbmV3VmFsdWUgTmV3IHJlc29sdmVkIHZhbHVlLlxyXG4gICAqIEBwYXJhbSBvbGRWYWx1ZSBPbGQgcmVzb2x2ZWQgdmFsdWUuXHJcbiAgICovXHJcbiAgb25SZXNvbHZlZFZhbHVlQ2hhbmdlPzogUmVmT25SZXNvbHZlZFZhbHVlQ2hhbmdlPFQ+XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDcmVhdGVzIGEgcm9vdCByZWYgdG8gYW4gb2JqZWN0LCB3aGljaCBpbiBpdHMgc25hcHNob3QgZm9ybSBoYXMgYW4gaWQuXHJcbiAqIEEgcm9vdCByZWYgd2lsbCBvbmx5IGJlIGFibGUgdG8gcmVzb2x2ZSByZWZlcmVuY2VzIGFzIGxvbmcgYXMgYm90aCB0aGUgUmVmXHJcbiAqIGFuZCB0aGUgcmVmZXJlbmNlZCBvYmplY3Qgc2hhcmUgYSBjb21tb24gcm9vdC5cclxuICpcclxuICogQHR5cGVwYXJhbSBUIFRhcmdldCBvYmplY3QgdHlwZS5cclxuICogQHBhcmFtIG1vZGVsVHlwZUlkIFVuaXF1ZSBtb2RlbCB0eXBlIGlkLlxyXG4gKiBAcGFyYW0gW29wdGlvbnNdIFJvb3QgcmVmZXJlbmNlIG9wdGlvbnMuXHJcbiAqIEByZXR1cm5zIEEgZnVuY3Rpb24gdGhhdCBhbGxvd3MgeW91IHRvIGNvbnN0cnVjdCB0aGF0IHR5cGUgb2Ygcm9vdCByZWZlcmVuY2UuXHJcbiAqL1xyXG5leHBvcnQgY29uc3Qgcm9vdFJlZjogPFQgZXh0ZW5kcyBvYmplY3Q+KFxyXG4gIG1vZGVsVHlwZUlkOiBzdHJpbmcsXHJcbiAgb3B0aW9ucz86IFJvb3RSZWZPcHRpb25zPFQ+IHwgdW5kZWZpbmVkXHJcbikgPT4gUmVmQ29uc3RydWN0b3I8VD4gPSBhY3Rpb24oXHJcbiAgXCJyb290UmVmXCIsXHJcbiAgPFQgZXh0ZW5kcyBvYmplY3Q+KG1vZGVsVHlwZUlkOiBzdHJpbmcsIG9wdGlvbnM/OiBSb290UmVmT3B0aW9uczxUPik6IFJlZkNvbnN0cnVjdG9yPFQ+ID0+IHtcclxuICAgIGNvbnN0IGdldElkID0gb3B0aW9ucz8uZ2V0SWQgPz8gZ2V0TW9kZWxSZWZJZFxyXG4gICAgY29uc3Qgb25SZXNvbHZlZFZhbHVlQ2hhbmdlID0gb3B0aW9ucz8ub25SZXNvbHZlZFZhbHVlQ2hhbmdlXHJcblxyXG4gICAgY29uc3QgcmVzb2x2ZXJHZW4gPSAocmVmOiBSZWY8VD4pOiBSZWZSZXNvbHZlcjxUPiA9PiB7XHJcbiAgICAgIGxldCBjYWNoZWRUYXJnZXQ6IFQgfCB1bmRlZmluZWRcclxuXHJcbiAgICAgIHJldHVybiAoKSA9PiB7XHJcbiAgICAgICAgY29uc3QgcmVmUm9vdCA9IGZhc3RHZXRSb290KHJlZilcclxuXHJcbiAgICAgICAgaWYgKGlzUmVmUm9vdENhY2hlZFRhcmdldE9rKHJlZiwgcmVmUm9vdCwgY2FjaGVkVGFyZ2V0LCBnZXRJZCkpIHtcclxuICAgICAgICAgIHJldHVybiBjYWNoZWRUYXJnZXRcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHdoZW4gbm90IGZvdW5kLCBldmVyeXRpbWUgYSBjaGlsZCBpcyBhZGRlZC9yZW1vdmVkIG9yIGl0cyBpZCBjaGFuZ2VzIHdlIHdpbGwgcGVyZm9ybSBhbm90aGVyIHNlYXJjaFxyXG4gICAgICAgIC8vIHRoaXMgc2VhcmNoIGlzIG9ubHkgZG9uZSBvbmNlIGZvciBldmVyeSBkaXN0aW5jdCBnZXRJZCBmdW5jdGlvblxyXG4gICAgICAgIGNvbnN0IG5ld1RhcmdldCA9IHJlc29sdmVJZDxUPihyZWZSb290LCByZWYuaWQsIGdldElkKVxyXG4gICAgICAgIGlmIChuZXdUYXJnZXQpIHtcclxuICAgICAgICAgIGNhY2hlZFRhcmdldCA9IG5ld1RhcmdldFxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gbmV3VGFyZ2V0XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gaW50ZXJuYWxDdXN0b21SZWYobW9kZWxUeXBlSWQsIHJlc29sdmVyR2VuLCBnZXRJZCwgb25SZXNvbHZlZFZhbHVlQ2hhbmdlKVxyXG4gIH1cclxuKVxyXG5cclxuZnVuY3Rpb24gaXNSZWZSb290Q2FjaGVkVGFyZ2V0T2s8VCBleHRlbmRzIG9iamVjdD4oXHJcbiAgcmVmOiBSZWY8VD4sXHJcbiAgcmVmUm9vdDogb2JqZWN0LFxyXG4gIGNhY2hlZFRhcmdldDogVCB8IHVuZGVmaW5lZCxcclxuICBnZXRJZDogUmVmSWRSZXNvbHZlclxyXG4pOiBjYWNoZWRUYXJnZXQgaXMgVCB7XHJcbiAgaWYgKCFjYWNoZWRUYXJnZXQpIHJldHVybiBmYWxzZVxyXG4gIGlmIChyZWYuaWQgIT09IGdldElkKGNhY2hlZFRhcmdldCkpIHJldHVybiBmYWxzZVxyXG4gIGlmIChyZWZSb290ICE9PSBmYXN0R2V0Um9vdChjYWNoZWRUYXJnZXQpKSByZXR1cm4gZmFsc2VcclxuICByZXR1cm4gdHJ1ZVxyXG59XHJcbiIsImltcG9ydCB7IGFkZFN0YW5kYWxvbmVBY3Rpb24gfSBmcm9tIFwiLi9hY3Rpb25zXCJcblxuLyoqXG4gKiBDcmVhdGVzIGEgc3RhbmRhbG9uZSBhY3Rpb24uIEEgc3RhbmRhbG9uZSBhY3Rpb24gbXVzdCBhbHdheXMgdGFrZSBhbiBleGlzdGluZyB0cmVlIG5vZGUgYXMgZmlyc3QgYXJndW1lbnQuXG4gKlxuICogQHBhcmFtIGFjdGlvbk5hbWUgVW5pcXVlIGFjdGlvbiBuYW1lLlxuICogQHBhcmFtIGZuIEZ1bmN0aW9uLlxuICogQHJldHVybnMgVGhlIGZ1bmN0aW9uIGFzIGFuIHN0YW5kYWxvbmUgYWN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RhbmRhbG9uZUFjdGlvbjxGTiBleHRlbmRzICh0YXJnZXQ6IGFueSwgLi4uYXJnczogYW55W10pID0+IGFueT4oXG4gIGFjdGlvbk5hbWU6IHN0cmluZyxcbiAgZm46IEZOXG4pOiBGTiB7XG4gIHJldHVybiBhZGRTdGFuZGFsb25lQWN0aW9uKGFjdGlvbk5hbWUsIGZuLCBmYWxzZSkgYXMgdW5rbm93biBhcyBGTlxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBzdGFuZGFsb25lIGZsb3cuIEEgc3RhbmRhbG9uZSBmbG93IG11c3QgYWx3YXlzIHRha2UgYW4gZXhpc3RpbmcgdHJlZSBub2RlIGFzIGZpcnN0IGFyZ3VtZW50LlxuICpcbiAqIEBwYXJhbSBhY3Rpb25OYW1lIFVuaXF1ZSBhY3Rpb24gbmFtZS5cbiAqIEBwYXJhbSBmbiBGdW5jdGlvbi5cbiAqIEByZXR1cm5zIFRoZSBmdW5jdGlvbiBhcyBhbiBzdGFuZGFsb25lIGZsb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdGFuZGFsb25lRmxvdzxUVGFyZ2V0LCBUQXJncyBleHRlbmRzIGFueVtdLCBUUmVzdWx0PihcbiAgYWN0aW9uTmFtZTogc3RyaW5nLFxuICBmbjogKHRhcmdldDogVFRhcmdldCwgLi4uYXJnczogVEFyZ3MpID0+IEdlbmVyYXRvcjxhbnksIFRSZXN1bHQsIGFueT5cbik6ICh0YXJnZXQ6IFRUYXJnZXQsIC4uLmFyZ3M6IFRBcmdzKSA9PiBQcm9taXNlPFRSZXN1bHQ+IHtcbiAgcmV0dXJuIGFkZFN0YW5kYWxvbmVBY3Rpb24oYWN0aW9uTmFtZSwgZm4sIHRydWUpIGFzIHVua25vd24gYXMgYW55XG59XG4iLCJpbXBvcnQgeyByZW1vdmUgfSBmcm9tIFwibW9ieFwiXG5pbXBvcnQgeyB0b1RyZWVOb2RlIH0gZnJvbSBcIi4uL3R3ZWFrZXIvdHdlYWtcIlxuaW1wb3J0IHsgbmFtZXNwYWNlIGFzIG5zIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IHNldElmRGlmZmVyZW50IH0gZnJvbSBcIi4uL3V0aWxzL3NldElmRGlmZmVyZW50XCJcbmltcG9ydCB7IHN0YW5kYWxvbmVBY3Rpb24gfSBmcm9tIFwiLi9zdGFuZGFsb25lQWN0aW9uc1wiXG5cbmZ1bmN0aW9uIF9zcGxpY2UoYXJyYXk6IGFueVtdLCBzdGFydDogbnVtYmVyLCBkZWxldGVDb3VudD86IG51bWJlcik6IGFueVtdXG5mdW5jdGlvbiBfc3BsaWNlKGFycmF5OiBhbnlbXSwgc3RhcnQ6IG51bWJlciwgZGVsZXRlQ291bnQ6IG51bWJlciwgLi4uaXRlbXM6IGFueVtdKTogYW55W11cbmZ1bmN0aW9uIF9zcGxpY2UoYXJyYXk6IGFueVtdLCAuLi5hcmdzOiBhbnlbXSk6IGFueVtdIHtcbiAgcmV0dXJuIChhcnJheS5zcGxpY2UgYXMgYW55KSguLi5hcmdzKVxufVxuXG5jb25zdCBuYW1lc3BhY2UgPSBgJHtuc30vYXJyYXlBY3Rpb25zYFxuXG5leHBvcnQgY29uc3QgYXJyYXlBY3Rpb25zID0ge1xuICBzZXQ6IHN0YW5kYWxvbmVBY3Rpb24oYCR7bmFtZXNwYWNlfTo6c2V0YCwgPFQ+KGFycmF5OiBUW10sIGluZGV4OiBudW1iZXIsIHZhbHVlOiBhbnkpOiB2b2lkID0+IHtcbiAgICBzZXRJZkRpZmZlcmVudChhcnJheSwgaW5kZXgsIHZhbHVlKVxuICB9KSxcblxuICBkZWxldGU6IHN0YW5kYWxvbmVBY3Rpb24oYCR7bmFtZXNwYWNlfTo6ZGVsZXRlYCwgPFQ+KGFycmF5OiBUW10sIGluZGV4OiBudW1iZXIpOiBib29sZWFuID0+IHtcbiAgICByZXR1cm4gcmVtb3ZlKGFycmF5LCBcIlwiICsgaW5kZXgpXG4gIH0pLFxuXG4gIHNldExlbmd0aDogc3RhbmRhbG9uZUFjdGlvbihgJHtuYW1lc3BhY2V9OjpzZXRMZW5ndGhgLCA8VD4oYXJyYXk6IFRbXSwgbGVuZ3RoOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgICBhcnJheS5sZW5ndGggPSBsZW5ndGhcbiAgfSksXG5cbiAgY29uY2F0OiBzdGFuZGFsb25lQWN0aW9uKFxuICAgIGAke25hbWVzcGFjZX06OmNvbmNhdGAsXG4gICAgPFQ+KGFycmF5OiBUW10sIC4uLml0ZW1zOiBDb25jYXRBcnJheTxUPltdKTogVFtdID0+IHtcbiAgICAgIHJldHVybiBhcnJheS5jb25jYXQoLi4uaXRlbXMpXG4gICAgfVxuICApLFxuXG4gIGNvcHlXaXRoaW46IHN0YW5kYWxvbmVBY3Rpb24oXG4gICAgYCR7bmFtZXNwYWNlfTo6Y29weVdpdGhpbmAsXG4gICAgPFQ+KGFycmF5OiBUW10sIHRhcmdldDogbnVtYmVyLCBzdGFydDogbnVtYmVyLCBlbmQ/OiBudW1iZXIgfCB1bmRlZmluZWQpOiBUW10gPT4ge1xuICAgICAgcmV0dXJuIGFycmF5LmNvcHlXaXRoaW4odGFyZ2V0LCBzdGFydCwgZW5kKVxuICAgIH1cbiAgKSxcblxuICBmaWxsOiBzdGFuZGFsb25lQWN0aW9uKFxuICAgIGAke25hbWVzcGFjZX06OmZpbGxgLFxuICAgIDxUPihhcnJheTogVFtdLCB2YWx1ZTogVCwgc3RhcnQ/OiBudW1iZXIgfCB1bmRlZmluZWQsIGVuZD86IG51bWJlciB8IHVuZGVmaW5lZCk6IFRbXSA9PiB7XG4gICAgICByZXR1cm4gYXJyYXkuZmlsbCh2YWx1ZSwgc3RhcnQsIGVuZClcbiAgICB9XG4gICksXG5cbiAgcG9wOiBzdGFuZGFsb25lQWN0aW9uKGAke25hbWVzcGFjZX06OnBvcGAsIDxUPihhcnJheTogVFtdKTogVCB8IHVuZGVmaW5lZCA9PiB7XG4gICAgcmV0dXJuIGFycmF5LnBvcCgpXG4gIH0pLFxuXG4gIHB1c2g6IHN0YW5kYWxvbmVBY3Rpb24oYCR7bmFtZXNwYWNlfTo6cHVzaGAsIDxUPihhcnJheTogVFtdLCAuLi5pdGVtczogVFtdKTogbnVtYmVyID0+IHtcbiAgICByZXR1cm4gYXJyYXkucHVzaCguLi5pdGVtcylcbiAgfSksXG5cbiAgcmV2ZXJzZTogc3RhbmRhbG9uZUFjdGlvbihgJHtuYW1lc3BhY2V9OjpyZXZlcnNlYCwgPFQ+KGFycmF5OiBUW10pOiBUW10gPT4ge1xuICAgIHJldHVybiBhcnJheS5yZXZlcnNlKClcbiAgfSksXG5cbiAgc2hpZnQ6IHN0YW5kYWxvbmVBY3Rpb24oYCR7bmFtZXNwYWNlfTo6c2hpZnRgLCA8VD4oYXJyYXk6IFRbXSk6IFQgfCB1bmRlZmluZWQgPT4ge1xuICAgIHJldHVybiBhcnJheS5zaGlmdCgpXG4gIH0pLFxuXG4gIHNsaWNlOiBzdGFuZGFsb25lQWN0aW9uKFxuICAgIGAke25hbWVzcGFjZX06OnNsaWNlYCxcbiAgICA8VD4oYXJyYXk6IFRbXSwgc3RhcnQ/OiBudW1iZXIgfCB1bmRlZmluZWQsIGVuZD86IG51bWJlciB8IHVuZGVmaW5lZCk6IFRbXSA9PiB7XG4gICAgICByZXR1cm4gYXJyYXkuc2xpY2Uoc3RhcnQsIGVuZClcbiAgICB9XG4gICksXG5cbiAgc29ydDogc3RhbmRhbG9uZUFjdGlvbihcbiAgICBgJHtuYW1lc3BhY2V9Ojpzb3J0YCxcbiAgICA8VD4oYXJyYXk6IFRbXSwgY29tcGFyZUZuPzogKChhOiBULCBiOiBUKSA9PiBudW1iZXIpIHwgdW5kZWZpbmVkKTogVFtdID0+IHtcbiAgICAgIHJldHVybiBhcnJheS5zb3J0KGNvbXBhcmVGbilcbiAgICB9XG4gICksXG5cbiAgc3BsaWNlOiBzdGFuZGFsb25lQWN0aW9uKFxuICAgIGAke25hbWVzcGFjZX06OnNwbGljZWAsXG4gICAgX3NwbGljZSBhc1xuICAgICAgfCAoPFQ+KGFycmF5OiBUW10sIHN0YXJ0OiBudW1iZXIsIGRlbGV0ZUNvdW50PzogbnVtYmVyKSA9PiBUW10pXG4gICAgICB8ICg8VD4oYXJyYXk6IFRbXSwgc3RhcnQ6IG51bWJlciwgZGVsZXRlQ291bnQ6IG51bWJlciwgLi4uaXRlbXM6IFRbXSkgPT4gVFtdKVxuICApLFxuXG4gIHVuc2hpZnQ6IHN0YW5kYWxvbmVBY3Rpb24oYCR7bmFtZXNwYWNlfTo6dW5zaGlmdGAsIDxUPihhcnJheTogVFtdLCAuLi5pdGVtczogVFtdKTogbnVtYmVyID0+IHtcbiAgICByZXR1cm4gYXJyYXkudW5zaGlmdCguLi5pdGVtcylcbiAgfSksXG5cbiAgc3dhcDogc3RhbmRhbG9uZUFjdGlvbihcbiAgICBgJHtuYW1lc3BhY2V9Ojpzd2FwYCxcbiAgICA8VD4oYXJyYXk6IFRbXSwgaW5kZXgxOiBudW1iZXIsIGluZGV4MjogbnVtYmVyKTogYm9vbGVhbiA9PiB7XG4gICAgICBpZiAoaW5kZXgxIDwgMCB8fCBpbmRleDIgPCAwIHx8IGluZGV4MSA+PSBhcnJheS5sZW5ndGggfHwgaW5kZXgyID49IGFycmF5Lmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIH1cbiAgICAgIGlmIChpbmRleDIgPCBpbmRleDEpIHtcbiAgICAgICAgO1tpbmRleDEsIGluZGV4Ml0gPSBbaW5kZXgyLCBpbmRleDFdXG4gICAgICB9XG4gICAgICAvLyBzaW5jZSBhIHNhbWUgbm9kZSBjYW5ub3QgYmUgaW4gdHdvIHBsYWNlcyBhdCBvbmNlIHdlIHdpbGwgcmVtb3ZlXG4gICAgICAvLyBib3RoIHRoZW4gcmVpbnNlcnQgdGhlbVxuICAgICAgY29uc3QgW3YxXSA9IGFycmF5LnNwbGljZShpbmRleDEsIDEpXG4gICAgICBjb25zdCBbdjJdID0gYXJyYXkuc3BsaWNlKGluZGV4MiAtIDEsIDEpXG4gICAgICBhcnJheS5zcGxpY2UoaW5kZXgxLCAwLCB2MilcbiAgICAgIGFycmF5LnNwbGljZShpbmRleDIsIDAsIHYxKVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gICksXG5cbiAgY3JlYXRlOiA8VD4oZGF0YTogVFtdKTogVFtdID0+IHRvVHJlZU5vZGUoZGF0YSksXG59XG4iLCJpbXBvcnQgeyBpc09ic2VydmFibGUsIHJlbW92ZSB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IHRvVHJlZU5vZGUgfSBmcm9tIFwiLi4vdHdlYWtlci90d2Vha1wiXG5pbXBvcnQgeyBhc3NlcnRJc09iamVjdCwgbmFtZXNwYWNlIGFzIG5zIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IHNldElmRGlmZmVyZW50IH0gZnJvbSBcIi4uL3V0aWxzL3NldElmRGlmZmVyZW50XCJcbmltcG9ydCB7IHN0YW5kYWxvbmVBY3Rpb24gfSBmcm9tIFwiLi9zdGFuZGFsb25lQWN0aW9uc1wiXG5cbmNvbnN0IG5hbWVzcGFjZSA9IGAke25zfS9vYmplY3RBY3Rpb25zYFxuXG5leHBvcnQgY29uc3Qgb2JqZWN0QWN0aW9ucyA9IHtcbiAgc2V0OiBzdGFuZGFsb25lQWN0aW9uKFxuICAgIGAke25hbWVzcGFjZX06OnNldGAsXG4gICAgPFQgZXh0ZW5kcyBvYmplY3QsIEsgZXh0ZW5kcyBrZXlvZiBUPih0YXJnZXQ6IFQsIGtleTogSywgdmFsdWU6IFRbS10pOiB2b2lkID0+IHtcbiAgICAgIGlmIChpc09ic2VydmFibGUodGFyZ2V0KSkge1xuICAgICAgICBzZXRJZkRpZmZlcmVudCh0YXJnZXQsIGtleSwgdmFsdWUpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0YXJnZXRba2V5XSA9IHZhbHVlXG4gICAgICB9XG4gICAgfVxuICApLFxuXG4gIGFzc2lnbjogc3RhbmRhbG9uZUFjdGlvbihcbiAgICBgJHtuYW1lc3BhY2V9Ojphc3NpZ25gLFxuICAgIDxUIGV4dGVuZHMgb2JqZWN0Pih0YXJnZXQ6IFQsIHBhcnRpYWxPYmplY3Q6IFBhcnRpYWw8VD4pOiB2b2lkID0+IHtcbiAgICAgIGFzc2VydElzT2JqZWN0KHBhcnRpYWxPYmplY3QsIFwicGFydGlhbE9iamVjdFwiKVxuICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHBhcnRpYWxPYmplY3QpXG5cbiAgICAgIGlmIChpc09ic2VydmFibGUodGFyZ2V0KSkge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgICAgICAgY29uc3QgbmV3VmFsdWUgPSAocGFydGlhbE9iamVjdCBhcyBhbnkpW2tleV1cbiAgICAgICAgICBzZXRJZkRpZmZlcmVudCh0YXJnZXQsIGtleSwgbmV3VmFsdWUpXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICAgICAgICA7KHRhcmdldCBhcyBhbnkpW2tleV0gPSAocGFydGlhbE9iamVjdCBhcyBhbnkpW2tleV1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgKSxcblxuICBkZWxldGU6IHN0YW5kYWxvbmVBY3Rpb24oXG4gICAgYCR7bmFtZXNwYWNlfTo6ZGVsZXRlYCxcbiAgICA8VCBleHRlbmRzIG9iamVjdCwgSyBleHRlbmRzIGtleW9mIFQ+KHRhcmdldDogVCwga2V5OiBLKTogYm9vbGVhbiA9PiB7XG4gICAgICByZXR1cm4gcmVtb3ZlKHRhcmdldCwga2V5IGFzIGFueSlcbiAgICB9XG4gICksXG5cbiAgY2FsbDogc3RhbmRhbG9uZUFjdGlvbihcbiAgICBgJHtuYW1lc3BhY2V9OjpjYWxsYCxcbiAgICA8VCBleHRlbmRzIG9iamVjdCwgSyBleHRlbmRzIGtleW9mIFQ+KFxuICAgICAgdGFyZ2V0OiBULFxuICAgICAgbWV0aG9kTmFtZTogSyxcbiAgICAgIC4uLmFyZ3M6IFRbS10gZXh0ZW5kcyAoLi4uYXJnczogYW55W10pID0+IGFueSA/IFBhcmFtZXRlcnM8VFtLXT4gOiBuZXZlclxuICAgICk6IFRbS10gZXh0ZW5kcyAoLi4uYXJnczogYW55W10pID0+IGFueSA/IFJldHVyblR5cGU8VFtLXT4gOiBuZXZlciA9PiB7XG4gICAgICByZXR1cm4gKHRhcmdldCBhcyBhbnkpW21ldGhvZE5hbWVdKC4uLmFyZ3MpXG4gICAgfVxuICApLFxuXG4gIGNyZWF0ZTogPFQgZXh0ZW5kcyBvYmplY3Q+KGRhdGE6IFQpOiBUID0+IHRvVHJlZU5vZGUoZGF0YSksXG59XG4iLCIvKipcbiAqIENyZWF0ZXMgYSB0YWcgZGF0YSBhY2Nlc3NvciBmb3IgYSB0YXJnZXQgb2JqZWN0IG9mIGEgY2VydGFpbiB0eXBlLlxuICogVGFnIGRhdGEgd2lsbCBiZSBsYXp5IGNyZWF0ZWQgb24gYWNjZXNzIGFuZCByZXVzZWQgZm9yIHRoZSBzYW1lIHRhcmdldCBvYmplY3QuXG4gKlxuICogQHR5cGVwYXJhbSBUYXJnZXQgVGFyZ2V0IHR5cGUuXG4gKiBAdHlwZXBhcmFtIFRhZ0RhdGEgVGFnIGRhdGEgdHlwZS5cbiAqIEBwYXJhbSB0YWdEYXRhQ29uc3RydWN0b3IgRnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCB0aGUgZmlyc3QgdGltZSB0aGUgdGFnXG4gKiBmb3IgYSBnaXZlbiBvYmplY3QgaXMgcmVxdWVzdGVkLlxuICogQHJldHVybnMgVGhlIHRhZyBkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGUgdGFyZ2V0IG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRhZzxUYXJnZXQgZXh0ZW5kcyBvYmplY3QsIFRhZ0RhdGE+KFxuICB0YWdEYXRhQ29uc3RydWN0b3I6ICh0YXJnZXQ6IFRhcmdldCkgPT4gVGFnRGF0YVxuKToge1xuICBmb3IodGFyZ2V0OiBUYXJnZXQpOiBUYWdEYXRhXG59IHtcbiAgY29uc3QgbWFwID0gbmV3IFdlYWtNYXA8VGFyZ2V0LCBUYWdEYXRhPigpXG5cbiAgcmV0dXJuIHtcbiAgICBmb3IodGFyZ2V0KTogVGFnRGF0YSB7XG4gICAgICBpZiAoIW1hcC5oYXModGFyZ2V0KSkge1xuICAgICAgICBjb25zdCBkYXRhID0gdGFnRGF0YUNvbnN0cnVjdG9yKHRhcmdldClcbiAgICAgICAgbWFwLnNldCh0YXJnZXQsIGRhdGEpXG4gICAgICAgIHJldHVybiBkYXRhXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbWFwLmdldCh0YXJnZXQpIVxuICAgICAgfVxuICAgIH0sXG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIGFjdGlvbixcbiAgSU1hcFdpbGxDaGFuZ2UsXG4gIGludGVyY2VwdCxcbiAgSU9iamVjdERpZENoYW5nZSxcbiAgSU9ic2VydmFibGVBcnJheSxcbiAgaXNPYnNlcnZhYmxlQXJyYXksXG4gIGlzT2JzZXJ2YWJsZU9iamVjdCxcbiAgb2JzZXJ2YWJsZSxcbiAgT2JzZXJ2YWJsZU1hcCxcbiAgb2JzZXJ2ZSxcbiAgcmVtb3ZlLFxufSBmcm9tIFwibW9ieFwiXG5pbXBvcnQge1xuICBhc3NlcnRJc01hcCxcbiAgYXNzZXJ0SXNPYnNlcnZhYmxlQXJyYXksXG4gIGFzc2VydElzT2JzZXJ2YWJsZU9iamVjdCxcbiAgZmFpbHVyZSxcbiAgZ2V0TW9ieFZlcnNpb24sXG4gIGluRGV2TW9kZSxcbiAgaXNBcnJheSxcbn0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IHNldElmRGlmZmVyZW50IH0gZnJvbSBcIi4uL3V0aWxzL3NldElmRGlmZmVyZW50XCJcbmltcG9ydCB7IHRhZyB9IGZyb20gXCIuLi91dGlscy90YWdcIlxuXG5jb25zdCBvYnNlcnZhYmxlTWFwQmFja2VkQnlPYnNlcnZhYmxlT2JqZWN0ID0gYWN0aW9uKFxuICA8VD4oXG4gICAgb2JqOiBvYmplY3RcbiAgKTogT2JzZXJ2YWJsZU1hcDxzdHJpbmcsIFQ+ICYge1xuICAgIGRhdGFPYmplY3Q6IHR5cGVvZiBvYmpcbiAgfSA9PiB7XG4gICAgaWYgKGluRGV2TW9kZSkge1xuICAgICAgaWYgKCFpc09ic2VydmFibGVPYmplY3Qob2JqKSkge1xuICAgICAgICB0aHJvdyBmYWlsdXJlKFwiYXNzZXJ0aW9uIGZhaWxlZDogZXhwZWN0ZWQgYW4gb2JzZXJ2YWJsZSBvYmplY3RcIilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtYXAgPSBvYnNlcnZhYmxlLm1hcCgpXG4gICAgOyhtYXAgYXMgYW55KS5kYXRhT2JqZWN0ID0gb2JqXG5cbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMob2JqKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgayA9IGtleXNbaV1cbiAgICAgIG1hcC5zZXQoaywgKG9iaiBhcyBhbnkpW2tdKVxuICAgIH1cblxuICAgIGxldCBtYXBBbHJlYWR5Q2hhbmdlZCA9IGZhbHNlXG4gICAgbGV0IG9iamVjdEFscmVhZHlDaGFuZ2VkID0gZmFsc2VcblxuICAgIC8vIHdoZW4gdGhlIG9iamVjdCBjaGFuZ2VzIHRoZSBtYXAgY2hhbmdlc1xuICAgIG9ic2VydmUoXG4gICAgICBvYmosXG4gICAgICBhY3Rpb24oKGNoYW5nZTogSU9iamVjdERpZENoYW5nZSkgPT4ge1xuICAgICAgICBpZiAobWFwQWxyZWFkeUNoYW5nZWQpIHtcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIG9iamVjdEFscmVhZHlDaGFuZ2VkID0gdHJ1ZVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgc3dpdGNoIChjaGFuZ2UudHlwZSkge1xuICAgICAgICAgICAgY2FzZSBcImFkZFwiOlxuICAgICAgICAgICAgY2FzZSBcInVwZGF0ZVwiOiB7XG4gICAgICAgICAgICAgIG1hcC5zZXQoY2hhbmdlLm5hbWUsIGNoYW5nZS5uZXdWYWx1ZSlcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FzZSBcInJlbW92ZVwiOiB7XG4gICAgICAgICAgICAgIG1hcC5kZWxldGUoY2hhbmdlLm5hbWUpXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIG9iamVjdEFscmVhZHlDaGFuZ2VkID0gZmFsc2VcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApXG5cbiAgICAvLyB3aGVuIHRoZSBtYXAgY2hhbmdlcyBhbHNvIGNoYW5nZSB0aGUgb2JqZWN0XG4gICAgaW50ZXJjZXB0KFxuICAgICAgbWFwLFxuICAgICAgYWN0aW9uKChjaGFuZ2U6IElNYXBXaWxsQ2hhbmdlPHN0cmluZywgVD4pID0+IHtcbiAgICAgICAgaWYgKG1hcEFscmVhZHlDaGFuZ2VkKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvYmplY3RBbHJlYWR5Q2hhbmdlZCkge1xuICAgICAgICAgIHJldHVybiBjaGFuZ2VcbiAgICAgICAgfVxuXG4gICAgICAgIG1hcEFscmVhZHlDaGFuZ2VkID0gdHJ1ZVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgc3dpdGNoIChjaGFuZ2UudHlwZSkge1xuICAgICAgICAgICAgY2FzZSBcImFkZFwiOlxuICAgICAgICAgICAgY2FzZSBcInVwZGF0ZVwiOiB7XG4gICAgICAgICAgICAgIHNldElmRGlmZmVyZW50KG9iaiwgY2hhbmdlLm5hbWUsIGNoYW5nZS5uZXdWYWx1ZSlcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FzZSBcImRlbGV0ZVwiOiB7XG4gICAgICAgICAgICAgIHJlbW92ZShvYmosIGNoYW5nZS5uYW1lKVxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBjaGFuZ2VcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBtYXBBbHJlYWR5Q2hhbmdlZCA9IGZhbHNlXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKVxuXG4gICAgcmV0dXJuIG1hcCBhcyBhbnlcbiAgfVxuKVxuXG5jb25zdCBvYnNlcnZhYmxlTWFwQmFja2VkQnlPYnNlcnZhYmxlQXJyYXkgPSBhY3Rpb24oXG4gIDxUPihcbiAgICBhcnJheTogSU9ic2VydmFibGVBcnJheTxbc3RyaW5nLCBUXT5cbiAgKTogT2JzZXJ2YWJsZU1hcDxzdHJpbmcsIFQ+ICYgeyBkYXRhT2JqZWN0OiB0eXBlb2YgYXJyYXkgfSA9PiB7XG4gICAgaWYgKGluRGV2TW9kZSkge1xuICAgICAgaWYgKCFpc09ic2VydmFibGVBcnJheShhcnJheSkpIHtcbiAgICAgICAgdGhyb3cgZmFpbHVyZShcImFzc2VydGlvbiBmYWlsZWQ6IGV4cGVjdGVkIGFuIG9ic2VydmFibGUgYXJyYXlcIilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgbWFwOiBPYnNlcnZhYmxlTWFwPHN0cmluZywgVD5cbiAgICBpZiAoZ2V0TW9ieFZlcnNpb24oKSA+PSA2KSB7XG4gICAgICBtYXAgPSBvYnNlcnZhYmxlLm1hcChhcnJheSlcbiAgICB9IGVsc2Uge1xuICAgICAgbWFwID0gb2JzZXJ2YWJsZS5tYXAoKVxuICAgICAgYXJyYXkuZm9yRWFjaCgoW2ssIHZdKSA9PiB7XG4gICAgICAgIG1hcC5zZXQoaywgdilcbiAgICAgIH0pXG4gICAgfVxuICAgIDsobWFwIGFzIGFueSkuZGF0YU9iamVjdCA9IGFycmF5XG5cbiAgICBpZiAobWFwLnNpemUgIT09IGFycmF5Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgZmFpbHVyZShcImFycmF5cyBiYWNraW5nIGEgbWFwIGNhbm5vdCBjb250YWluIGR1cGxpY2F0ZSBrZXlzXCIpXG4gICAgfVxuXG4gICAgbGV0IG1hcEFscmVhZHlDaGFuZ2VkID0gZmFsc2VcbiAgICBsZXQgYXJyYXlBbHJlYWR5Q2hhbmdlZCA9IGZhbHNlXG5cbiAgICAvLyBmb3Igc3BlZWQgcmVhc29ucyB3ZSB3aWxsIGp1c3QgYXNzdW1lIGRpc3RpbmN0IHZhbHVlcyBhcmUgb25seSBvbmNlIGluIHRoZSBhcnJheVxuICAgIC8vIGFsc28gd2UgYXNzdW1lIHR1cGxlcyB0aGVtc2VsdmVzIGFyZSBpbW11dGFibGVcblxuICAgIC8vIHdoZW4gdGhlIGFycmF5IGNoYW5nZXMgdGhlIG1hcCBjaGFuZ2VzXG4gICAgb2JzZXJ2ZShcbiAgICAgIGFycmF5LFxuICAgICAgYWN0aW9uKChjaGFuZ2U6IGFueSAvKklBcnJheURpZENoYW5nZTxbc3RyaW5nLCBUXT4qLykgPT4ge1xuICAgICAgICBpZiAobWFwQWxyZWFkeUNoYW5nZWQpIHtcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIGFycmF5QWxyZWFkeUNoYW5nZWQgPSB0cnVlXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgc3dpdGNoIChjaGFuZ2UudHlwZSkge1xuICAgICAgICAgICAgY2FzZSBcInNwbGljZVwiOiB7XG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZW1vdmVkID0gY2hhbmdlLnJlbW92ZWRcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlbW92ZWQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgIG1hcC5kZWxldGUocmVtb3ZlZFtpXVswXSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgY29uc3QgYWRkZWQgPSBjaGFuZ2UuYWRkZWRcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFkZGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICBtYXAuc2V0KGFkZGVkW2ldWzBdLCBhZGRlZFtpXVsxXSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYXNlIFwidXBkYXRlXCI6IHtcbiAgICAgICAgICAgICAgbWFwLmRlbGV0ZShjaGFuZ2Uub2xkVmFsdWVbMF0pXG4gICAgICAgICAgICAgIG1hcC5zZXQoY2hhbmdlLm5ld1ZhbHVlWzBdLCBjaGFuZ2UubmV3VmFsdWVbMV0pXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIGFycmF5QWxyZWFkeUNoYW5nZWQgPSBmYWxzZVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIClcblxuICAgIC8vIHdoZW4gdGhlIG1hcCBjaGFuZ2VzIGFsc28gY2hhbmdlIHRoZSBhcnJheVxuICAgIGludGVyY2VwdChcbiAgICAgIG1hcCxcbiAgICAgIGFjdGlvbigoY2hhbmdlOiBJTWFwV2lsbENoYW5nZTxzdHJpbmcsIFQ+KSA9PiB7XG4gICAgICAgIGlmIChtYXBBbHJlYWR5Q2hhbmdlZCkge1xuICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYXJyYXlBbHJlYWR5Q2hhbmdlZCkge1xuICAgICAgICAgIHJldHVybiBjaGFuZ2VcbiAgICAgICAgfVxuXG4gICAgICAgIG1hcEFscmVhZHlDaGFuZ2VkID0gdHJ1ZVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgc3dpdGNoIChjaGFuZ2UudHlwZSkge1xuICAgICAgICAgICAgY2FzZSBcInVwZGF0ZVwiOiB7XG4gICAgICAgICAgICAgIC8vIHJlcGxhY2UgdGhlIHdob2xlIHR1cGxlIHRvIGtlZXAgdHVwbGUgaW1tdXRhYmlsaXR5XG4gICAgICAgICAgICAgIGNvbnN0IGkgPSBhcnJheS5maW5kSW5kZXgoKGkpID0+IGlbMF0gPT09IGNoYW5nZS5uYW1lKVxuICAgICAgICAgICAgICBhcnJheVtpXSA9IFtjaGFuZ2UubmFtZSwgY2hhbmdlLm5ld1ZhbHVlIV1cbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FzZSBcImFkZFwiOiB7XG4gICAgICAgICAgICAgIGFycmF5LnB1c2goW2NoYW5nZS5uYW1lLCBjaGFuZ2UubmV3VmFsdWUhXSlcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FzZSBcImRlbGV0ZVwiOiB7XG4gICAgICAgICAgICAgIGNvbnN0IGkgPSBhcnJheS5maW5kSW5kZXgoKGkpID0+IGlbMF0gPT09IGNoYW5nZS5uYW1lKVxuICAgICAgICAgICAgICBpZiAoaSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgYXJyYXkuc3BsaWNlKGksIDEpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gY2hhbmdlXG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgbWFwQWxyZWFkeUNoYW5nZWQgPSBmYWxzZVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIClcblxuICAgIHJldHVybiBtYXAgYXMgYW55XG4gIH1cbilcblxuY29uc3QgYXNNYXBUYWcgPSB0YWcoKG9iak9yQXJyYXk6IFJlY29yZDxzdHJpbmcsIGFueT4gfCBBcnJheTxbc3RyaW5nLCBhbnldPikgPT4ge1xuICBpZiAoaXNBcnJheShvYmpPckFycmF5KSkge1xuICAgIGFzc2VydElzT2JzZXJ2YWJsZUFycmF5KG9iak9yQXJyYXksIFwib2JqT3JBcnJheVwiKVxuICAgIHJldHVybiBvYnNlcnZhYmxlTWFwQmFja2VkQnlPYnNlcnZhYmxlQXJyYXkob2JqT3JBcnJheSlcbiAgfSBlbHNlIHtcbiAgICBhc3NlcnRJc09ic2VydmFibGVPYmplY3Qob2JqT3JBcnJheSwgXCJvYmpPckFycmF5XCIpXG4gICAgcmV0dXJuIG9ic2VydmFibGVNYXBCYWNrZWRCeU9ic2VydmFibGVPYmplY3Qob2JqT3JBcnJheSlcbiAgfVxufSlcblxuLyoqXG4gKiBXcmFwcyBhbiBvYnNlcnZhYmxlIG9iamVjdCBvciBhIHR1cGxlIGFycmF5IHRvIG9mZmVyIGEgbWFwIGxpa2UgaW50ZXJmYWNlLlxuICpcbiAqIEBwYXJhbSBhcnJheSBBcnJheS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzTWFwPEssIFY+KFxuICBhcnJheTogQXJyYXk8W0ssIFZdPlxuKTogT2JzZXJ2YWJsZU1hcDxLLCBWPiAmIHsgZGF0YU9iamVjdDogQXJyYXk8W0ssIFZdPiB9XG5cbi8qKlxuICogV3JhcHMgYW4gb2JzZXJ2YWJsZSBvYmplY3Qgb3IgYSB0dXBsZSBhcnJheSB0byBvZmZlciBhIG1hcCBsaWtlIGludGVyZmFjZS5cbiAqXG4gKiBAcGFyYW0gb2JqZWN0IE9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzTWFwPFQ+KFxuICBvYmplY3Q6IFJlY29yZDxzdHJpbmcsIFQ+XG4pOiBPYnNlcnZhYmxlTWFwPHN0cmluZywgVD4gJiB7IGRhdGFPYmplY3Q6IFJlY29yZDxzdHJpbmcsIFQ+IH1cblxuLyoqXG4gKiBXcmFwcyBhbiBvYnNlcnZhYmxlIG9iamVjdCBvciBhIHR1cGxlIGFycmF5IHRvIG9mZmVyIGEgbWFwIGxpa2UgaW50ZXJmYWNlLlxuICpcbiAqIEBwYXJhbSBvYmpPckFycmF5IE9iamVjdCBvciBhcnJheS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzTWFwKFxuICBvYmpPckFycmF5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IEFycmF5PFt1bmtub3duLCB1bmtub3duXT5cbik6IE9ic2VydmFibGVNYXA8dW5rbm93biwgdW5rbm93bj4gJiB7IGRhdGFPYmplY3Q6IHR5cGVvZiBvYmpPckFycmF5IH0ge1xuICByZXR1cm4gYXNNYXBUYWcuZm9yKG9iak9yQXJyYXkpIGFzIGFueVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgbWFwIHRvIGFuIG9iamVjdC4gSWYgdGhlIG1hcCBpcyBhIGNvbGxlY3Rpb24gd3JhcHBlciBpdCB3aWxsIHJldHVybiB0aGUgYmFja2VkIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0gbWFwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXBUb09iamVjdDxUPihtYXA6IE1hcDxzdHJpbmcsIFQ+KTogUmVjb3JkPHN0cmluZywgVD4ge1xuICBhc3NlcnRJc01hcChtYXAsIFwibWFwXCIpXG5cbiAgY29uc3QgZGF0YU9iamVjdCA9IChtYXAgYXMgYW55KS5kYXRhT2JqZWN0XG4gIGlmIChkYXRhT2JqZWN0ICYmICFpc0FycmF5KGRhdGFPYmplY3QpKSB7XG4gICAgcmV0dXJuIGRhdGFPYmplY3RcbiAgfVxuXG4gIGNvbnN0IG9iajogUmVjb3JkPHN0cmluZywgVD4gPSB7fVxuICBmb3IgKGNvbnN0IGsgb2YgbWFwLmtleXMoKSkge1xuICAgIG9ialtrXSA9IG1hcC5nZXQoaykhXG4gIH1cblxuICByZXR1cm4gb2JqXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBtYXAgdG8gYW4gYXJyYXkuIElmIHRoZSBtYXAgaXMgYSBjb2xsZWN0aW9uIHdyYXBwZXIgaXQgd2lsbCByZXR1cm4gdGhlIGJhY2tlZCBhcnJheS5cbiAqXG4gKiBAcGFyYW0gbWFwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXBUb0FycmF5PEssIFY+KG1hcDogTWFwPEssIFY+KTogQXJyYXk8W0ssIFZdPiB7XG4gIGFzc2VydElzTWFwKG1hcCwgXCJtYXBcIilcblxuICBjb25zdCBkYXRhT2JqZWN0ID0gKG1hcCBhcyBhbnkpLmRhdGFPYmplY3RcbiAgaWYgKGRhdGFPYmplY3QgJiYgaXNBcnJheShkYXRhT2JqZWN0KSkge1xuICAgIHJldHVybiBkYXRhT2JqZWN0XG4gIH1cblxuICBjb25zdCBhcnI6IFtLLCBWXVtdID0gW11cbiAgZm9yIChjb25zdCBrIG9mIG1hcC5rZXlzKCkpIHtcbiAgICBhcnIucHVzaChbaywgbWFwLmdldChrKSFdKVxuICB9XG5cbiAgcmV0dXJuIGFyclxufVxuIiwiaW1wb3J0IHR5cGUgeyBNb2RlbFByb3BUcmFuc2Zvcm0gfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvcHJvcFwiXG5pbXBvcnQgeyBhc01hcCB9IGZyb20gXCIuLi93cmFwcGVycy9hc01hcFwiXG5cbmNvbnN0IF9vYmplY3RUb01hcFRyYW5zZm9ybTogTW9kZWxQcm9wVHJhbnNmb3JtPFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBNYXA8c3RyaW5nLCB1bmtub3duPj4gPSB7XG4gIHRyYW5zZm9ybSh7IG9yaWdpbmFsVmFsdWU6IG9iaiwgY2FjaGVkVHJhbnNmb3JtZWRWYWx1ZTogY2FjaGVkTWFwIH0pIHtcbiAgICByZXR1cm4gY2FjaGVkTWFwID8/IGFzTWFwKG9iailcbiAgfSxcblxuICB1bnRyYW5zZm9ybSh7IHRyYW5zZm9ybWVkVmFsdWU6IG1hcCB9KSB7XG4gICAgLy8gZG8gbm90IGNhY2hlIG1hcCA8LT4gb2JqIHJlbGF0aW9uc2hpcFxuXG4gICAgY29uc3Qgb2JqOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9XG4gICAgZm9yIChjb25zdCBrIG9mIG1hcC5rZXlzKCkpIHtcbiAgICAgIG9ialtrXSA9IG1hcC5nZXQoaykhXG4gICAgfVxuXG4gICAgcmV0dXJuIG9ialxuICB9LFxufVxuXG5leHBvcnQgY29uc3Qgb2JqZWN0VG9NYXBUcmFuc2Zvcm0gPSA8VD4oKSA9PlxuICBfb2JqZWN0VG9NYXBUcmFuc2Zvcm0gYXMgTW9kZWxQcm9wVHJhbnNmb3JtPFJlY29yZDxzdHJpbmcsIFQ+LCBNYXA8c3RyaW5nLCBUPj5cblxuY29uc3QgX2FycmF5VG9NYXBUcmFuc2Zvcm06IE1vZGVsUHJvcFRyYW5zZm9ybTxBcnJheTxbdW5rbm93biwgdW5rbm93bl0+LCBNYXA8dW5rbm93biwgdW5rbm93bj4+ID0ge1xuICB0cmFuc2Zvcm0oeyBvcmlnaW5hbFZhbHVlOiBhcnIsIGNhY2hlZFRyYW5zZm9ybWVkVmFsdWU6IGNhY2hlZE1hcCB9KSB7XG4gICAgcmV0dXJuIGNhY2hlZE1hcCA/PyBhc01hcChhcnIpXG4gIH0sXG5cbiAgdW50cmFuc2Zvcm0oeyB0cmFuc2Zvcm1lZFZhbHVlOiBtYXAgfSkge1xuICAgIC8vIGRvIG5vdCBjYWNoZSBtYXAgPC0+IGFyciByZWxhdGlvbnNoaXBcblxuICAgIGNvbnN0IGFycjogQXJyYXk8W3Vua25vd24sIHVua25vd25dPiA9IFtdXG4gICAgZm9yIChjb25zdCBrIG9mIG1hcC5rZXlzKCkpIHtcbiAgICAgIGFyci5wdXNoKFtrLCBtYXAuZ2V0KGspIV0pXG4gICAgfVxuXG4gICAgcmV0dXJuIGFyclxuICB9LFxufVxuXG5leHBvcnQgY29uc3QgYXJyYXlUb01hcFRyYW5zZm9ybSA9IDxLLCBWPigpID0+XG4gIF9hcnJheVRvTWFwVHJhbnNmb3JtIGFzIE1vZGVsUHJvcFRyYW5zZm9ybTxBcnJheTxbSywgVl0+LCBNYXA8SywgVj4+XG4iLCJpbXBvcnQge1xyXG4gIGFjdGlvbixcclxuICBpbnRlcmNlcHQsXHJcbiAgSU9ic2VydmFibGVBcnJheSxcclxuICBJU2V0V2lsbENoYW5nZSxcclxuICBpc09ic2VydmFibGVBcnJheSxcclxuICBvYnNlcnZhYmxlLFxyXG4gIE9ic2VydmFibGVTZXQsXHJcbiAgb2JzZXJ2ZSxcclxufSBmcm9tIFwibW9ieFwiXHJcbmltcG9ydCB7IGFzc2VydElzT2JzZXJ2YWJsZUFycmF5LCBhc3NlcnRJc1NldCwgZmFpbHVyZSwgZ2V0TW9ieFZlcnNpb24sIGluRGV2TW9kZSB9IGZyb20gXCIuLi91dGlsc1wiXHJcbmltcG9ydCB7IHRhZyB9IGZyb20gXCIuLi91dGlscy90YWdcIlxyXG5cclxuY29uc3Qgb2JzZXJ2YWJsZVNldEJhY2tlZEJ5T2JzZXJ2YWJsZUFycmF5ID0gYWN0aW9uKFxyXG4gIDxUPihhcnJheTogSU9ic2VydmFibGVBcnJheTxUPik6IE9ic2VydmFibGVTZXQ8VD4gJiB7IGRhdGFPYmplY3Q6IHR5cGVvZiBhcnJheSB9ID0+IHtcclxuICAgIGlmIChpbkRldk1vZGUpIHtcclxuICAgICAgaWYgKCFpc09ic2VydmFibGVBcnJheShhcnJheSkpIHtcclxuICAgICAgICB0aHJvdyBmYWlsdXJlKFwiYXNzZXJ0aW9uIGZhaWxlZDogZXhwZWN0ZWQgYW4gb2JzZXJ2YWJsZSBhcnJheVwiKVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHNldDogT2JzZXJ2YWJsZVNldDxUPlxyXG4gICAgaWYgKGdldE1vYnhWZXJzaW9uKCkgPj0gNikge1xyXG4gICAgICBzZXQgPSBvYnNlcnZhYmxlLnNldChhcnJheSlcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHNldCA9IG9ic2VydmFibGUuc2V0KClcclxuICAgICAgYXJyYXkuZm9yRWFjaCgoaXRlbSkgPT4ge1xyXG4gICAgICAgIHNldC5hZGQoaXRlbSlcclxuICAgICAgfSlcclxuICAgIH1cclxuICAgIDsoc2V0IGFzIGFueSkuZGF0YU9iamVjdCA9IGFycmF5XHJcblxyXG4gICAgaWYgKHNldC5zaXplICE9PSBhcnJheS5sZW5ndGgpIHtcclxuICAgICAgdGhyb3cgZmFpbHVyZShcImFycmF5cyBiYWNraW5nIGEgc2V0IGNhbm5vdCBjb250YWluIGR1cGxpY2F0ZSB2YWx1ZXNcIilcclxuICAgIH1cclxuXHJcbiAgICBsZXQgc2V0QWxyZWFkeUNoYW5nZWQgPSBmYWxzZVxyXG4gICAgbGV0IGFycmF5QWxyZWFkeUNoYW5nZWQgPSBmYWxzZVxyXG5cclxuICAgIC8vIGZvciBzcGVlZCByZWFzb25zIHdlIHdpbGwganVzdCBhc3N1bWUgZGlzdGluY3QgdmFsdWVzIGFyZSBvbmx5IG9uY2UgaW4gdGhlIGFycmF5XHJcblxyXG4gICAgLy8gd2hlbiB0aGUgYXJyYXkgY2hhbmdlcyB0aGUgc2V0IGNoYW5nZXNcclxuICAgIG9ic2VydmUoXHJcbiAgICAgIGFycmF5LFxyXG4gICAgICBhY3Rpb24oKGNoYW5nZTogYW55IC8qSUFycmF5RGlkQ2hhbmdlPFQ+Ki8pID0+IHtcclxuICAgICAgICBpZiAoc2V0QWxyZWFkeUNoYW5nZWQpIHtcclxuICAgICAgICAgIHJldHVyblxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYXJyYXlBbHJlYWR5Q2hhbmdlZCA9IHRydWVcclxuXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIHN3aXRjaCAoY2hhbmdlLnR5cGUpIHtcclxuICAgICAgICAgICAgY2FzZSBcInNwbGljZVwiOiB7XHJcbiAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVtb3ZlZCA9IGNoYW5nZS5yZW1vdmVkXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlbW92ZWQubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgc2V0LmRlbGV0ZShyZW1vdmVkW2ldKVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgYWRkZWQgPSBjaGFuZ2UuYWRkZWRcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWRkZWQubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgc2V0LmFkZChhZGRlZFtpXSlcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNhc2UgXCJ1cGRhdGVcIjoge1xyXG4gICAgICAgICAgICAgIHNldC5kZWxldGUoY2hhbmdlLm9sZFZhbHVlKVxyXG4gICAgICAgICAgICAgIHNldC5hZGQoY2hhbmdlLm5ld1ZhbHVlKVxyXG4gICAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGZpbmFsbHkge1xyXG4gICAgICAgICAgYXJyYXlBbHJlYWR5Q2hhbmdlZCA9IGZhbHNlXHJcbiAgICAgICAgfVxyXG4gICAgICB9KVxyXG4gICAgKVxyXG5cclxuICAgIC8vIHdoZW4gdGhlIHNldCBjaGFuZ2VzIGFsc28gY2hhbmdlIHRoZSBhcnJheVxyXG4gICAgaW50ZXJjZXB0KFxyXG4gICAgICBzZXQsXHJcbiAgICAgIGFjdGlvbigoY2hhbmdlOiBJU2V0V2lsbENoYW5nZTxUPikgPT4ge1xyXG4gICAgICAgIGlmIChzZXRBbHJlYWR5Q2hhbmdlZCkge1xyXG4gICAgICAgICAgcmV0dXJuIG51bGxcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChhcnJheUFscmVhZHlDaGFuZ2VkKSB7XHJcbiAgICAgICAgICByZXR1cm4gY2hhbmdlXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBzZXRBbHJlYWR5Q2hhbmdlZCA9IHRydWVcclxuXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIHN3aXRjaCAoY2hhbmdlLnR5cGUpIHtcclxuICAgICAgICAgICAgY2FzZSBcImFkZFwiOiB7XHJcbiAgICAgICAgICAgICAgYXJyYXkucHVzaChjaGFuZ2UubmV3VmFsdWUpXHJcbiAgICAgICAgICAgICAgYnJlYWtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY2FzZSBcImRlbGV0ZVwiOiB7XHJcbiAgICAgICAgICAgICAgY29uc3QgaSA9IGFycmF5LmluZGV4T2YoY2hhbmdlLm9sZFZhbHVlKVxyXG4gICAgICAgICAgICAgIGlmIChpID49IDApIHtcclxuICAgICAgICAgICAgICAgIGFycmF5LnNwbGljZShpLCAxKVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBicmVha1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgcmV0dXJuIGNoYW5nZVxyXG4gICAgICAgIH0gZmluYWxseSB7XHJcbiAgICAgICAgICBzZXRBbHJlYWR5Q2hhbmdlZCA9IGZhbHNlXHJcbiAgICAgICAgfVxyXG4gICAgICB9KVxyXG4gICAgKVxyXG5cclxuICAgIHJldHVybiBzZXQgYXMgYW55XHJcbiAgfVxyXG4pXHJcblxyXG5jb25zdCBhc1NldFRhZyA9IHRhZygoYXJyYXk6IEFycmF5PGFueT4pID0+IHtcclxuICBhc3NlcnRJc09ic2VydmFibGVBcnJheShhcnJheSwgXCJhcnJheVwiKVxyXG4gIHJldHVybiBvYnNlcnZhYmxlU2V0QmFja2VkQnlPYnNlcnZhYmxlQXJyYXkoYXJyYXkpXHJcbn0pXHJcblxyXG4vKipcclxuICogV3JhcHMgYW4gb2JzZXJ2YWJsZSBhcnJheSB0byBvZmZlciBhIHNldCBsaWtlIGludGVyZmFjZS5cclxuICpcclxuICogQHBhcmFtIGFycmF5XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYXNTZXQ8VD4oYXJyYXk6IEFycmF5PFQ+KTogT2JzZXJ2YWJsZVNldDxUPiAmIHsgZGF0YU9iamVjdDogdHlwZW9mIGFycmF5IH0ge1xyXG4gIHJldHVybiBhc1NldFRhZy5mb3IoYXJyYXkpIGFzIGFueVxyXG59XHJcblxyXG4vKipcclxuICogQ29udmVydHMgYSBzZXQgdG8gYW4gYXJyYXkuIElmIHRoZSBzZXQgaXMgYSBjb2xsZWN0aW9uIHdyYXBwZXIgaXQgd2lsbCByZXR1cm4gdGhlIGJhY2tlZCBhcnJheS5cclxuICpcclxuICogQHBhcmFtIHNldFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHNldFRvQXJyYXk8VD4oc2V0OiBTZXQ8VD4pOiBBcnJheTxUPiB7XHJcbiAgYXNzZXJ0SXNTZXQoc2V0LCBcInNldFwiKVxyXG5cclxuICBjb25zdCBkYXRhT2JqZWN0ID0gKHNldCBhcyBhbnkpLmRhdGFPYmplY3RcclxuICBpZiAoZGF0YU9iamVjdCkge1xyXG4gICAgcmV0dXJuIGRhdGFPYmplY3RcclxuICB9XHJcblxyXG4gIHJldHVybiBBcnJheS5mcm9tKHNldC52YWx1ZXMoKSlcclxufVxyXG4iLCJpbXBvcnQgdHlwZSB7IE1vZGVsUHJvcFRyYW5zZm9ybSB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9wcm9wXCJcbmltcG9ydCB7IGFzU2V0IH0gZnJvbSBcIi4uL3dyYXBwZXJzL2FzU2V0XCJcblxuY29uc3QgX2FycmF5VG9TZXRUcmFuc2Zvcm06IE1vZGVsUHJvcFRyYW5zZm9ybTxBcnJheTx1bmtub3duPiwgU2V0PHVua25vd24+PiA9IHtcbiAgdHJhbnNmb3JtKHsgb3JpZ2luYWxWYWx1ZTogYXJyLCBjYWNoZWRUcmFuc2Zvcm1lZFZhbHVlOiBjYWNoZWRTZXQgfSkge1xuICAgIHJldHVybiBjYWNoZWRTZXQgPz8gYXNTZXQoYXJyKVxuICB9LFxuXG4gIHVudHJhbnNmb3JtKHsgdHJhbnNmb3JtZWRWYWx1ZTogc2V0IH0pIHtcbiAgICAvLyBkbyBub3QgY2FjaGUgc2V0IDwtPiBhcnIgcmVsYXRpb25zaGlwXG5cbiAgICByZXR1cm4gQXJyYXkuZnJvbShzZXQudmFsdWVzKCkpXG4gIH0sXG59XG5cbmV4cG9ydCBjb25zdCBhcnJheVRvU2V0VHJhbnNmb3JtID0gPFQ+KCkgPT5cbiAgX2FycmF5VG9TZXRUcmFuc2Zvcm0gYXMgTW9kZWxQcm9wVHJhbnNmb3JtPEFycmF5PFQ+LCBTZXQ8VD4+XG4iLCJpbXBvcnQgdHlwZSB7IE1vZGVsUHJvcFRyYW5zZm9ybSB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9wcm9wXCJcblxuY29uc3QgX3N0cmluZ1RvQmlnSW50VHJhbnNmb3JtOiBNb2RlbFByb3BUcmFuc2Zvcm08c3RyaW5nLCBiaWdpbnQ+ID0ge1xuICB0cmFuc2Zvcm0oeyBvcmlnaW5hbFZhbHVlLCBjYWNoZWRUcmFuc2Zvcm1lZFZhbHVlIH0pIHtcbiAgICByZXR1cm4gY2FjaGVkVHJhbnNmb3JtZWRWYWx1ZSA/PyBCaWdJbnQob3JpZ2luYWxWYWx1ZSlcbiAgfSxcblxuICB1bnRyYW5zZm9ybSh7IHRyYW5zZm9ybWVkVmFsdWUsIGNhY2hlVHJhbnNmb3JtZWRWYWx1ZSB9KSB7XG4gICAgaWYgKHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlID09PSBcImJpZ2ludFwiKSB7XG4gICAgICBjYWNoZVRyYW5zZm9ybWVkVmFsdWUoKVxuICAgIH1cbiAgICByZXR1cm4gdHJhbnNmb3JtZWRWYWx1ZS50b1N0cmluZygpXG4gIH0sXG59XG5cbmV4cG9ydCBjb25zdCBzdHJpbmdUb0JpZ0ludFRyYW5zZm9ybSA9ICgpID0+IF9zdHJpbmdUb0JpZ0ludFRyYW5zZm9ybVxuIiwiaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW1tdXRhYmxlRGF0ZVxuICBleHRlbmRzIE9taXQ8XG4gICAgRGF0ZSxcbiAgICB8IFwic2V0VGltZVwiXG4gICAgfCBcInNldE1pbGxpc2Vjb25kc1wiXG4gICAgfCBcInNldFVUQ01pbGxpc2Vjb25kc1wiXG4gICAgfCBcInNldFNlY29uZHNcIlxuICAgIHwgXCJzZXRVVENTZWNvbmRzXCJcbiAgICB8IFwic2V0TWludXRlc1wiXG4gICAgfCBcInNldFVUQ01pbnV0ZXNcIlxuICAgIHwgXCJzZXRIb3Vyc1wiXG4gICAgfCBcInNldFVUQ0hvdXJzXCJcbiAgICB8IFwic2V0RGF0ZVwiXG4gICAgfCBcInNldFVUQ0RhdGVcIlxuICAgIHwgXCJzZXRNb250aFwiXG4gICAgfCBcInNldFVUQ01vbnRoXCJcbiAgICB8IFwic2V0RnVsbFllYXJcIlxuICAgIHwgXCJzZXRVVENGdWxsWWVhclwiXG4gID4ge31cblxuY29uc3QgZXJyTWVzc2FnZSA9IFwidGhpcyBEYXRlIG9iamVjdCBpcyBpbW11dGFibGVcIlxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY2xhc3MgSW1tdXRhYmxlRGF0ZSBleHRlbmRzIERhdGUge1xuICAvLyBkaXNhYmxlIG11dGFibGUgbWV0aG9kc1xuXG4gIHNldFRpbWUoKTogYW55IHtcbiAgICB0aHJvdyBmYWlsdXJlKGVyck1lc3NhZ2UpXG4gIH1cblxuICBzZXRNaWxsaXNlY29uZHMoKTogYW55IHtcbiAgICB0aHJvdyBmYWlsdXJlKGVyck1lc3NhZ2UpXG4gIH1cblxuICBzZXRVVENNaWxsaXNlY29uZHMoKTogYW55IHtcbiAgICB0aHJvdyBmYWlsdXJlKGVyck1lc3NhZ2UpXG4gIH1cblxuICBzZXRTZWNvbmRzKCk6IGFueSB7XG4gICAgdGhyb3cgZmFpbHVyZShlcnJNZXNzYWdlKVxuICB9XG5cbiAgc2V0VVRDU2Vjb25kcygpOiBhbnkge1xuICAgIHRocm93IGZhaWx1cmUoZXJyTWVzc2FnZSlcbiAgfVxuXG4gIHNldE1pbnV0ZXMoKTogYW55IHtcbiAgICB0aHJvdyBmYWlsdXJlKGVyck1lc3NhZ2UpXG4gIH1cblxuICBzZXRVVENNaW51dGVzKCk6IGFueSB7XG4gICAgdGhyb3cgZmFpbHVyZShlcnJNZXNzYWdlKVxuICB9XG5cbiAgc2V0SG91cnMoKTogYW55IHtcbiAgICB0aHJvdyBmYWlsdXJlKGVyck1lc3NhZ2UpXG4gIH1cblxuICBzZXRVVENIb3VycygpOiBhbnkge1xuICAgIHRocm93IGZhaWx1cmUoZXJyTWVzc2FnZSlcbiAgfVxuXG4gIHNldERhdGUoKTogYW55IHtcbiAgICB0aHJvdyBmYWlsdXJlKGVyck1lc3NhZ2UpXG4gIH1cblxuICBzZXRVVENEYXRlKCk6IGFueSB7XG4gICAgdGhyb3cgZmFpbHVyZShlcnJNZXNzYWdlKVxuICB9XG5cbiAgc2V0TW9udGgoKTogYW55IHtcbiAgICB0aHJvdyBmYWlsdXJlKGVyck1lc3NhZ2UpXG4gIH1cblxuICBzZXRVVENNb250aCgpOiBhbnkge1xuICAgIHRocm93IGZhaWx1cmUoZXJyTWVzc2FnZSlcbiAgfVxuXG4gIHNldEZ1bGxZZWFyKCk6IGFueSB7XG4gICAgdGhyb3cgZmFpbHVyZShlcnJNZXNzYWdlKVxuICB9XG5cbiAgc2V0VVRDRnVsbFllYXIoKTogYW55IHtcbiAgICB0aHJvdyBmYWlsdXJlKGVyck1lc3NhZ2UpXG4gIH1cbn1cbiIsImltcG9ydCB0eXBlIHsgTW9kZWxQcm9wVHJhbnNmb3JtIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL3Byb3BcIlxuaW1wb3J0IHsgSW1tdXRhYmxlRGF0ZSB9IGZyb20gXCIuL0ltbXV0YWJsZURhdGVcIlxuXG5jb25zdCBfdGltZXN0YW1wVG9EYXRlVHJhbnNmb3JtOiBNb2RlbFByb3BUcmFuc2Zvcm08bnVtYmVyLCBEYXRlPiA9IHtcbiAgdHJhbnNmb3JtKHsgb3JpZ2luYWxWYWx1ZSwgY2FjaGVkVHJhbnNmb3JtZWRWYWx1ZSB9KSB7XG4gICAgcmV0dXJuIGNhY2hlZFRyYW5zZm9ybWVkVmFsdWUgPz8gbmV3IEltbXV0YWJsZURhdGUob3JpZ2luYWxWYWx1ZSlcbiAgfSxcblxuICB1bnRyYW5zZm9ybSh7IHRyYW5zZm9ybWVkVmFsdWUsIGNhY2hlVHJhbnNmb3JtZWRWYWx1ZSB9KSB7XG4gICAgaWYgKHRyYW5zZm9ybWVkVmFsdWUgaW5zdGFuY2VvZiBJbW11dGFibGVEYXRlKSB7XG4gICAgICBjYWNoZVRyYW5zZm9ybWVkVmFsdWUoKVxuICAgIH1cbiAgICByZXR1cm4gK3RyYW5zZm9ybWVkVmFsdWVcbiAgfSxcbn1cblxuZXhwb3J0IGNvbnN0IHRpbWVzdGFtcFRvRGF0ZVRyYW5zZm9ybSA9ICgpID0+IF90aW1lc3RhbXBUb0RhdGVUcmFuc2Zvcm1cblxuY29uc3QgX2lzb1N0cmluZ1RvRGF0ZVRyYW5zZm9ybTogTW9kZWxQcm9wVHJhbnNmb3JtPHN0cmluZywgRGF0ZT4gPSB7XG4gIHRyYW5zZm9ybSh7IG9yaWdpbmFsVmFsdWUsIGNhY2hlZFRyYW5zZm9ybWVkVmFsdWUgfSkge1xuICAgIHJldHVybiBjYWNoZWRUcmFuc2Zvcm1lZFZhbHVlID8/IG5ldyBJbW11dGFibGVEYXRlKG9yaWdpbmFsVmFsdWUpXG4gIH0sXG5cbiAgdW50cmFuc2Zvcm0oeyB0cmFuc2Zvcm1lZFZhbHVlLCBjYWNoZVRyYW5zZm9ybWVkVmFsdWUgfSkge1xuICAgIGlmICh0cmFuc2Zvcm1lZFZhbHVlIGluc3RhbmNlb2YgSW1tdXRhYmxlRGF0ZSkge1xuICAgICAgY2FjaGVUcmFuc2Zvcm1lZFZhbHVlKClcbiAgICB9XG4gICAgcmV0dXJuIHRyYW5zZm9ybWVkVmFsdWUudG9JU09TdHJpbmcoKVxuICB9LFxufVxuXG5leHBvcnQgY29uc3QgaXNvU3RyaW5nVG9EYXRlVHJhbnNmb3JtID0gKCkgPT4gX2lzb1N0cmluZ1RvRGF0ZVRyYW5zZm9ybVxuIiwiaW1wb3J0IHsgYWN0aW9uLCBjb21wdXRlZCB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IHBhdGhUb1RhcmdldFBhdGhJZHMgfSBmcm9tIFwiLi4vYWN0aW9uTWlkZGxld2FyZXMvdXRpbHNcIlxuaW1wb3J0IHsgcmVzb2x2ZVBhdGgsIHJlc29sdmVQYXRoQ2hlY2tpbmdJZHMsIHNraXBJZENoZWNraW5nIH0gZnJvbSBcIi4uL3BhcmVudC9wYXRoXCJcbmltcG9ydCB0eXBlIHsgUGF0aCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFR5cGVzXCJcbmltcG9ydCB7IGFwcGx5UGF0Y2hlcyB9IGZyb20gXCIuLi9wYXRjaC9hcHBseVBhdGNoZXNcIlxuaW1wb3J0IHsgYXBwbHlTbmFwc2hvdCB9IGZyb20gXCIuLi9zbmFwc2hvdC9hcHBseVNuYXBzaG90XCJcbmltcG9ydCB7IGZyb21TbmFwc2hvdCB9IGZyb20gXCIuLi9zbmFwc2hvdC9mcm9tU25hcHNob3RcIlxuaW1wb3J0IHsgZ2V0U25hcHNob3QgfSBmcm9tIFwiLi4vc25hcHNob3QvZ2V0U25hcHNob3RcIlxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxuaW1wb3J0IHsgZmFpbHVyZSB9IGZyb20gXCIuLi91dGlsc1wiXG5pbXBvcnQgeyBkZWVwRXF1YWxzIH0gZnJvbSBcIi4vZGVlcEVxdWFsc1wiXG5cbi8qKlxuICogQSBjbGFzcyB3aXRoIHRoZSBpbXBsZW1lbnRhdGlvbm0gb2YgZHJhZnQuXG4gKiBVc2UgYGRyYWZ0YCB0byBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgdGhpcyBjbGFzcy5cbiAqXG4gKiBAdHlwZXBhcmFtIFQgRGF0YSB0eXBlLlxuICovXG5leHBvcnQgY2xhc3MgRHJhZnQ8VCBleHRlbmRzIG9iamVjdD4ge1xuICAvKipcbiAgICogRHJhZnQgZGF0YSBvYmplY3QuXG4gICAqL1xuICByZWFkb25seSBkYXRhOiBUXG5cbiAgLyoqXG4gICAqIENvbW1pdHMgY3VycmVudCBkcmFmdCBjaGFuZ2VzIHRvIHRoZSBvcmlnaW5hbCBvYmplY3QuXG4gICAqL1xuICBAYWN0aW9uXG4gIGNvbW1pdCgpOiB2b2lkIHtcbiAgICBhcHBseVNuYXBzaG90KHRoaXMub3JpZ2luYWxEYXRhLCBnZXRTbmFwc2hvdCh0aGlzLmRhdGEpKVxuICB9XG5cbiAgLyoqXG4gICAqIFBhcnRpYWxseSBjb21taXRzIGN1cnJlbnQgZHJhZnQgY2hhbmdlcyB0byB0aGUgb3JpZ2luYWwgb2JqZWN0LlxuICAgKiBJZiB0aGUgcGF0aCBjYW5ub3QgYmUgcmVzb2x2ZWQgaW4gZWl0aGVyIHRoZSBkcmFmdCBvciB0aGUgb3JpZ2luYWwgb2JqZWN0IGl0IHdpbGwgdGhyb3cuXG4gICAqIE5vdGUgdGhhdCBtb2RlbCBJRHMgYXJlIGNoZWNrZWQgdG8gYmUgdGhlIHNhbWUgd2hlbiByZXNvbHZpbmcgdGhlIHBhdGhzLlxuICAgKlxuICAgKiBAcGFyYW0gcGF0aCBQYXRoIHRvIGNvbW1pdC5cbiAgICovXG4gIEBhY3Rpb25cbiAgY29tbWl0QnlQYXRoKHBhdGg6IFBhdGgpOiB2b2lkIHtcbiAgICBjb25zdCBkcmFmdFRhcmdldCA9IHJlc29sdmVQYXRoKHRoaXMuZGF0YSwgcGF0aClcbiAgICBpZiAoIWRyYWZ0VGFyZ2V0LnJlc29sdmVkKSB7XG4gICAgICB0aHJvdyBmYWlsdXJlKGBwYXRoICR7SlNPTi5zdHJpbmdpZnkocGF0aCl9IGNvdWxkIG5vdCBiZSByZXNvbHZlZCBpbiBkcmFmdCBvYmplY3RgKVxuICAgIH1cblxuICAgIGNvbnN0IGRyYWZ0UGF0aElkcyA9IHBhdGhUb1RhcmdldFBhdGhJZHNJZ25vcmluZ0xhc3QodGhpcy5kYXRhLCBwYXRoKVxuXG4gICAgY29uc3Qgb3JpZ2luYWxUYXJnZXQgPSByZXNvbHZlUGF0aENoZWNraW5nSWRzKHRoaXMub3JpZ2luYWxEYXRhLCBwYXRoLCBkcmFmdFBhdGhJZHMpXG4gICAgaWYgKCFvcmlnaW5hbFRhcmdldC5yZXNvbHZlZCkge1xuICAgICAgdGhyb3cgZmFpbHVyZShgcGF0aCAke0pTT04uc3RyaW5naWZ5KHBhdGgpfSBjb3VsZCBub3QgYmUgcmVzb2x2ZWQgaW4gb3JpZ2luYWwgb2JqZWN0YClcbiAgICB9XG5cbiAgICBhcHBseVBhdGNoZXModGhpcy5vcmlnaW5hbERhdGEsIFtcbiAgICAgIHtcbiAgICAgICAgcGF0aCxcbiAgICAgICAgb3A6IFwicmVwbGFjZVwiLFxuICAgICAgICB2YWx1ZTogZ2V0U25hcHNob3QoZHJhZnRUYXJnZXQudmFsdWUpLFxuICAgICAgfSxcbiAgICBdKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0cyB0aGUgZHJhZnQgdG8gYmUgYW4gZXhhY3QgY29weSBvZiB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgb3JpZ2luYWwgb2JqZWN0LlxuICAgKi9cbiAgQGFjdGlvblxuICByZXNldCgpOiB2b2lkIHtcbiAgICBhcHBseVNuYXBzaG90KHRoaXMuZGF0YSwgdGhpcy5vcmlnaW5hbFNuYXBzaG90KVxuICB9XG5cbiAgLyoqXG4gICAqIFBhcnRpYWxseSByZXNldHMgY3VycmVudCBkcmFmdCBjaGFuZ2VzIHRvIGJlIHRoZSBzYW1lIGFzIHRoZSBvcmlnaW5hbCBvYmplY3QuXG4gICAqIElmIHRoZSBwYXRoIGNhbm5vdCBiZSByZXNvbHZlZCBpbiBlaXRoZXIgdGhlIGRyYWZ0IG9yIHRoZSBvcmlnaW5hbCBvYmplY3QgaXQgd2lsbCB0aHJvdy5cbiAgICogTm90ZSB0aGF0IG1vZGVsIElEcyBhcmUgY2hlY2tlZCB0byBiZSB0aGUgc2FtZSB3aGVuIHJlc29sdmluZyB0aGUgcGF0aHMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIFBhdGggdG8gcmVzZXQuXG4gICAqL1xuICBAYWN0aW9uXG4gIHJlc2V0QnlQYXRoKHBhdGg6IFBhdGgpOiB2b2lkIHtcbiAgICBjb25zdCBvcmlnaW5hbFRhcmdldCA9IHJlc29sdmVQYXRoKHRoaXMub3JpZ2luYWxEYXRhLCBwYXRoKVxuICAgIGlmICghb3JpZ2luYWxUYXJnZXQucmVzb2x2ZWQpIHtcbiAgICAgIHRocm93IGZhaWx1cmUoYHBhdGggJHtKU09OLnN0cmluZ2lmeShwYXRoKX0gY291bGQgbm90IGJlIHJlc29sdmVkIGluIG9yaWdpbmFsIG9iamVjdGApXG4gICAgfVxuXG4gICAgY29uc3Qgb3JpZ2luYWxQYXRoSWRzID0gcGF0aFRvVGFyZ2V0UGF0aElkc0lnbm9yaW5nTGFzdCh0aGlzLm9yaWdpbmFsRGF0YSwgcGF0aClcblxuICAgIGNvbnN0IGRyYWZ0VGFyZ2V0ID0gcmVzb2x2ZVBhdGhDaGVja2luZ0lkcyh0aGlzLmRhdGEsIHBhdGgsIG9yaWdpbmFsUGF0aElkcylcbiAgICBpZiAoIWRyYWZ0VGFyZ2V0LnJlc29sdmVkKSB7XG4gICAgICB0aHJvdyBmYWlsdXJlKGBwYXRoICR7SlNPTi5zdHJpbmdpZnkocGF0aCl9IGNvdWxkIG5vdCBiZSByZXNvbHZlZCBpbiBkcmFmdCBvYmplY3RgKVxuICAgIH1cblxuICAgIGFwcGx5UGF0Y2hlcyh0aGlzLmRhdGEsIFtcbiAgICAgIHtcbiAgICAgICAgcGF0aCxcbiAgICAgICAgb3A6IFwicmVwbGFjZVwiLFxuICAgICAgICB2YWx1ZTogZ2V0U25hcHNob3Qob3JpZ2luYWxUYXJnZXQudmFsdWUpLFxuICAgICAgfSxcbiAgICBdKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYHRydWVgIGlmIHRoZSBkcmFmdCBoYXMgY2hhbmdlZCBjb21wYXJlZCB0byB0aGUgb3JpZ2luYWwgb2JqZWN0LCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICovXG4gIEBjb21wdXRlZFxuICBnZXQgaXNEaXJ0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIWRlZXBFcXVhbHMoZ2V0U25hcHNob3QodGhpcy5kYXRhKSwgdGhpcy5vcmlnaW5hbFNuYXBzaG90KVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4gcGF0aCBvZiB0aGUgZHJhZnQgaGFzIGNoYW5nZWQgY29tcGFyZWQgdG8gdGhlIG9yaWdpbmFsIG9iamVjdC5cbiAgICogSWYgdGhlIHBhdGggY2Fubm90IGJlIHJlc29sdmVkIGluIHRoZSBkcmFmdCBpdCB3aWxsIHRocm93LlxuICAgKiBJZiB0aGUgcGF0aCBjYW5ub3QgYmUgcmVzb2x2ZWQgaW4gdGhlIG9yaWdpbmFsIG9iamVjdCBpdCB3aWxsIHJldHVybiBgdHJ1ZWAuXG4gICAqIE5vdGUgdGhhdCBtb2RlbCBJRHMgYXJlIGNoZWNrZWQgdG8gYmUgdGhlIHNhbWUgd2hlbiByZXNvbHZpbmcgdGhlIHBhdGhzLlxuICAgKlxuICAgKiBAcGFyYW0gcGF0aCBQYXRoIHRvIGNoZWNrLlxuICAgKi9cbiAgaXNEaXJ0eUJ5UGF0aChwYXRoOiBQYXRoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZHJhZnRUYXJnZXQgPSByZXNvbHZlUGF0aCh0aGlzLmRhdGEsIHBhdGgpXG4gICAgaWYgKCFkcmFmdFRhcmdldC5yZXNvbHZlZCkge1xuICAgICAgdGhyb3cgZmFpbHVyZShgcGF0aCAke0pTT04uc3RyaW5naWZ5KHBhdGgpfSBjb3VsZCBub3QgYmUgcmVzb2x2ZWQgaW4gZHJhZnQgb2JqZWN0YClcbiAgICB9XG5cbiAgICBjb25zdCBkcmFmdFBhdGhJZHMgPSBwYXRoVG9UYXJnZXRQYXRoSWRzSWdub3JpbmdMYXN0KHRoaXMuZGF0YSwgcGF0aClcblxuICAgIGNvbnN0IG9yaWdpbmFsVGFyZ2V0ID0gcmVzb2x2ZVBhdGhDaGVja2luZ0lkcyh0aGlzLm9yaWdpbmFsRGF0YSwgcGF0aCwgZHJhZnRQYXRoSWRzKVxuICAgIGlmICghb3JpZ2luYWxUYXJnZXQucmVzb2x2ZWQpIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgcmV0dXJuICFkZWVwRXF1YWxzKGRyYWZ0VGFyZ2V0LnZhbHVlLCBvcmlnaW5hbFRhcmdldC52YWx1ZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBPcmlnaW5hbCBkYXRhIG9iamVjdC5cbiAgICovXG4gIHJlYWRvbmx5IG9yaWdpbmFsRGF0YTogVFxuXG4gIEBjb21wdXRlZFxuICBwcml2YXRlIGdldCBvcmlnaW5hbFNuYXBzaG90KCkge1xuICAgIHJldHVybiBnZXRTbmFwc2hvdCh0aGlzLm9yaWdpbmFsRGF0YSlcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIERyYWZ0LlxuICAgKiBEbyBub3QgdXNlIGRpcmVjdGx5LCB1c2UgYGRyYWZ0YCBpbnN0ZWFkLlxuICAgKlxuICAgKiBAcGFyYW0gb3JpZ2luYWxcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9yaWdpbmFsOiBUKSB7XG4gICAgYXNzZXJ0VHdlYWtlZE9iamVjdChvcmlnaW5hbCwgXCJvcmlnaW5hbFwiKVxuXG4gICAgdGhpcy5vcmlnaW5hbERhdGEgPSBvcmlnaW5hbFxuICAgIHRoaXMuZGF0YSA9IGZyb21TbmFwc2hvdCh0aGlzLm9yaWdpbmFsU25hcHNob3QsIHsgZ2VuZXJhdGVOZXdJZHM6IGZhbHNlIH0pXG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZHJhZnQgY29weSBvZiBhIHRyZWUgbm9kZSBhbmQgYWxsIGl0cyBjaGlsZHJlbi5cbiAqXG4gKiBAdHlwZXBhcmFtIFQgRGF0YSB0eXBlLlxuICogQHBhcmFtIG9yaWdpbmFsIE9yaWdpbmFsIG5vZGUuXG4gKiBAcmV0dXJucyBUaGUgZHJhZnQgb2JqZWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZHJhZnQ8VCBleHRlbmRzIG9iamVjdD4ob3JpZ2luYWw6IFQpOiBEcmFmdDxUPiB7XG4gIHJldHVybiBuZXcgRHJhZnQob3JpZ2luYWwpXG59XG5cbmZ1bmN0aW9uIHBhdGhUb1RhcmdldFBhdGhJZHNJZ25vcmluZ0xhc3Qocm9vdDogYW55LCBwYXRoOiBQYXRoKSB7XG4gIGNvbnN0IHBhdGhJZHM6IChzdHJpbmcgfCBudWxsIHwgdHlwZW9mIHNraXBJZENoZWNraW5nKVtdID0gcGF0aFRvVGFyZ2V0UGF0aElkcyhyb290LCBwYXRoKVxuICBpZiAocGF0aElkcy5sZW5ndGggPj0gMSkge1xuICAgIC8vIG5ldmVyIGNoZWNrIHRoZSBsYXN0IG9iamVjdCBpZFxuICAgIHBhdGhJZHNbcGF0aElkcy5sZW5ndGggLSAxXSA9IHNraXBJZENoZWNraW5nXG4gIH1cblxuICByZXR1cm4gcGF0aElkc1xufVxuIiwiaW1wb3J0IHsgcmVhY3Rpb24sIHJ1bkluQWN0aW9uIH0gZnJvbSBcIm1vYnhcIlxyXG5pbXBvcnQge1xyXG4gIHJlYWRvbmx5TWlkZGxld2FyZSxcclxuICBSZWFkb25seU1pZGRsZXdhcmVSZXR1cm4sXHJcbn0gZnJvbSBcIi4uL2FjdGlvbk1pZGRsZXdhcmVzL3JlYWRvbmx5TWlkZGxld2FyZVwiXHJcbmltcG9ydCB7IGNyZWF0ZUNvbnRleHQgfSBmcm9tIFwiLi4vY29udGV4dFwiXHJcbmltcG9ydCB7IGdldFBhcmVudFRvQ2hpbGRQYXRoLCByZXNvbHZlUGF0aCB9IGZyb20gXCIuLi9wYXJlbnQvcGF0aFwiXHJcbmltcG9ydCB7IGFwcGx5UGF0Y2hlcyB9IGZyb20gXCIuLi9wYXRjaC9hcHBseVBhdGNoZXNcIlxyXG5pbXBvcnQgeyBvblBhdGNoZXMgfSBmcm9tIFwiLi4vcGF0Y2gvZW1pdFBhdGNoXCJcclxuaW1wb3J0IHR5cGUgeyBQYXRjaCB9IGZyb20gXCIuLi9wYXRjaC9QYXRjaFwiXHJcbmltcG9ydCB7IFBhdGNoUmVjb3JkZXIsIHBhdGNoUmVjb3JkZXIgfSBmcm9tIFwiLi4vcGF0Y2gvcGF0Y2hSZWNvcmRlclwiXHJcbmltcG9ydCB7IGZhc3RJc1Jvb3RTdG9yZSwgcmVnaXN0ZXJSb290U3RvcmUsIHVucmVnaXN0ZXJSb290U3RvcmUgfSBmcm9tIFwiLi4vcm9vdFN0b3JlL3Jvb3RTdG9yZVwiXHJcbmltcG9ydCB7IGNsb25lIH0gZnJvbSBcIi4uL3NuYXBzaG90L2Nsb25lXCJcclxuaW1wb3J0IHsgYXNzZXJ0VHdlYWtlZE9iamVjdCB9IGZyb20gXCIuLi90d2Vha2VyL2NvcmVcIlxyXG5pbXBvcnQgeyBhc3NlcnRJc0Z1bmN0aW9uLCBmYWlsdXJlIH0gZnJvbSBcIi4uL3V0aWxzXCJcclxuXHJcbi8qKlxyXG4gKiBDb250ZXh0IHRoYXQgYWxsb3dzIGFjY2VzcyB0byB0aGUgc2FuZGJveCBtYW5hZ2VyIHRoaXMgbm9kZSBydW5zIHVuZGVyIChpZiBhbnkpLlxyXG4gKi9cclxuY29uc3Qgc2FuZGJveE1hbmFnZXJDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxTYW5kYm94TWFuYWdlcj4oKVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHNhbmRib3ggbWFuYWdlciBvZiBhIG5vZGUsIG9yIGB1bmRlZmluZWRgIGlmIG5vbmUuXHJcbiAqXHJcbiAqIEBwYXJhbSBub2RlIE5vZGUgdG8gY2hlY2suXHJcbiAqIEByZXR1cm5zIFRoZSBzYW5kYm94IG1hbmFnZXIgb2YgYSBub2RlLCBvciBgdW5kZWZpbmVkYCBpZiBub25lLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdldE5vZGVTYW5kYm94TWFuYWdlcihub2RlOiBvYmplY3QpOiBTYW5kYm94TWFuYWdlciB8IHVuZGVmaW5lZCB7XHJcbiAgcmV0dXJuIHNhbmRib3hNYW5hZ2VyQ29udGV4dC5nZXQobm9kZSlcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgaWYgYSBnaXZlbiBub2RlIGlzIGEgc2FuZGJveGVkIG5vZGUuXHJcbiAqXHJcbiAqIEBwYXJhbSBub2RlIE5vZGUgdG8gY2hlY2suXHJcbiAqIEByZXR1cm5zIGB0cnVlYCBpZiBpdCBpcyBzYW5kYm94ZWQsIGBmYWxzZWBcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1NhbmRib3hlZE5vZGUobm9kZTogb2JqZWN0KTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuICEhZ2V0Tm9kZVNhbmRib3hNYW5hZ2VyKG5vZGUpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgYFNhbmRib3hNYW5hZ2VyLndpdGhTYW5kYm94YC5cclxuICovXHJcbmV4cG9ydCB0eXBlIFdpdGhTYW5kYm94Q2FsbGJhY2s8VCBleHRlbmRzIHJlYWRvbmx5IFtvYmplY3QsIC4uLm9iamVjdFtdXSwgUj4gPSAoXHJcbiAgLi4ubm9kZXM6IFRcclxuKSA9PiBib29sZWFuIHwgeyBjb21taXQ6IGJvb2xlYW47IHJldHVybjogUiB9XHJcblxyXG4vKipcclxuICogTWFuYWdlciBjbGFzcyByZXR1cm5lZCBieSBgc2FuZGJveGAgdGhhdCBhbGxvd3MgeW91IHRvIG1ha2UgY2hhbmdlcyB0byBhIHNhbmRib3ggY29weSBvZiB0aGVcclxuICogb3JpZ2luYWwgc3VidHJlZSBhbmQgYXBwbHkgdGhlbSB0byB0aGUgb3JpZ2luYWwgc3VidHJlZSBvciByZWplY3QgdGhlbS5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBTYW5kYm94TWFuYWdlciB7XHJcbiAgLyoqXHJcbiAgICogVGhlIHNhbmRib3ggY29weSBvZiB0aGUgb3JpZ2luYWwgc3VidHJlZS5cclxuICAgKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IHN1YnRyZWVSb290Q2xvbmU6IG9iamVjdFxyXG5cclxuICAvKipcclxuICAgKiBUaGUgaW50ZXJuYWwgZGlzcG9zZXIuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBkaXNwb3NlcjogKCkgPT4gdm9pZFxyXG5cclxuICAvKipcclxuICAgKiBUaGUgaW50ZXJuYWwgYHdpdGhTYW5kYm94YCBwYXRjaCByZWNvcmRlci4gSWYgYHVuZGVmaW5lZGAsIG5vIGB3aXRoU2FuZGJveGAgY2FsbCBpcyBiZWluZ1xyXG4gICAqIGV4ZWN1dGVkLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgd2l0aFNhbmRib3hQYXRjaFJlY29yZGVyOiBQYXRjaFJlY29yZGVyIHwgdW5kZWZpbmVkXHJcblxyXG4gIC8qKlxyXG4gICAqIEZ1bmN0aW9uIGZyb20gYHJlYWRvbmx5TWlkZGxld2FyZWAgdGhhdCB3aWxsIGFsbG93IGFjdGlvbnMgdG8gYmUgc3RhcnRlZCBpbnNpZGUgdGhlIHByb3ZpZGVkXHJcbiAgICogY29kZSBibG9jayBvbiBhIHJlYWRvbmx5IG5vZGUuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhbGxvd1dyaXRlOiBSZWFkb25seU1pZGRsZXdhcmVSZXR1cm5bXCJhbGxvd1dyaXRlXCJdXHJcblxyXG4gIC8qKlxyXG4gICAqIFdoZXRoZXIgY2hhbmdlcyBtYWRlIGluIHRoZSBzYW5kYm94IGFyZSBjdXJyZW50bHkgYmVpbmcgY29tbWl0dGVkIHRvIHRoZSBvcmlnaW5hbCBzdWJ0cmVlLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgaXNDb21taXR0aW5nOiBib29sZWFuID0gZmFsc2VcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBgU2FuZGJveE1hbmFnZXJgLlxyXG4gICAqIERvIG5vdCB1c2UgZGlyZWN0bHksIHVzZSBgc2FuZGJveGAgaW5zdGVhZC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBzdWJ0cmVlUm9vdCBTdWJ0cmVlIHJvb3QgdGFyZ2V0IG9iamVjdC5cclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHN1YnRyZWVSb290OiBvYmplY3QpIHtcclxuICAgIGFzc2VydFR3ZWFrZWRPYmplY3Qoc3VidHJlZVJvb3QsIFwic3VidHJlZVJvb3RcIilcclxuXHJcbiAgICAvLyB3ZSB0ZW1wb3JhcmlseSBzZXQgdGhlIGRlZmF1bHQgdmFsdWUgb2YgdGhlIGNvbnRleHQgbWFuYWdlciBzbyB0aGF0XHJcbiAgICAvLyBjbG9uZWQgbm9kZXMgY2FuIGFjY2VzcyBpdCB3aGlsZSBpbiB0aGVpciBvbkluaXQgcGhhc2VcclxuXHJcbiAgICBsZXQgcHJldmlvdXNDb250ZXh0RGVmYXVsdCA9IHNhbmRib3hNYW5hZ2VyQ29udGV4dC5nZXREZWZhdWx0KClcclxuICAgIHNhbmRib3hNYW5hZ2VyQ29udGV4dC5zZXREZWZhdWx0KHRoaXMpXHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLnN1YnRyZWVSb290Q2xvbmUgPSBjbG9uZShzdWJ0cmVlUm9vdCwgeyBnZW5lcmF0ZU5ld0lkczogZmFsc2UgfSlcclxuICAgICAgc2FuZGJveE1hbmFnZXJDb250ZXh0LnNldCh0aGlzLnN1YnRyZWVSb290Q2xvbmUsIHRoaXMpXHJcbiAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgdGhyb3cgZXJyXHJcbiAgICB9IGZpbmFsbHkge1xyXG4gICAgICBzYW5kYm94TWFuYWdlckNvbnRleHQuc2V0RGVmYXVsdChwcmV2aW91c0NvbnRleHREZWZhdWx0KVxyXG4gICAgfVxyXG5cclxuICAgIGxldCB3YXNSUyA9IGZhbHNlXHJcbiAgICBjb25zdCBkaXNwb3NlUmVhY3Rpb25SUyA9IHJlYWN0aW9uKFxyXG4gICAgICAoKSA9PiBmYXN0SXNSb290U3RvcmUoc3VidHJlZVJvb3QpLFxyXG4gICAgICAoaXNSUykgPT4ge1xyXG4gICAgICAgIGlmIChpc1JTICE9PSB3YXNSUykge1xyXG4gICAgICAgICAgd2FzUlMgPSBpc1JTXHJcbiAgICAgICAgICBpZiAoaXNSUykge1xyXG4gICAgICAgICAgICByZWdpc3RlclJvb3RTdG9yZSh0aGlzLnN1YnRyZWVSb290Q2xvbmUpXHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB1bnJlZ2lzdGVyUm9vdFN0b3JlKHRoaXMuc3VidHJlZVJvb3RDbG9uZSlcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0sXHJcbiAgICAgIHsgZmlyZUltbWVkaWF0ZWx5OiB0cnVlIH1cclxuICAgIClcclxuXHJcbiAgICBjb25zdCBkaXNwb3NlT25QYXRjaGVzID0gb25QYXRjaGVzKHN1YnRyZWVSb290LCAocGF0Y2hlcykgPT4ge1xyXG4gICAgICBpZiAodGhpcy53aXRoU2FuZGJveFBhdGNoUmVjb3JkZXIpIHtcclxuICAgICAgICB0aHJvdyBmYWlsdXJlKFwib3JpZ2luYWwgc3VidHJlZSBtdXN0IG5vdCBjaGFuZ2Ugd2hpbGUgJ3dpdGhTYW5kYm94JyBleGVjdXRlc1wiKVxyXG4gICAgICB9XHJcbiAgICAgIGlmICghdGhpcy5pc0NvbW1pdHRpbmcpIHtcclxuICAgICAgICB0aGlzLmFsbG93V3JpdGUoKCkgPT4ge1xyXG4gICAgICAgICAgYXBwbHlQYXRjaGVzKHRoaXMuc3VidHJlZVJvb3RDbG9uZSwgcGF0Y2hlcylcclxuICAgICAgICB9KVxyXG4gICAgICB9XHJcbiAgICB9KVxyXG5cclxuICAgIGNvbnN0IHsgYWxsb3dXcml0ZSwgZGlzcG9zZTogZGlzcG9zZVJlYWRvbmx5TVcgfSA9IHJlYWRvbmx5TWlkZGxld2FyZSh0aGlzLnN1YnRyZWVSb290Q2xvbmUpXHJcbiAgICB0aGlzLmFsbG93V3JpdGUgPSBhbGxvd1dyaXRlXHJcblxyXG4gICAgdGhpcy5kaXNwb3NlciA9ICgpID0+IHtcclxuICAgICAgZGlzcG9zZVJlYWN0aW9uUlMoKVxyXG4gICAgICBkaXNwb3NlT25QYXRjaGVzKClcclxuICAgICAgZGlzcG9zZVJlYWRvbmx5TVcoKVxyXG4gICAgICBpZiAoZmFzdElzUm9vdFN0b3JlKHRoaXMuc3VidHJlZVJvb3RDbG9uZSkpIHtcclxuICAgICAgICB1bnJlZ2lzdGVyUm9vdFN0b3JlKHRoaXMuc3VidHJlZVJvb3RDbG9uZSlcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmRpc3Bvc2VyID0gKCkgPT4ge31cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEV4ZWN1dGVzIGBmbmAgd2l0aCBzYW5kYm94IGNvcGllcyBvZiB0aGUgZWxlbWVudHMgb2YgYG5vZGVzYC4gVGhlIGNoYW5nZXMgbWFkZSB0byB0aGUgc2FuZGJveFxyXG4gICAqIGluIGBmbmAgY2FuIGJlIGFjY2VwdGVkLCBpLmUuIGFwcGxpZWQgdG8gdGhlIG9yaWdpbmFsIHN1YnRyZWUsIG9yIHJlamVjdGVkLlxyXG4gICAqXHJcbiAgICogQHR5cGVwYXJhbSBUIE9iamVjdCB0eXBlLlxyXG4gICAqIEB0eXBlcGFyYW0gUiBSZXR1cm4gdHlwZS5cclxuICAgKiBAcGFyYW0gbm9kZXMgVHVwbGUgb2Ygb2JqZWN0cyBmb3Igd2hpY2ggdG8gb2J0YWluIHNhbmRib3ggY29waWVzLlxyXG4gICAqIEBwYXJhbSBmbiBGdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aXRoIHNhbmRib3ggY29waWVzIG9mIHRoZSBlbGVtZW50cyBvZiBgbm9kZXNgLiBBbnkgY2hhbmdlc1xyXG4gICAqIG1hZGUgdG8gdGhlIHNhbmRib3ggYXJlIGFwcGxpZWQgdG8gdGhlIG9yaWdpbmFsIHN1YnRyZWUgd2hlbiBgZm5gIHJldHVybnMgYHRydWVgIG9yXHJcbiAgICogYHsgY29tbWl0OiB0cnVlLCAuLi4gfWAuIFdoZW4gYGZuYCByZXR1cm5zIGBmYWxzZWAgb3IgYHsgY29tbWl0OiBmYWxzZSwgLi4uIH1gIHRoZSBjaGFuZ2VzIG1hZGVcclxuICAgKiB0byB0aGUgc2FuZGJveCBhcmUgcmVqZWN0ZWQuXHJcbiAgICogQHJldHVybnMgVmFsdWUgb2YgdHlwZSBgUmAgd2hlbiBgZm5gIHJldHVybnMgYW4gb2JqZWN0IG9mIHR5cGUgYHsgY29tbWl0OiBib29sZWFuOyByZXR1cm46IFIgfWBcclxuICAgKiBvciBgdm9pZGAgd2hlbiBgZm5gIHJldHVybnMgYSBib29sZWFuLlxyXG4gICAqL1xyXG4gIHdpdGhTYW5kYm94PFQgZXh0ZW5kcyByZWFkb25seSBbb2JqZWN0LCAuLi5vYmplY3RbXV0sIFIgPSB2b2lkPihcclxuICAgIG5vZGVzOiBULFxyXG4gICAgZm46IFdpdGhTYW5kYm94Q2FsbGJhY2s8VCwgUj5cclxuICApOiBSIHtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgYXNzZXJ0VHdlYWtlZE9iamVjdChub2Rlc1tpXSwgYG5vZGVzWyR7aX1dYClcclxuICAgIH1cclxuICAgIGFzc2VydElzRnVuY3Rpb24oZm4sIFwiZm5cIilcclxuXHJcbiAgICBjb25zdCB7IHNhbmRib3hOb2RlcywgYXBwbHlSZWNvcmRlckNoYW5nZXMgfSA9IHRoaXMucHJlcGFyZVNhbmRib3hDaGFuZ2VzKG5vZGVzKVxyXG5cclxuICAgIGxldCBjb21taXQgPSBmYWxzZVxyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSB0aGlzLmFsbG93V3JpdGUoKCkgPT4gZm4oLi4uc2FuZGJveE5vZGVzKSlcclxuICAgICAgaWYgKHR5cGVvZiByZXR1cm5WYWx1ZSA9PT0gXCJib29sZWFuXCIpIHtcclxuICAgICAgICBjb21taXQgPSByZXR1cm5WYWx1ZVxyXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQgYXMgYW55XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY29tbWl0ID0gcmV0dXJuVmFsdWUuY29tbWl0XHJcbiAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlLnJldHVyblxyXG4gICAgICB9XHJcbiAgICB9IGZpbmFsbHkge1xyXG4gICAgICBhcHBseVJlY29yZGVyQ2hhbmdlcyhjb21taXQpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEaXNwb3NlcyBvZiB0aGUgc2FuZGJveC5cclxuICAgKi9cclxuICBkaXNwb3NlKCk6IHZvaWQge1xyXG4gICAgdGhpcy5kaXNwb3NlcigpXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByZXBhcmVTYW5kYm94Q2hhbmdlczxUIGV4dGVuZHMgcmVhZG9ubHkgW29iamVjdCwgLi4ub2JqZWN0W11dPihcclxuICAgIG5vZGVzOiBUXHJcbiAgKTogeyBzYW5kYm94Tm9kZXM6IFQ7IGFwcGx5UmVjb3JkZXJDaGFuZ2VzOiAoY29tbWl0OiBib29sZWFuKSA9PiB2b2lkIH0ge1xyXG4gICAgY29uc3QgaXNOZXN0ZWRXaXRoU2FuZGJveENhbGwgPSAhIXRoaXMud2l0aFNhbmRib3hQYXRjaFJlY29yZGVyXHJcblxyXG4gICAgY29uc3Qgc2FuZGJveE5vZGVzID0gbm9kZXMubWFwKChub2RlKSA9PiB7XHJcbiAgICAgIGNvbnN0IHBhdGggPSBnZXRQYXJlbnRUb0NoaWxkUGF0aChcclxuICAgICAgICBpc05lc3RlZFdpdGhTYW5kYm94Q2FsbCA/IHRoaXMuc3VidHJlZVJvb3RDbG9uZSA6IHRoaXMuc3VidHJlZVJvb3QsXHJcbiAgICAgICAgbm9kZVxyXG4gICAgICApXHJcbiAgICAgIGlmICghcGF0aCkge1xyXG4gICAgICAgIHRocm93IGZhaWx1cmUoYG5vZGUgaXMgbm90IGEgY2hpbGQgb2Ygc3VidHJlZVJvb3Qke2lzTmVzdGVkV2l0aFNhbmRib3hDYWxsID8gXCJDbG9uZVwiIDogXCJcIn1gKVxyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCBzYW5kYm94Tm9kZSA9IHJlc29sdmVQYXRoPHR5cGVvZiBub2RlPih0aGlzLnN1YnRyZWVSb290Q2xvbmUsIHBhdGgpLnZhbHVlXHJcbiAgICAgIGlmICghc2FuZGJveE5vZGUpIHtcclxuICAgICAgICB0aHJvdyBmYWlsdXJlKFwicGF0aCBjb3VsZCBub3QgYmUgcmVzb2x2ZWQgLSBzYW5kYm94IG1heSBiZSBvdXQgb2Ygc3luYyB3aXRoIG9yaWdpbmFsIHRyZWVcIilcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIHNhbmRib3hOb2RlXHJcbiAgICB9KSBhcyB1bmtub3duIGFzIFRcclxuXHJcbiAgICBpZiAoIXRoaXMud2l0aFNhbmRib3hQYXRjaFJlY29yZGVyKSB7XHJcbiAgICAgIHRoaXMud2l0aFNhbmRib3hQYXRjaFJlY29yZGVyID0gcGF0Y2hSZWNvcmRlcih0aGlzLnN1YnRyZWVSb290Q2xvbmUpXHJcbiAgICB9XHJcbiAgICBjb25zdCByZWNvcmRlciA9IHRoaXMud2l0aFNhbmRib3hQYXRjaFJlY29yZGVyXHJcbiAgICBjb25zdCBudW1SZWNvcmRlckV2ZW50cyA9IHJlY29yZGVyLmV2ZW50cy5sZW5ndGhcclxuXHJcbiAgICBjb25zdCBhcHBseVJlY29yZGVyQ2hhbmdlcyA9IChjb21taXQ6IGJvb2xlYW4pOiB2b2lkID0+IHtcclxuICAgICAgaWYgKCFpc05lc3RlZFdpdGhTYW5kYm94Q2FsbCkge1xyXG4gICAgICAgIHJlY29yZGVyLmRpc3Bvc2UoKVxyXG4gICAgICAgIHRoaXMud2l0aFNhbmRib3hQYXRjaFJlY29yZGVyID0gdW5kZWZpbmVkXHJcbiAgICAgIH1cclxuICAgICAgaWYgKGNvbW1pdCkge1xyXG4gICAgICAgIGlmICghaXNOZXN0ZWRXaXRoU2FuZGJveENhbGwpIHtcclxuICAgICAgICAgIGNvbnN0IHBhdGNoZXM6IFBhdGNoW10gPSBbXVxyXG4gICAgICAgICAgY29uc3QgbGVuID0gcmVjb3JkZXIuZXZlbnRzLmxlbmd0aFxyXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICAgICAgICBwYXRjaGVzLnB1c2goLi4ucmVjb3JkZXIuZXZlbnRzW2ldLnBhdGNoZXMpXHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgY29uc3QgaXNDb21taXR0aW5nID0gdGhpcy5pc0NvbW1pdHRpbmdcclxuICAgICAgICAgIHRoaXMuaXNDb21taXR0aW5nID0gdHJ1ZVxyXG4gICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgYXBwbHlQYXRjaGVzKHRoaXMuc3VidHJlZVJvb3QsIHBhdGNoZXMpXHJcbiAgICAgICAgICB9IGZpbmFsbHkge1xyXG4gICAgICAgICAgICB0aGlzLmlzQ29tbWl0dGluZyA9IGlzQ29tbWl0dGluZ1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLmFsbG93V3JpdGUoKCkgPT4ge1xyXG4gICAgICAgICAgcnVuSW5BY3Rpb24oKCkgPT4ge1xyXG4gICAgICAgICAgICBsZXQgaSA9IHJlY29yZGVyLmV2ZW50cy5sZW5ndGhcclxuICAgICAgICAgICAgd2hpbGUgKGktLSA+IG51bVJlY29yZGVyRXZlbnRzKSB7XHJcbiAgICAgICAgICAgICAgYXBwbHlQYXRjaGVzKHRoaXMuc3VidHJlZVJvb3RDbG9uZSwgcmVjb3JkZXIuZXZlbnRzW2ldLmludmVyc2VQYXRjaGVzLCB0cnVlKVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgIH0pXHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4geyBzYW5kYm94Tm9kZXMsIGFwcGx5UmVjb3JkZXJDaGFuZ2VzIH1cclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDcmVhdGVzIGEgc2FuZGJveC5cclxuICpcclxuICogQHBhcmFtIHN1YnRyZWVSb290IFN1YnRyZWUgcm9vdCB0YXJnZXQgb2JqZWN0LlxyXG4gKiBAcmV0dXJucyBBIGBTYW5kYm94TWFuYWdlcmAgd2hpY2ggYWxsb3dzIHlvdSB0byBtYW5hZ2UgdGhlIHNhbmRib3ggb3BlcmF0aW9ucyBhbmQgZGlzcG9zZSBvZiB0aGVcclxuICogc2FuZGJveC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBzYW5kYm94KHN1YnRyZWVSb290OiBvYmplY3QpOiBTYW5kYm94TWFuYWdlciB7XHJcbiAgcmV0dXJuIG5ldyBTYW5kYm94TWFuYWdlcihzdWJ0cmVlUm9vdClcclxufVxyXG4iLCJpbXBvcnQgeyBpc0FycmF5LCBsYXp5IH0gZnJvbSBcIi4uLy4uL3V0aWxzXCJcbmltcG9ydCB7IGdldFR5cGVJbmZvIH0gZnJvbSBcIi4uL2dldFR5cGVJbmZvXCJcbmltcG9ydCB7IHJlc29sdmVTdGFuZGFyZFR5cGUsIHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuLi9yZXNvbHZlVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHR5cGUgeyBBbnlTdGFuZGFyZFR5cGUsIEFueVR5cGUsIEFycmF5VHlwZSB9IGZyb20gXCIuLi9zY2hlbWFzXCJcbmltcG9ydCB7XG4gIGxhdGVUeXBlQ2hlY2tlcixcbiAgVHlwZUNoZWNrZXIsXG4gIFR5cGVDaGVja2VyQmFzZVR5cGUsXG4gIFR5cGVJbmZvLFxuICBUeXBlSW5mb0dlbixcbn0gZnJvbSBcIi4uL1R5cGVDaGVja2VyXCJcbmltcG9ydCB7IFR5cGVDaGVja0Vycm9yIH0gZnJvbSBcIi4uL1R5cGVDaGVja0Vycm9yXCJcblxuLyoqXG4gKiBBIHR5cGUgdGhhdCByZXByZXNlbnRzIGFuIHR1cGxlIG9mIHZhbHVlcyBvZiBhIGdpdmVuIHR5cGUuXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYHRzXG4gKiBjb25zdCBzdHJpbmdOdW1iZXJUdXBsZVR5cGUgPSB0eXBlcy50dXBsZSh0eXBlcy5zdHJpbmcsIHR5cGVzLm51bWJlcilcbiAqIGBgYFxuICpcbiAqIEB0eXBlcGFyYW0gVCBJdGVtIHR5cGVzLlxuICogQHBhcmFtIGl0ZW1UeXBlIFR5cGUgb2YgaW5uZXIgaXRlbXMuXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHlwZXNUdXBsZTxUIGV4dGVuZHMgQW55VHlwZVtdPiguLi5pdGVtVHlwZXM6IFQpOiBBcnJheVR5cGU8VD4ge1xuICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT4gbmV3IFR1cGxlVHlwZUluZm8odCwgaXRlbVR5cGVzLm1hcChyZXNvbHZlU3RhbmRhcmRUeXBlKSlcblxuICByZXR1cm4gbGF0ZVR5cGVDaGVja2VyKCgpID0+IHtcbiAgICBjb25zdCBjaGVja2VycyA9IGl0ZW1UeXBlcy5tYXAocmVzb2x2ZVR5cGVDaGVja2VyKVxuXG4gICAgY29uc3QgZ2V0VHlwZU5hbWUgPSAoLi4ucmVjdXJzaXZlVHlwZUNoZWNrZXJzOiBUeXBlQ2hlY2tlcltdKSA9PiB7XG4gICAgICBjb25zdCB0eXBlTmFtZXMgPSBjaGVja2Vycy5tYXAoKHRjKSA9PiB7XG4gICAgICAgIGlmIChyZWN1cnNpdmVUeXBlQ2hlY2tlcnMuaW5jbHVkZXModGMpKSB7XG4gICAgICAgICAgcmV0dXJuIFwiLi4uXCJcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGMuZ2V0VHlwZU5hbWUoLi4ucmVjdXJzaXZlVHlwZUNoZWNrZXJzLCB0YylcbiAgICAgIH0pXG5cbiAgICAgIHJldHVybiBcIltcIiArIHR5cGVOYW1lcy5qb2luKFwiLCBcIikgKyBcIl1cIlxuICAgIH1cblxuICAgIGNvbnN0IHRoaXNUYzogVHlwZUNoZWNrZXIgPSBuZXcgVHlwZUNoZWNrZXIoXG4gICAgICBUeXBlQ2hlY2tlckJhc2VUeXBlLkFycmF5LFxuXG4gICAgICAoYXJyYXksIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+IHtcbiAgICAgICAgaWYgKCFpc0FycmF5KGFycmF5KSB8fCBhcnJheS5sZW5ndGggIT09IGl0ZW1UeXBlcy5sZW5ndGgpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFR5cGVDaGVja0Vycm9yKHBhdGgsIGdldFR5cGVOYW1lKHRoaXNUYyksIGFycmF5LCB0eXBlQ2hlY2tlZFZhbHVlKVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IGl0ZW1FcnJvciA9IGNoZWNrZXJzW2ldLmNoZWNrKGFycmF5W2ldLCBbLi4ucGF0aCwgaV0sIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICAgICAgaWYgKGl0ZW1FcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW1FcnJvclxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsXG4gICAgICB9LFxuXG4gICAgICBnZXRUeXBlTmFtZSxcbiAgICAgIHR5cGVJbmZvR2VuLFxuXG4gICAgICAoYXJyYXkpID0+IHtcbiAgICAgICAgaWYgKCFpc0FycmF5KGFycmF5KSB8fCBhcnJheS5sZW5ndGggIT09IGl0ZW1UeXBlcy5sZW5ndGgpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IGl0ZW1BY3R1YWxDaGVja2VyID0gY2hlY2tlcnNbaV0uc25hcHNob3RUeXBlKGFycmF5W2ldKVxuICAgICAgICAgIGlmICghaXRlbUFjdHVhbENoZWNrZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXNUY1xuICAgICAgfSxcblxuICAgICAgKGFycmF5OiB1bmtub3duW10pID0+IHtcbiAgICAgICAgcmV0dXJuIGFycmF5Lm1hcCgoaXRlbSwgaSkgPT4ge1xuICAgICAgICAgIHJldHVybiBjaGVja2Vyc1tpXS5mcm9tU25hcHNob3RQcm9jZXNzb3IoaXRlbSlcbiAgICAgICAgfSlcbiAgICAgIH0sXG5cbiAgICAgIChhcnJheTogdW5rbm93bltdKSA9PiB7XG4gICAgICAgIHJldHVybiBhcnJheS5tYXAoKGl0ZW0sIGkpID0+IHtcbiAgICAgICAgICByZXR1cm4gY2hlY2tlcnNbaV0udG9TbmFwc2hvdFByb2Nlc3NvcihpdGVtKVxuICAgICAgICB9KVxuICAgICAgfVxuICAgIClcblxuICAgIHJldHVybiB0aGlzVGNcbiAgfSwgdHlwZUluZm9HZW4pIGFzIGFueVxufVxuXG4vKipcbiAqIGB0eXBlcy50dXBsZWAgdHlwZSBpbmZvLlxuICovXG5leHBvcnQgY2xhc3MgVHVwbGVUeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHtcbiAgLy8gbWVtb2l6ZSB0byBhbHdheXMgcmV0dXJuIHRoZSBzYW1lIGFycmF5IG9uIHRoZSBnZXR0ZXJcbiAgcHJpdmF0ZSBfaXRlbVR5cGVJbmZvcyA9IGxhenkoKCkgPT4gdGhpcy5pdGVtVHlwZXMubWFwKGdldFR5cGVJbmZvKSlcblxuICBnZXQgaXRlbVR5cGVJbmZvcygpOiBSZWFkb25seUFycmF5PFR5cGVJbmZvPiB7XG4gICAgcmV0dXJuIHRoaXMuX2l0ZW1UeXBlSW5mb3MoKVxuICB9XG5cbiAgY29uc3RydWN0b3IodGhpc1R5cGU6IEFueVN0YW5kYXJkVHlwZSwgcmVhZG9ubHkgaXRlbVR5cGVzOiBSZWFkb25seUFycmF5PEFueVN0YW5kYXJkVHlwZT4pIHtcbiAgICBzdXBlcih0aGlzVHlwZSlcbiAgfVxufVxuIiwiaW1wb3J0IHsgdmFsdWVzIH0gZnJvbSBcIm1vYnhcIlxuaW1wb3J0IHsgbW9kZWxBY3Rpb24gfSBmcm9tIFwiLi4vYWN0aW9uL21vZGVsQWN0aW9uXCJcbmltcG9ydCB7IG1vZGVsSWRLZXkgfSBmcm9tIFwiLi4vbW9kZWwvbWV0YWRhdGFcIlxuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvTW9kZWxcIlxuaW1wb3J0IHsgbW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxTaGFyZWQvbW9kZWxEZWNvcmF0b3JcIlxuaW1wb3J0IHsgaWRQcm9wIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL3Byb3BcIlxuaW1wb3J0IHsgdHlwZXNBcnJheSB9IGZyb20gXCIuLi90eXBlcy9hcnJheUJhc2VkL3R5cGVzQXJyYXlcIlxuaW1wb3J0IHsgdFByb3AgfSBmcm9tIFwiLi4vdHlwZXMvdFByb3BcIlxuaW1wb3J0IHsgdHlwZXNVbmNoZWNrZWQgfSBmcm9tIFwiLi4vdHlwZXMvdXRpbGl0eS90eXBlc1VuY2hlY2tlZFwiXG5pbXBvcnQgeyBuYW1lc3BhY2UgfSBmcm9tIFwiLi4vdXRpbHNcIlxuXG4vKipcbiAqIEEgc2V0IHRoYXQgaXMgYmFja2VkIGJ5IGFuIGFycmF5LlxuICogVXNlIGBhcnJheVNldGAgdG8gY3JlYXRlIGl0LlxuICovXG5AbW9kZWwoYCR7bmFtZXNwYWNlfS9BcnJheVNldGApXG5leHBvcnQgY2xhc3MgQXJyYXlTZXQ8Vj5cbiAgZXh0ZW5kcyBNb2RlbCh7XG4gICAgW21vZGVsSWRLZXldOiBpZFByb3AsXG4gICAgaXRlbXM6IHRQcm9wKHR5cGVzQXJyYXkodHlwZXNVbmNoZWNrZWQ8YW55PigpKSwgKCkgPT4gW10pLCAvLyB3aWxsIGJlIHByb3Blcmx5IGNoZWNrZWQgYnkgdHlwZXMuYXJyYXlTZXQoc3ViVHlwZSlcbiAgfSlcbiAgaW1wbGVtZW50cyBTZXQ8Vj5cbntcbiAgQG1vZGVsQWN0aW9uXG4gIGFkZCh2YWx1ZTogVik6IHRoaXMge1xuICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5pdGVtc1xuXG4gICAgaWYgKCFpdGVtcy5pbmNsdWRlcyh2YWx1ZSkpIHtcbiAgICAgIGl0ZW1zLnB1c2godmFsdWUpXG4gICAgfVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBAbW9kZWxBY3Rpb25cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgdGhpcy5pdGVtcy5sZW5ndGggPSAwXG4gIH1cblxuICBAbW9kZWxBY3Rpb25cbiAgZGVsZXRlKHZhbHVlOiBWKTogYm9vbGVhbiB7XG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zXG5cbiAgICBjb25zdCBpbmRleCA9IGl0ZW1zLmZpbmRJbmRleCgodCkgPT4gdCA9PT0gdmFsdWUpXG4gICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgIGl0ZW1zLnNwbGljZShpbmRleCwgMSlcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIGZvckVhY2goY2FsbGJhY2tmbjogKHZhbHVlOiBWLCB2YWx1ZTI6IFYsIHNldDogU2V0PFY+KSA9PiB2b2lkLCB0aGlzQXJnPzogYW55KTogdm9pZCB7XG4gICAgLy8gd2UgY2Fubm90IHVzZSB0aGUgc2V0IGltcGxlbWVudGF0aW9uIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyB0aGlzIGFzIHNldFxuICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5pdGVtc1xuICAgIGNvbnN0IGxlbiA9IGl0ZW1zLmxlbmd0aFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGNvbnN0IGsgPSBpdGVtc1tpXVxuICAgICAgY2FsbGJhY2tmbi5jYWxsKHRoaXNBcmcsIGssIGssIHRoaXMpXG4gICAgfVxuICB9XG5cbiAgaGFzKHZhbHVlOiBWKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXRlbXMuaW5jbHVkZXModmFsdWUpXG4gIH1cblxuICBnZXQgc2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLml0ZW1zLmxlbmd0aFxuICB9XG5cbiAga2V5cygpOiBJdGVyYWJsZUl0ZXJhdG9yPFY+IHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXMoKSAvLyB5ZXMsIHZhbHVlc1xuICB9XG5cbiAgdmFsdWVzKCk6IEl0ZXJhYmxlSXRlcmF0b3I8Vj4ge1xuICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5pdGVtc1xuXG4gICAgcmV0dXJuIHZhbHVlcyhpdGVtcylbU3ltYm9sLml0ZXJhdG9yXSgpXG4gIH1cblxuICBlbnRyaWVzKCk6IEl0ZXJhYmxlSXRlcmF0b3I8W1YsIFZdPiB7XG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zXG5cbiAgICAvLyBUT0RPOiBzaG91bGQgdXNlIGFuIGFjdHVhbCBpdGVyYXRvclxuICAgIHJldHVybiBpdGVtcy5tYXAoKHYpID0+IFt2LCB2XSBhcyBbViwgVl0pLnZhbHVlcygpXG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpOiBJdGVyYWJsZUl0ZXJhdG9yPFY+IHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXMoKVxuICB9XG5cbiAgZ2V0IFtTeW1ib2wudG9TdHJpbmdUYWddKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFwiQXJyYXlTZXRcIlxuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBBcnJheVNldCBtb2RlbCBpbnN0YW5jZS5cbiAqXG4gKiBAdHlwZXBhcmFtIFYgVmFsdWUgdHlwZS5cbiAqIEBwYXJhbSBbZW50cmllc10gT3B0aW9uYWwgaW5pdGlhbCB2YWx1ZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcnJheVNldDxWPih2YWx1ZXM/OiBSZWFkb25seUFycmF5PFY+IHwgbnVsbCk6IEFycmF5U2V0PFY+IHtcbiAgY29uc3QgaW5pdGlhbEFycjogVltdID0gdmFsdWVzID8gdmFsdWVzLnNsaWNlKCkgOiBbXVxuXG4gIHJldHVybiBuZXcgQXJyYXlTZXQoeyBpdGVtczogaW5pdGlhbEFyciB9KVxufVxuIiwiaW1wb3J0IHsgbW9kZWxUeXBlS2V5IH0gZnJvbSBcIi4uLy4uL21vZGVsL21ldGFkYXRhXCJcbmltcG9ydCB7IG1vZGVsSW5mb0J5Q2xhc3MgfSBmcm9tIFwiLi4vLi4vbW9kZWxTaGFyZWQvbW9kZWxJbmZvXCJcbmltcG9ydCB7IGlzT2JqZWN0IH0gZnJvbSBcIi4uLy4uL3V0aWxzXCJcbmltcG9ydCB7IEFycmF5U2V0IH0gZnJvbSBcIi4uLy4uL3dyYXBwZXJzL0FycmF5U2V0XCJcbmltcG9ydCB7IHR5cGVzQXJyYXkgfSBmcm9tIFwiLi4vYXJyYXlCYXNlZC90eXBlc0FycmF5XCJcbmltcG9ydCB7IGdldFR5cGVJbmZvIH0gZnJvbSBcIi4uL2dldFR5cGVJbmZvXCJcbmltcG9ydCB7IHJlc29sdmVTdGFuZGFyZFR5cGUsIHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuLi9yZXNvbHZlVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHR5cGUgeyBBbnlTdGFuZGFyZFR5cGUsIEFueVR5cGUsIE1vZGVsVHlwZSwgVHlwZVRvRGF0YSB9IGZyb20gXCIuLi9zY2hlbWFzXCJcbmltcG9ydCB7XG4gIGxhdGVUeXBlQ2hlY2tlcixcbiAgVHlwZUNoZWNrZXIsXG4gIFR5cGVDaGVja2VyQmFzZVR5cGUsXG4gIFR5cGVJbmZvLFxuICBUeXBlSW5mb0dlbixcbn0gZnJvbSBcIi4uL1R5cGVDaGVja2VyXCJcbmltcG9ydCB7IFR5cGVDaGVja0Vycm9yIH0gZnJvbSBcIi4uL1R5cGVDaGVja0Vycm9yXCJcbmltcG9ydCB7IHR5cGVzT2JqZWN0IH0gZnJvbSBcIi4vdHlwZXNPYmplY3RcIlxuXG4vKipcbiAqIEEgdHlwZSB0aGF0IHJlcHJlc2VudHMgYW4gYXJyYXkgYmFja2VkIHNldCBBcnJheVNldC5cbiAqXG4gKiBFeGFtcGxlOlxuICogYGBgdHNcbiAqIGNvbnN0IG51bWJlclNldFR5cGUgPSB0eXBlcy5hcnJheVNldCh0eXBlcy5udW1iZXIpXG4gKiBgYGBcbiAqXG4gKiBAdHlwZXBhcmFtIFQgVmFsdWUgdHlwZS5cbiAqIEBwYXJhbSB2YWx1ZVR5cGUgVmFsdWUgdHlwZS5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc0FycmF5U2V0PFQgZXh0ZW5kcyBBbnlUeXBlPih2YWx1ZVR5cGU6IFQpOiBNb2RlbFR5cGU8QXJyYXlTZXQ8VHlwZVRvRGF0YTxUPj4+IHtcbiAgY29uc3QgdHlwZUluZm9HZW46IFR5cGVJbmZvR2VuID0gKHQpID0+IG5ldyBBcnJheVNldFR5cGVJbmZvKHQsIHJlc29sdmVTdGFuZGFyZFR5cGUodmFsdWVUeXBlKSlcblxuICByZXR1cm4gbGF0ZVR5cGVDaGVja2VyKCgpID0+IHtcbiAgICBjb25zdCBtb2RlbEluZm8gPSBtb2RlbEluZm9CeUNsYXNzLmdldChBcnJheVNldCkhXG5cbiAgICBjb25zdCB2YWx1ZUNoZWNrZXIgPSByZXNvbHZlVHlwZUNoZWNrZXIodmFsdWVUeXBlKVxuXG4gICAgY29uc3QgZ2V0VHlwZU5hbWUgPSAoLi4ucmVjdXJzaXZlVHlwZUNoZWNrZXJzOiBUeXBlQ2hlY2tlcltdKSA9PlxuICAgICAgYEFycmF5U2V0PCR7dmFsdWVDaGVja2VyLmdldFR5cGVOYW1lKC4uLnJlY3Vyc2l2ZVR5cGVDaGVja2VycywgdmFsdWVDaGVja2VyKX0+YFxuXG4gICAgY29uc3QgZGF0YVR5cGVDaGVja2VyID0gdHlwZXNPYmplY3QoKCkgPT4gKHtcbiAgICAgIGl0ZW1zOiB0eXBlc0FycmF5KHZhbHVlQ2hlY2tlciBhcyBhbnkpLFxuICAgIH0pKVxuXG4gICAgY29uc3QgdGhpc1RjOiBUeXBlQ2hlY2tlciA9IG5ldyBUeXBlQ2hlY2tlcihcbiAgICAgIFR5cGVDaGVja2VyQmFzZVR5cGUuT2JqZWN0LCAvLyBiZWNhdXNlIGl0IGlzIHJlYWxseSBhIG1vZGVsXG5cbiAgICAgIChvYmosIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+IHtcbiAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgQXJyYXlTZXQpKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCBnZXRUeXBlTmFtZSh0aGlzVGMpLCBvYmosIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXNvbHZlZFRjID0gcmVzb2x2ZVR5cGVDaGVja2VyKGRhdGFUeXBlQ2hlY2tlcilcbiAgICAgICAgcmV0dXJuIHJlc29sdmVkVGMuY2hlY2sob2JqLiQsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICB9LFxuXG4gICAgICBnZXRUeXBlTmFtZSxcbiAgICAgIHR5cGVJbmZvR2VuLFxuXG4gICAgICAob2JqKSA9PiB7XG4gICAgICAgIGlmICghaXNPYmplY3Qob2JqKSkge1xuICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgIH1cblxuICAgICAgICBpZiAob2JqW21vZGVsVHlwZUtleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIC8vIGZhc3QgY2hlY2tcbiAgICAgICAgICByZXR1cm4gb2JqW21vZGVsVHlwZUtleV0gPT09IG1vZGVsSW5mby5uYW1lID8gdGhpc1RjIDogbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzb2x2ZWRUYyA9IHJlc29sdmVUeXBlQ2hlY2tlcihkYXRhVHlwZUNoZWNrZXIpXG4gICAgICAgIHJldHVybiByZXNvbHZlZFRjLnNuYXBzaG90VHlwZShvYmopID8gdGhpc1RjIDogbnVsbFxuICAgICAgfSxcblxuICAgICAgKHNuOiB7IGl0ZW1zOiB1bmtub3duW10gfSkgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLnNuLFxuICAgICAgICAgIFttb2RlbFR5cGVLZXldOiBtb2RlbEluZm8ubmFtZSxcbiAgICAgICAgICBpdGVtczogc24uaXRlbXMubWFwKCh2KSA9PiB2YWx1ZUNoZWNrZXIuZnJvbVNuYXBzaG90UHJvY2Vzc29yKHYpKSxcbiAgICAgICAgfVxuICAgICAgfSxcblxuICAgICAgKHNuOiB7IGl0ZW1zOiB1bmtub3duW107IFttb2RlbFR5cGVLZXldPzogc3RyaW5nIH0pID0+IHtcbiAgICAgICAgY29uc3Qgc25Db3B5ID0ge1xuICAgICAgICAgIC4uLnNuLFxuICAgICAgICAgIGl0ZW1zOiBzbi5pdGVtcy5tYXAoKHYpID0+IHZhbHVlQ2hlY2tlci50b1NuYXBzaG90UHJvY2Vzc29yKHYpKSxcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzbkNvcHlcbiAgICAgIH1cbiAgICApXG5cbiAgICByZXR1cm4gdGhpc1RjXG4gIH0sIHR5cGVJbmZvR2VuKSBhcyBhbnlcbn1cblxuLyoqXG4gKiBgdHlwZXMuYXJyYXlTZXRgIHR5cGUgaW5mby5cbiAqL1xuZXhwb3J0IGNsYXNzIEFycmF5U2V0VHlwZUluZm8gZXh0ZW5kcyBUeXBlSW5mbyB7XG4gIGdldCB2YWx1ZVR5cGVJbmZvKCk6IFR5cGVJbmZvIHtcbiAgICByZXR1cm4gZ2V0VHlwZUluZm8odGhpcy52YWx1ZVR5cGUpXG4gIH1cblxuICBjb25zdHJ1Y3RvcihvcmlnaW5hbFR5cGU6IEFueVN0YW5kYXJkVHlwZSwgcmVhZG9ubHkgdmFsdWVUeXBlOiBBbnlTdGFuZGFyZFR5cGUpIHtcbiAgICBzdXBlcihvcmlnaW5hbFR5cGUpXG4gIH1cbn1cbiIsImltcG9ydCB7IGlzT2JqZWN0IH0gZnJvbSBcIi4uLy4uL3V0aWxzXCJcbmltcG9ydCB7IGdldFR5cGVJbmZvIH0gZnJvbSBcIi4uL2dldFR5cGVJbmZvXCJcbmltcG9ydCB7IHJlc29sdmVTdGFuZGFyZFR5cGUsIHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuLi9yZXNvbHZlVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHR5cGUgeyBBbnlTdGFuZGFyZFR5cGUsIEFueVR5cGUsIFJlY29yZFR5cGUgfSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQge1xuICBsYXRlVHlwZUNoZWNrZXIsXG4gIFR5cGVDaGVja2VyLFxuICBUeXBlQ2hlY2tlckJhc2VUeXBlLFxuICBUeXBlSW5mbyxcbiAgVHlwZUluZm9HZW4sXG59IGZyb20gXCIuLi9UeXBlQ2hlY2tlclwiXG5pbXBvcnQgeyBUeXBlQ2hlY2tFcnJvciB9IGZyb20gXCIuLi9UeXBlQ2hlY2tFcnJvclwiXG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBhbiBvYmplY3QtbGlrZSBtYXAsIGFuIG9iamVjdCB3aXRoIHN0cmluZyBrZXlzIGFuZCB2YWx1ZXMgYWxsIG9mIGEgc2FtZSBnaXZlbiB0eXBlLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogLy8geyBbazogc3RyaW5nXTogbnVtYmVyIH1cbiAqIGNvbnN0IG51bWJlck1hcFR5cGUgPSB0eXBlcy5yZWNvcmQodHlwZXMubnVtYmVyKVxuICogYGBgXG4gKlxuICogQHR5cGVwYXJhbSBUIFR5cGUuXG4gKiBAcGFyYW0gdmFsdWVUeXBlIFR5cGUgb2YgdGhlIHZhbHVlcyBvZiB0aGUgb2JqZWN0LWxpa2UgbWFwLlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGVzUmVjb3JkPFQgZXh0ZW5kcyBBbnlUeXBlPih2YWx1ZVR5cGU6IFQpOiBSZWNvcmRUeXBlPFQ+IHtcbiAgY29uc3QgdHlwZUluZm9HZW46IFR5cGVJbmZvR2VuID0gKHRjKSA9PiBuZXcgUmVjb3JkVHlwZUluZm8odGMsIHJlc29sdmVTdGFuZGFyZFR5cGUodmFsdWVUeXBlKSlcblxuICByZXR1cm4gbGF0ZVR5cGVDaGVja2VyKCgpID0+IHtcbiAgICBjb25zdCB2YWx1ZUNoZWNrZXIgPSByZXNvbHZlVHlwZUNoZWNrZXIodmFsdWVUeXBlKVxuXG4gICAgY29uc3QgZ2V0VHlwZU5hbWUgPSAoLi4ucmVjdXJzaXZlVHlwZUNoZWNrZXJzOiBUeXBlQ2hlY2tlcltdKSA9PlxuICAgICAgYFJlY29yZDwke3ZhbHVlQ2hlY2tlci5nZXRUeXBlTmFtZSguLi5yZWN1cnNpdmVUeXBlQ2hlY2tlcnMsIHZhbHVlQ2hlY2tlcil9PmBcblxuICAgIGNvbnN0IGFwcGx5U25hcHNob3RQcm9jZXNzb3IgPSAob2JqOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgbW9kZTogXCJmcm9tXCIgfCBcInRvXCIpID0+IHtcbiAgICAgIGlmICh2YWx1ZUNoZWNrZXIudW5jaGVja2VkKSB7XG4gICAgICAgIHJldHVybiBvYmpcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmV3T2JqOiB0eXBlb2Ygb2JqID0ge31cblxuICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iailcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBrID0ga2V5c1tpXVxuICAgICAgICBjb25zdCB2ID1cbiAgICAgICAgICBtb2RlID09PSBcImZyb21cIlxuICAgICAgICAgICAgPyB2YWx1ZUNoZWNrZXIuZnJvbVNuYXBzaG90UHJvY2Vzc29yKG9ialtrXSlcbiAgICAgICAgICAgIDogdmFsdWVDaGVja2VyLnRvU25hcHNob3RQcm9jZXNzb3Iob2JqW2tdKVxuICAgICAgICBuZXdPYmpba10gPSB2XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXdPYmpcbiAgICB9XG5cbiAgICBjb25zdCB0aGlzVGM6IFR5cGVDaGVja2VyID0gbmV3IFR5cGVDaGVja2VyKFxuICAgICAgVHlwZUNoZWNrZXJCYXNlVHlwZS5PYmplY3QsXG5cbiAgICAgIChvYmosIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+IHtcbiAgICAgICAgaWYgKCFpc09iamVjdChvYmopKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCBnZXRUeXBlTmFtZSh0aGlzVGMpLCBvYmosIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXZhbHVlQ2hlY2tlci51bmNoZWNrZWQpIHtcbiAgICAgICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMob2JqKVxuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgayA9IGtleXNbaV1cbiAgICAgICAgICAgIGNvbnN0IHYgPSBvYmpba11cbiAgICAgICAgICAgIGNvbnN0IHZhbHVlRXJyb3IgPSB2YWx1ZUNoZWNrZXIuY2hlY2sodiwgWy4uLnBhdGgsIGtdLCB0eXBlQ2hlY2tlZFZhbHVlKVxuICAgICAgICAgICAgaWYgKHZhbHVlRXJyb3IpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlRXJyb3JcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgfSxcblxuICAgICAgZ2V0VHlwZU5hbWUsXG4gICAgICB0eXBlSW5mb0dlbixcblxuICAgICAgKG9iaikgPT4ge1xuICAgICAgICBpZiAoIWlzT2JqZWN0KG9iaikpIHJldHVybiBudWxsXG5cbiAgICAgICAgaWYgKCF2YWx1ZUNoZWNrZXIudW5jaGVja2VkKSB7XG4gICAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iailcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGsgPSBrZXlzW2ldXG4gICAgICAgICAgICBjb25zdCB2ID0gb2JqW2tdXG4gICAgICAgICAgICBjb25zdCB2YWx1ZUFjdHVhbENoZWNrZXIgPSB2YWx1ZUNoZWNrZXIuc25hcHNob3RUeXBlKHYpXG4gICAgICAgICAgICBpZiAoIXZhbHVlQWN0dWFsQ2hlY2tlcikge1xuICAgICAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzVGNcbiAgICAgIH0sXG5cbiAgICAgIChvYmo6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB7XG4gICAgICAgIHJldHVybiBhcHBseVNuYXBzaG90UHJvY2Vzc29yKG9iaiwgXCJmcm9tXCIpXG4gICAgICB9LFxuXG4gICAgICAob2JqOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xuICAgICAgICByZXR1cm4gYXBwbHlTbmFwc2hvdFByb2Nlc3NvcihvYmosIFwidG9cIilcbiAgICAgIH1cbiAgICApXG5cbiAgICByZXR1cm4gdGhpc1RjXG4gIH0sIHR5cGVJbmZvR2VuKSBhcyBhbnlcbn1cblxuLyoqXG4gKiBgdHlwZXMucmVjb3JkYCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRUeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHtcbiAgZ2V0IHZhbHVlVHlwZUluZm8oKTogVHlwZUluZm8ge1xuICAgIHJldHVybiBnZXRUeXBlSW5mbyh0aGlzLnZhbHVlVHlwZSlcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHRoaXNUeXBlOiBBbnlTdGFuZGFyZFR5cGUsIHJlYWRvbmx5IHZhbHVlVHlwZTogQW55U3RhbmRhcmRUeXBlKSB7XG4gICAgc3VwZXIodGhpc1R5cGUpXG4gIH1cbn1cbiIsImltcG9ydCB7IGVudHJpZXMsIGdldCwgaGFzLCBrZXlzLCByZW1vdmUsIHZhbHVlcyB9IGZyb20gXCJtb2J4XCJcbmltcG9ydCB7IG1vZGVsQWN0aW9uIH0gZnJvbSBcIi4uL2FjdGlvbi9tb2RlbEFjdGlvblwiXG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9Nb2RlbFwiXG5pbXBvcnQgeyBtb2RlbElkS2V5IH0gZnJvbSBcIi4uL21vZGVsL21ldGFkYXRhXCJcbmltcG9ydCB7IG1vZGVsIH0gZnJvbSBcIi4uL21vZGVsU2hhcmVkL21vZGVsRGVjb3JhdG9yXCJcbmltcG9ydCB7IGlkUHJvcCB9IGZyb20gXCIuLi9tb2RlbFNoYXJlZC9wcm9wXCJcbmltcG9ydCB7IHR5cGVzUmVjb3JkIH0gZnJvbSBcIi4uL3R5cGVzL29iamVjdEJhc2VkL3R5cGVzUmVjb3JkXCJcbmltcG9ydCB7IHRQcm9wIH0gZnJvbSBcIi4uL3R5cGVzL3RQcm9wXCJcbmltcG9ydCB7IHR5cGVzVW5jaGVja2VkIH0gZnJvbSBcIi4uL3R5cGVzL3V0aWxpdHkvdHlwZXNVbmNoZWNrZWRcIlxuaW1wb3J0IHsgbmFtZXNwYWNlIH0gZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IHNldElmRGlmZmVyZW50IH0gZnJvbSBcIi4uL3V0aWxzL3NldElmRGlmZmVyZW50XCJcblxuLyoqXG4gKiBBIG1hcCB0aGF0IGlzIGJhY2tlZCBieSBhbiBvYmplY3QtbGlrZSBtYXAuXG4gKiBVc2UgYG9iamVjdE1hcGAgdG8gY3JlYXRlIGl0LlxuICovXG5AbW9kZWwoYCR7bmFtZXNwYWNlfS9PYmplY3RNYXBgKVxuZXhwb3J0IGNsYXNzIE9iamVjdE1hcDxWPlxuICBleHRlbmRzIE1vZGVsKHtcbiAgICBbbW9kZWxJZEtleV06IGlkUHJvcCxcbiAgICBpdGVtczogdFByb3AodHlwZXNSZWNvcmQodHlwZXNVbmNoZWNrZWQ8YW55PigpKSwgKCkgPT4gKHt9KSksIC8vIHdpbGwgYmUgcHJvcGVybHkgY2hlY2tlZCBieSB0eXBlcy5vYmplY3RNYXAoc3ViVHlwZSlcbiAgfSlcbiAgaW1wbGVtZW50cyBNYXA8c3RyaW5nLCBWPlxue1xuICBAbW9kZWxBY3Rpb25cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zXG5cbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoaXRlbXMpXG4gICAgY29uc3QgbGVuID0ga2V5cy5sZW5ndGhcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBjb25zdCBrID0ga2V5c1tpXVxuICAgICAgcmVtb3ZlKGl0ZW1zLCBrKVxuICAgIH1cbiAgfVxuXG4gIEBtb2RlbEFjdGlvblxuICBkZWxldGUoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBoYXNLZXkgPSB0aGlzLmhhcyhrZXkpXG4gICAgaWYgKGhhc0tleSkge1xuICAgICAgcmVtb3ZlKHRoaXMuaXRlbXMsIGtleSlcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIGZvckVhY2goY2FsbGJhY2tmbjogKHZhbHVlOiBWLCBrZXk6IHN0cmluZywgbWFwOiBNYXA8c3RyaW5nLCBWPikgPT4gdm9pZCwgdGhpc0FyZz86IGFueSk6IHZvaWQge1xuICAgIC8vIHdlIGNhbm5vdCB1c2UgdGhlIG1hcCBpbXBsZW1lbnRhdGlvbiBzaW5jZSB3ZSBuZWVkIHRvIHBhc3MgdGhpcyBhcyBtYXBcbiAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXNcblxuICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhpdGVtcylcbiAgICBjb25zdCBsZW4gPSBrZXlzLmxlbmd0aFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGNvbnN0IGsgPSBrZXlzW2ldXG4gICAgICBjYWxsYmFja2ZuLmNhbGwodGhpc0FyZywgaXRlbXNba10sIGssIHRoaXMpXG4gICAgfVxuICB9XG5cbiAgZ2V0KGtleTogc3RyaW5nKTogViB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGdldCh0aGlzLml0ZW1zLCBrZXkpXG4gIH1cblxuICBoYXMoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaGFzKHRoaXMuaXRlbXMsIGtleSlcbiAgfVxuXG4gIEBtb2RlbEFjdGlvblxuICBzZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWKTogdGhpcyB7XG4gICAgc2V0SWZEaWZmZXJlbnQodGhpcy5pdGVtcywga2V5LCB2YWx1ZSlcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgZ2V0IHNpemUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4ga2V5cyh0aGlzLml0ZW1zKS5sZW5ndGhcbiAgfVxuXG4gIGtleXMoKTogSXRlcmFibGVJdGVyYXRvcjxzdHJpbmc+IHtcbiAgICAvLyBUT0RPOiBzaG91bGQgdXNlIGFuIGFjdHVhbCBpdGVyYXRvclxuICAgIHJldHVybiBrZXlzKHRoaXMuaXRlbXMpW1N5bWJvbC5pdGVyYXRvcl0oKSBhcyBJdGVyYWJsZUl0ZXJhdG9yPHN0cmluZz5cbiAgfVxuXG4gIHZhbHVlcygpOiBJdGVyYWJsZUl0ZXJhdG9yPFY+IHtcbiAgICAvLyBUT0RPOiBzaG91bGQgdXNlIGFuIGFjdHVhbCBpdGVyYXRvclxuICAgIHJldHVybiB2YWx1ZXModGhpcy5pdGVtcylbU3ltYm9sLml0ZXJhdG9yXSgpXG4gIH1cblxuICBlbnRyaWVzKCk6IEl0ZXJhYmxlSXRlcmF0b3I8W3N0cmluZywgVl0+IHtcbiAgICAvLyBUT0RPOiBzaG91bGQgdXNlIGFuIGFjdHVhbCBpdGVyYXRvclxuICAgIHJldHVybiBlbnRyaWVzKHRoaXMuaXRlbXMpW1N5bWJvbC5pdGVyYXRvcl0oKVxuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKTogSXRlcmFibGVJdGVyYXRvcjxbc3RyaW5nLCBWXT4ge1xuICAgIHJldHVybiB0aGlzLmVudHJpZXMoKVxuICB9XG5cbiAgZ2V0IFtTeW1ib2wudG9TdHJpbmdUYWddKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFwiT2JqZWN0TWFwXCJcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgT2JqZWN0TWFwIG1vZGVsIGluc3RhbmNlLlxuICpcbiAqIEB0eXBlcGFyYW0gViBWYWx1ZSB0eXBlLlxuICogQHBhcmFtIFtlbnRyaWVzXSBPcHRpb25hbCBpbml0aWFsIHZhbHVlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9iamVjdE1hcDxWPihlbnRyaWVzPzogUmVhZG9ubHlBcnJheTxyZWFkb25seSBbc3RyaW5nLCBWXT4gfCBudWxsKTogT2JqZWN0TWFwPFY+IHtcbiAgY29uc3QgaW5pdGlhbE9iajogeyBbazogc3RyaW5nXTogViB9ID0ge31cblxuICBpZiAoZW50cmllcykge1xuICAgIGxldCBsZW4gPSBlbnRyaWVzLmxlbmd0aFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGNvbnN0IGVudHJ5ID0gZW50cmllc1tpXVxuICAgICAgaW5pdGlhbE9ialtlbnRyeVswXV0gPSBlbnRyeVsxXVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgT2JqZWN0TWFwKHsgaXRlbXM6IGluaXRpYWxPYmogfSlcbn1cbiIsImltcG9ydCB7IG1vZGVsVHlwZUtleSB9IGZyb20gXCIuLi8uLi9tb2RlbC9tZXRhZGF0YVwiXG5pbXBvcnQgeyBtb2RlbEluZm9CeUNsYXNzIH0gZnJvbSBcIi4uLy4uL21vZGVsU2hhcmVkL21vZGVsSW5mb1wiXG5pbXBvcnQgeyBpc09iamVjdCB9IGZyb20gXCIuLi8uLi91dGlsc1wiXG5pbXBvcnQgeyBPYmplY3RNYXAgfSBmcm9tIFwiLi4vLi4vd3JhcHBlcnMvT2JqZWN0TWFwXCJcbmltcG9ydCB7IGdldFR5cGVJbmZvIH0gZnJvbSBcIi4uL2dldFR5cGVJbmZvXCJcbmltcG9ydCB7IHJlc29sdmVTdGFuZGFyZFR5cGUsIHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuLi9yZXNvbHZlVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHR5cGUgeyBBbnlTdGFuZGFyZFR5cGUsIEFueVR5cGUsIE1vZGVsVHlwZSwgVHlwZVRvRGF0YSB9IGZyb20gXCIuLi9zY2hlbWFzXCJcbmltcG9ydCB7XG4gIGxhdGVUeXBlQ2hlY2tlcixcbiAgVHlwZUNoZWNrZXIsXG4gIFR5cGVDaGVja2VyQmFzZVR5cGUsXG4gIFR5cGVJbmZvLFxuICBUeXBlSW5mb0dlbixcbn0gZnJvbSBcIi4uL1R5cGVDaGVja2VyXCJcbmltcG9ydCB7IFR5cGVDaGVja0Vycm9yIH0gZnJvbSBcIi4uL1R5cGVDaGVja0Vycm9yXCJcbmltcG9ydCB7IHR5cGVzT2JqZWN0IH0gZnJvbSBcIi4vdHlwZXNPYmplY3RcIlxuaW1wb3J0IHsgdHlwZXNSZWNvcmQgfSBmcm9tIFwiLi90eXBlc1JlY29yZFwiXG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBhbiBvYmplY3QtbGlrZSBtYXAgT2JqZWN0TWFwLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogY29uc3QgbnVtYmVyTWFwVHlwZSA9IHR5cGVzLm9iamVjdE1hcCh0eXBlcy5udW1iZXIpXG4gKiBgYGBcbiAqXG4gKiBAdHlwZXBhcmFtIFQgVmFsdWUgdHlwZS5cbiAqIEBwYXJhbSB2YWx1ZVR5cGUgVmFsdWUgdHlwZS5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc09iamVjdE1hcDxUIGV4dGVuZHMgQW55VHlwZT4oXG4gIHZhbHVlVHlwZTogVFxuKTogTW9kZWxUeXBlPE9iamVjdE1hcDxUeXBlVG9EYXRhPFQ+Pj4ge1xuICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT4gbmV3IE9iamVjdE1hcFR5cGVJbmZvKHQsIHJlc29sdmVTdGFuZGFyZFR5cGUodmFsdWVUeXBlKSlcblxuICByZXR1cm4gbGF0ZVR5cGVDaGVja2VyKCgpID0+IHtcbiAgICBjb25zdCBtb2RlbEluZm8gPSBtb2RlbEluZm9CeUNsYXNzLmdldChPYmplY3RNYXApIVxuXG4gICAgY29uc3QgdmFsdWVDaGVja2VyID0gcmVzb2x2ZVR5cGVDaGVja2VyKHZhbHVlVHlwZSlcblxuICAgIGNvbnN0IGdldFR5cGVOYW1lID0gKC4uLnJlY3Vyc2l2ZVR5cGVDaGVja2VyczogVHlwZUNoZWNrZXJbXSkgPT5cbiAgICAgIGBPYmplY3RNYXA8JHt2YWx1ZUNoZWNrZXIuZ2V0VHlwZU5hbWUoLi4ucmVjdXJzaXZlVHlwZUNoZWNrZXJzLCB2YWx1ZUNoZWNrZXIpfT5gXG5cbiAgICBjb25zdCBkYXRhVHlwZUNoZWNrZXIgPSB0eXBlc09iamVjdCgoKSA9PiAoe1xuICAgICAgaXRlbXM6IHR5cGVzUmVjb3JkKHZhbHVlQ2hlY2tlciBhcyBhbnkpLFxuICAgIH0pKVxuICAgIGNvbnN0IHJlc29sdmVkRGF0YVR5cGVDaGVja2VyID0gcmVzb2x2ZVR5cGVDaGVja2VyKGRhdGFUeXBlQ2hlY2tlcilcblxuICAgIGNvbnN0IHRoaXNUYzogVHlwZUNoZWNrZXIgPSBuZXcgVHlwZUNoZWNrZXIoXG4gICAgICBUeXBlQ2hlY2tlckJhc2VUeXBlLk9iamVjdCxcblxuICAgICAgKG9iaiwgcGF0aCwgdHlwZUNoZWNrZWRWYWx1ZSkgPT4ge1xuICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBPYmplY3RNYXApKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCBnZXRUeXBlTmFtZSh0aGlzVGMpLCBvYmosIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzb2x2ZWREYXRhVHlwZUNoZWNrZXIuY2hlY2sob2JqLiQsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICB9LFxuXG4gICAgICBnZXRUeXBlTmFtZSxcbiAgICAgIHR5cGVJbmZvR2VuLFxuXG4gICAgICAob2JqKSA9PiB7XG4gICAgICAgIGlmICghaXNPYmplY3Qob2JqKSkge1xuICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgIH1cblxuICAgICAgICBpZiAob2JqW21vZGVsVHlwZUtleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIC8vIGZhc3QgY2hlY2tcbiAgICAgICAgICByZXR1cm4gb2JqW21vZGVsVHlwZUtleV0gPT09IG1vZGVsSW5mby5uYW1lID8gdGhpc1RjIDogbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc29sdmVkRGF0YVR5cGVDaGVja2VyLnNuYXBzaG90VHlwZShvYmopID8gdGhpc1RjIDogbnVsbFxuICAgICAgfSxcblxuICAgICAgKHNuOiB7IGl0ZW1zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9KSA9PiB7XG4gICAgICAgIGNvbnN0IG5ld0l0ZW1zOiAodHlwZW9mIHNuKVtcIml0ZW1zXCJdID0ge31cblxuICAgICAgICBmb3IgKGNvbnN0IGsgb2YgT2JqZWN0LmtleXMoc24uaXRlbXMpKSB7XG4gICAgICAgICAgbmV3SXRlbXNba10gPSB2YWx1ZUNoZWNrZXIuZnJvbVNuYXBzaG90UHJvY2Vzc29yKHNuLml0ZW1zW2tdKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5zbixcbiAgICAgICAgICBbbW9kZWxUeXBlS2V5XTogbW9kZWxJbmZvLm5hbWUsXG4gICAgICAgICAgaXRlbXM6IG5ld0l0ZW1zLFxuICAgICAgICB9XG4gICAgICB9LFxuXG4gICAgICAoc246IHsgaXRlbXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+OyBbbW9kZWxUeXBlS2V5XT86IHN0cmluZyB9KSA9PiB7XG4gICAgICAgIGNvbnN0IG5ld0l0ZW1zOiAodHlwZW9mIHNuKVtcIml0ZW1zXCJdID0ge31cblxuICAgICAgICBmb3IgKGNvbnN0IGsgb2YgT2JqZWN0LmtleXMoc24uaXRlbXMpKSB7XG4gICAgICAgICAgbmV3SXRlbXNba10gPSB2YWx1ZUNoZWNrZXIudG9TbmFwc2hvdFByb2Nlc3Nvcihzbi5pdGVtc1trXSlcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNuQ29weSA9IHtcbiAgICAgICAgICAuLi5zbixcbiAgICAgICAgICBpdGVtczogbmV3SXRlbXMsXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc25Db3B5XG4gICAgICB9XG4gICAgKVxuXG4gICAgcmV0dXJuIHRoaXNUY1xuICB9LCB0eXBlSW5mb0dlbikgYXMgYW55XG59XG5cbi8qKlxuICogYHR5cGVzLm9iamVjdE1hcGAgdHlwZSBpbmZvLlxuICovXG5leHBvcnQgY2xhc3MgT2JqZWN0TWFwVHlwZUluZm8gZXh0ZW5kcyBUeXBlSW5mbyB7XG4gIGdldCB2YWx1ZVR5cGVJbmZvKCk6IFR5cGVJbmZvIHtcbiAgICByZXR1cm4gZ2V0VHlwZUluZm8odGhpcy52YWx1ZVR5cGUpXG4gIH1cblxuICBjb25zdHJ1Y3Rvcih0aGlzVHlwZTogQW55U3RhbmRhcmRUeXBlLCByZWFkb25seSB2YWx1ZVR5cGU6IEFueVN0YW5kYXJkVHlwZSkge1xuICAgIHN1cGVyKHRoaXNUeXBlKVxuICB9XG59XG4iLCJpbXBvcnQgeyBtb2RlbFR5cGVLZXkgfSBmcm9tIFwiLi4vLi4vbW9kZWwvbWV0YWRhdGFcIlxuaW1wb3J0IHsgbW9kZWxJbmZvQnlDbGFzcyB9IGZyb20gXCIuLi8uLi9tb2RlbFNoYXJlZC9tb2RlbEluZm9cIlxuaW1wb3J0IHsgUmVmLCBSZWZDb25zdHJ1Y3RvciB9IGZyb20gXCIuLi8uLi9yZWYvUmVmXCJcbmltcG9ydCB7IGlzT2JqZWN0IH0gZnJvbSBcIi4uLy4uL3V0aWxzXCJcbmltcG9ydCB7IHR5cGVzU3RyaW5nIH0gZnJvbSBcIi4uL3ByaW1pdGl2ZUJhc2VkL3R5cGVzUHJpbWl0aXZlXCJcbmltcG9ydCB7IHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuLi9yZXNvbHZlVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHR5cGUgeyBNb2RlbFR5cGUgfSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQgeyBUeXBlQ2hlY2tlciwgVHlwZUNoZWNrZXJCYXNlVHlwZSwgVHlwZUluZm8gfSBmcm9tIFwiLi4vVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHsgVHlwZUNoZWNrRXJyb3IgfSBmcm9tIFwiLi4vVHlwZUNoZWNrRXJyb3JcIlxuaW1wb3J0IHsgdHlwZXNPYmplY3QgfSBmcm9tIFwiLi90eXBlc09iamVjdFwiXG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBhIHJlZmVyZW5jZSB0byBhbiBvYmplY3Qgb3IgbW9kZWwuXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYHRzXG4gKiBjb25zdCByZWZUb1NvbWVPYmplY3QgPSB0eXBlcy5yZWYoU29tZU9iamVjdClcbiAqIGBgYFxuICpcbiAqIEB0eXBlcGFyYW0gTyBPYmplY3Qgb3IgbW9kZWwgdHlwZS5cbiAqIEBwYXJhbSByZWZDb25zdHJ1Y3RvciBSZWYgb2JqZWN0IHR5cGUuXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHlwZXNSZWY8TyBleHRlbmRzIG9iamVjdD4ocmVmQ29uc3RydWN0b3I6IFJlZkNvbnN0cnVjdG9yPE8+KTogTW9kZWxUeXBlPFJlZjxPPj4ge1xuICBjb25zdCB0eXBlTmFtZSA9IFwiUmVmXCJcblxuICBjb25zdCBtb2RlbEluZm8gPSBtb2RlbEluZm9CeUNsYXNzLmdldChyZWZDb25zdHJ1Y3Rvci5yZWZDbGFzcykhXG5cbiAgY29uc3QgcmVmRGF0YVR5cGVDaGVja2VyID0gcmVzb2x2ZVR5cGVDaGVja2VyKFxuICAgIHR5cGVzT2JqZWN0KCgpID0+ICh7XG4gICAgICBpZDogdHlwZXNTdHJpbmcsXG4gICAgfSkpXG4gIClcblxuICBjb25zdCB0aGlzVGM6IFR5cGVDaGVja2VyID0gbmV3IFR5cGVDaGVja2VyKFxuICAgIFR5cGVDaGVja2VyQmFzZVR5cGUuT2JqZWN0LFxuXG4gICAgKHZhbHVlLCBwYXRoLCB0eXBlQ2hlY2tlZFZhbHVlKSA9PiB7XG4gICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIFJlZikpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUeXBlQ2hlY2tFcnJvcihwYXRoLCB0eXBlTmFtZSwgdmFsdWUsIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZWZEYXRhVHlwZUNoZWNrZXIuY2hlY2sodmFsdWUuJCwgcGF0aCwgdHlwZUNoZWNrZWRWYWx1ZSlcbiAgICB9LFxuXG4gICAgKCkgPT4gdHlwZU5hbWUsXG4gICAgKHQpID0+IG5ldyBSZWZUeXBlSW5mbyh0KSxcblxuICAgIChvYmopID0+IHtcbiAgICAgIGlmICghaXNPYmplY3Qob2JqKSkge1xuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgfVxuXG4gICAgICBpZiAob2JqW21vZGVsVHlwZUtleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBmYXN0IGNoZWNrXG4gICAgICAgIHJldHVybiBvYmpbbW9kZWxUeXBlS2V5XSA9PT0gbW9kZWxJbmZvLm5hbWUgPyB0aGlzVGMgOiBudWxsXG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZWZEYXRhVHlwZUNoZWNrZXIuc25hcHNob3RUeXBlKG9iaikgPyB0aGlzVGMgOiBudWxsXG4gICAgfSxcblxuICAgIChzbjogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHtcbiAgICAgIGlmIChzblttb2RlbFR5cGVLZXldKSB7XG4gICAgICAgIHJldHVybiBzblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5zbixcbiAgICAgICAgICBbbW9kZWxUeXBlS2V5XTogbW9kZWxJbmZvLm5hbWUsXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgKHNuKSA9PiBzblxuICApXG5cbiAgcmV0dXJuIHRoaXNUYyBhcyBhbnlcbn1cblxuLyoqXG4gKiBgdHlwZXMucmVmYCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWZUeXBlSW5mbyBleHRlbmRzIFR5cGVJbmZvIHt9XG4iLCJpbXBvcnQgeyBhc3NlcnRJc09iamVjdCB9IGZyb20gXCIuLi8uLi91dGlsc1wiXG5pbXBvcnQgdHlwZSB7IElkZW50aXR5VHlwZSB9IGZyb20gXCIuLi9zY2hlbWFzXCJcbmltcG9ydCB7IHR5cGVzT3IgfSBmcm9tIFwiLi4vdXRpbGl0eS90eXBlc09yXCJcbmltcG9ydCB7IHR5cGVzTGl0ZXJhbCB9IGZyb20gXCIuL3R5cGVzUHJpbWl0aXZlXCJcblxuLyoqXG4gKiBAaWdub3JlXG4gKiBFbnVtIGxpa2Ugb2JqZWN0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVudW1MaWtlIHtcbiAgW2s6IHN0cmluZ106IG51bWJlciB8IHN0cmluZ1xuICBbdjogbnVtYmVyXTogc3RyaW5nXG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnVtVmFsdWVzKGU6IEVudW1MaWtlKTogKHN0cmluZyB8IG51bWJlcilbXSB7XG4gIGNvbnN0IHZhbHM6IChzdHJpbmcgfCBudW1iZXIpW10gPSBbXVxuICBmb3IgKGNvbnN0IGsgb2YgT2JqZWN0LmtleXMoZSkpIHtcbiAgICBjb25zdCB2ID0gZVtrXVxuICAgIC8vIHdlIGhhdmUgdG8gZG8gdGhpcyBzaW5jZSBUUyBkb2VzIHNvbWV0aGluZyB3ZWlyZFxuICAgIC8vIHRvIG51bWJlciB2YWx1ZXNcbiAgICAvLyBIaSA9IDAgLT4geyBIaTogMCwgMDogXCJIaVwiIH1cbiAgICAvLyBhbmQgU1dDIGN1cnJlbnRseSBnZW5lcmF0ZXMgZW51bSBjb2RlIGluY29uc2lzdGVudCB3aXRoIFRTL0JhYmVsXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3N3Yy1wcm9qZWN0L3N3Yy9pc3N1ZXMvMzcxMVxuICAgIGlmICghdmFscy5pbmNsdWRlcyh2KSAmJiAoKHR5cGVvZiB2ICE9PSBcInN0cmluZ1wiICYmIHYgIT09ICtrKSB8fCBlW3ZdICE9PSAraykpIHtcbiAgICAgIHZhbHMucHVzaCh2KVxuICAgIH1cbiAgfVxuICByZXR1cm4gdmFsc1xufVxuXG4vKipcbiAqIEBpZ25vcmVcbiAqIEV4dHJhY3QgZW51bSB2YWx1ZXMgb3V0IG9mIGEgZW51bSBvYmplY3QuXG4gKi9cbmV4cG9ydCB0eXBlIEVudW1WYWx1ZXM8RSBleHRlbmRzIEVudW1MaWtlPiA9IEUgZXh0ZW5kcyBSZWNvcmQ8XG4gIGluZmVyIF9LLCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBpbmZlciBWXG4+XG4gID8gVlxuICA6IG5ldmVyXG5cbi8qKlxuICogQW4gZW51bSB0eXBlLCBiYXNlZCBvbiBhIFR5cGVTY3JpcHQgYWxpa2UgZW51bSBvYmplY3QuXG4gKiBTeW50YWN0aWMgc3VnYXIgZm9yIGB0eXBlcy5vciguLi5lbnVtX3ZhbHVlcy5tYXAodHlwZXMubGl0ZXJhbCkpYFxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogZW51bSBDb2xvciB7XG4gKiAgIFJlZCA9IFwicmVkXCIsXG4gKiAgIEdyZWVuID0gXCJncmVlblwiXG4gKiB9XG4gKlxuICogY29uc3QgY29sb3JUeXBlID0gdHlwZXMuZW51bShDb2xvcilcbiAqIGBgYFxuICpcbiAqIEB0eXBlcGFyYW0gRSBFbnVtIHR5cGUuXG4gKiBAcGFyYW0gZW51bU9iamVjdFxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGVzRW51bTxFIGV4dGVuZHMgRW51bUxpa2U+KGVudW1PYmplY3Q6IEUpOiBJZGVudGl0eVR5cGU8RW51bVZhbHVlczxFPj4ge1xuICBhc3NlcnRJc09iamVjdChlbnVtT2JqZWN0LCBcImVudW1PYmplY3RcIilcblxuICBjb25zdCBsaXRlcmFscyA9IGVudW1WYWx1ZXMoZW51bU9iamVjdCkubWFwKChlKSA9PiB0eXBlc0xpdGVyYWwoZSkpXG4gIHJldHVybiB0eXBlc09yKC4uLmxpdGVyYWxzKSBhcyBhbnlcbn1cbiIsImltcG9ydCB7IGdldFR5cGVJbmZvIH0gZnJvbSBcIi4uL2dldFR5cGVJbmZvXCJcbmltcG9ydCB7IHJlc29sdmVTdGFuZGFyZFR5cGUsIHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuLi9yZXNvbHZlVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHR5cGUgeyBBbnlTdGFuZGFyZFR5cGUsIEFueVR5cGUsIFR5cGVUb0RhdGEgfSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQgeyBsYXRlVHlwZUNoZWNrZXIsIFR5cGVDaGVja2VyLCBUeXBlSW5mbywgVHlwZUluZm9HZW4gfSBmcm9tIFwiLi4vVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHsgVHlwZUNoZWNrRXJyb3IgfSBmcm9tIFwiLi4vVHlwZUNoZWNrRXJyb3JcIlxuXG4vKipcbiAqIEEgcmVmaW5lbWVudCBvdmVyIGEgZ2l2ZW4gdHlwZS4gVGhpcyBhbGxvd3MgeW91IHRvIGRvIGV4dHJhIGNoZWNrc1xuICogb3ZlciBtb2RlbHMsIGVuc3VyZSBudW1iZXJzIGFyZSBpbnRlZ2VycywgZXRjLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogY29uc3QgaW50ZWdlclR5cGUgPSB0eXBlcy5yZWZpbmVtZW50KHR5cGVzLm51bWJlciwgKG4pID0+IHtcbiAqICAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIobilcbiAqIH0sIFwiaW50ZWdlclwiKVxuICpcbiAqIGNvbnN0IHN1bU1vZGVsVHlwZSA9IHR5cGVzLnJlZmluZW1lbnQodHlwZXMubW9kZWwoU3VtKSwgKHN1bSkgPT4ge1xuICogICAvLyBpbWFnaW5lIHRoYXQgZm9yIHNvbWUgcmVhc29uIHN1bSBpbmNsdWRlcyBhIG51bWJlciAnYScsIGEgbnVtYmVyICdiJ1xuICogICAvLyBhbmQgdGhlIHJlc3VsdFxuICpcbiAqICAgY29uc3QgcmlnaHRSZXN1bHQgPSBzdW0uYSArIHN1bS5iID09PSBzdW0ucmVzdWx0XG4gKlxuICogICAvLyBzaW1wbGUgbW9kZSB0aGF0IHdpbGwganVzdCByZXR1cm4gdGhhdCB0aGUgd2hvbGUgbW9kZWwgaXMgaW5jb3JyZWN0XG4gKiAgIHJldHVybiByaWdodFJlc3VsdFxuICpcbiAqICAgLy8gdGhpcyB3aWxsIHJldHVybiB0aGF0IHRoZSByZXN1bHQgZmllbGQgaXMgd3JvbmdcbiAqICAgcmV0dXJuIHJpZ2h0UmVzdWx0ID8gbnVsbCA6IG5ldyBUeXBlQ2hlY2tFcnJvcihbXCJyZXN1bHRcIl0sIFwiYStiXCIsIHN1bS5yZXN1bHQpXG4gKiB9KVxuICogYGBgXG4gKlxuICogQHR5cGVwYXJhbSBUIEJhc2UgdHlwZS5cbiAqIEBwYXJhbSBiYXNlVHlwZSBCYXNlIHR5cGUuXG4gKiBAcGFyYW0gY2hlY2tGbiBGdW5jdGlvbiB0aGF0IHdpbGwgcmVjZWl2ZSB0aGUgZGF0YSAoaWYgaXQgcGFzc2VzIHRoZSBiYXNlIHR5cGVcbiAqIGNoZWNrKSBhbmQgcmV0dXJuIG51bGwgb3IgZmFsc2UgaWYgdGhlcmUgd2VyZSBubyBlcnJvcnMgb3IgZWl0aGVyIGEgVHlwZUNoZWNrRXJyb3IgaW5zdGFuY2Ugb3JcbiAqIHRydWUgaWYgdGhlcmUgd2VyZS5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc1JlZmluZW1lbnQ8VCBleHRlbmRzIEFueVR5cGU+KFxuICBiYXNlVHlwZTogVCxcbiAgY2hlY2tGbjogKGRhdGE6IFR5cGVUb0RhdGE8VD4pID0+IFR5cGVDaGVja0Vycm9yIHwgbnVsbCB8IGJvb2xlYW4sXG4gIHR5cGVOYW1lPzogc3RyaW5nXG4pOiBUIHtcbiAgY29uc3QgdHlwZUluZm9HZW46IFR5cGVJbmZvR2VuID0gKHQpID0+XG4gICAgbmV3IFJlZmluZW1lbnRUeXBlSW5mbyh0LCByZXNvbHZlU3RhbmRhcmRUeXBlKGJhc2VUeXBlKSwgY2hlY2tGbiwgdHlwZU5hbWUpXG5cbiAgcmV0dXJuIGxhdGVUeXBlQ2hlY2tlcigoKSA9PiB7XG4gICAgY29uc3QgYmFzZUNoZWNrZXIgPSByZXNvbHZlVHlwZUNoZWNrZXIoYmFzZVR5cGUpXG5cbiAgICBjb25zdCBnZXRUeXBlTmFtZSA9ICguLi5yZWN1cnNpdmVUeXBlQ2hlY2tlcnM6IFR5cGVDaGVja2VyW10pID0+IHtcbiAgICAgIGNvbnN0IGJhc2VUeXBlTmFtZSA9IGJhc2VDaGVja2VyLmdldFR5cGVOYW1lKC4uLnJlY3Vyc2l2ZVR5cGVDaGVja2VycywgYmFzZUNoZWNrZXIpXG4gICAgICBjb25zdCByZWZpbmVtZW50TmFtZSA9IHR5cGVOYW1lIHx8IFwicmVmaW5lbWVudE9mXCJcbiAgICAgIHJldHVybiBgJHtyZWZpbmVtZW50TmFtZX08JHtiYXNlVHlwZU5hbWV9PmBcbiAgICB9XG5cbiAgICBjb25zdCB0aGlzVGM6IFR5cGVDaGVja2VyID0gbmV3IFR5cGVDaGVja2VyKFxuICAgICAgYmFzZUNoZWNrZXIuYmFzZVR5cGUsXG5cbiAgICAgIChkYXRhLCBwYXRoLCB0eXBlQ2hlY2tlZFZhbHVlKSA9PiB7XG4gICAgICAgIGNvbnN0IGJhc2VFcnIgPSBiYXNlQ2hlY2tlci5jaGVjayhkYXRhLCBwYXRoLCB0eXBlQ2hlY2tlZFZhbHVlKVxuICAgICAgICBpZiAoYmFzZUVycikge1xuICAgICAgICAgIHJldHVybiBiYXNlRXJyXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZWZpbmVtZW50RXJyID0gY2hlY2tGbihkYXRhKVxuXG4gICAgICAgIGlmIChyZWZpbmVtZW50RXJyID09PSB0cnVlIHx8IHJlZmluZW1lbnRFcnIgPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgIH0gZWxzZSBpZiAocmVmaW5lbWVudEVyciA9PT0gZmFsc2UpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFR5cGVDaGVja0Vycm9yKHBhdGgsIGdldFR5cGVOYW1lKHRoaXNUYyksIGRhdGEsIHR5cGVDaGVja2VkVmFsdWUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gb3ZlcnJpZGUgdHlwZUNoZWNrZWRWYWx1ZVxuICAgICAgICAgIHJldHVybiBuZXcgVHlwZUNoZWNrRXJyb3IoXG4gICAgICAgICAgICByZWZpbmVtZW50RXJyLnBhdGgsXG4gICAgICAgICAgICByZWZpbmVtZW50RXJyLmV4cGVjdGVkVHlwZU5hbWUsXG4gICAgICAgICAgICByZWZpbmVtZW50RXJyLmFjdHVhbFZhbHVlLFxuICAgICAgICAgICAgdHlwZUNoZWNrZWRWYWx1ZVxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfSxcblxuICAgICAgZ2V0VHlwZU5hbWUsXG4gICAgICB0eXBlSW5mb0dlbixcblxuICAgICAgLy8gd2UgY2Fubm90IGNoZWNrIHJlZmluZW1lbnQgaGVyZSBzaW5jZSBpdCBjaGVja3MgZGF0YSBpbnN0YW5jZXMsIG5vdCBzbmFwc2hvdHNcbiAgICAgIChzbikgPT4gYmFzZUNoZWNrZXIuc25hcHNob3RUeXBlKHNuKSxcblxuICAgICAgKHNuKSA9PiBiYXNlQ2hlY2tlci5mcm9tU25hcHNob3RQcm9jZXNzb3Ioc24pLFxuICAgICAgKHNuKSA9PiBiYXNlQ2hlY2tlci50b1NuYXBzaG90UHJvY2Vzc29yKHNuKVxuICAgIClcblxuICAgIHJldHVybiB0aGlzVGNcbiAgfSwgdHlwZUluZm9HZW4pIGFzIGFueVxufVxuXG4vKipcbiAqIGB0eXBlcy5yZWZpbmVtZW50YCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWZpbmVtZW50VHlwZUluZm8gZXh0ZW5kcyBUeXBlSW5mbyB7XG4gIGdldCBiYXNlVHlwZUluZm8oKTogVHlwZUluZm8ge1xuICAgIHJldHVybiBnZXRUeXBlSW5mbyh0aGlzLmJhc2VUeXBlKVxuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgdGhpc1R5cGU6IEFueVN0YW5kYXJkVHlwZSxcbiAgICByZWFkb25seSBiYXNlVHlwZTogQW55U3RhbmRhcmRUeXBlLFxuICAgIHJlYWRvbmx5IGNoZWNrRnVuY3Rpb246IChkYXRhOiBhbnkpID0+IFR5cGVDaGVja0Vycm9yIHwgbnVsbCB8IGJvb2xlYW4sXG4gICAgcmVhZG9ubHkgdHlwZU5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZFxuICApIHtcbiAgICBzdXBlcih0aGlzVHlwZSlcbiAgfVxufVxuIiwiaW1wb3J0IHsgdHlwZXNSZWZpbmVtZW50IH0gZnJvbSBcIi4uL3V0aWxpdHkvdHlwZXNSZWZpbmVtZW50XCJcbmltcG9ydCB7IHR5cGVzTnVtYmVyLCB0eXBlc1N0cmluZyB9IGZyb20gXCIuL3R5cGVzUHJpbWl0aXZlXCJcblxuLyoqXG4gKiBBIHR5cGUgdGhhdCByZXByZXNlbnRzIGFueSBpbnRlZ2VyIG51bWJlciB2YWx1ZS5cbiAqIFN5bnRhY3RpYyBzdWdhciBmb3IgYHR5cGVzLnJlZmluZW1lbnQodHlwZXMubnVtYmVyLCBuID0+IE51bWJlci5pc0ludGVnZXIobiksIFwiaW50ZWdlclwiKWBcbiAqXG4gKiBgYGB0c1xuICogdHlwZXMuaW50ZWdlclxuICogYGBgXG4gKi9cbmV4cG9ydCBjb25zdCB0eXBlc0ludGVnZXIgPSB0eXBlc1JlZmluZW1lbnQodHlwZXNOdW1iZXIsIChuKSA9PiBOdW1iZXIuaXNJbnRlZ2VyKG4pLCBcImludGVnZXJcIilcblxuLyoqXG4gKiBBIHR5cGUgdGhhdCByZXByZXNlbnRzIGFueSBzdHJpbmcgdmFsdWUgb3RoZXIgdGhhbiBcIlwiLlxuICogU3ludGFjdGljIHN1Z2FyIGZvciBgdHlwZXMucmVmaW5lbWVudCh0eXBlcy5zdHJpbmcsIHMgPT4gcyAhPT0gXCJcIiwgXCJub25FbXB0eVwiKWBcbiAqXG4gKiBgYGB0c1xuICogdHlwZXMubm9uRW1wdHlTdHJpbmdcbiAqIGBgYFxuICovXG5leHBvcnQgY29uc3QgdHlwZXNOb25FbXB0eVN0cmluZyA9IHR5cGVzUmVmaW5lbWVudCh0eXBlc1N0cmluZywgKHMpID0+IHMgIT09IFwiXCIsIFwibm9uRW1wdHlcIilcbiIsImltcG9ydCB7IHR5cGVzTnVsbCwgdHlwZXNVbmRlZmluZWQgfSBmcm9tIFwiLi4vcHJpbWl0aXZlQmFzZWQvdHlwZXNQcmltaXRpdmVcIlxuaW1wb3J0IHR5cGUgeyBBbnlUeXBlLCBJZGVudGl0eVR5cGUgfSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQgeyB0eXBlc09yIH0gZnJvbSBcIi4vdHlwZXNPclwiXG5cbi8qKlxuICogQSB0eXBlIHRoYXQgcmVwcmVzZW50cyBlaXRoZXIgYSB0eXBlIG9yIHVuZGVmaW5lZC5cbiAqIFN5bnRhY3RpYyBzdWdhciBmb3IgYHR5cGVzLm9yKGJhc2VUeXBlLCB0eXBlcy51bmRlZmluZWQpYFxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogY29uc3QgbnVtYmVyT3JVbmRlZmluZWRUeXBlID0gdHlwZXMubWF5YmUodHlwZXMubnVtYmVyKVxuICogYGBgXG4gKlxuICogQHR5cGVwYXJhbSBUIFR5cGUuXG4gKiBAcGFyYW0gYmFzZVR5cGUgVHlwZS5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0eXBlc01heWJlPFQgZXh0ZW5kcyBBbnlUeXBlPihiYXNlVHlwZTogVCk6IFQgfCBJZGVudGl0eVR5cGU8dW5kZWZpbmVkPiB7XG4gIHJldHVybiB0eXBlc09yKGJhc2VUeXBlLCB0eXBlc1VuZGVmaW5lZClcbn1cblxuLyoqXG4gKiBBIHR5cGUgdGhhdCByZXByZXNlbnRzIGVpdGhlciBhIHR5cGUgb3IgbnVsbC5cbiAqIFN5bnRhY3RpYyBzdWdhciBmb3IgYHR5cGVzLm9yKGJhc2VUeXBlLCB0eXBlcy5udWxsKWBcbiAqXG4gKiAgKiBFeGFtcGxlOlxuICogYGBgdHNcbiAqIGNvbnN0IG51bWJlck9yTnVsbFR5cGUgPSB0eXBlcy5tYXliZU51bGwodHlwZXMubnVtYmVyKVxuICogYGBgXG4gKlxuICogQHR5cGVwYXJhbSBUIFR5cGUuXG4gKiBAcGFyYW0gdHlwZSBUeXBlLlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGVzTWF5YmVOdWxsPFQgZXh0ZW5kcyBBbnlUeXBlPih0eXBlOiBUKTogVCB8IElkZW50aXR5VHlwZTxudWxsPiB7XG4gIHJldHVybiB0eXBlc09yKHR5cGUsIHR5cGVzTnVsbClcbn1cbiIsImltcG9ydCB7IGdldFR5cGVJbmZvIH0gZnJvbSBcIi4uL2dldFR5cGVJbmZvXCJcbmltcG9ydCB7IHJlc29sdmVTdGFuZGFyZFR5cGUsIHJlc29sdmVUeXBlQ2hlY2tlciB9IGZyb20gXCIuLi9yZXNvbHZlVHlwZUNoZWNrZXJcIlxuaW1wb3J0IHR5cGUgeyBBbnlTdGFuZGFyZFR5cGUsIEFueVR5cGUgfSBmcm9tIFwiLi4vc2NoZW1hc1wiXG5pbXBvcnQgeyBsYXRlVHlwZUNoZWNrZXIsIFR5cGVDaGVja2VyLCBUeXBlSW5mbywgVHlwZUluZm9HZW4gfSBmcm9tIFwiLi4vVHlwZUNoZWNrZXJcIlxuXG4vKipcbiAqIFdyYXAgYSBnaXZlbiB0eXBlIHdpdGggdGFnIGluZm9ybWF0aW9uLlxuICogVGhpcyBhbGxvd3MgeW91IHRvIGFzc29jaWF0ZSBtZXRhZGF0YSB3aXRoIHRoZSB0eXBlIG9mIGEgcHJvcCB0aGF0XG4gKiB5b3UgY2FuIHVzZSBhdCBydW50aW1lLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGB0c1xuICogY29uc3Qgd2lkdGhUeXBlID0gdHlwZXMudGFnKHR5cGVzLm51bWJlciwgeyBkaXNwbGF5TmFtZTogXCJXaWR0aCBpbiBJbmNoZXNcIiwgcmVxdWlyZWQ6IHRydWUgfSwgXCJkaW1lbnNpb25cIilcbiAqIGNvbnN0IGhlaWdodFR5cGUgPSB0eXBlcy50YWcodHlwZXMubnVtYmVyLCB7IGRpc3BsYXlOYW1lOiBcIkhlaWdodCBpbiBJbmNoZXNcIiwgcmVxdWlyZWQ6IHRydWUgfSwgXCJkaW1lbnNpb25cIilcbiAqIGBgYFxuICpcbiAqIFRoZXNlIGNhbiB0aGVuIGJlIGFjY2Vzc2VkIGF0IHJ1bnRpbWUgdGhyb3VnaCBpbnNwZWN0aW9uIEFQSXMsIGUuZy5cbiAqIGBgYFxuICogQG1vZGVsKCdNeU1vZGVsJylcbiAqIGNsYXNzIE15TW9kZWwgZXh0ZW5kcyBNb2RlbCh7XG4gKiAgIHdpZHRoOiB0UHJvcCh3aWR0aFR5cGUsIDEwKSxcbiAqICAgaGVpZ2h0OiB0UHJvcChoZWlnaHRUeXBlLCAxMClcbiAqIH0pIHt9XG4gKlxuICogY29uc3QgbSA9IG5ldyBNeU1vZGVsKHt9KVxuICogY29uc3QgdHlwZSA9IHR5cGVzLm1vZGVsPHR5cGVvZiBNb2RlbD4obS5jb25zdHJ1Y3RvcilcbiAqIGNvbnN0IG1vZGVsVHlwZUluZm8gPSBnZXRUeXBlSW5mbyh0eXBlKSBhcyBNb2RlbFR5cGVJbmZvXG4gKiBjb25zdCBwcm9wVHlwZUluZm8gPSBtb2RlbFR5cGVJbmZvLnByb3BzLndpZHRoLnR5cGVJbmZvIGFzIFRhZ1R5cGVJbmZvXG4gKiBjb25zdCBkaXNwbGF5TmFtZSA9IHByb3BUeXBlSW5mby5kaXNwbGF5TmFtZVxuICogYGBgXG4gKiBAdHlwZXBhcmFtIFQgQmFzZSB0eXBlLlxuICogQHBhcmFtIGJhc2VUeXBlIEJhc2UgdHlwZS5cbiAqIEB0eXBlcGFyYW0gQSBUYWcgb2JqZWN0LlxuICogQHBhcmFtIHRhZyBBYml0cmFyeSBvYmplY3QgdGhhdCBjYW4gYmUgcXVlcmllZCBhdCBydW50aW1lLlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGVzVGFnPFQgZXh0ZW5kcyBBbnlUeXBlLCBBPihiYXNlVHlwZTogVCwgdGFnOiBBLCB0eXBlTmFtZT86IHN0cmluZyk6IFQge1xuICBjb25zdCB0eXBlSW5mb0dlbjogVHlwZUluZm9HZW4gPSAodCkgPT5cbiAgICBuZXcgVGFnVHlwZUluZm8odCwgcmVzb2x2ZVN0YW5kYXJkVHlwZShiYXNlVHlwZSksIHRhZywgdHlwZU5hbWUpXG5cbiAgcmV0dXJuIGxhdGVUeXBlQ2hlY2tlcigoKSA9PiB7XG4gICAgY29uc3QgYmFzZUNoZWNrZXIgPSByZXNvbHZlVHlwZUNoZWNrZXIoYmFzZVR5cGUpXG5cbiAgICBjb25zdCBnZXRUeXBlTmFtZSA9ICguLi5yZWN1cnNpdmVUeXBlQ2hlY2tlcnM6IFR5cGVDaGVja2VyW10pID0+IHtcbiAgICAgIGNvbnN0IGJhc2VUeXBlTmFtZSA9IGJhc2VDaGVja2VyLmdldFR5cGVOYW1lKC4uLnJlY3Vyc2l2ZVR5cGVDaGVja2VycywgYmFzZUNoZWNrZXIpXG4gICAgICBjb25zdCB0YWdnZWROYW1lID0gdHlwZU5hbWUgfHwgXCJ0YWdnZWRcIlxuICAgICAgcmV0dXJuIGAke3RhZ2dlZE5hbWV9PCR7YmFzZVR5cGVOYW1lfT5gXG4gICAgfVxuXG4gICAgY29uc3QgdGhpc1RjOiBUeXBlQ2hlY2tlciA9IG5ldyBUeXBlQ2hlY2tlcihcbiAgICAgIGJhc2VDaGVja2VyLmJhc2VUeXBlLFxuICAgICAgKGRhdGEsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpID0+IGJhc2VDaGVja2VyLmNoZWNrKGRhdGEsIHBhdGgsIHR5cGVDaGVja2VkVmFsdWUpLFxuICAgICAgZ2V0VHlwZU5hbWUsXG4gICAgICB0eXBlSW5mb0dlbixcbiAgICAgIChzbikgPT4gYmFzZUNoZWNrZXIuc25hcHNob3RUeXBlKHNuKSxcbiAgICAgIChzbikgPT4gYmFzZUNoZWNrZXIuZnJvbVNuYXBzaG90UHJvY2Vzc29yKHNuKSxcbiAgICAgIChzbikgPT4gYmFzZUNoZWNrZXIudG9TbmFwc2hvdFByb2Nlc3NvcihzbilcbiAgICApXG5cbiAgICByZXR1cm4gdGhpc1RjXG4gIH0sIHR5cGVJbmZvR2VuKSBhcyBhbnlcbn1cblxuLyoqXG4gKiBgdHlwZXMudGFnYCB0eXBlIGluZm8uXG4gKi9cbmV4cG9ydCBjbGFzcyBUYWdUeXBlSW5mbzxBPiBleHRlbmRzIFR5cGVJbmZvIHtcbiAgZ2V0IGJhc2VUeXBlSW5mbygpOiBUeXBlSW5mbyB7XG4gICAgcmV0dXJuIGdldFR5cGVJbmZvKHRoaXMuYmFzZVR5cGUpXG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICB0aGlzVHlwZTogQW55U3RhbmRhcmRUeXBlLFxuICAgIHJlYWRvbmx5IGJhc2VUeXBlOiBBbnlTdGFuZGFyZFR5cGUsXG4gICAgcmVhZG9ubHkgdGFnOiBBLFxuICAgIHJlYWRvbmx5IHR5cGVOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWRcbiAgKSB7XG4gICAgc3VwZXIodGhpc1R5cGUpXG4gIH1cbn1cbiIsImltcG9ydCB7IEFycmF5VHlwZUluZm8sIHR5cGVzQXJyYXkgfSBmcm9tIFwiLi9hcnJheUJhc2VkL3R5cGVzQXJyYXlcIlxuaW1wb3J0IHsgVHVwbGVUeXBlSW5mbywgdHlwZXNUdXBsZSB9IGZyb20gXCIuL2FycmF5QmFzZWQvdHlwZXNUdXBsZVwiXG5pbXBvcnQgeyBBcnJheVNldFR5cGVJbmZvLCB0eXBlc0FycmF5U2V0IH0gZnJvbSBcIi4vb2JqZWN0QmFzZWQvdHlwZXNBcnJheVNldFwiXG5pbXBvcnQgeyB0eXBlc0RhdGFNb2RlbERhdGEgfSBmcm9tIFwiLi9vYmplY3RCYXNlZC90eXBlc0RhdGFNb2RlbERhdGFcIlxuaW1wb3J0IHsgTW9kZWxUeXBlSW5mbywgTW9kZWxUeXBlSW5mb1Byb3BzLCB0eXBlc01vZGVsIH0gZnJvbSBcIi4vb2JqZWN0QmFzZWQvdHlwZXNNb2RlbFwiXG5pbXBvcnQge1xuICBGcm96ZW5UeXBlSW5mbyxcbiAgT2JqZWN0VHlwZUluZm8sXG4gIE9iamVjdFR5cGVJbmZvUHJvcHMsXG4gIHR5cGVzRnJvemVuLFxuICB0eXBlc09iamVjdCxcbn0gZnJvbSBcIi4vb2JqZWN0QmFzZWQvdHlwZXNPYmplY3RcIlxuaW1wb3J0IHsgT2JqZWN0TWFwVHlwZUluZm8sIHR5cGVzT2JqZWN0TWFwIH0gZnJvbSBcIi4vb2JqZWN0QmFzZWQvdHlwZXNPYmplY3RNYXBcIlxuaW1wb3J0IHsgUmVjb3JkVHlwZUluZm8sIHR5cGVzUmVjb3JkIH0gZnJvbSBcIi4vb2JqZWN0QmFzZWQvdHlwZXNSZWNvcmRcIlxuaW1wb3J0IHsgUmVmVHlwZUluZm8sIHR5cGVzUmVmIH0gZnJvbSBcIi4vb2JqZWN0QmFzZWQvdHlwZXNSZWZcIlxuaW1wb3J0IHsgdHlwZXNFbnVtIH0gZnJvbSBcIi4vcHJpbWl0aXZlQmFzZWQvdHlwZXNFbnVtXCJcbmltcG9ydCB7XG4gIEJvb2xlYW5UeXBlSW5mbyxcbiAgTGl0ZXJhbFR5cGVJbmZvLFxuICBOdW1iZXJUeXBlSW5mbyxcbiAgU3RyaW5nVHlwZUluZm8sXG4gIHR5cGVzQm9vbGVhbixcbiAgdHlwZXNMaXRlcmFsLFxuICB0eXBlc051bGwsXG4gIHR5cGVzTnVtYmVyLFxuICB0eXBlc1N0cmluZyxcbiAgdHlwZXNVbmRlZmluZWQsXG59IGZyb20gXCIuL3ByaW1pdGl2ZUJhc2VkL3R5cGVzUHJpbWl0aXZlXCJcbmltcG9ydCB7IHR5cGVzSW50ZWdlciwgdHlwZXNOb25FbXB0eVN0cmluZyB9IGZyb20gXCIuL3ByaW1pdGl2ZUJhc2VkL3R5cGVzUmVmaW5lZFByaW1pdGl2ZVwiXG5pbXBvcnQgdHlwZSB7IEFueVR5cGUgfSBmcm9tIFwiLi9zY2hlbWFzXCJcbmltcG9ydCB7IHR5cGVzTWF5YmUsIHR5cGVzTWF5YmVOdWxsIH0gZnJvbSBcIi4vdXRpbGl0eS90eXBlc01heWJlXCJcbmltcG9ydCB7IE9yVHlwZUluZm8sIHR5cGVzT3IgfSBmcm9tIFwiLi91dGlsaXR5L3R5cGVzT3JcIlxuaW1wb3J0IHsgUmVmaW5lbWVudFR5cGVJbmZvLCB0eXBlc1JlZmluZW1lbnQgfSBmcm9tIFwiLi91dGlsaXR5L3R5cGVzUmVmaW5lbWVudFwiXG5pbXBvcnQgeyBUYWdUeXBlSW5mbywgdHlwZXNUYWcgfSBmcm9tIFwiLi91dGlsaXR5L3R5cGVzVGFnXCJcbmltcG9ydCB7IHR5cGVzVW5jaGVja2VkLCBVbmNoZWNrZWRUeXBlSW5mbyB9IGZyb20gXCIuL3V0aWxpdHkvdHlwZXNVbmNoZWNrZWRcIlxuZXhwb3J0IHsgZ2V0VHlwZUluZm8gfSBmcm9tIFwiLi9nZXRUeXBlSW5mb1wiXG5leHBvcnQgeyBUeXBlSW5mbyB9IGZyb20gXCIuL1R5cGVDaGVja2VyXCJcbmV4cG9ydCB0eXBlIHsgT2JqZWN0VHlwZUluZm9Qcm9wcywgTW9kZWxUeXBlSW5mb1Byb3BzIH1cbmV4cG9ydCB7XG4gIEJvb2xlYW5UeXBlSW5mbyxcbiAgTGl0ZXJhbFR5cGVJbmZvLFxuICBOdW1iZXJUeXBlSW5mbyxcbiAgU3RyaW5nVHlwZUluZm8sXG4gIEZyb3plblR5cGVJbmZvLFxuICBPYmplY3RNYXBUeXBlSW5mbyxcbiAgVGFnVHlwZUluZm8sXG4gIFJlZmluZW1lbnRUeXBlSW5mbyxcbiAgUmVjb3JkVHlwZUluZm8sXG4gIFJlZlR5cGVJbmZvLFxuICBVbmNoZWNrZWRUeXBlSW5mbyxcbiAgT2JqZWN0VHlwZUluZm8sXG4gIEFycmF5U2V0VHlwZUluZm8sXG4gIEFycmF5VHlwZUluZm8sXG4gIE1vZGVsVHlwZUluZm8sXG4gIE9yVHlwZUluZm8sXG4gIFR1cGxlVHlwZUluZm8sXG59XG5cbmV4cG9ydCBjb25zdCB0eXBlcyA9IHtcbiAgbGl0ZXJhbDogdHlwZXNMaXRlcmFsLFxuICB1bmRlZmluZWQ6IHR5cGVzVW5kZWZpbmVkLFxuICBudWxsOiB0eXBlc051bGwsXG4gIGJvb2xlYW46IHR5cGVzQm9vbGVhbixcbiAgbnVtYmVyOiB0eXBlc051bWJlcixcbiAgc3RyaW5nOiB0eXBlc1N0cmluZyxcbiAgb3I6IHR5cGVzT3IsXG4gIG1heWJlOiB0eXBlc01heWJlLFxuICBtYXliZU51bGw6IHR5cGVzTWF5YmVOdWxsLFxuICBhcnJheTogdHlwZXNBcnJheSxcbiAgcmVjb3JkOiB0eXBlc1JlY29yZCxcbiAgdW5jaGVja2VkOiB0eXBlc1VuY2hlY2tlZCxcbiAgbW9kZWw6IHR5cGVzTW9kZWwsXG4gIGRhdGFNb2RlbERhdGE6IHR5cGVzRGF0YU1vZGVsRGF0YSxcbiAgb2JqZWN0OiB0eXBlc09iamVjdCxcbiAgcmVmOiB0eXBlc1JlZixcbiAgZnJvemVuOiB0eXBlc0Zyb3plbixcbiAgZW51bTogdHlwZXNFbnVtLFxuICB0YWc6IHR5cGVzVGFnLFxuICByZWZpbmVtZW50OiB0eXBlc1JlZmluZW1lbnQsXG4gIGludGVnZXI6IHR5cGVzSW50ZWdlcixcbiAgbm9uRW1wdHlTdHJpbmc6IHR5cGVzTm9uRW1wdHlTdHJpbmcsXG4gIG9iamVjdE1hcDogdHlwZXNPYmplY3RNYXAsXG4gIGFycmF5U2V0OiB0eXBlc0FycmF5U2V0LFxuICB0dXBsZTogdHlwZXNUdXBsZSxcblxuICBtYXBBcnJheTxUIGV4dGVuZHMgQW55VHlwZT4odmFsdWVUeXBlOiBUKSB7XG4gICAgcmV0dXJuIHR5cGVzQXJyYXkodHlwZXNUdXBsZSh0eXBlc1N0cmluZywgdmFsdWVUeXBlKSlcbiAgfSxcbiAgc2V0QXJyYXk8VCBleHRlbmRzIEFueVR5cGU+KHZhbHVlVHlwZTogVCkge1xuICAgIHJldHVybiB0eXBlc0FycmF5KHZhbHVlVHlwZSlcbiAgfSxcbiAgbWFwT2JqZWN0PFQgZXh0ZW5kcyBBbnlUeXBlPih2YWx1ZVR5cGU6IFQpIHtcbiAgICByZXR1cm4gdHlwZXNSZWNvcmQodmFsdWVUeXBlKVxuICB9LFxuICBkYXRlU3RyaW5nOiB0eXBlc05vbkVtcHR5U3RyaW5nLFxuICBkYXRlVGltZXN0YW1wOiB0eXBlc0ludGVnZXIsXG59XG4iXSwibmFtZXMiOlsibW9kZWxDbGFzcyIsIkJ1aWx0SW5BY3Rpb24iLCJBY3Rpb25Db250ZXh0QWN0aW9uVHlwZSIsIkFjdGlvbkNvbnRleHRBc3luY1N0ZXBUeXBlIiwibmFtZXNwYWNlIiwiZnJvbVNuYXBzaG90IiwibW9kZWwiLCJwcm9wQ2FjaGUiLCJNb2RlbEF1dG9UeXBlQ2hlY2tpbmdNb2RlIiwiYWN0aW9uIiwiSG9va0FjdGlvbiIsIldhbGtUcmVlTW9kZSIsInJldCIsIlR5cGVDaGVja2VyQmFzZVR5cGUiLCJzZXQiLCJfYSIsImtleXMiLCJUd2Vha2VyUHJpb3JpdHkiLCJkaXNwb3NlciIsIlNuYXBzaG90dGVyQW5kUmVjb25jaWxlclByaW9yaXR5IiwiRnJvemVuQ2hlY2tNb2RlIiwicHJvcCIsInBhdGNoUmVjb3JkZXIiLCJvYnNlcnZhYmxlT3B0aW9ucyIsIm11dGF0ZVNldCIsInJlbW92ZSIsInN0YW5kYXJkVHlwZVJlc29sdmVycyIsImlkUHJvcCIsImVyck1lc3NhZ2UiLCJpc01vZGVsIiwiaXNEYXRhTW9kZWwiLCJlcnIiLCJzdGFuZGFsb25lQWN0aW9uIiwiQWN0aW9uVHJhY2tpbmdSZXN1bHQiLCJTdGF0ZSIsImRhdGEiLCJmcm96ZW4iLCJiYXNlUHJvcCIsImJhc2VNb2RlbCIsImludGVybmFsTW9kZWwiLCJ0YWciLCJVbmRvRXZlbnRUeXBlIiwiVW5kb1N0b3JlIiwiX2MiLCJfYiIsImV2ZW50IiwiaW5zdGFuY2UiLCJucyIsImkiLCJBcnJheVNldCIsInZhbHVlcyIsIk9iamVjdE1hcCIsImVudHJpZXMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUdBLE1BQU0sOENBQThCO0FBVzlCLFNBQVUsbUJBQW1CLGdCQUFzQjtBQUNoRCxTQUFBLHdCQUF3QixJQUFJLGNBQWM7QUFDbkQ7QUFLZ0IsU0FBQSxtQkFDZCxnQkFDQUEsYUFDQSxRQUFjO0FBRWQsMEJBQXdCLElBQUksZ0JBQWdCO0FBQUEsSUFDMUMsWUFBQUE7QUFBQSxJQUNBO0FBQUEsRUFBQSxDQUNEO0FBQ0g7QUMzQlksSUFBQTtBQUFBLENBQVosU0FBWUMsZ0JBQWE7QUFJdkJBLGlCQUFBLGNBQUEsSUFBQTtBQUlBQSxpQkFBQSxlQUFBLElBQUE7QUFJQUEsaUJBQUEsUUFBQSxJQUFBO0FBSUFBLGlCQUFBLFVBQUEsSUFBQTtBQUlBQSxpQkFBQSxhQUFBLElBQUE7QUFJQUEsaUJBQUEsaUJBQUEsSUFBQTtBQUNGLEdBekJZLGtCQUFBLGdCQXlCWCxDQUFBLEVBQUE7QUFFRCxNQUFNLHNCQUEyQyxJQUFJLElBQUksT0FBTyxPQUFPLGFBQWEsQ0FBQztBQVcvRSxTQUFVLGdCQUFnQixZQUFrQjtBQUN6QyxTQUFBLG9CQUFvQixJQUFJLFVBQVU7QUFDM0M7QUNTWSxJQUFB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\n","var __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __publicField = (obj, key, value) => {\n __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\n return value;\n};\n\n// pure.ts\nimport { schnorr } from \"@noble/curves/secp256k1\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\n\n// core.ts\nvar verifiedSymbol = Symbol(\"verified\");\nvar isRecord = (obj) => obj instanceof Object;\nfunction validateEvent(event) {\n if (!isRecord(event))\n return false;\n if (typeof event.kind !== \"number\")\n return false;\n if (typeof event.content !== \"string\")\n return false;\n if (typeof event.created_at !== \"number\")\n return false;\n if (typeof event.pubkey !== \"string\")\n return false;\n if (!event.pubkey.match(/^[a-f0-9]{64}$/))\n return false;\n if (!Array.isArray(event.tags))\n return false;\n for (let i2 = 0; i2 < event.tags.length; i2++) {\n let tag = event.tags[i2];\n if (!Array.isArray(tag))\n return false;\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] === \"object\")\n return false;\n }\n }\n return true;\n}\nfunction sortEvents(events) {\n return events.sort((a, b) => {\n if (a.created_at !== b.created_at) {\n return b.created_at - a.created_at;\n }\n return a.id.localeCompare(b.id);\n });\n}\n\n// pure.ts\nimport { sha256 } from \"@noble/hashes/sha256\";\n\n// utils.ts\nvar utils_exports = {};\n__export(utils_exports, {\n Queue: () => Queue,\n QueueNode: () => QueueNode,\n binarySearch: () => binarySearch,\n insertEventIntoAscendingList: () => insertEventIntoAscendingList,\n insertEventIntoDescendingList: () => insertEventIntoDescendingList,\n normalizeURL: () => normalizeURL,\n utf8Decoder: () => utf8Decoder,\n utf8Encoder: () => utf8Encoder\n});\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\nfunction normalizeURL(url) {\n if (url.indexOf(\"://\") === -1)\n url = \"wss://\" + url;\n let p = new URL(url);\n p.pathname = p.pathname.replace(/\\/+/g, \"/\");\n if (p.pathname.endsWith(\"/\"))\n p.pathname = p.pathname.slice(0, -1);\n if (p.port === \"80\" && p.protocol === \"ws:\" || p.port === \"443\" && p.protocol === \"wss:\")\n p.port = \"\";\n p.searchParams.sort();\n p.hash = \"\";\n return p.toString();\n}\nfunction insertEventIntoDescendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return b.created_at - event.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction insertEventIntoAscendingList(sortedArray, event) {\n const [idx, found] = binarySearch(sortedArray, (b) => {\n if (event.id === b.id)\n return 0;\n if (event.created_at === b.created_at)\n return -1;\n return event.created_at - b.created_at;\n });\n if (!found) {\n sortedArray.splice(idx, 0, event);\n }\n return sortedArray;\n}\nfunction binarySearch(arr, compare) {\n let start = 0;\n let end = arr.length - 1;\n while (start <= end) {\n const mid = Math.floor((start + end) / 2);\n const cmp = compare(arr[mid]);\n if (cmp === 0) {\n return [mid, true];\n }\n if (cmp < 0) {\n end = mid - 1;\n } else {\n start = mid + 1;\n }\n }\n return [start, false];\n}\nvar QueueNode = class {\n value;\n next = null;\n prev = null;\n constructor(message) {\n this.value = message;\n }\n};\nvar Queue = class {\n first;\n last;\n constructor() {\n this.first = null;\n this.last = null;\n }\n enqueue(value) {\n const newNode = new QueueNode(value);\n if (!this.last) {\n this.first = newNode;\n this.last = newNode;\n } else if (this.last === this.first) {\n this.last = newNode;\n this.last.prev = this.first;\n this.first.next = newNode;\n } else {\n newNode.prev = this.last;\n this.last.next = newNode;\n this.last = newNode;\n }\n return true;\n }\n dequeue() {\n if (!this.first)\n return null;\n if (this.first === this.last) {\n const target2 = this.first;\n this.first = null;\n this.last = null;\n return target2.value;\n }\n const target = this.first;\n this.first = target.next;\n return target.value;\n }\n};\n\n// pure.ts\nvar JS = class {\n generateSecretKey() {\n return schnorr.utils.randomPrivateKey();\n }\n getPublicKey(secretKey) {\n return bytesToHex(schnorr.getPublicKey(secretKey));\n }\n finalizeEvent(t, secretKey) {\n const event = t;\n event.pubkey = bytesToHex(schnorr.getPublicKey(secretKey));\n event.id = getEventHash(event);\n event.sig = bytesToHex(schnorr.sign(getEventHash(event), secretKey));\n event[verifiedSymbol] = true;\n return event;\n }\n verifyEvent(event) {\n if (typeof event[verifiedSymbol] === \"boolean\")\n return event[verifiedSymbol];\n const hash = getEventHash(event);\n if (hash !== event.id) {\n event[verifiedSymbol] = false;\n return false;\n }\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey);\n event[verifiedSymbol] = valid;\n return valid;\n } catch (err) {\n event[verifiedSymbol] = false;\n return false;\n }\n }\n};\nfunction serializeEvent(evt) {\n if (!validateEvent(evt))\n throw new Error(\"can't serialize event with wrong or missing properties\");\n return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);\n}\nfunction getEventHash(event) {\n let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)));\n return bytesToHex(eventHash);\n}\nvar i = new JS();\nvar generateSecretKey = i.generateSecretKey;\nvar getPublicKey = i.getPublicKey;\nvar finalizeEvent = i.finalizeEvent;\nvar verifyEvent = i.verifyEvent;\n\n// kinds.ts\nvar kinds_exports = {};\n__export(kinds_exports, {\n Application: () => Application,\n BadgeAward: () => BadgeAward,\n BadgeDefinition: () => BadgeDefinition,\n BlockedRelaysList: () => BlockedRelaysList,\n BookmarkList: () => BookmarkList,\n Bookmarksets: () => Bookmarksets,\n Calendar: () => Calendar,\n CalendarEventRSVP: () => CalendarEventRSVP,\n ChannelCreation: () => ChannelCreation,\n ChannelHideMessage: () => ChannelHideMessage,\n ChannelMessage: () => ChannelMessage,\n ChannelMetadata: () => ChannelMetadata,\n ChannelMuteUser: () => ChannelMuteUser,\n ClassifiedListing: () => ClassifiedListing,\n ClientAuth: () => ClientAuth,\n CommunitiesList: () => CommunitiesList,\n CommunityDefinition: () => CommunityDefinition,\n CommunityPostApproval: () => CommunityPostApproval,\n Contacts: () => Contacts,\n CreateOrUpdateProduct: () => CreateOrUpdateProduct,\n CreateOrUpdateStall: () => CreateOrUpdateStall,\n Curationsets: () => Curationsets,\n Date: () => Date2,\n DraftClassifiedListing: () => DraftClassifiedListing,\n DraftLong: () => DraftLong,\n Emojisets: () => Emojisets,\n EncryptedDirectMessage: () => EncryptedDirectMessage,\n EncryptedDirectMessages: () => EncryptedDirectMessages,\n EventDeletion: () => EventDeletion,\n FileMetadata: () => FileMetadata,\n FileServerPreference: () => FileServerPreference,\n Followsets: () => Followsets,\n GenericRepost: () => GenericRepost,\n Genericlists: () => Genericlists,\n HTTPAuth: () => HTTPAuth,\n Handlerinformation: () => Handlerinformation,\n Handlerrecommendation: () => Handlerrecommendation,\n Highlights: () => Highlights,\n InterestsList: () => InterestsList,\n Interestsets: () => Interestsets,\n JobFeedback: () => JobFeedback,\n JobRequest: () => JobRequest,\n JobResult: () => JobResult,\n Label: () => Label,\n LightningPubRPC: () => LightningPubRPC,\n LiveChatMessage: () => LiveChatMessage,\n LiveEvent: () => LiveEvent,\n LongFormArticle: () => LongFormArticle,\n Metadata: () => Metadata,\n Mutelist: () => Mutelist,\n NWCWalletInfo: () => NWCWalletInfo,\n NWCWalletRequest: () => NWCWalletRequest,\n NWCWalletResponse: () => NWCWalletResponse,\n NostrConnect: () => NostrConnect,\n OpenTimestamps: () => OpenTimestamps,\n Pinlist: () => Pinlist,\n ProblemTracker: () => ProblemTracker,\n ProfileBadges: () => ProfileBadges,\n PublicChatsList: () => PublicChatsList,\n Reaction: () => Reaction,\n RecommendRelay: () => RecommendRelay,\n RelayList: () => RelayList,\n Relaysets: () => Relaysets,\n Report: () => Report,\n Reporting: () => Reporting,\n Repost: () => Repost,\n SearchRelaysList: () => SearchRelaysList,\n ShortTextNote: () => ShortTextNote,\n Time: () => Time,\n UserEmojiList: () => UserEmojiList,\n UserStatuses: () => UserStatuses,\n Zap: () => Zap,\n ZapGoal: () => ZapGoal,\n ZapRequest: () => ZapRequest,\n classifyKind: () => classifyKind,\n isEphemeralKind: () => isEphemeralKind,\n isParameterizedReplaceableKind: () => isParameterizedReplaceableKind,\n isRegularKind: () => isRegularKind,\n isReplaceableKind: () => isReplaceableKind\n});\nfunction isRegularKind(kind) {\n return 1e3 <= kind && kind < 1e4 || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind);\n}\nfunction isReplaceableKind(kind) {\n return [0, 3].includes(kind) || 1e4 <= kind && kind < 2e4;\n}\nfunction isEphemeralKind(kind) {\n return 2e4 <= kind && kind < 3e4;\n}\nfunction isParameterizedReplaceableKind(kind) {\n return 3e4 <= kind && kind < 4e4;\n}\nfunction classifyKind(kind) {\n if (isRegularKind(kind))\n return \"regular\";\n if (isReplaceableKind(kind))\n return \"replaceable\";\n if (isEphemeralKind(kind))\n return \"ephemeral\";\n if (isParameterizedReplaceableKind(kind))\n return \"parameterized\";\n return \"unknown\";\n}\nvar Metadata = 0;\nvar ShortTextNote = 1;\nvar RecommendRelay = 2;\nvar Contacts = 3;\nvar EncryptedDirectMessage = 4;\nvar EncryptedDirectMessages = 4;\nvar EventDeletion = 5;\nvar Repost = 6;\nvar Reaction = 7;\nvar BadgeAward = 8;\nvar GenericRepost = 16;\nvar ChannelCreation = 40;\nvar ChannelMetadata = 41;\nvar ChannelMessage = 42;\nvar ChannelHideMessage = 43;\nvar ChannelMuteUser = 44;\nvar OpenTimestamps = 1040;\nvar FileMetadata = 1063;\nvar LiveChatMessage = 1311;\nvar ProblemTracker = 1971;\nvar Report = 1984;\nvar Reporting = 1984;\nvar Label = 1985;\nvar CommunityPostApproval = 4550;\nvar JobRequest = 5999;\nvar JobResult = 6999;\nvar JobFeedback = 7e3;\nvar ZapGoal = 9041;\nvar ZapRequest = 9734;\nvar Zap = 9735;\nvar Highlights = 9802;\nvar Mutelist = 1e4;\nvar Pinlist = 10001;\nvar RelayList = 10002;\nvar BookmarkList = 10003;\nvar CommunitiesList = 10004;\nvar PublicChatsList = 10005;\nvar BlockedRelaysList = 10006;\nvar SearchRelaysList = 10007;\nvar InterestsList = 10015;\nvar UserEmojiList = 10030;\nvar FileServerPreference = 10096;\nvar NWCWalletInfo = 13194;\nvar LightningPubRPC = 21e3;\nvar ClientAuth = 22242;\nvar NWCWalletRequest = 23194;\nvar NWCWalletResponse = 23195;\nvar NostrConnect = 24133;\nvar HTTPAuth = 27235;\nvar Followsets = 3e4;\nvar Genericlists = 30001;\nvar Relaysets = 30002;\nvar Bookmarksets = 30003;\nvar Curationsets = 30004;\nvar ProfileBadges = 30008;\nvar BadgeDefinition = 30009;\nvar Interestsets = 30015;\nvar CreateOrUpdateStall = 30017;\nvar CreateOrUpdateProduct = 30018;\nvar LongFormArticle = 30023;\nvar DraftLong = 30024;\nvar Emojisets = 30030;\nvar Application = 30078;\nvar LiveEvent = 30311;\nvar UserStatuses = 30315;\nvar ClassifiedListing = 30402;\nvar DraftClassifiedListing = 30403;\nvar Date2 = 31922;\nvar Time = 31923;\nvar Calendar = 31924;\nvar CalendarEventRSVP = 31925;\nvar Handlerrecommendation = 31989;\nvar Handlerinformation = 31990;\nvar CommunityDefinition = 34550;\n\n// filter.ts\nfunction matchFilter(filter, event) {\n if (filter.ids && filter.ids.indexOf(event.id) === -1) {\n if (!filter.ids.some((prefix) => event.id.startsWith(prefix))) {\n return false;\n }\n }\n if (filter.kinds && filter.kinds.indexOf(event.kind) === -1)\n return false;\n if (filter.authors && filter.authors.indexOf(event.pubkey) === -1) {\n if (!filter.authors.some((prefix) => event.pubkey.startsWith(prefix))) {\n return false;\n }\n }\n for (let f in filter) {\n if (f[0] === \"#\") {\n let tagName = f.slice(1);\n let values = filter[`#${tagName}`];\n if (values && !event.tags.find(([t, v]) => t === f.slice(1) && values.indexOf(v) !== -1))\n return false;\n }\n }\n if (filter.since && event.created_at < filter.since)\n return false;\n if (filter.until && event.created_at > filter.until)\n return false;\n return true;\n}\nfunction matchFilters(filters, event) {\n for (let i2 = 0; i2 < filters.length; i2++) {\n if (matchFilter(filters[i2], event)) {\n return true;\n }\n }\n return false;\n}\nfunction mergeFilters(...filters) {\n let result = {};\n for (let i2 = 0; i2 < filters.length; i2++) {\n let filter = filters[i2];\n Object.entries(filter).forEach(([property, values]) => {\n if (property === \"kinds\" || property === \"ids\" || property === \"authors\" || property[0] === \"#\") {\n result[property] = result[property] || [];\n for (let v = 0; v < values.length; v++) {\n let value = values[v];\n if (!result[property].includes(value))\n result[property].push(value);\n }\n }\n });\n if (filter.limit && (!result.limit || filter.limit > result.limit))\n result.limit = filter.limit;\n if (filter.until && (!result.until || filter.until > result.until))\n result.until = filter.until;\n if (filter.since && (!result.since || filter.since < result.since))\n result.since = filter.since;\n }\n return result;\n}\nfunction getFilterLimit(filter) {\n if (filter.ids && !filter.ids.length)\n return 0;\n if (filter.kinds && !filter.kinds.length)\n return 0;\n if (filter.authors && !filter.authors.length)\n return 0;\n return Math.min(\n Math.max(0, filter.limit ?? Infinity),\n filter.ids?.length ?? Infinity,\n filter.authors?.length && filter.kinds?.every((kind) => isReplaceableKind(kind)) ? filter.authors.length * filter.kinds.length : Infinity\n );\n}\n\n// fakejson.ts\nvar fakejson_exports = {};\n__export(fakejson_exports, {\n getHex64: () => getHex64,\n getInt: () => getInt,\n getSubscriptionId: () => getSubscriptionId,\n matchEventId: () => matchEventId,\n matchEventKind: () => matchEventKind,\n matchEventPubkey: () => matchEventPubkey\n});\nfunction getHex64(json, field) {\n let len = field.length + 3;\n let idx = json.indexOf(`\"${field}\":`) + len;\n let s = json.slice(idx).indexOf(`\"`) + idx + 1;\n return json.slice(s, s + 64);\n}\nfunction getInt(json, field) {\n let len = field.length;\n let idx = json.indexOf(`\"${field}\":`) + len + 3;\n let sliced = json.slice(idx);\n let end = Math.min(sliced.indexOf(\",\"), sliced.indexOf(\"}\"));\n return parseInt(sliced.slice(0, end), 10);\n}\nfunction getSubscriptionId(json) {\n let idx = json.slice(0, 22).indexOf(`\"EVENT\"`);\n if (idx === -1)\n return null;\n let pstart = json.slice(idx + 7 + 1).indexOf(`\"`);\n if (pstart === -1)\n return null;\n let start = idx + 7 + 1 + pstart;\n let pend = json.slice(start + 1, 80).indexOf(`\"`);\n if (pend === -1)\n return null;\n let end = start + 1 + pend;\n return json.slice(start + 1, end);\n}\nfunction matchEventId(json, id) {\n return id === getHex64(json, \"id\");\n}\nfunction matchEventPubkey(json, pubkey) {\n return pubkey === getHex64(json, \"pubkey\");\n}\nfunction matchEventKind(json, kind) {\n return kind === getInt(json, \"kind\");\n}\n\n// nip42.ts\nvar nip42_exports = {};\n__export(nip42_exports, {\n makeAuthEvent: () => makeAuthEvent\n});\nfunction makeAuthEvent(relayURL, challenge) {\n return {\n kind: ClientAuth,\n created_at: Math.floor(Date.now() / 1e3),\n tags: [\n [\"relay\", relayURL],\n [\"challenge\", challenge]\n ],\n content: \"\"\n };\n}\n\n// helpers.ts\nasync function yieldThread() {\n return new Promise((resolve) => {\n const ch = new MessageChannel();\n const handler = () => {\n ch.port1.removeEventListener(\"message\", handler);\n resolve();\n };\n ch.port1.addEventListener(\"message\", handler);\n ch.port2.postMessage(0);\n ch.port1.start();\n });\n}\nvar alwaysTrue = (t) => {\n t[verifiedSymbol] = true;\n return true;\n};\n\n// abstract-relay.ts\nvar _WebSocket;\ntry {\n _WebSocket = WebSocket;\n} catch {\n}\nfunction useWebSocketImplementation(websocketImplementation) {\n _WebSocket = websocketImplementation;\n}\nvar AbstractRelay = class {\n url;\n _connected = false;\n onclose = null;\n onnotice = (msg) => console.debug(`NOTICE from ${this.url}: ${msg}`);\n _onauth = null;\n baseEoseTimeout = 4400;\n connectionTimeout = 4400;\n openSubs = /* @__PURE__ */ new Map();\n connectionTimeoutHandle;\n connectionPromise;\n openCountRequests = /* @__PURE__ */ new Map();\n openEventPublishes = /* @__PURE__ */ new Map();\n ws;\n incomingMessageQueue = new Queue();\n queueRunning = false;\n challenge;\n serial = 0;\n verifyEvent;\n constructor(url, opts) {\n this.url = normalizeURL(url);\n this.verifyEvent = opts.verifyEvent;\n }\n static async connect(url, opts) {\n const relay = new AbstractRelay(url, opts);\n await relay.connect();\n return relay;\n }\n closeAllSubscriptions(reason) {\n for (let [_, sub] of this.openSubs) {\n sub.close(reason);\n }\n this.openSubs.clear();\n for (let [_, ep] of this.openEventPublishes) {\n ep.reject(new Error(reason));\n }\n this.openEventPublishes.clear();\n for (let [_, cr] of this.openCountRequests) {\n cr.reject(new Error(reason));\n }\n this.openCountRequests.clear();\n }\n get connected() {\n return this._connected;\n }\n async connect() {\n if (this.connectionPromise)\n return this.connectionPromise;\n this.challenge = void 0;\n this.connectionPromise = new Promise((resolve, reject) => {\n this.connectionTimeoutHandle = setTimeout(() => {\n reject(\"connection timed out\");\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection timed out\");\n }, this.connectionTimeout);\n try {\n this.ws = new _WebSocket(this.url);\n } catch (err) {\n reject(err);\n return;\n }\n this.ws.onopen = () => {\n clearTimeout(this.connectionTimeoutHandle);\n this._connected = true;\n resolve();\n };\n this.ws.onerror = (ev) => {\n reject(ev.message);\n if (this._connected) {\n this._connected = false;\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection errored\");\n }\n };\n this.ws.onclose = async () => {\n if (this._connected) {\n this._connected = false;\n this.connectionPromise = void 0;\n this.onclose?.();\n this.closeAllSubscriptions(\"relay connection closed\");\n }\n };\n this.ws.onmessage = this._onmessage.bind(this);\n });\n return this.connectionPromise;\n }\n async runQueue() {\n this.queueRunning = true;\n while (true) {\n if (false === this.handleNext()) {\n break;\n }\n await yieldThread();\n }\n this.queueRunning = false;\n }\n handleNext() {\n const json = this.incomingMessageQueue.dequeue();\n if (!json) {\n return false;\n }\n const subid = getSubscriptionId(json);\n if (subid) {\n const so = this.openSubs.get(subid);\n if (!so) {\n return;\n }\n const id = getHex64(json, \"id\");\n const alreadyHave = so.alreadyHaveEvent?.(id);\n so.receivedEvent?.(this, id);\n if (alreadyHave) {\n return;\n }\n }\n try {\n let data = JSON.parse(json);\n switch (data[0]) {\n case \"EVENT\": {\n const so = this.openSubs.get(data[1]);\n const event = data[2];\n if (this.verifyEvent(event) && matchFilters(so.filters, event)) {\n so.onevent(event);\n }\n return;\n }\n case \"COUNT\": {\n const id = data[1];\n const payload = data[2];\n const cr = this.openCountRequests.get(id);\n if (cr) {\n cr.resolve(payload.count);\n this.openCountRequests.delete(id);\n }\n return;\n }\n case \"EOSE\": {\n const so = this.openSubs.get(data[1]);\n if (!so)\n return;\n so.receivedEose();\n return;\n }\n case \"OK\": {\n const id = data[1];\n const ok = data[2];\n const reason = data[3];\n const ep = this.openEventPublishes.get(id);\n if (ok)\n ep.resolve(reason);\n else\n ep.reject(new Error(reason));\n this.openEventPublishes.delete(id);\n return;\n }\n case \"CLOSED\": {\n const id = data[1];\n const so = this.openSubs.get(id);\n if (!so)\n return;\n so.closed = true;\n so.close(data[2]);\n return;\n }\n case \"NOTICE\":\n this.onnotice(data[1]);\n return;\n case \"AUTH\": {\n this.challenge = data[1];\n this._onauth?.(data[1]);\n return;\n }\n }\n } catch (err) {\n return;\n }\n }\n async send(message) {\n if (!this.connectionPromise)\n throw new Error(\"sending on closed connection\");\n this.connectionPromise.then(() => {\n this.ws?.send(message);\n });\n }\n async auth(signAuthEvent) {\n if (!this.challenge)\n throw new Error(\"can't perform auth, no challenge was received\");\n const evt = await signAuthEvent(makeAuthEvent(this.url, this.challenge));\n const ret = new Promise((resolve, reject) => {\n this.openEventPublishes.set(evt.id, { resolve, reject });\n });\n this.send('[\"AUTH\",' + JSON.stringify(evt) + \"]\");\n return ret;\n }\n async publish(event) {\n const ret = new Promise((resolve, reject) => {\n this.openEventPublishes.set(event.id, { resolve, reject });\n });\n this.send('[\"EVENT\",' + JSON.stringify(event) + \"]\");\n return ret;\n }\n async count(filters, params) {\n this.serial++;\n const id = params?.id || \"count:\" + this.serial;\n const ret = new Promise((resolve, reject) => {\n this.openCountRequests.set(id, { resolve, reject });\n });\n this.send('[\"COUNT\",\"' + id + '\",' + JSON.stringify(filters).substring(1));\n return ret;\n }\n subscribe(filters, params) {\n const subscription = this.prepareSubscription(filters, params);\n subscription.fire();\n return subscription;\n }\n prepareSubscription(filters, params) {\n this.serial++;\n const id = params.id || \"sub:\" + this.serial;\n const subscription = new Subscription(this, id, filters, params);\n this.openSubs.set(id, subscription);\n return subscription;\n }\n close() {\n this.closeAllSubscriptions(\"relay connection closed by us\");\n this._connected = false;\n this.ws?.close();\n }\n _onmessage(ev) {\n this.incomingMessageQueue.enqueue(ev.data);\n if (!this.queueRunning) {\n this.runQueue();\n }\n }\n};\nvar Subscription = class {\n relay;\n id;\n closed = false;\n eosed = false;\n filters;\n alreadyHaveEvent;\n receivedEvent;\n onevent;\n oneose;\n onclose;\n eoseTimeout;\n eoseTimeoutHandle;\n constructor(relay, id, filters, params) {\n this.relay = relay;\n this.filters = filters;\n this.id = id;\n this.alreadyHaveEvent = params.alreadyHaveEvent;\n this.receivedEvent = params.receivedEvent;\n this.eoseTimeout = params.eoseTimeout || relay.baseEoseTimeout;\n this.oneose = params.oneose;\n this.onclose = params.onclose;\n this.onevent = params.onevent || ((event) => {\n console.warn(\n `onevent() callback not defined for subscription '${this.id}' in relay ${this.relay.url}. event received:`,\n event\n );\n });\n }\n fire() {\n this.relay.send('[\"REQ\",\"' + this.id + '\",' + JSON.stringify(this.filters).substring(1));\n this.eoseTimeoutHandle = setTimeout(this.receivedEose.bind(this), this.eoseTimeout);\n }\n receivedEose() {\n if (this.eosed)\n return;\n clearTimeout(this.eoseTimeoutHandle);\n this.eosed = true;\n this.oneose?.();\n }\n close(reason = \"closed by caller\") {\n if (!this.closed && this.relay.connected) {\n this.relay.send('[\"CLOSE\",' + JSON.stringify(this.id) + \"]\");\n this.closed = true;\n }\n this.relay.openSubs.delete(this.id);\n this.onclose?.(reason);\n }\n};\n\n// relay.ts\nfunction relayConnect(url) {\n return Relay.connect(url);\n}\nvar Relay = class extends AbstractRelay {\n constructor(url) {\n super(url, { verifyEvent });\n }\n static async connect(url) {\n const relay = new Relay(url);\n await relay.connect();\n return relay;\n }\n};\n\n// abstract-pool.ts\nvar AbstractSimplePool = class {\n relays = /* @__PURE__ */ new Map();\n seenOn = /* @__PURE__ */ new Map();\n trackRelays = false;\n verifyEvent;\n trustedRelayURLs = /* @__PURE__ */ new Set();\n constructor(opts) {\n this.verifyEvent = opts.verifyEvent;\n }\n async ensureRelay(url, params) {\n url = normalizeURL(url);\n let relay = this.relays.get(url);\n if (!relay) {\n relay = new AbstractRelay(url, {\n verifyEvent: this.trustedRelayURLs.has(url) ? alwaysTrue : this.verifyEvent\n });\n if (params?.connectionTimeout)\n relay.connectionTimeout = params.connectionTimeout;\n this.relays.set(url, relay);\n }\n await relay.connect();\n return relay;\n }\n close(relays) {\n relays.map(normalizeURL).forEach((url) => {\n this.relays.get(url)?.close();\n });\n }\n subscribeMany(relays, filters, params) {\n return this.subscribeManyMap(Object.fromEntries(relays.map((url) => [url, filters])), params);\n }\n subscribeManyMap(requests, params) {\n if (this.trackRelays) {\n params.receivedEvent = (relay, id) => {\n let set = this.seenOn.get(id);\n if (!set) {\n set = /* @__PURE__ */ new Set();\n this.seenOn.set(id, set);\n }\n set.add(relay);\n };\n }\n const _knownIds = /* @__PURE__ */ new Set();\n const subs = [];\n const relaysLength = Object.keys(requests).length;\n const eosesReceived = [];\n let handleEose = (i2) => {\n eosesReceived[i2] = true;\n if (eosesReceived.filter((a) => a).length === relaysLength) {\n params.oneose?.();\n handleEose = () => {\n };\n }\n };\n const closesReceived = [];\n let handleClose = (i2, reason) => {\n handleEose(i2);\n closesReceived[i2] = reason;\n if (closesReceived.filter((a) => a).length === relaysLength) {\n params.onclose?.(closesReceived);\n handleClose = () => {\n };\n }\n };\n const localAlreadyHaveEventHandler = (id) => {\n if (params.alreadyHaveEvent?.(id)) {\n return true;\n }\n const have = _knownIds.has(id);\n _knownIds.add(id);\n return have;\n };\n const allOpened = Promise.all(\n Object.entries(requests).map(async (req, i2, arr) => {\n if (arr.indexOf(req) !== i2) {\n handleClose(i2, \"duplicate url\");\n return;\n }\n let [url, filters] = req;\n url = normalizeURL(url);\n let relay;\n try {\n relay = await this.ensureRelay(url, {\n connectionTimeout: params.maxWait ? Math.max(params.maxWait * 0.8, params.maxWait - 1e3) : void 0\n });\n } catch (err) {\n handleClose(i2, err?.message || String(err));\n return;\n }\n let subscription = relay.subscribe(filters, {\n ...params,\n oneose: () => handleEose(i2),\n onclose: (reason) => handleClose(i2, reason),\n alreadyHaveEvent: localAlreadyHaveEventHandler,\n eoseTimeout: params.maxWait\n });\n subs.push(subscription);\n })\n );\n return {\n async close() {\n await allOpened;\n subs.forEach((sub) => {\n sub.close();\n });\n }\n };\n }\n subscribeManyEose(relays, filters, params) {\n const subcloser = this.subscribeMany(relays, filters, {\n ...params,\n oneose() {\n subcloser.close();\n }\n });\n return subcloser;\n }\n async querySync(relays, filter, params) {\n return new Promise(async (resolve) => {\n const events = [];\n this.subscribeManyEose(relays, [filter], {\n ...params,\n onevent(event) {\n events.push(event);\n },\n onclose(_) {\n resolve(events);\n }\n });\n });\n }\n async get(relays, filter, params) {\n filter.limit = 1;\n const events = await this.querySync(relays, filter, params);\n events.sort((a, b) => b.created_at - a.created_at);\n return events[0] || null;\n }\n publish(relays, event) {\n return relays.map(normalizeURL).map(async (url, i2, arr) => {\n if (arr.indexOf(url) !== i2) {\n return Promise.reject(\"duplicate url\");\n }\n let r = await this.ensureRelay(url);\n return r.publish(event);\n });\n }\n};\n\n// pool.ts\nvar SimplePool = class extends AbstractSimplePool {\n constructor() {\n super({ verifyEvent });\n }\n};\n\n// nip19.ts\nvar nip19_exports = {};\n__export(nip19_exports, {\n BECH32_REGEX: () => BECH32_REGEX,\n Bech32MaxSize: () => Bech32MaxSize,\n decode: () => decode,\n encodeBytes: () => encodeBytes,\n naddrEncode: () => naddrEncode,\n neventEncode: () => neventEncode,\n noteEncode: () => noteEncode,\n nprofileEncode: () => nprofileEncode,\n npubEncode: () => npubEncode,\n nrelayEncode: () => nrelayEncode,\n nsecEncode: () => nsecEncode\n});\nimport { bytesToHex as bytesToHex2, concatBytes, hexToBytes } from \"@noble/hashes/utils\";\nimport { bech32 } from \"@scure/base\";\nvar Bech32MaxSize = 5e3;\nvar BECH32_REGEX = /[\\x21-\\x7E]{1,83}1[023456789acdefghjklmnpqrstuvwxyz]{6,}/;\nfunction integerToUint8Array(number) {\n const uint8Array = new Uint8Array(4);\n uint8Array[0] = number >> 24 & 255;\n uint8Array[1] = number >> 16 & 255;\n uint8Array[2] = number >> 8 & 255;\n uint8Array[3] = number & 255;\n return uint8Array;\n}\nfunction decode(nip19) {\n let { prefix, words } = bech32.decode(nip19, Bech32MaxSize);\n let data = new Uint8Array(bech32.fromWords(words));\n switch (prefix) {\n case \"nprofile\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for nprofile\");\n if (tlv[0][0].length !== 32)\n throw new Error(\"TLV 0 should be 32 bytes\");\n return {\n type: \"nprofile\",\n data: {\n pubkey: bytesToHex2(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []\n }\n };\n }\n case \"nevent\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for nevent\");\n if (tlv[0][0].length !== 32)\n throw new Error(\"TLV 0 should be 32 bytes\");\n if (tlv[2] && tlv[2][0].length !== 32)\n throw new Error(\"TLV 2 should be 32 bytes\");\n if (tlv[3] && tlv[3][0].length !== 4)\n throw new Error(\"TLV 3 should be 4 bytes\");\n return {\n type: \"nevent\",\n data: {\n id: bytesToHex2(tlv[0][0]),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : [],\n author: tlv[2]?.[0] ? bytesToHex2(tlv[2][0]) : void 0,\n kind: tlv[3]?.[0] ? parseInt(bytesToHex2(tlv[3][0]), 16) : void 0\n }\n };\n }\n case \"naddr\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for naddr\");\n if (!tlv[2]?.[0])\n throw new Error(\"missing TLV 2 for naddr\");\n if (tlv[2][0].length !== 32)\n throw new Error(\"TLV 2 should be 32 bytes\");\n if (!tlv[3]?.[0])\n throw new Error(\"missing TLV 3 for naddr\");\n if (tlv[3][0].length !== 4)\n throw new Error(\"TLV 3 should be 4 bytes\");\n return {\n type: \"naddr\",\n data: {\n identifier: utf8Decoder.decode(tlv[0][0]),\n pubkey: bytesToHex2(tlv[2][0]),\n kind: parseInt(bytesToHex2(tlv[3][0]), 16),\n relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []\n }\n };\n }\n case \"nrelay\": {\n let tlv = parseTLV(data);\n if (!tlv[0]?.[0])\n throw new Error(\"missing TLV 0 for nrelay\");\n return {\n type: \"nrelay\",\n data: utf8Decoder.decode(tlv[0][0])\n };\n }\n case \"nsec\":\n return { type: prefix, data };\n case \"npub\":\n case \"note\":\n return { type: prefix, data: bytesToHex2(data) };\n default:\n throw new Error(`unknown prefix ${prefix}`);\n }\n}\nfunction parseTLV(data) {\n let result = {};\n let rest = data;\n while (rest.length > 0) {\n let t = rest[0];\n let l = rest[1];\n let v = rest.slice(2, 2 + l);\n rest = rest.slice(2 + l);\n if (v.length < l)\n throw new Error(`not enough data to read on TLV ${t}`);\n result[t] = result[t] || [];\n result[t].push(v);\n }\n return result;\n}\nfunction nsecEncode(key) {\n return encodeBytes(\"nsec\", key);\n}\nfunction npubEncode(hex) {\n return encodeBytes(\"npub\", hexToBytes(hex));\n}\nfunction noteEncode(hex) {\n return encodeBytes(\"note\", hexToBytes(hex));\n}\nfunction encodeBech32(prefix, data) {\n let words = bech32.toWords(data);\n return bech32.encode(prefix, words, Bech32MaxSize);\n}\nfunction encodeBytes(prefix, bytes) {\n return encodeBech32(prefix, bytes);\n}\nfunction nprofileEncode(profile) {\n let data = encodeTLV({\n 0: [hexToBytes(profile.pubkey)],\n 1: (profile.relays || []).map((url) => utf8Encoder.encode(url))\n });\n return encodeBech32(\"nprofile\", data);\n}\nfunction neventEncode(event) {\n let kindArray;\n if (event.kind !== void 0) {\n kindArray = integerToUint8Array(event.kind);\n }\n let data = encodeTLV({\n 0: [hexToBytes(event.id)],\n 1: (event.relays || []).map((url) => utf8Encoder.encode(url)),\n 2: event.author ? [hexToBytes(event.author)] : [],\n 3: kindArray ? [new Uint8Array(kindArray)] : []\n });\n return encodeBech32(\"nevent\", data);\n}\nfunction naddrEncode(addr) {\n let kind = new ArrayBuffer(4);\n new DataView(kind).setUint32(0, addr.kind, false);\n let data = encodeTLV({\n 0: [utf8Encoder.encode(addr.identifier)],\n 1: (addr.relays || []).map((url) => utf8Encoder.encode(url)),\n 2: [hexToBytes(addr.pubkey)],\n 3: [new Uint8Array(kind)]\n });\n return encodeBech32(\"naddr\", data);\n}\nfunction nrelayEncode(url) {\n let data = encodeTLV({\n 0: [utf8Encoder.encode(url)]\n });\n return encodeBech32(\"nrelay\", data);\n}\nfunction encodeTLV(tlv) {\n let entries = [];\n Object.entries(tlv).reverse().forEach(([t, vs]) => {\n vs.forEach((v) => {\n let entry = new Uint8Array(v.length + 2);\n entry.set([parseInt(t)], 0);\n entry.set([v.length], 1);\n entry.set(v, 2);\n entries.push(entry);\n });\n });\n return concatBytes(...entries);\n}\n\n// references.ts\nvar mentionRegex = /\\bnostr:((note|npub|naddr|nevent|nprofile)1\\w+)\\b|#\\[(\\d+)\\]/g;\nfunction parseReferences(evt) {\n let references = [];\n for (let ref of evt.content.matchAll(mentionRegex)) {\n if (ref[2]) {\n try {\n let { type, data } = decode(ref[1]);\n switch (type) {\n case \"npub\": {\n references.push({\n text: ref[0],\n profile: { pubkey: data, relays: [] }\n });\n break;\n }\n case \"nprofile\": {\n references.push({\n text: ref[0],\n profile: data\n });\n break;\n }\n case \"note\": {\n references.push({\n text: ref[0],\n event: { id: data, relays: [] }\n });\n break;\n }\n case \"nevent\": {\n references.push({\n text: ref[0],\n event: data\n });\n break;\n }\n case \"naddr\": {\n references.push({\n text: ref[0],\n address: data\n });\n break;\n }\n }\n } catch (err) {\n }\n } else if (ref[3]) {\n let idx = parseInt(ref[3], 10);\n let tag = evt.tags[idx];\n if (!tag)\n continue;\n switch (tag[0]) {\n case \"p\": {\n references.push({\n text: ref[0],\n profile: { pubkey: tag[1], relays: tag[2] ? [tag[2]] : [] }\n });\n break;\n }\n case \"e\": {\n references.push({\n text: ref[0],\n event: { id: tag[1], relays: tag[2] ? [tag[2]] : [] }\n });\n break;\n }\n case \"a\": {\n try {\n let [kind, pubkey, identifier] = tag[1].split(\":\");\n references.push({\n text: ref[0],\n address: {\n identifier,\n pubkey,\n kind: parseInt(kind, 10),\n relays: tag[2] ? [tag[2]] : []\n }\n });\n } catch (err) {\n }\n break;\n }\n }\n }\n }\n return references;\n}\n\n// nip04.ts\nvar nip04_exports = {};\n__export(nip04_exports, {\n decrypt: () => decrypt,\n encrypt: () => encrypt\n});\nimport { bytesToHex as bytesToHex3, randomBytes } from \"@noble/hashes/utils\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { cbc } from \"@noble/ciphers/aes\";\nimport { base64 } from \"@scure/base\";\nasync function encrypt(secretKey, pubkey, text) {\n const privkey = secretKey instanceof Uint8Array ? bytesToHex3(secretKey) : secretKey;\n const key = secp256k1.getSharedSecret(privkey, \"02\" + pubkey);\n const normalizedKey = getNormalizedX(key);\n let iv = Uint8Array.from(randomBytes(16));\n let plaintext = utf8Encoder.encode(text);\n let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext);\n let ctb64 = base64.encode(new Uint8Array(ciphertext));\n let ivb64 = base64.encode(new Uint8Array(iv.buffer));\n return `${ctb64}?iv=${ivb64}`;\n}\nasync function decrypt(secretKey, pubkey, data) {\n const privkey = secretKey instanceof Uint8Array ? bytesToHex3(secretKey) : secretKey;\n let [ctb64, ivb64] = data.split(\"?iv=\");\n let key = secp256k1.getSharedSecret(privkey, \"02\" + pubkey);\n let normalizedKey = getNormalizedX(key);\n let iv = base64.decode(ivb64);\n let ciphertext = base64.decode(ctb64);\n let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext);\n return utf8Decoder.decode(plaintext);\n}\nfunction getNormalizedX(key) {\n return key.slice(1, 33);\n}\n\n// nip05.ts\nvar nip05_exports = {};\n__export(nip05_exports, {\n NIP05_REGEX: () => NIP05_REGEX,\n isValid: () => isValid,\n queryProfile: () => queryProfile,\n searchDomain: () => searchDomain,\n useFetchImplementation: () => useFetchImplementation\n});\nvar NIP05_REGEX = /^(?:([\\w.+-]+)@)?([\\w_-]+(\\.[\\w_-]+)+)$/;\nvar _fetch;\ntry {\n _fetch = fetch;\n} catch {\n}\nfunction useFetchImplementation(fetchImplementation) {\n _fetch = fetchImplementation;\n}\nasync function searchDomain(domain, query = \"\") {\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${query}`;\n const res = await _fetch(url, { redirect: \"error\" });\n const json = await res.json();\n return json.names;\n } catch (_) {\n return {};\n }\n}\nasync function queryProfile(fullname) {\n const match = fullname.match(NIP05_REGEX);\n if (!match)\n return null;\n const [_, name = \"_\", domain] = match;\n try {\n const url = `https://${domain}/.well-known/nostr.json?name=${name}`;\n const res = await (await _fetch(url, { redirect: \"error\" })).json();\n let pubkey = res.names[name];\n return pubkey ? { pubkey, relays: res.relays?.[pubkey] } : null;\n } catch (_e) {\n return null;\n }\n}\nasync function isValid(pubkey, nip05) {\n let res = await queryProfile(nip05);\n return res ? res.pubkey === pubkey : false;\n}\n\n// nip10.ts\nvar nip10_exports = {};\n__export(nip10_exports, {\n parse: () => parse\n});\nfunction parse(event) {\n const result = {\n reply: void 0,\n root: void 0,\n mentions: [],\n profiles: []\n };\n const eTags = [];\n for (const tag of event.tags) {\n if (tag[0] === \"e\" && tag[1]) {\n eTags.push(tag);\n }\n if (tag[0] === \"p\" && tag[1]) {\n result.profiles.push({\n pubkey: tag[1],\n relays: tag[2] ? [tag[2]] : []\n });\n }\n }\n for (let eTagIndex = 0; eTagIndex < eTags.length; eTagIndex++) {\n const eTag = eTags[eTagIndex];\n const [_, eTagEventId, eTagRelayUrl, eTagMarker] = eTag;\n const eventPointer = {\n id: eTagEventId,\n relays: eTagRelayUrl ? [eTagRelayUrl] : []\n };\n const isFirstETag = eTagIndex === 0;\n const isLastETag = eTagIndex === eTags.length - 1;\n if (eTagMarker === \"root\") {\n result.root = eventPointer;\n continue;\n }\n if (eTagMarker === \"reply\") {\n result.reply = eventPointer;\n continue;\n }\n if (eTagMarker === \"mention\") {\n result.mentions.push(eventPointer);\n continue;\n }\n if (isFirstETag) {\n result.root = eventPointer;\n continue;\n }\n if (isLastETag) {\n result.reply = eventPointer;\n continue;\n }\n result.mentions.push(eventPointer);\n }\n return result;\n}\n\n// nip11.ts\nvar nip11_exports = {};\n__export(nip11_exports, {\n fetchRelayInformation: () => fetchRelayInformation,\n useFetchImplementation: () => useFetchImplementation2\n});\nvar _fetch2;\ntry {\n _fetch2 = fetch;\n} catch {\n}\nfunction useFetchImplementation2(fetchImplementation) {\n _fetch2 = fetchImplementation;\n}\nasync function fetchRelayInformation(url) {\n return await (await fetch(url.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\"), {\n headers: { Accept: \"application/nostr+json\" }\n })).json();\n}\n\n// nip13.ts\nvar nip13_exports = {};\n__export(nip13_exports, {\n getPow: () => getPow,\n minePow: () => minePow\n});\nfunction getPow(hex) {\n let count = 0;\n for (let i2 = 0; i2 < hex.length; i2++) {\n const nibble = parseInt(hex[i2], 16);\n if (nibble === 0) {\n count += 4;\n } else {\n count += Math.clz32(nibble) - 28;\n break;\n }\n }\n return count;\n}\nfunction minePow(unsigned, difficulty) {\n let count = 0;\n const event = unsigned;\n const tag = [\"nonce\", count.toString(), difficulty.toString()];\n event.tags.push(tag);\n while (true) {\n const now = Math.floor(new Date().getTime() / 1e3);\n if (now !== event.created_at) {\n count = 0;\n event.created_at = now;\n }\n tag[1] = (++count).toString();\n event.id = getEventHash(event);\n if (getPow(event.id) >= difficulty) {\n break;\n }\n }\n return event;\n}\n\n// nip18.ts\nvar nip18_exports = {};\n__export(nip18_exports, {\n finishRepostEvent: () => finishRepostEvent,\n getRepostedEvent: () => getRepostedEvent,\n getRepostedEventPointer: () => getRepostedEventPointer\n});\nfunction finishRepostEvent(t, reposted, relayUrl, privateKey) {\n return finalizeEvent(\n {\n kind: Repost,\n tags: [...t.tags ?? [], [\"e\", reposted.id, relayUrl], [\"p\", reposted.pubkey]],\n content: t.content === \"\" ? \"\" : JSON.stringify(reposted),\n created_at: t.created_at\n },\n privateKey\n );\n}\nfunction getRepostedEventPointer(event) {\n if (event.kind !== Repost) {\n return void 0;\n }\n let lastETag;\n let lastPTag;\n for (let i2 = event.tags.length - 1; i2 >= 0 && (lastETag === void 0 || lastPTag === void 0); i2--) {\n const tag = event.tags[i2];\n if (tag.length >= 2) {\n if (tag[0] === \"e\" && lastETag === void 0) {\n lastETag = tag;\n } else if (tag[0] === \"p\" && lastPTag === void 0) {\n lastPTag = tag;\n }\n }\n }\n if (lastETag === void 0) {\n return void 0;\n }\n return {\n id: lastETag[1],\n relays: [lastETag[2], lastPTag?.[2]].filter((x) => typeof x === \"string\"),\n author: lastPTag?.[1]\n };\n}\nfunction getRepostedEvent(event, { skipVerification } = {}) {\n const pointer = getRepostedEventPointer(event);\n if (pointer === void 0 || event.content === \"\") {\n return void 0;\n }\n let repostedEvent;\n try {\n repostedEvent = JSON.parse(event.content);\n } catch (error) {\n return void 0;\n }\n if (repostedEvent.id !== pointer.id) {\n return void 0;\n }\n if (!skipVerification && !verifyEvent(repostedEvent)) {\n return void 0;\n }\n return repostedEvent;\n}\n\n// nip21.ts\nvar nip21_exports = {};\n__export(nip21_exports, {\n NOSTR_URI_REGEX: () => NOSTR_URI_REGEX,\n parse: () => parse2,\n test: () => test\n});\nvar NOSTR_URI_REGEX = new RegExp(`nostr:(${BECH32_REGEX.source})`);\nfunction test(value) {\n return typeof value === \"string\" && new RegExp(`^${NOSTR_URI_REGEX.source}$`).test(value);\n}\nfunction parse2(uri) {\n const match = uri.match(new RegExp(`^${NOSTR_URI_REGEX.source}$`));\n if (!match)\n throw new Error(`Invalid Nostr URI: ${uri}`);\n return {\n uri: match[0],\n value: match[1],\n decoded: decode(match[1])\n };\n}\n\n// nip25.ts\nvar nip25_exports = {};\n__export(nip25_exports, {\n finishReactionEvent: () => finishReactionEvent,\n getReactedEventPointer: () => getReactedEventPointer\n});\nfunction finishReactionEvent(t, reacted, privateKey) {\n const inheritedTags = reacted.tags.filter((tag) => tag.length >= 2 && (tag[0] === \"e\" || tag[0] === \"p\"));\n return finalizeEvent(\n {\n ...t,\n kind: Reaction,\n tags: [...t.tags ?? [], ...inheritedTags, [\"e\", reacted.id], [\"p\", reacted.pubkey]],\n content: t.content ?? \"+\"\n },\n privateKey\n );\n}\nfunction getReactedEventPointer(event) {\n if (event.kind !== Reaction) {\n return void 0;\n }\n let lastETag;\n let lastPTag;\n for (let i2 = event.tags.length - 1; i2 >= 0 && (lastETag === void 0 || lastPTag === void 0); i2--) {\n const tag = event.tags[i2];\n if (tag.length >= 2) {\n if (tag[0] === \"e\" && lastETag === void 0) {\n lastETag = tag;\n } else if (tag[0] === \"p\" && lastPTag === void 0) {\n lastPTag = tag;\n }\n }\n }\n if (lastETag === void 0 || lastPTag === void 0) {\n return void 0;\n }\n return {\n id: lastETag[1],\n relays: [lastETag[2], lastPTag[2]].filter((x) => x !== void 0),\n author: lastPTag[1]\n };\n}\n\n// nip27.ts\nvar nip27_exports = {};\n__export(nip27_exports, {\n matchAll: () => matchAll,\n regex: () => regex,\n replaceAll: () => replaceAll\n});\nvar regex = () => new RegExp(`\\\\b${NOSTR_URI_REGEX.source}\\\\b`, \"g\");\nfunction* matchAll(content) {\n const matches = content.matchAll(regex());\n for (const match of matches) {\n try {\n const [uri, value] = match;\n yield {\n uri,\n value,\n decoded: decode(value),\n start: match.index,\n end: match.index + uri.length\n };\n } catch (_e) {\n }\n }\n}\nfunction replaceAll(content, replacer) {\n return content.replaceAll(regex(), (uri, value) => {\n return replacer({\n uri,\n value,\n decoded: decode(value)\n });\n });\n}\n\n// nip28.ts\nvar nip28_exports = {};\n__export(nip28_exports, {\n channelCreateEvent: () => channelCreateEvent,\n channelHideMessageEvent: () => channelHideMessageEvent,\n channelMessageEvent: () => channelMessageEvent,\n channelMetadataEvent: () => channelMetadataEvent,\n channelMuteUserEvent: () => channelMuteUserEvent\n});\nvar channelCreateEvent = (t, privateKey) => {\n let content;\n if (typeof t.content === \"object\") {\n content = JSON.stringify(t.content);\n } else if (typeof t.content === \"string\") {\n content = t.content;\n } else {\n return void 0;\n }\n return finalizeEvent(\n {\n kind: ChannelCreation,\n tags: [...t.tags ?? []],\n content,\n created_at: t.created_at\n },\n privateKey\n );\n};\nvar channelMetadataEvent = (t, privateKey) => {\n let content;\n if (typeof t.content === \"object\") {\n content = JSON.stringify(t.content);\n } else if (typeof t.content === \"string\") {\n content = t.content;\n } else {\n return void 0;\n }\n return finalizeEvent(\n {\n kind: ChannelMetadata,\n tags: [[\"e\", t.channel_create_event_id], ...t.tags ?? []],\n content,\n created_at: t.created_at\n },\n privateKey\n );\n};\nvar channelMessageEvent = (t, privateKey) => {\n const tags = [[\"e\", t.channel_create_event_id, t.relay_url, \"root\"]];\n if (t.reply_to_channel_message_event_id) {\n tags.push([\"e\", t.reply_to_channel_message_event_id, t.relay_url, \"reply\"]);\n }\n return finalizeEvent(\n {\n kind: ChannelMessage,\n tags: [...tags, ...t.tags ?? []],\n content: t.content,\n created_at: t.created_at\n },\n privateKey\n );\n};\nvar channelHideMessageEvent = (t, privateKey) => {\n let content;\n if (typeof t.content === \"object\") {\n content = JSON.stringify(t.content);\n } else if (typeof t.content === \"string\") {\n content = t.content;\n } else {\n return void 0;\n }\n return finalizeEvent(\n {\n kind: ChannelHideMessage,\n tags: [[\"e\", t.channel_message_event_id], ...t.tags ?? []],\n content,\n created_at: t.created_at\n },\n privateKey\n );\n};\nvar channelMuteUserEvent = (t, privateKey) => {\n let content;\n if (typeof t.content === \"object\") {\n content = JSON.stringify(t.content);\n } else if (typeof t.content === \"string\") {\n content = t.content;\n } else {\n return void 0;\n }\n return finalizeEvent(\n {\n kind: ChannelMuteUser,\n tags: [[\"p\", t.pubkey_to_mute], ...t.tags ?? []],\n content,\n created_at: t.created_at\n },\n privateKey\n );\n};\n\n// nip30.ts\nvar nip30_exports = {};\n__export(nip30_exports, {\n EMOJI_SHORTCODE_REGEX: () => EMOJI_SHORTCODE_REGEX,\n matchAll: () => matchAll2,\n regex: () => regex2,\n replaceAll: () => replaceAll2\n});\nvar EMOJI_SHORTCODE_REGEX = /:(\\w+):/;\nvar regex2 = () => new RegExp(`\\\\B${EMOJI_SHORTCODE_REGEX.source}\\\\B`, \"g\");\nfunction* matchAll2(content) {\n const matches = content.matchAll(regex2());\n for (const match of matches) {\n try {\n const [shortcode, name] = match;\n yield {\n shortcode,\n name,\n start: match.index,\n end: match.index + shortcode.length\n };\n } catch (_e) {\n }\n }\n}\nfunction replaceAll2(content, replacer) {\n return content.replaceAll(regex2(), (shortcode, name) => {\n return replacer({\n shortcode,\n name\n });\n });\n}\n\n// nip39.ts\nvar nip39_exports = {};\n__export(nip39_exports, {\n useFetchImplementation: () => useFetchImplementation3,\n validateGithub: () => validateGithub\n});\nvar _fetch3;\ntry {\n _fetch3 = fetch;\n} catch {\n}\nfunction useFetchImplementation3(fetchImplementation) {\n _fetch3 = fetchImplementation;\n}\nasync function validateGithub(pubkey, username, proof) {\n try {\n let res = await (await _fetch3(`https://gist.github.com/${username}/${proof}/raw`)).text();\n return res === `Verifying that I control the following Nostr public key: ${pubkey}`;\n } catch (_) {\n return false;\n }\n}\n\n// nip44.ts\nvar nip44_exports = {};\n__export(nip44_exports, {\n default: () => nip44_default,\n v2: () => v2\n});\nimport { chacha20 } from \"@noble/ciphers/chacha\";\nimport { equalBytes } from \"@noble/ciphers/utils\";\nimport { secp256k1 as secp256k12 } from \"@noble/curves/secp256k1\";\nimport { extract as hkdf_extract, expand as hkdf_expand } from \"@noble/hashes/hkdf\";\nimport { hmac } from \"@noble/hashes/hmac\";\nimport { sha256 as sha2562 } from \"@noble/hashes/sha256\";\nimport { concatBytes as concatBytes2, randomBytes as randomBytes2, utf8ToBytes } from \"@noble/hashes/utils\";\nimport { base64 as base642 } from \"@scure/base\";\nvar decoder = new TextDecoder();\nvar _u = class {\n static utf8Decode(bytes) {\n return decoder.decode(bytes);\n }\n static getConversationKey(privkeyA, pubkeyB) {\n const sharedX = secp256k12.getSharedSecret(privkeyA, \"02\" + pubkeyB).subarray(1, 33);\n return hkdf_extract(sha2562, sharedX, \"nip44-v2\");\n }\n static getMessageKeys(conversationKey, nonce) {\n const keys = hkdf_expand(sha2562, conversationKey, nonce, 76);\n return {\n chacha_key: keys.subarray(0, 32),\n chacha_nonce: keys.subarray(32, 44),\n hmac_key: keys.subarray(44, 76)\n };\n }\n static calcPaddedLen(len) {\n if (!Number.isSafeInteger(len) || len < 1)\n throw new Error(\"expected positive integer\");\n if (len <= 32)\n return 32;\n const nextPower = 1 << Math.floor(Math.log2(len - 1)) + 1;\n const chunk = nextPower <= 256 ? 32 : nextPower / 8;\n return chunk * (Math.floor((len - 1) / chunk) + 1);\n }\n static writeU16BE(num) {\n if (!Number.isSafeInteger(num) || num < _u.minPlaintextSize || num > _u.maxPlaintextSize)\n throw new Error(\"invalid plaintext size: must be between 1 and 65535 bytes\");\n const arr = new Uint8Array(2);\n new DataView(arr.buffer).setUint16(0, num, false);\n return arr;\n }\n static pad(plaintext) {\n const unpadded = _u.utf8Encode(plaintext);\n const unpaddedLen = unpadded.length;\n const prefix = _u.writeU16BE(unpaddedLen);\n const suffix = new Uint8Array(_u.calcPaddedLen(unpaddedLen) - unpaddedLen);\n return concatBytes2(prefix, unpadded, suffix);\n }\n static unpad(padded) {\n const unpaddedLen = new DataView(padded.buffer).getUint16(0);\n const unpadded = padded.subarray(2, 2 + unpaddedLen);\n if (unpaddedLen < _u.minPlaintextSize || unpaddedLen > _u.maxPlaintextSize || unpadded.length !== unpaddedLen || padded.length !== 2 + _u.calcPaddedLen(unpaddedLen))\n throw new Error(\"invalid padding\");\n return _u.utf8Decode(unpadded);\n }\n static hmacAad(key, message, aad) {\n if (aad.length !== 32)\n throw new Error(\"AAD associated data must be 32 bytes\");\n const combined = concatBytes2(aad, message);\n return hmac(sha2562, key, combined);\n }\n static decodePayload(payload) {\n if (typeof payload !== \"string\")\n throw new Error(\"payload must be a valid string\");\n const plen = payload.length;\n if (plen < 132 || plen > 87472)\n throw new Error(\"invalid payload length: \" + plen);\n if (payload[0] === \"#\")\n throw new Error(\"unknown encryption version\");\n let data;\n try {\n data = base642.decode(payload);\n } catch (error) {\n throw new Error(\"invalid base64: \" + error.message);\n }\n const dlen = data.length;\n if (dlen < 99 || dlen > 65603)\n throw new Error(\"invalid data length: \" + dlen);\n const vers = data[0];\n if (vers !== 2)\n throw new Error(\"unknown encryption version \" + vers);\n return {\n nonce: data.subarray(1, 33),\n ciphertext: data.subarray(33, -32),\n mac: data.subarray(-32)\n };\n }\n};\nvar u = _u;\n__publicField(u, \"minPlaintextSize\", 1);\n__publicField(u, \"maxPlaintextSize\", 65535);\n__publicField(u, \"utf8Encode\", utf8ToBytes);\nvar v2 = class {\n static encrypt(plaintext, conversationKey, nonce = randomBytes2(32)) {\n const { chacha_key, chacha_nonce, hmac_key } = u.getMessageKeys(conversationKey, nonce);\n const padded = u.pad(plaintext);\n const ciphertext = chacha20(chacha_key, chacha_nonce, padded);\n const mac = u.hmacAad(hmac_key, ciphertext, nonce);\n return base642.encode(concatBytes2(new Uint8Array([2]), nonce, ciphertext, mac));\n }\n static decrypt(payload, conversationKey) {\n const { nonce, ciphertext, mac } = u.decodePayload(payload);\n const { chacha_key, chacha_nonce, hmac_key } = u.getMessageKeys(conversationKey, nonce);\n const calculatedMac = u.hmacAad(hmac_key, ciphertext, nonce);\n if (!equalBytes(calculatedMac, mac))\n throw new Error(\"invalid MAC\");\n const padded = chacha20(chacha_key, chacha_nonce, ciphertext);\n return u.unpad(padded);\n }\n};\n__publicField(v2, \"utils\", u);\nvar nip44_default = { v2 };\n\n// nip47.ts\nvar nip47_exports = {};\n__export(nip47_exports, {\n makeNwcRequestEvent: () => makeNwcRequestEvent,\n parseConnectionString: () => parseConnectionString\n});\nfunction parseConnectionString(connectionString) {\n const { pathname, searchParams } = new URL(connectionString);\n const pubkey = pathname;\n const relay = searchParams.get(\"relay\");\n const secret = searchParams.get(\"secret\");\n if (!pubkey || !relay || !secret) {\n throw new Error(\"invalid connection string\");\n }\n return { pubkey, relay, secret };\n}\nasync function makeNwcRequestEvent(pubkey, secretKey, invoice) {\n const content = {\n method: \"pay_invoice\",\n params: {\n invoice\n }\n };\n const encryptedContent = await encrypt(secretKey, pubkey, JSON.stringify(content));\n const eventTemplate = {\n kind: NWCWalletRequest,\n created_at: Math.round(Date.now() / 1e3),\n content: encryptedContent,\n tags: [[\"p\", pubkey]]\n };\n return finalizeEvent(eventTemplate, secretKey);\n}\n\n// nip57.ts\nvar nip57_exports = {};\n__export(nip57_exports, {\n getZapEndpoint: () => getZapEndpoint,\n makeZapReceipt: () => makeZapReceipt,\n makeZapRequest: () => makeZapRequest,\n useFetchImplementation: () => useFetchImplementation4,\n validateZapRequest: () => validateZapRequest\n});\nimport { bech32 as bech322 } from \"@scure/base\";\nvar _fetch4;\ntry {\n _fetch4 = fetch;\n} catch {\n}\nfunction useFetchImplementation4(fetchImplementation) {\n _fetch4 = fetchImplementation;\n}\nasync function getZapEndpoint(metadata) {\n try {\n let lnurl = \"\";\n let { lud06, lud16 } = JSON.parse(metadata.content);\n if (lud06) {\n let { words } = bech322.decode(lud06, 1e3);\n let data = bech322.fromWords(words);\n lnurl = utf8Decoder.decode(data);\n } else if (lud16) {\n let [name, domain] = lud16.split(\"@\");\n lnurl = new URL(`/.well-known/lnurlp/${name}`, `https://${domain}`).toString();\n } else {\n return null;\n }\n let res = await _fetch4(lnurl);\n let body = await res.json();\n if (body.allowsNostr && body.nostrPubkey) {\n return body.callback;\n }\n } catch (err) {\n }\n return null;\n}\nfunction makeZapRequest({\n profile,\n event,\n amount,\n relays,\n comment = \"\"\n}) {\n if (!amount)\n throw new Error(\"amount not given\");\n if (!profile)\n throw new Error(\"profile not given\");\n let zr = {\n kind: 9734,\n created_at: Math.round(Date.now() / 1e3),\n content: comment,\n tags: [\n [\"p\", profile],\n [\"amount\", amount.toString()],\n [\"relays\", ...relays]\n ]\n };\n if (event) {\n zr.tags.push([\"e\", event]);\n }\n return zr;\n}\nfunction validateZapRequest(zapRequestString) {\n let zapRequest;\n try {\n zapRequest = JSON.parse(zapRequestString);\n } catch (err) {\n return \"Invalid zap request JSON.\";\n }\n if (!validateEvent(zapRequest))\n return \"Zap request is not a valid Nostr event.\";\n if (!verifyEvent(zapRequest))\n return \"Invalid signature on zap request.\";\n let p = zapRequest.tags.find(([t, v]) => t === \"p\" && v);\n if (!p)\n return \"Zap request doesn't have a 'p' tag.\";\n if (!p[1].match(/^[a-f0-9]{64}$/))\n return \"Zap request 'p' tag is not valid hex.\";\n let e = zapRequest.tags.find(([t, v]) => t === \"e\" && v);\n if (e && !e[1].match(/^[a-f0-9]{64}$/))\n return \"Zap request 'e' tag is not valid hex.\";\n let relays = zapRequest.tags.find(([t, v]) => t === \"relays\" && v);\n if (!relays)\n return \"Zap request doesn't have a 'relays' tag.\";\n return null;\n}\nfunction makeZapReceipt({\n zapRequest,\n preimage,\n bolt11,\n paidAt\n}) {\n let zr = JSON.parse(zapRequest);\n let tagsFromZapRequest = zr.tags.filter(([t]) => t === \"e\" || t === \"p\" || t === \"a\");\n let zap = {\n kind: 9735,\n created_at: Math.round(paidAt.getTime() / 1e3),\n content: \"\",\n tags: [...tagsFromZapRequest, [\"P\", zr.pubkey], [\"bolt11\", bolt11], [\"description\", zapRequest]]\n };\n if (preimage) {\n zap.tags.push([\"preimage\", preimage]);\n }\n return zap;\n}\n\n// nip98.ts\nvar nip98_exports = {};\n__export(nip98_exports, {\n getToken: () => getToken,\n hashPayload: () => hashPayload,\n unpackEventFromToken: () => unpackEventFromToken,\n validateEvent: () => validateEvent2,\n validateEventKind: () => validateEventKind,\n validateEventMethodTag: () => validateEventMethodTag,\n validateEventPayloadTag: () => validateEventPayloadTag,\n validateEventTimestamp: () => validateEventTimestamp,\n validateEventUrlTag: () => validateEventUrlTag,\n validateToken: () => validateToken\n});\nimport { sha256 as sha2563 } from \"@noble/hashes/sha256\";\nimport { bytesToHex as bytesToHex4 } from \"@noble/hashes/utils\";\nimport { base64 as base643 } from \"@scure/base\";\nvar _authorizationScheme = \"Nostr \";\nasync function getToken(loginUrl, httpMethod, sign, includeAuthorizationScheme = false, payload) {\n const event = {\n kind: HTTPAuth,\n tags: [\n [\"u\", loginUrl],\n [\"method\", httpMethod]\n ],\n created_at: Math.round(new Date().getTime() / 1e3),\n content: \"\"\n };\n if (payload) {\n event.tags.push([\"payload\", hashPayload(payload)]);\n }\n const signedEvent = await sign(event);\n const authorizationScheme = includeAuthorizationScheme ? _authorizationScheme : \"\";\n return authorizationScheme + base643.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));\n}\nasync function validateToken(token, url, method) {\n const event = await unpackEventFromToken(token).catch((error) => {\n throw error;\n });\n const valid = await validateEvent2(event, url, method).catch((error) => {\n throw error;\n });\n return valid;\n}\nasync function unpackEventFromToken(token) {\n if (!token) {\n throw new Error(\"Missing token\");\n }\n token = token.replace(_authorizationScheme, \"\");\n const eventB64 = utf8Decoder.decode(base643.decode(token));\n if (!eventB64 || eventB64.length === 0 || !eventB64.startsWith(\"{\")) {\n throw new Error(\"Invalid token\");\n }\n const event = JSON.parse(eventB64);\n return event;\n}\nfunction validateEventTimestamp(event) {\n if (!event.created_at) {\n return false;\n }\n return Math.round(new Date().getTime() / 1e3) - event.created_at < 60;\n}\nfunction validateEventKind(event) {\n return event.kind === HTTPAuth;\n}\nfunction validateEventUrlTag(event, url) {\n const urlTag = event.tags.find((t) => t[0] === \"u\");\n if (!urlTag) {\n return false;\n }\n return urlTag.length > 0 && urlTag[1] === url;\n}\nfunction validateEventMethodTag(event, method) {\n const methodTag = event.tags.find((t) => t[0] === \"method\");\n if (!methodTag) {\n return false;\n }\n return methodTag.length > 0 && methodTag[1].toLowerCase() === method.toLowerCase();\n}\nfunction hashPayload(payload) {\n const hash = sha2563(utf8Encoder.encode(JSON.stringify(payload)));\n return bytesToHex4(hash);\n}\nfunction validateEventPayloadTag(event, payload) {\n const payloadTag = event.tags.find((t) => t[0] === \"payload\");\n if (!payloadTag) {\n return false;\n }\n const payloadHash = hashPayload(payload);\n return payloadTag.length > 0 && payloadTag[1] === payloadHash;\n}\nasync function validateEvent2(event, url, method, body) {\n if (!verifyEvent(event)) {\n throw new Error(\"Invalid nostr event, signature invalid\");\n }\n if (!validateEventKind(event)) {\n throw new Error(\"Invalid nostr event, kind invalid\");\n }\n if (!validateEventTimestamp(event)) {\n throw new Error(\"Invalid nostr event, created_at timestamp invalid\");\n }\n if (!validateEventUrlTag(event, url)) {\n throw new Error(\"Invalid nostr event, url tag invalid\");\n }\n if (!validateEventMethodTag(event, method)) {\n throw new Error(\"Invalid nostr event, method tag invalid\");\n }\n if (Boolean(body) && typeof body === \"object\" && Object.keys(body).length > 0) {\n if (!validateEventPayloadTag(event, body)) {\n throw new Error(\"Invalid nostr event, payload tag does not match request body hash\");\n }\n }\n return true;\n}\nexport {\n AbstractRelay,\n AbstractSimplePool,\n Relay,\n SimplePool,\n Subscription,\n finalizeEvent,\n fakejson_exports as fj,\n generateSecretKey,\n getEventHash,\n getFilterLimit,\n getPublicKey,\n kinds_exports as kinds,\n matchFilter,\n matchFilters,\n mergeFilters,\n nip04_exports as nip04,\n nip05_exports as nip05,\n nip10_exports as nip10,\n nip11_exports as nip11,\n nip13_exports as nip13,\n nip18_exports as nip18,\n nip19_exports as nip19,\n nip21_exports as nip21,\n nip25_exports as nip25,\n nip27_exports as nip27,\n nip28_exports as nip28,\n nip30_exports as nip30,\n nip39_exports as nip39,\n nip42_exports as nip42,\n nip44_exports as nip44,\n nip47_exports as nip47,\n nip57_exports as nip57,\n nip98_exports as nip98,\n parseReferences,\n relayConnect,\n serializeEvent,\n sortEvents,\n useWebSocketImplementation,\n utils_exports as utils,\n validateEvent,\n verifiedSymbol,\n verifyEvent\n};\n","/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */\nexport function assertNumber(n) {\n if (!Number.isSafeInteger(n))\n throw new Error(`Wrong integer: ${n}`);\n}\nfunction chain(...args) {\n const wrap = (a, b) => (c) => a(b(c));\n const encode = Array.from(args)\n .reverse()\n .reduce((acc, i) => (acc ? wrap(acc, i.encode) : i.encode), undefined);\n const decode = args.reduce((acc, i) => (acc ? wrap(acc, i.decode) : i.decode), undefined);\n return { encode, decode };\n}\nfunction alphabet(alphabet) {\n return {\n encode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('alphabet.encode input should be an array of numbers');\n return digits.map((i) => {\n assertNumber(i);\n if (i < 0 || i >= alphabet.length)\n throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);\n return alphabet[i];\n });\n },\n decode: (input) => {\n if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))\n throw new Error('alphabet.decode input should be array of strings');\n return input.map((letter) => {\n if (typeof letter !== 'string')\n throw new Error(`alphabet.decode: not string element=${letter}`);\n const index = alphabet.indexOf(letter);\n if (index === -1)\n throw new Error(`Unknown letter: \"${letter}\". Allowed: ${alphabet}`);\n return index;\n });\n },\n };\n}\nfunction join(separator = '') {\n if (typeof separator !== 'string')\n throw new Error('join separator should be string');\n return {\n encode: (from) => {\n if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))\n throw new Error('join.encode input should be array of strings');\n for (let i of from)\n if (typeof i !== 'string')\n throw new Error(`join.encode: non-string input=${i}`);\n return from.join(separator);\n },\n decode: (to) => {\n if (typeof to !== 'string')\n throw new Error('join.decode input should be string');\n return to.split(separator);\n },\n };\n}\nfunction padding(bits, chr = '=') {\n assertNumber(bits);\n if (typeof chr !== 'string')\n throw new Error('padding chr should be string');\n return {\n encode(data) {\n if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))\n throw new Error('padding.encode input should be array of strings');\n for (let i of data)\n if (typeof i !== 'string')\n throw new Error(`padding.encode: non-string input=${i}`);\n while ((data.length * bits) % 8)\n data.push(chr);\n return data;\n },\n decode(input) {\n if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))\n throw new Error('padding.encode input should be array of strings');\n for (let i of input)\n if (typeof i !== 'string')\n throw new Error(`padding.decode: non-string input=${i}`);\n let end = input.length;\n if ((end * bits) % 8)\n throw new Error('Invalid padding: string should have whole number of bytes');\n for (; end > 0 && input[end - 1] === chr; end--) {\n if (!(((end - 1) * bits) % 8))\n throw new Error('Invalid padding: string has too much padding');\n }\n return input.slice(0, end);\n },\n };\n}\nfunction normalize(fn) {\n if (typeof fn !== 'function')\n throw new Error('normalize fn should be function');\n return { encode: (from) => from, decode: (to) => fn(to) };\n}\nfunction convertRadix(data, from, to) {\n if (from < 2)\n throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);\n if (to < 2)\n throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);\n if (!Array.isArray(data))\n throw new Error('convertRadix: data should be array');\n if (!data.length)\n return [];\n let pos = 0;\n const res = [];\n const digits = Array.from(data);\n digits.forEach((d) => {\n assertNumber(d);\n if (d < 0 || d >= from)\n throw new Error(`Wrong integer: ${d}`);\n });\n while (true) {\n let carry = 0;\n let done = true;\n for (let i = pos; i < digits.length; i++) {\n const digit = digits[i];\n const digitBase = from * carry + digit;\n if (!Number.isSafeInteger(digitBase) ||\n (from * carry) / from !== carry ||\n digitBase - digit !== from * carry) {\n throw new Error('convertRadix: carry overflow');\n }\n carry = digitBase % to;\n digits[i] = Math.floor(digitBase / to);\n if (!Number.isSafeInteger(digits[i]) || digits[i] * to + carry !== digitBase)\n throw new Error('convertRadix: carry overflow');\n if (!done)\n continue;\n else if (!digits[i])\n pos = i;\n else\n done = false;\n }\n res.push(carry);\n if (done)\n break;\n }\n for (let i = 0; i < data.length - 1 && data[i] === 0; i++)\n res.push(0);\n return res.reverse();\n}\nconst gcd = (a, b) => (!b ? a : gcd(b, a % b));\nconst radix2carry = (from, to) => from + (to - gcd(from, to));\nfunction convertRadix2(data, from, to, padding) {\n if (!Array.isArray(data))\n throw new Error('convertRadix2: data should be array');\n if (from <= 0 || from > 32)\n throw new Error(`convertRadix2: wrong from=${from}`);\n if (to <= 0 || to > 32)\n throw new Error(`convertRadix2: wrong to=${to}`);\n if (radix2carry(from, to) > 32) {\n throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);\n }\n let carry = 0;\n let pos = 0;\n const mask = 2 ** to - 1;\n const res = [];\n for (const n of data) {\n assertNumber(n);\n if (n >= 2 ** from)\n throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);\n carry = (carry << from) | n;\n if (pos + from > 32)\n throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);\n pos += from;\n for (; pos >= to; pos -= to)\n res.push(((carry >> (pos - to)) & mask) >>> 0);\n carry &= 2 ** pos - 1;\n }\n carry = (carry << (to - pos)) & mask;\n if (!padding && pos >= from)\n throw new Error('Excess padding');\n if (!padding && carry)\n throw new Error(`Non-zero padding: ${carry}`);\n if (padding && pos > 0)\n res.push(carry >>> 0);\n return res;\n}\nfunction radix(num) {\n assertNumber(num);\n return {\n encode: (bytes) => {\n if (!(bytes instanceof Uint8Array))\n throw new Error('radix.encode input should be Uint8Array');\n return convertRadix(Array.from(bytes), 2 ** 8, num);\n },\n decode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('radix.decode input should be array of strings');\n return Uint8Array.from(convertRadix(digits, num, 2 ** 8));\n },\n };\n}\nfunction radix2(bits, revPadding = false) {\n assertNumber(bits);\n if (bits <= 0 || bits > 32)\n throw new Error('radix2: bits should be in (0..32]');\n if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)\n throw new Error('radix2: carry overflow');\n return {\n encode: (bytes) => {\n if (!(bytes instanceof Uint8Array))\n throw new Error('radix2.encode input should be Uint8Array');\n return convertRadix2(Array.from(bytes), 8, bits, !revPadding);\n },\n decode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('radix2.decode input should be array of strings');\n return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));\n },\n };\n}\nfunction unsafeWrapper(fn) {\n if (typeof fn !== 'function')\n throw new Error('unsafeWrapper fn should be function');\n return function (...args) {\n try {\n return fn.apply(null, args);\n }\n catch (e) { }\n };\n}\nfunction checksum(len, fn) {\n assertNumber(len);\n if (typeof fn !== 'function')\n throw new Error('checksum fn should be function');\n return {\n encode(data) {\n if (!(data instanceof Uint8Array))\n throw new Error('checksum.encode: input should be Uint8Array');\n const checksum = fn(data).slice(0, len);\n const res = new Uint8Array(data.length + len);\n res.set(data);\n res.set(checksum, data.length);\n return res;\n },\n decode(data) {\n if (!(data instanceof Uint8Array))\n throw new Error('checksum.decode: input should be Uint8Array');\n const payload = data.slice(0, -len);\n const newChecksum = fn(payload).slice(0, len);\n const oldChecksum = data.slice(-len);\n for (let i = 0; i < len; i++)\n if (newChecksum[i] !== oldChecksum[i])\n throw new Error('Invalid checksum');\n return payload;\n },\n };\n}\nexport const utils = { alphabet, chain, checksum, radix, radix2, join, padding };\nexport const base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));\nexport const base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));\nexport const base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));\nexport const base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));\nexport const base64 = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));\nexport const base64url = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));\nconst genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));\nexport const base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');\nexport const base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');\nexport const base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');\nconst XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];\nexport const base58xmr = {\n encode(data) {\n let res = '';\n for (let i = 0; i < data.length; i += 8) {\n const block = data.subarray(i, i + 8);\n res += base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');\n }\n return res;\n },\n decode(str) {\n let res = [];\n for (let i = 0; i < str.length; i += 11) {\n const slice = str.slice(i, i + 11);\n const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);\n const block = base58.decode(slice);\n for (let j = 0; j < block.length - blockLen; j++) {\n if (block[j] !== 0)\n throw new Error('base58xmr: wrong padding');\n }\n res = res.concat(Array.from(block.slice(block.length - blockLen)));\n }\n return Uint8Array.from(res);\n },\n};\nexport const base58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), base58);\nconst BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));\nconst POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\nfunction bech32Polymod(pre) {\n const b = pre >> 25;\n let chk = (pre & 0x1ffffff) << 5;\n for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {\n if (((b >> i) & 1) === 1)\n chk ^= POLYMOD_GENERATORS[i];\n }\n return chk;\n}\nfunction bechChecksum(prefix, words, encodingConst = 1) {\n const len = prefix.length;\n let chk = 1;\n for (let i = 0; i < len; i++) {\n const c = prefix.charCodeAt(i);\n if (c < 33 || c > 126)\n throw new Error(`Invalid prefix (${prefix})`);\n chk = bech32Polymod(chk) ^ (c >> 5);\n }\n chk = bech32Polymod(chk);\n for (let i = 0; i < len; i++)\n chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (let v of words)\n chk = bech32Polymod(chk) ^ v;\n for (let i = 0; i < 6; i++)\n chk = bech32Polymod(chk);\n chk ^= encodingConst;\n return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));\n}\nfunction genBech32(encoding) {\n const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;\n const _words = radix2(5);\n const fromWords = _words.decode;\n const toWords = _words.encode;\n const fromWordsUnsafe = unsafeWrapper(fromWords);\n function encode(prefix, words, limit = 90) {\n if (typeof prefix !== 'string')\n throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);\n if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))\n throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);\n const actualLength = prefix.length + 7 + words.length;\n if (limit !== false && actualLength > limit)\n throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);\n prefix = prefix.toLowerCase();\n return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;\n }\n function decode(str, limit = 90) {\n if (typeof str !== 'string')\n throw new Error(`bech32.decode input should be string, not ${typeof str}`);\n if (str.length < 8 || (limit !== false && str.length > limit))\n throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit})`);\n const lowered = str.toLowerCase();\n if (str !== lowered && str !== str.toUpperCase())\n throw new Error(`String must be lowercase or uppercase`);\n str = lowered;\n const sepIndex = str.lastIndexOf('1');\n if (sepIndex === 0 || sepIndex === -1)\n throw new Error(`Letter \"1\" must be present between prefix and data only`);\n const prefix = str.slice(0, sepIndex);\n const _words = str.slice(sepIndex + 1);\n if (_words.length < 6)\n throw new Error('Data must be at least 6 characters long');\n const words = BECH_ALPHABET.decode(_words).slice(0, -6);\n const sum = bechChecksum(prefix, words, ENCODING_CONST);\n if (!_words.endsWith(sum))\n throw new Error(`Invalid checksum in ${str}: expected \"${sum}\"`);\n return { prefix, words };\n }\n const decodeUnsafe = unsafeWrapper(decode);\n function decodeToBytes(str) {\n const { prefix, words } = decode(str, false);\n return { prefix, words, bytes: fromWords(words) };\n }\n return { encode, decode, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };\n}\nexport const bech32 = genBech32('bech32');\nexport const bech32m = genBech32('bech32m');\nexport const utf8 = {\n encode: (data) => new TextDecoder().decode(data),\n decode: (str) => new TextEncoder().encode(str),\n};\nexport const hex = chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {\n if (typeof s !== 'string' || s.length % 2)\n throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);\n return s.toLowerCase();\n}));\nconst CODERS = {\n utf8, hex, base16, base32, base64, base64url, base58, base58xmr\n};\nconst coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(', ')}`;\nexport const bytesToString = (type, bytes) => {\n if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))\n throw new TypeError(coderTypeError);\n if (!(bytes instanceof Uint8Array))\n throw new TypeError('bytesToString() expects Uint8Array');\n return CODERS[type].encode(bytes);\n};\nexport const str = bytesToString;\nexport const stringToBytes = (type, str) => {\n if (!CODERS.hasOwnProperty(type))\n throw new TypeError(coderTypeError);\n if (typeof str !== 'string')\n throw new TypeError('stringToBytes() expects string');\n return CODERS[type].decode(str);\n};\nexport const bytes = stringToBytes;\n","/**\n * @typedef {import('./lib/util/info.js').Info} Info\n * @typedef {import('./lib/util/schema.js').Schema} Schema\n */\n\nimport {merge} from './lib/util/merge.js'\nimport {xlink} from './lib/xlink.js'\nimport {xml} from './lib/xml.js'\nimport {xmlns} from './lib/xmlns.js'\nimport {aria} from './lib/aria.js'\nimport {html as htmlBase} from './lib/html.js'\nimport {svg as svgBase} from './lib/svg.js'\n\nexport {find} from './lib/find.js'\nexport {hastToReact} from './lib/hast-to-react.js'\nexport {normalize} from './lib/normalize.js'\nexport const html = merge([xml, xlink, xmlns, aria, htmlBase], 'html')\nexport const svg = merge([xml, xlink, xmlns, aria, svgBase], 'svg')\n","import {booleanish, number, spaceSeparated} from './util/types.js'\nimport {create} from './util/create.js'\n\nexport const aria = create({\n transform(_, prop) {\n return prop === 'role' ? prop : 'aria-' + prop.slice(4).toLowerCase()\n },\n properties: {\n ariaActiveDescendant: null,\n ariaAtomic: booleanish,\n ariaAutoComplete: null,\n ariaBusy: booleanish,\n ariaChecked: booleanish,\n ariaColCount: number,\n ariaColIndex: number,\n ariaColSpan: number,\n ariaControls: spaceSeparated,\n ariaCurrent: null,\n ariaDescribedBy: spaceSeparated,\n ariaDetails: null,\n ariaDisabled: booleanish,\n ariaDropEffect: spaceSeparated,\n ariaErrorMessage: null,\n ariaExpanded: booleanish,\n ariaFlowTo: spaceSeparated,\n ariaGrabbed: booleanish,\n ariaHasPopup: null,\n ariaHidden: booleanish,\n ariaInvalid: null,\n ariaKeyShortcuts: null,\n ariaLabel: null,\n ariaLabelledBy: spaceSeparated,\n ariaLevel: number,\n ariaLive: null,\n ariaModal: booleanish,\n ariaMultiLine: booleanish,\n ariaMultiSelectable: booleanish,\n ariaOrientation: null,\n ariaOwns: spaceSeparated,\n ariaPlaceholder: null,\n ariaPosInSet: number,\n ariaPressed: booleanish,\n ariaReadOnly: booleanish,\n ariaRelevant: null,\n ariaRequired: booleanish,\n ariaRoleDescription: spaceSeparated,\n ariaRowCount: number,\n ariaRowIndex: number,\n ariaRowSpan: number,\n ariaSelected: booleanish,\n ariaSetSize: number,\n ariaSort: null,\n ariaValueMax: number,\n ariaValueMin: number,\n ariaValueNow: number,\n ariaValueText: null,\n role: null\n }\n})\n","/**\n * @typedef {import('./util/schema.js').Schema} Schema\n */\n\nimport {normalize} from './normalize.js'\nimport {DefinedInfo} from './util/defined-info.js'\nimport {Info} from './util/info.js'\n\nconst valid = /^data[-\\w.:]+$/i\nconst dash = /-[a-z]/g\nconst cap = /[A-Z]/g\n\n/**\n * @param {Schema} schema\n * @param {string} value\n * @returns {Info}\n */\nexport function find(schema, value) {\n const normal = normalize(value)\n let prop = value\n let Type = Info\n\n if (normal in schema.normal) {\n return schema.property[schema.normal[normal]]\n }\n\n if (normal.length > 4 && normal.slice(0, 4) === 'data' && valid.test(value)) {\n // Attribute or property.\n if (value.charAt(4) === '-') {\n // Turn it into a property.\n const rest = value.slice(5).replace(dash, camelcase)\n prop = 'data' + rest.charAt(0).toUpperCase() + rest.slice(1)\n } else {\n // Turn it into an attribute.\n const rest = value.slice(4)\n\n if (!dash.test(rest)) {\n let dashes = rest.replace(cap, kebab)\n\n if (dashes.charAt(0) !== '-') {\n dashes = '-' + dashes\n }\n\n value = 'data' + dashes\n }\n }\n\n Type = DefinedInfo\n }\n\n return new Type(prop, value)\n}\n\n/**\n * @param {string} $0\n * @returns {string}\n */\nfunction kebab($0) {\n return '-' + $0.toLowerCase()\n}\n\n/**\n * @param {string} $0\n * @returns {string}\n */\nfunction camelcase($0) {\n return $0.charAt(1).toUpperCase()\n}\n","/**\n * `hast` is close to `React`, but differs in a couple of cases.\n *\n * To get a React property from a hast property, check if it is in\n * `hastToReact`, if it is, then use the corresponding value,\n * otherwise, use the hast property.\n *\n * @type {Record}\n */\nexport const hastToReact = {\n classId: 'classID',\n dataType: 'datatype',\n itemId: 'itemID',\n strokeDashArray: 'strokeDasharray',\n strokeDashOffset: 'strokeDashoffset',\n strokeLineCap: 'strokeLinecap',\n strokeLineJoin: 'strokeLinejoin',\n strokeMiterLimit: 'strokeMiterlimit',\n typeOf: 'typeof',\n xLinkActuate: 'xlinkActuate',\n xLinkArcRole: 'xlinkArcrole',\n xLinkHref: 'xlinkHref',\n xLinkRole: 'xlinkRole',\n xLinkShow: 'xlinkShow',\n xLinkTitle: 'xlinkTitle',\n xLinkType: 'xlinkType',\n xmlnsXLink: 'xmlnsXlink'\n}\n","import {\n boolean,\n overloadedBoolean,\n booleanish,\n number,\n spaceSeparated,\n commaSeparated\n} from './util/types.js'\nimport {create} from './util/create.js'\nimport {caseInsensitiveTransform} from './util/case-insensitive-transform.js'\n\nexport const html = create({\n space: 'html',\n attributes: {\n acceptcharset: 'accept-charset',\n classname: 'class',\n htmlfor: 'for',\n httpequiv: 'http-equiv'\n },\n transform: caseInsensitiveTransform,\n mustUseProperty: ['checked', 'multiple', 'muted', 'selected'],\n properties: {\n // Standard Properties.\n abbr: null,\n accept: commaSeparated,\n acceptCharset: spaceSeparated,\n accessKey: spaceSeparated,\n action: null,\n allow: null,\n allowFullScreen: boolean,\n allowPaymentRequest: boolean,\n allowUserMedia: boolean,\n alt: null,\n as: null,\n async: boolean,\n autoCapitalize: null,\n autoComplete: spaceSeparated,\n autoFocus: boolean,\n autoPlay: boolean,\n blocking: spaceSeparated,\n capture: null,\n charSet: null,\n checked: boolean,\n cite: null,\n className: spaceSeparated,\n cols: number,\n colSpan: null,\n content: null,\n contentEditable: booleanish,\n controls: boolean,\n controlsList: spaceSeparated,\n coords: number | commaSeparated,\n crossOrigin: null,\n data: null,\n dateTime: null,\n decoding: null,\n default: boolean,\n defer: boolean,\n dir: null,\n dirName: null,\n disabled: boolean,\n download: overloadedBoolean,\n draggable: booleanish,\n encType: null,\n enterKeyHint: null,\n fetchPriority: null,\n form: null,\n formAction: null,\n formEncType: null,\n formMethod: null,\n formNoValidate: boolean,\n formTarget: null,\n headers: spaceSeparated,\n height: number,\n hidden: boolean,\n high: number,\n href: null,\n hrefLang: null,\n htmlFor: spaceSeparated,\n httpEquiv: spaceSeparated,\n id: null,\n imageSizes: null,\n imageSrcSet: null,\n inert: boolean,\n inputMode: null,\n integrity: null,\n is: null,\n isMap: boolean,\n itemId: null,\n itemProp: spaceSeparated,\n itemRef: spaceSeparated,\n itemScope: boolean,\n itemType: spaceSeparated,\n kind: null,\n label: null,\n lang: null,\n language: null,\n list: null,\n loading: null,\n loop: boolean,\n low: number,\n manifest: null,\n max: null,\n maxLength: number,\n media: null,\n method: null,\n min: null,\n minLength: number,\n multiple: boolean,\n muted: boolean,\n name: null,\n nonce: null,\n noModule: boolean,\n noValidate: boolean,\n onAbort: null,\n onAfterPrint: null,\n onAuxClick: null,\n onBeforeMatch: null,\n onBeforePrint: null,\n onBeforeToggle: null,\n onBeforeUnload: null,\n onBlur: null,\n onCancel: null,\n onCanPlay: null,\n onCanPlayThrough: null,\n onChange: null,\n onClick: null,\n onClose: null,\n onContextLost: null,\n onContextMenu: null,\n onContextRestored: null,\n onCopy: null,\n onCueChange: null,\n onCut: null,\n onDblClick: null,\n onDrag: null,\n onDragEnd: null,\n onDragEnter: null,\n onDragExit: null,\n onDragLeave: null,\n onDragOver: null,\n onDragStart: null,\n onDrop: null,\n onDurationChange: null,\n onEmptied: null,\n onEnded: null,\n onError: null,\n onFocus: null,\n onFormData: null,\n onHashChange: null,\n onInput: null,\n onInvalid: null,\n onKeyDown: null,\n onKeyPress: null,\n onKeyUp: null,\n onLanguageChange: null,\n onLoad: null,\n onLoadedData: null,\n onLoadedMetadata: null,\n onLoadEnd: null,\n onLoadStart: null,\n onMessage: null,\n onMessageError: null,\n onMouseDown: null,\n onMouseEnter: null,\n onMouseLeave: null,\n onMouseMove: null,\n onMouseOut: null,\n onMouseOver: null,\n onMouseUp: null,\n onOffline: null,\n onOnline: null,\n onPageHide: null,\n onPageShow: null,\n onPaste: null,\n onPause: null,\n onPlay: null,\n onPlaying: null,\n onPopState: null,\n onProgress: null,\n onRateChange: null,\n onRejectionHandled: null,\n onReset: null,\n onResize: null,\n onScroll: null,\n onScrollEnd: null,\n onSecurityPolicyViolation: null,\n onSeeked: null,\n onSeeking: null,\n onSelect: null,\n onSlotChange: null,\n onStalled: null,\n onStorage: null,\n onSubmit: null,\n onSuspend: null,\n onTimeUpdate: null,\n onToggle: null,\n onUnhandledRejection: null,\n onUnload: null,\n onVolumeChange: null,\n onWaiting: null,\n onWheel: null,\n open: boolean,\n optimum: number,\n pattern: null,\n ping: spaceSeparated,\n placeholder: null,\n playsInline: boolean,\n popover: null,\n popoverTarget: null,\n popoverTargetAction: null,\n poster: null,\n preload: null,\n readOnly: boolean,\n referrerPolicy: null,\n rel: spaceSeparated,\n required: boolean,\n reversed: boolean,\n rows: number,\n rowSpan: number,\n sandbox: spaceSeparated,\n scope: null,\n scoped: boolean,\n seamless: boolean,\n selected: boolean,\n shadowRootDelegatesFocus: boolean,\n shadowRootMode: null,\n shape: null,\n size: number,\n sizes: null,\n slot: null,\n span: number,\n spellCheck: booleanish,\n src: null,\n srcDoc: null,\n srcLang: null,\n srcSet: null,\n start: number,\n step: null,\n style: null,\n tabIndex: number,\n target: null,\n title: null,\n translate: null,\n type: null,\n typeMustMatch: boolean,\n useMap: null,\n value: booleanish,\n width: number,\n wrap: null,\n\n // Legacy.\n // See: https://html.spec.whatwg.org/#other-elements,-attributes-and-apis\n align: null, // Several. Use CSS `text-align` instead,\n aLink: null, // ``. Use CSS `a:active {color}` instead\n archive: spaceSeparated, // `