UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

628 lines 77.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const cloudformation_lang_1 = require("./private/cloudformation-lang"); const intrinsic_1 = require("./private/intrinsic"); const reference_1 = require("./reference"); const stack_trace_1 = require("./stack-trace"); const token_1 = require("./token"); // tslint:disable:max-line-length /** * CloudFormation intrinsic functions. * http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html */ class Fn { /** * The ``Fn::GetAtt`` intrinsic function returns the value of an attribute * from a resource in the template. * @param logicalNameOfResource The logical name (also called logical ID) of * the resource that contains the attribute that you want. * @param attributeName The name of the resource-specific attribute whose * value you want. See the resource's reference page for details about the * attributes available for that resource type. * @returns an IResolvable object */ static getAtt(logicalNameOfResource, attributeName) { return new FnGetAtt(logicalNameOfResource, attributeName); } /** * The intrinsic function ``Fn::Join`` appends a set of values into a single * value, separated by the specified delimiter. If a delimiter is the empty * string, the set of values are concatenated with no delimiter. * @param delimiter The value you want to occur between fragments. The * delimiter will occur between fragments only. It will not terminate the * final value. * @param listOfValues The list of values you want combined. * @returns a token represented as a string */ static join(delimiter, listOfValues) { if (listOfValues.length === 0) { throw new Error(`FnJoin requires at least one value to be provided`); } return new FnJoin(delimiter, listOfValues).toString(); } /** * To split a string into a list of string values so that you can select an element from the * resulting string list, use the ``Fn::Split`` intrinsic function. Specify the location of splits * with a delimiter, such as , (a comma). After you split a string, use the ``Fn::Select`` function * to pick a specific element. * @param delimiter A string value that determines where the source string is divided. * @param source The string value that you want to split. * @returns a token represented as a string array */ static split(delimiter, source) { // short-circut if source is not a token if (!token_1.Token.isUnresolved(source)) { return source.split(delimiter); } return token_1.Token.asList(new FnSplit(delimiter, source)); } /** * The intrinsic function ``Fn::Select`` returns a single object from a list of objects by index. * @param index The index of the object to retrieve. This must be a value from zero to N-1, where N represents the number of elements in the array. * @param array The list of objects to select from. This list must not be null, nor can it have null entries. * @returns a token represented as a string */ static select(index, array) { if (!token_1.Token.isUnresolved(array)) { return array[index]; } return new FnSelect(index, array).toString(); } /** * The intrinsic function ``Fn::Sub`` substitutes variables in an input string * with values that you specify. In your templates, you can use this function * to construct commands or outputs that include values that aren't available * until you create or update a stack. * @param body A string with variables that AWS CloudFormation substitutes * with their associated values at runtime. Write variables as ${MyVarName}. * Variables can be template parameter names, resource logical IDs, resource * attributes, or a variable in a key-value map. If you specify only template * parameter names, resource logical IDs, and resource attributes, don't * specify a key-value map. * @param variables The name of a variable that you included in the String * parameter. The value that AWS CloudFormation substitutes for the associated * variable name at runtime. * @returns a token represented as a string */ static sub(body, variables) { return new FnSub(body, variables).toString(); } /** * The intrinsic function ``Fn::Base64`` returns the Base64 representation of * the input string. This function is typically used to pass encoded data to * Amazon EC2 instances by way of the UserData property. * @param data The string value you want to convert to Base64. * @returns a token represented as a string */ static base64(data) { return new FnBase64(data).toString(); } /** * The intrinsic function ``Fn::Cidr`` returns the specified Cidr address block. * @param ipBlock The user-specified default Cidr address block. * @param count The number of subnets' Cidr block wanted. Count can be 1 to 256. * @param sizeMask The digit covered in the subnet. * @returns a token represented as a string */ static cidr(ipBlock, count, sizeMask) { return token_1.Token.asList(new FnCidr(ipBlock, count, sizeMask)); } /** * The intrinsic function ``Fn::GetAZs`` returns an array that lists * Availability Zones for a specified region. Because customers have access to * different Availability Zones, the intrinsic function ``Fn::GetAZs`` enables * template authors to write templates that adapt to the calling user's * access. That way you don't have to hard-code a full list of Availability * Zones for a specified region. * @param region The name of the region for which you want to get the * Availability Zones. You can use the AWS::Region pseudo parameter to specify * the region in which the stack is created. Specifying an empty string is * equivalent to specifying AWS::Region. * @returns a token represented as a string array */ static getAzs(region) { return token_1.Token.asList(new FnGetAZs(region)); } /** * The intrinsic function ``Fn::ImportValue`` returns the value of an output * exported by another stack. You typically use this function to create * cross-stack references. In the following example template snippets, Stack A * exports VPC security group values and Stack B imports them. * @param sharedValueToImport The stack output value that you want to import. * @returns a token represented as a string */ static importValue(sharedValueToImport) { return new FnImportValue(sharedValueToImport).toString(); } /** * The intrinsic function ``Fn::FindInMap`` returns the value corresponding to * keys in a two-level map that is declared in the Mappings section. * @returns a token represented as a string */ static findInMap(mapName, topLevelKey, secondLevelKey) { return new FnFindInMap(mapName, topLevelKey, secondLevelKey).toString(); } /** * Returns true if all the specified conditions evaluate to true, or returns * false if any one of the conditions evaluates to false. ``Fn::And`` acts as * an AND operator. The minimum number of conditions that you can include is * 2, and the maximum is 10. * @param conditions conditions to AND * @returns an FnCondition token */ static conditionAnd(...conditions) { return new FnAnd(...conditions); } /** * Compares if two values are equal. Returns true if the two values are equal * or false if they aren't. * @param lhs A value of any type that you want to compare. * @param rhs A value of any type that you want to compare. * @returns an FnCondition token */ static conditionEquals(lhs, rhs) { return new FnEquals(lhs, rhs); } /** * Returns one value if the specified condition evaluates to true and another * value if the specified condition evaluates to false. Currently, AWS * CloudFormation supports the ``Fn::If`` intrinsic function in the metadata * attribute, update policy attribute, and property values in the Resources * section and Outputs sections of a template. You can use the AWS::NoValue * pseudo parameter as a return value to remove the corresponding property. * @param conditionId A reference to a condition in the Conditions section. Use * the condition's name to reference it. * @param valueIfTrue A value to be returned if the specified condition * evaluates to true. * @param valueIfFalse A value to be returned if the specified condition * evaluates to false. * @returns an FnCondition token */ static conditionIf(conditionId, valueIfTrue, valueIfFalse) { return new FnIf(conditionId, valueIfTrue, valueIfFalse); } /** * Returns true for a condition that evaluates to false or returns false for a * condition that evaluates to true. ``Fn::Not`` acts as a NOT operator. * @param condition A condition such as ``Fn::Equals`` that evaluates to true * or false. * @returns an FnCondition token */ static conditionNot(condition) { return new FnNot(condition); } /** * Returns true if any one of the specified conditions evaluate to true, or * returns false if all of the conditions evaluates to false. ``Fn::Or`` acts * as an OR operator. The minimum number of conditions that you can include is * 2, and the maximum is 10. * @param conditions conditions that evaluates to true or false. * @returns an FnCondition token */ static conditionOr(...conditions) { return new FnOr(...conditions); } /** * Returns true if a specified string matches at least one value in a list of * strings. * @param listOfStrings A list of strings, such as "A", "B", "C". * @param value A string, such as "A", that you want to compare against a list of strings. * @returns an FnCondition token */ static conditionContains(listOfStrings, value) { return new FnContains(listOfStrings, value); } /** * Returns true if a specified string matches all values in a list. * @param listOfStrings A list of strings, such as "A", "B", "C". * @param value A string, such as "A", that you want to compare against a list * of strings. * @returns an FnCondition token */ static conditionEachMemberEquals(listOfStrings, value) { return new FnEachMemberEquals(listOfStrings, value); } /** * Returns true if each member in a list of strings matches at least one value * in a second list of strings. * @param stringsToCheck A list of strings, such as "A", "B", "C". AWS * CloudFormation checks whether each member in the strings_to_check parameter * is in the strings_to_match parameter. * @param stringsToMatch A list of strings, such as "A", "B", "C". Each member * in the strings_to_match parameter is compared against the members of the * strings_to_check parameter. * @returns an FnCondition token */ static conditionEachMemberIn(stringsToCheck, stringsToMatch) { return new FnEachMemberIn(stringsToCheck, stringsToMatch); } /** * Returns all values for a specified parameter type. * @param parameterType An AWS-specific parameter type, such as * AWS::EC2::SecurityGroup::Id or AWS::EC2::VPC::Id. For more information, see * Parameters in the AWS CloudFormation User Guide. * @returns a token represented as a string array */ static refAll(parameterType) { return token_1.Token.asList(new FnRefAll(parameterType)); } /** * Returns an attribute value or list of values for a specific parameter and * attribute. * @param parameterOrLogicalId The name of a parameter for which you want to * retrieve attribute values. The parameter must be declared in the Parameters * section of the template. * @param attribute The name of an attribute from which you want to retrieve a * value. * @returns a token represented as a string */ static valueOf(parameterOrLogicalId, attribute) { return new FnValueOf(parameterOrLogicalId, attribute).toString(); } /** * Returns a list of all attribute values for a given parameter type and * attribute. * @param parameterType An AWS-specific parameter type, such as * AWS::EC2::SecurityGroup::Id or AWS::EC2::VPC::Id. For more information, see * Parameters in the AWS CloudFormation User Guide. * @param attribute The name of an attribute from which you want to retrieve a * value. For more information about attributes, see Supported Attributes. * @returns a token represented as a string array */ static valueOfAll(parameterType, attribute) { return token_1.Token.asList(new FnValueOfAll(parameterType, attribute)); } constructor() { } } exports.Fn = Fn; /** * Base class for tokens that represent CloudFormation intrinsic functions. */ class FnBase extends intrinsic_1.Intrinsic { constructor(name, value) { super({ [name]: value }); } } /** * The intrinsic function ``Fn::FindInMap`` returns the value corresponding to keys in a two-level * map that is declared in the Mappings section. */ class FnFindInMap extends FnBase { /** * Creates an ``Fn::FindInMap`` function. * @param mapName The logical name of a mapping declared in the Mappings section that contains the keys and values. * @param topLevelKey The top-level key name. Its value is a list of key-value pairs. * @param secondLevelKey The second-level key name, which is set to one of the keys from the list assigned to TopLevelKey. */ constructor(mapName, topLevelKey, secondLevelKey) { super('Fn::FindInMap', [mapName, topLevelKey, secondLevelKey]); } } /** * The ``Fn::GetAtt`` intrinsic function returns the value of an attribute from a resource in the template. */ class FnGetAtt extends FnBase { /** * Creates a ``Fn::GetAtt`` function. * @param logicalNameOfResource The logical name (also called logical ID) of the resource that contains the attribute that you want. * @param attributeName The name of the resource-specific attribute whose value you want. See the resource's reference page for details about the attributes available for that resource type. */ constructor(logicalNameOfResource, attributeName) { super('Fn::GetAtt', [logicalNameOfResource, attributeName]); } } /** * The intrinsic function ``Fn::GetAZs`` returns an array that lists Availability Zones for a * specified region. Because customers have access to different Availability Zones, the intrinsic * function ``Fn::GetAZs`` enables template authors to write templates that adapt to the calling * user's access. That way you don't have to hard-code a full list of Availability Zones for a * specified region. */ class FnGetAZs extends FnBase { /** * Creates an ``Fn::GetAZs`` function. * @param region The name of the region for which you want to get the Availability Zones. * You can use the AWS::Region pseudo parameter to specify the region in * which the stack is created. Specifying an empty string is equivalent to * specifying AWS::Region. */ constructor(region) { super('Fn::GetAZs', region || ''); } } /** * The intrinsic function ``Fn::ImportValue`` returns the value of an output exported by another stack. * You typically use this function to create cross-stack references. In the following example * template snippets, Stack A exports VPC security group values and Stack B imports them. */ class FnImportValue extends FnBase { /** * Creates an ``Fn::ImportValue`` function. * @param sharedValueToImport The stack output value that you want to import. */ constructor(sharedValueToImport) { super('Fn::ImportValue', sharedValueToImport); } } /** * The intrinsic function ``Fn::Select`` returns a single object from a list of objects by index. */ class FnSelect extends FnBase { /** * Creates an ``Fn::Select`` function. * @param index The index of the object to retrieve. This must be a value from zero to N-1, where N represents the number of elements in the array. * @param array The list of objects to select from. This list must not be null, nor can it have null entries. */ constructor(index, array) { super('Fn::Select', [index, array]); } } /** * To split a string into a list of string values so that you can select an element from the * resulting string list, use the ``Fn::Split`` intrinsic function. Specify the location of splits * with a delimiter, such as , (a comma). After you split a string, use the ``Fn::Select`` function * to pick a specific element. */ class FnSplit extends FnBase { /** * Create an ``Fn::Split`` function. * @param delimiter A string value that determines where the source string is divided. * @param source The string value that you want to split. */ constructor(delimiter, source) { super('Fn::Split', [delimiter, source]); } } /** * The intrinsic function ``Fn::Sub`` substitutes variables in an input string with values that * you specify. In your templates, you can use this function to construct commands or outputs * that include values that aren't available until you create or update a stack. */ class FnSub extends FnBase { /** * Creates an ``Fn::Sub`` function. * @param body A string with variables that AWS CloudFormation substitutes with their * associated values at runtime. Write variables as ${MyVarName}. Variables * can be template parameter names, resource logical IDs, resource attributes, * or a variable in a key-value map. If you specify only template parameter names, * resource logical IDs, and resource attributes, don't specify a key-value map. * @param variables The name of a variable that you included in the String parameter. * The value that AWS CloudFormation substitutes for the associated variable name at runtime. */ constructor(body, variables) { super('Fn::Sub', variables ? [body, variables] : body); } } /** * The intrinsic function ``Fn::Base64`` returns the Base64 representation of the input string. * This function is typically used to pass encoded data to Amazon EC2 instances by way of * the UserData property. */ class FnBase64 extends FnBase { /** * Creates an ``Fn::Base64`` function. * @param data The string value you want to convert to Base64. */ constructor(data) { super('Fn::Base64', data); } } /** * The intrinsic function ``Fn::Cidr`` returns the specified Cidr address block. */ class FnCidr extends FnBase { /** * Creates an ``Fn::Cidr`` function. * @param ipBlock The user-specified default Cidr address block. * @param count The number of subnets' Cidr block wanted. Count can be 1 to 256. * @param sizeMask The digit covered in the subnet. */ constructor(ipBlock, count, sizeMask) { if (count < 1 || count > 256) { throw new Error(`Fn::Cidr's count attribute must be betwen 1 and 256, ${count} was provided.`); } super('Fn::Cidr', [ipBlock, count, sizeMask]); } } class FnConditionBase extends intrinsic_1.Intrinsic { constructor(type, value) { super({ [type]: value }); } } /** * Returns true if all the specified conditions evaluate to true, or returns false if any one * of the conditions evaluates to false. ``Fn::And`` acts as an AND operator. The minimum number of * conditions that you can include is 2, and the maximum is 10. */ class FnAnd extends FnConditionBase { constructor(...condition) { super('Fn::And', condition); } } /** * Compares if two values are equal. Returns true if the two values are equal or false * if they aren't. */ class FnEquals extends FnConditionBase { /** * Creates an ``Fn::Equals`` condition function. * @param lhs A value of any type that you want to compare. * @param rhs A value of any type that you want to compare. */ constructor(lhs, rhs) { super('Fn::Equals', [lhs, rhs]); } } /** * Returns one value if the specified condition evaluates to true and another value if the * specified condition evaluates to false. Currently, AWS CloudFormation supports the ``Fn::If`` * intrinsic function in the metadata attribute, update policy attribute, and property values * in the Resources section and Outputs sections of a template. You can use the AWS::NoValue * pseudo parameter as a return value to remove the corresponding property. */ class FnIf extends FnConditionBase { /** * Creates an ``Fn::If`` condition function. * @param condition A reference to a condition in the Conditions section. Use the condition's name to reference it. * @param valueIfTrue A value to be returned if the specified condition evaluates to true. * @param valueIfFalse A value to be returned if the specified condition evaluates to false. */ constructor(condition, valueIfTrue, valueIfFalse) { super('Fn::If', [condition, valueIfTrue, valueIfFalse]); } } /** * Returns true for a condition that evaluates to false or returns false for a condition that evaluates to true. * ``Fn::Not`` acts as a NOT operator. */ class FnNot extends FnConditionBase { /** * Creates an ``Fn::Not`` condition function. * @param condition A condition such as ``Fn::Equals`` that evaluates to true or false. */ constructor(condition) { super('Fn::Not', [condition]); } } /** * Returns true if any one of the specified conditions evaluate to true, or returns false if * all of the conditions evaluates to false. ``Fn::Or`` acts as an OR operator. The minimum number * of conditions that you can include is 2, and the maximum is 10. */ class FnOr extends FnConditionBase { /** * Creates an ``Fn::Or`` condition function. * @param condition A condition that evaluates to true or false. */ constructor(...condition) { super('Fn::Or', condition); } } /** * Returns true if a specified string matches at least one value in a list of strings. */ class FnContains extends FnConditionBase { /** * Creates an ``Fn::Contains`` function. * @param listOfStrings A list of strings, such as "A", "B", "C". * @param value A string, such as "A", that you want to compare against a list of strings. */ constructor(listOfStrings, value) { super('Fn::Contains', [listOfStrings, value]); } } /** * Returns true if a specified string matches all values in a list. */ class FnEachMemberEquals extends FnConditionBase { /** * Creates an ``Fn::EachMemberEquals`` function. * @param listOfStrings A list of strings, such as "A", "B", "C". * @param value A string, such as "A", that you want to compare against a list of strings. */ constructor(listOfStrings, value) { super('Fn::EachMemberEquals', [listOfStrings, value]); } } /** * Returns true if each member in a list of strings matches at least one value in a second * list of strings. */ class FnEachMemberIn extends FnConditionBase { /** * Creates an ``Fn::EachMemberIn`` function. * @param stringsToCheck A list of strings, such as "A", "B", "C". AWS CloudFormation checks whether each member in the strings_to_check parameter is in the strings_to_match parameter. * @param stringsToMatch A list of strings, such as "A", "B", "C". Each member in the strings_to_match parameter is compared against the members of the strings_to_check parameter. */ constructor(stringsToCheck, stringsToMatch) { super('Fn::EachMemberIn', [stringsToCheck, stringsToMatch]); } } /** * Returns all values for a specified parameter type. */ class FnRefAll extends FnBase { /** * Creates an ``Fn::RefAll`` function. * @param parameterType An AWS-specific parameter type, such as AWS::EC2::SecurityGroup::Id or * AWS::EC2::VPC::Id. For more information, see Parameters in the AWS * CloudFormation User Guide. */ constructor(parameterType) { super('Fn::RefAll', parameterType); } } /** * Returns an attribute value or list of values for a specific parameter and attribute. */ class FnValueOf extends FnBase { /** * Creates an ``Fn::ValueOf`` function. * @param parameterOrLogicalId The name of a parameter for which you want to retrieve attribute values. The parameter must be declared in the Parameters section of the template. * @param attribute The name of an attribute from which you want to retrieve a value. */ constructor(parameterOrLogicalId, attribute) { super('Fn::ValueOf', [parameterOrLogicalId, attribute]); } } /** * Returns a list of all attribute values for a given parameter type and attribute. */ class FnValueOfAll extends FnBase { /** * Creates an ``Fn::ValueOfAll`` function. * @param parameterType An AWS-specific parameter type, such as AWS::EC2::SecurityGroup::Id or AWS::EC2::VPC::Id. For more information, see Parameters in the AWS CloudFormation User Guide. * @param attribute The name of an attribute from which you want to retrieve a value. For more information about attributes, see Supported Attributes. */ constructor(parameterType, attribute) { super('Fn::ValueOfAll', [parameterType, attribute]); } } /** * The intrinsic function ``Fn::Join`` appends a set of values into a single value, separated by * the specified delimiter. If a delimiter is the empty string, the set of values are concatenated * with no delimiter. */ class FnJoin { /** * Creates an ``Fn::Join`` function. * @param delimiter The value you want to occur between fragments. The delimiter will occur between fragments only. * It will not terminate the final value. * @param listOfValues The list of values you want combined. */ constructor(delimiter, listOfValues) { if (listOfValues.length === 0) { throw new Error(`FnJoin requires at least one value to be provided`); } this.delimiter = delimiter; this.listOfValues = listOfValues; this.creationStack = stack_trace_1.captureStackTrace(); } resolve(context) { if (token_1.Token.isUnresolved(this.listOfValues)) { // This is a list token, don't try to do smart things with it. return { 'Fn::Join': [this.delimiter, this.listOfValues] }; } const resolved = this.resolveValues(context); if (resolved.length === 1) { return resolved[0]; } return { 'Fn::Join': [this.delimiter, resolved] }; } toString() { return token_1.Token.asString(this, { displayHint: 'Fn::Join' }); } toJSON() { return `<Fn::Join>`; } /** * Optimization: if an Fn::Join is nested in another one and they share the same delimiter, then flatten it up. Also, * if two concatenated elements are literal strings (not tokens), then pre-concatenate them with the delimiter, to * generate shorter output. */ resolveValues(context) { const resolvedValues = this.listOfValues.map(x => reference_1.Reference.isReference(x) ? x : context.resolve(x)); return cloudformation_lang_1.minimalCloudFormationJoin(this.delimiter, resolvedValues); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2ZuLWZuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2ZuLWZuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0EsdUVBQTBFO0FBQzFFLG1EQUFnRDtBQUNoRCwyQ0FBd0M7QUFFeEMsK0NBQWtEO0FBQ2xELG1DQUFnQztBQUVoQyxpQ0FBaUM7QUFFakM7OztHQUdHO0FBQ0gsTUFBYSxFQUFFO0lBQ2I7Ozs7Ozs7OztPQVNHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxxQkFBNkIsRUFBRSxhQUFxQjtRQUN2RSxPQUFPLElBQUksUUFBUSxDQUFDLHFCQUFxQixFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQWlCLEVBQUUsWUFBc0I7UUFDMUQsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLG1EQUFtRCxDQUFDLENBQUM7U0FDdEU7UUFFRCxPQUFPLElBQUksTUFBTSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN4RCxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQWlCLEVBQUUsTUFBYztRQUVuRCx3Q0FBd0M7UUFDeEMsSUFBSSxDQUFDLGFBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDL0IsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ2hDO1FBRUQsT0FBTyxhQUFLLENBQUMsTUFBTSxDQUFDLElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBYSxFQUFFLEtBQWU7UUFDakQsSUFBSSxDQUFDLGFBQUssQ0FBQyxZQUFZLENB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RTtZQUN6QixPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNwQjtRQUNELE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBRSxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBRSxFQUFFLENBQUM7SUFDdEQsQ0FBQztJQUVNLFFBQVE7UUFDYixPQUFPLGFBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVNLE1BQU07UUFDWCxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGFBQWEsQ0FBQyxPQUF3QjtRQUM1QyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLHFCQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyRyxPQUFRLCtDQUF5QixDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDcEUsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSUNmbkNvbmRpdGlvbkV4cHJlc3Npb24gfSBmcm9tICcuL2Nmbi1jb25kaXRpb24nO1xuaW1wb3J0IHsgbWluaW1hbENsb3VkRm9ybWF0aW9uSm9pbiB9IGZyb20gJy4vcHJpdmF0ZS9jbG91ZGZvcm1hdGlvbi1sYW5nJztcbmltcG9ydCB7IEludHJpbnNpYyB9IGZyb20gJy4vcHJpdmF0ZS9pbnRyaW5zaWMnO1xuaW1wb3J0IHsgUmVmZXJlbmNlIH0gZnJvbSAnLi9yZWZlcmVuY2UnO1xuaW1wb3J0IHsgSVJlc29sdmFibGUsIElSZXNvbHZlQ29udGV4dCB9IGZyb20gJy4vcmVzb2x2YWJsZSc7XG5pbXBvcnQgeyBjYXB0dXJlU3RhY2tUcmFjZSB9IGZyb20gJy4vc3RhY2stdHJhY2UnO1xuaW1wb3J0IHsgVG9rZW4gfSBmcm9tICcuL3Rva2VuJztcblxuLy8gdHNsaW50OmRpc2FibGU6bWF4LWxpbmUtbGVuZ3RoXG5cbi8qKlxuICogQ2xvdWRGb3JtYXRpb24gaW50cmluc2ljIGZ1bmN0aW9ucy5cbiAqIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvaW50cmluc2ljLWZ1bmN0aW9uLXJlZmVyZW5jZS5odG1sXG4gKi9cbmV4cG9ydCBjbGFzcyBGbiB7XG4gIC8qKlxuICAgKiBUaGUgYGBGbjo6R2V0QXR0YGAgaW50cmluc2ljIGZ1bmN0aW9uIHJldHVybnMgdGhlIHZhbHVlIG9mIGFuIGF0dHJpYnV0ZVxuICAgKiBmcm9tIGEgcmVzb3VyY2UgaW4gdGhlIHRlbXBsYXRlLlxuICAgKiBAcGFyYW0gbG9naWNhbE5hbWVPZlJlc291cmNlIFRoZSBsb2dpY2FsIG5hbWUgKGFsc28gY2FsbGVkIGxvZ2ljYWwgSUQpIG9mXG4gICAqIHRoZSByZXNvdXJjZSB0aGF0IGNvbnRhaW5zIHRoZSBhdHRyaWJ1dGUgdGhhdCB5b3Ugd2FudC5cbiAgICogQHBhcmFtIGF0dHJpYnV0ZU5hbWUgVGhlIG5hbWUgb2YgdGhlIHJlc291cmNlLXNwZWNpZmljIGF0dHJpYnV0ZSB3aG9zZVxuICAgKiB2YWx1ZSB5b3Ugd2FudC4gU2VlIHRoZSByZXNvdXJjZSdzIHJlZmVyZW5jZSBwYWdlIGZvciBkZXRhaWxzIGFib3V0IHRoZVxuICAgKiBhdHRyaWJ1dGVzIGF2YWlsYWJsZSBmb3IgdGhhdCByZXNvdXJjZSB0eXBlLlxuICAgKiBAcmV0dXJucyBhbiBJUmVzb2x2YWJsZSBvYmplY3RcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ2V0QXR0KGxvZ2ljYWxOYW1lT2ZSZXNvdXJjZTogc3RyaW5nLCBhdHRyaWJ1dGVOYW1lOiBzdHJpbmcpOiBJUmVzb2x2YWJsZSB7XG4gICAgcmV0dXJuIG5ldyBGbkdldEF0dChsb2dpY2FsTmFtZU9mUmVzb3VyY2UsIGF0dHJpYnV0ZU5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6Sm9pbmBgIGFwcGVuZHMgYSBzZXQgb2YgdmFsdWVzIGludG8gYSBzaW5nbGVcbiAgICogdmFsdWUsIHNlcGFyYXRlZCBieSB0aGUgc3BlY2lmaWVkIGRlbGltaXRlci4gSWYgYSBkZWxpbWl0ZXIgaXMgdGhlIGVtcHR5XG4gICAqIHN0cmluZywgdGhlIHNldCBvZiB2YWx1ZXMgYXJlIGNvbmNhdGVuYXRlZCB3aXRoIG5vIGRlbGltaXRlci5cbiAgICogQHBhcmFtIGRlbGltaXRlciBUaGUgdmFsdWUgeW91IHdhbnQgdG8gb2NjdXIgYmV0d2VlbiBmcmFnbWVudHMuIFRoZVxuICAgKiBkZWxpbWl0ZXIgd2lsbCBvY2N1ciBiZXR3ZWVuIGZyYWdtZW50cyBvbmx5LiBJdCB3aWxsIG5vdCB0ZXJtaW5hdGUgdGhlXG4gICAqIGZpbmFsIHZhbHVlLlxuICAgKiBAcGFyYW0gbGlzdE9mVmFsdWVzIFRoZSBsaXN0IG9mIHZhbHVlcyB5b3Ugd2FudCBjb21iaW5lZC5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZ1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBqb2luKGRlbGltaXRlcjogc3RyaW5nLCBsaXN0T2ZWYWx1ZXM6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgICBpZiAobGlzdE9mVmFsdWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGbkpvaW4gcmVxdWlyZXMgYXQgbGVhc3Qgb25lIHZhbHVlIHRvIGJlIHByb3ZpZGVkYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBGbkpvaW4oZGVsaW1pdGVyLCBsaXN0T2ZWYWx1ZXMpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogVG8gc3BsaXQgYSBzdHJpbmcgaW50byBhIGxpc3Qgb2Ygc3RyaW5nIHZhbHVlcyBzbyB0aGF0IHlvdSBjYW4gc2VsZWN0IGFuIGVsZW1lbnQgZnJvbSB0aGVcbiAgICogcmVzdWx0aW5nIHN0cmluZyBsaXN0LCB1c2UgdGhlIGBgRm46OlNwbGl0YGAgaW50cmluc2ljIGZ1bmN0aW9uLiBTcGVjaWZ5IHRoZSBsb2NhdGlvbiBvZiBzcGxpdHNcbiAgICogd2l0aCBhIGRlbGltaXRlciwgc3VjaCBhcyAsIChhIGNvbW1hKS4gQWZ0ZXIgeW91IHNwbGl0IGEgc3RyaW5nLCB1c2UgdGhlIGBgRm46OlNlbGVjdGBgIGZ1bmN0aW9uXG4gICAqIHRvIHBpY2sgYSBzcGVjaWZpYyBlbGVtZW50LlxuICAgKiBAcGFyYW0gZGVsaW1pdGVyIEEgc3RyaW5nIHZhbHVlIHRoYXQgZGV0ZXJtaW5lcyB3aGVyZSB0aGUgc291cmNlIHN0cmluZyBpcyBkaXZpZGVkLlxuICAgKiBAcGFyYW0gc291cmNlIFRoZSBzdHJpbmcgdmFsdWUgdGhhdCB5b3Ugd2FudCB0byBzcGxpdC5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZyBhcnJheVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzcGxpdChkZWxpbWl0ZXI6IHN0cmluZywgc291cmNlOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG5cbiAgICAvLyBzaG9ydC1jaXJjdXQgaWYgc291cmNlIGlzIG5vdCBhIHRva2VuXG4gICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQoc291cmNlKSkge1xuICAgICAgcmV0dXJuIHNvdXJjZS5zcGxpdChkZWxpbWl0ZXIpO1xuICAgIH1cblxuICAgIHJldHVybiBUb2tlbi5hc0xpc3QobmV3IEZuU3BsaXQoZGVsaW1pdGVyLCBzb3VyY2UpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OlNlbGVjdGBgIHJldHVybnMgYSBzaW5nbGUgb2JqZWN0IGZyb20gYSBsaXN0IG9mIG9iamVjdHMgYnkgaW5kZXguXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIG9iamVjdCB0byByZXRyaWV2ZS4gVGhpcyBtdXN0IGJlIGEgdmFsdWUgZnJvbSB6ZXJvIHRvIE4tMSwgd2hlcmUgTiByZXByZXNlbnRzIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIGFycmF5LlxuICAgKiBAcGFyYW0gYXJyYXkgVGhlIGxpc3Qgb2Ygb2JqZWN0cyB0byBzZWxlY3QgZnJvbS4gVGhpcyBsaXN0IG11c3Qgbm90IGJlIG51bGwsIG5vciBjYW4gaXQgaGF2ZSBudWxsIGVudHJpZXMuXG4gICAqIEByZXR1cm5zIGEgdG9rZW4gcmVwcmVzZW50ZWQgYXMgYSBzdHJpbmdcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgc2VsZWN0KGluZGV4OiBudW1iZXIsIGFycmF5OiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQoYXJyYXkpKSB7XG4gICAgICByZXR1cm4gYXJyYXlbaW5kZXhdO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgRm5TZWxlY3QoaW5kZXgsIGFycmF5KS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6U3ViYGAgc3Vic3RpdHV0ZXMgdmFyaWFibGVzIGluIGFuIGlucHV0IHN0cmluZ1xuICAgKiB3aXRoIHZhbHVlcyB0aGF0IHlvdSBzcGVjaWZ5LiBJbiB5b3VyIHRlbXBsYXRlcywgeW91IGNhbiB1c2UgdGhpcyBmdW5jdGlvblxuICAgKiB0byBjb25zdHJ1Y3QgY29tbWFuZHMgb3Igb3V0cHV0cyB0aGF0IGluY2x1ZGUgdmFsdWVzIHRoYXQgYXJlbid0IGF2YWlsYWJsZVxuICAgKiB1bnRpbCB5b3UgY3JlYXRlIG9yIHVwZGF0ZSBhIHN0YWNrLlxuICAgKiBAcGFyYW0gYm9keSBBIHN0cmluZyB3aXRoIHZhcmlhYmxlcyB0aGF0IEFXUyBDbG91ZEZvcm1hdGlvbiBzdWJzdGl0dXRlc1xuICAgKiB3aXRoIHRoZWlyIGFzc29jaWF0ZWQgdmFsdWVzIGF0IHJ1bnRpbWUuIFdyaXRlIHZhcmlhYmxlcyBhcyAke015VmFyTmFtZX0uXG4gICAqIFZhcmlhYmxlcyBjYW4gYmUgdGVtcGxhdGUgcGFyYW1ldGVyIG5hbWVzLCByZXNvdXJjZSBsb2dpY2FsIElEcywgcmVzb3VyY2VcbiAgICogYXR0cmlidXRlcywgb3IgYSB2YXJpYWJsZSBpbiBhIGtleS12YWx1ZSBtYXAuIElmIHlvdSBzcGVjaWZ5IG9ubHkgdGVtcGxhdGVcbiAgICogcGFyYW1ldGVyIG5hbWVzLCByZXNvdXJjZSBsb2dpY2FsIElEcywgYW5kIHJlc291cmNlIGF0dHJpYnV0ZXMsIGRvbid0XG4gICAqIHNwZWNpZnkgYSBrZXktdmFsdWUgbWFwLlxuICAgKiBAcGFyYW0gdmFyaWFibGVzIFRoZSBuYW1lIG9mIGEgdmFyaWFibGUgdGhhdCB5b3UgaW5jbHVkZWQgaW4gdGhlIFN0cmluZ1xuICAgKiBwYXJhbWV0ZXIuIFRoZSB2YWx1ZSB0aGF0IEFXUyBDbG91ZEZvcm1hdGlvbiBzdWJzdGl0dXRlcyBmb3IgdGhlIGFzc29jaWF0ZWRcbiAgICogdmFyaWFibGUgbmFtZSBhdCBydW50aW1lLlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHN1Yihib2R5OiBzdHJpbmcsIHZhcmlhYmxlcz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0pOiBzdHJpbmcge1xuICAgIHJldHVybiBuZXcgRm5TdWIoYm9keSwgdmFyaWFibGVzKS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6QmFzZTY0YGAgcmV0dXJucyB0aGUgQmFzZTY0IHJlcHJlc2VudGF0aW9uIG9mXG4gICAqIHRoZSBpbnB1dCBzdHJpbmcuIFRoaXMgZnVuY3Rpb24gaXMgdHlwaWNhbGx5IHVzZWQgdG8gcGFzcyBlbmNvZGVkIGRhdGEgdG9cbiAgICogQW1hem9uIEVDMiBpbnN0YW5jZXMgYnkgd2F5IG9mIHRoZSBVc2VyRGF0YSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIGRhdGEgVGhlIHN0cmluZyB2YWx1ZSB5b3Ugd2FudCB0byBjb252ZXJ0IHRvIEJhc2U2NC5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZ1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBiYXNlNjQoZGF0YTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IEZuQmFzZTY0KGRhdGEpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpDaWRyYGAgcmV0dXJucyB0aGUgc3BlY2lmaWVkIENpZHIgYWRkcmVzcyBibG9jay5cbiAgICogQHBhcmFtIGlwQmxvY2sgIFRoZSB1c2VyLXNwZWNpZmllZCBkZWZhdWx0IENpZHIgYWRkcmVzcyBibG9jay5cbiAgICogQHBhcmFtIGNvdW50ICBUaGUgbnVtYmVyIG9mIHN1Ym5ldHMnIENpZHIgYmxvY2sgd2FudGVkLiBDb3VudCBjYW4gYmUgMSB0byAyNTYuXG4gICAqIEBwYXJhbSBzaXplTWFzayBUaGUgZGlnaXQgY292ZXJlZCBpbiB0aGUgc3VibmV0LlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNpZHIoaXBCbG9jazogc3RyaW5nLCBjb3VudDogbnVtYmVyLCBzaXplTWFzaz86IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gVG9rZW4uYXNMaXN0KG5ldyBGbkNpZHIoaXBCbG9jaywgY291bnQsIHNpemVNYXNrKSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpHZXRBWnNgYCByZXR1cm5zIGFuIGFycmF5IHRoYXQgbGlzdHNcbiAgICogQXZhaWxhYmlsaXR5IFpvbmVzIGZvciBhIHNwZWNpZmllZCByZWdpb24uIEJlY2F1c2UgY3VzdG9tZXJzIGhhdmUgYWNjZXNzIHRvXG4gICAqIGRpZmZlcmVudCBBdmFpbGFiaWxpdHkgWm9uZXMsIHRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6R2V0QVpzYGAgZW5hYmxlc1xuICAgKiB0ZW1wbGF0ZSBhdXRob3JzIHRvIHdyaXRlIHRlbXBsYXRlcyB0aGF0IGFkYXB0IHRvIHRoZSBjYWxsaW5nIHVzZXInc1xuICAgKiBhY2Nlc3MuIFRoYXQgd2F5IHlvdSBkb24ndCBoYXZlIHRvIGhhcmQtY29kZSBhIGZ1bGwgbGlzdCBvZiBBdmFpbGFiaWxpdHlcbiAgICogWm9uZXMgZm9yIGEgc3BlY2lmaWVkIHJlZ2lvbi5cbiAgICogQHBhcmFtIHJlZ2lvbiBUaGUgbmFtZSBvZiB0aGUgcmVnaW9uIGZvciB3aGljaCB5b3Ugd2FudCB0byBnZXQgdGhlXG4gICAqIEF2YWlsYWJpbGl0eSBab25lcy4gWW91IGNhbiB1c2UgdGhlIEFXUzo6UmVnaW9uIHBzZXVkbyBwYXJhbWV0ZXIgdG8gc3BlY2lmeVxuICAgKiB0aGUgcmVnaW9uIGluIHdoaWNoIHRoZSBzdGFjayBpcyBjcmVhdGVkLiBTcGVjaWZ5aW5nIGFuIGVtcHR5IHN0cmluZyBpc1xuICAgKiBlcXVpdmFsZW50IHRvIHNwZWNpZnlpbmcgQVdTOjpSZWdpb24uXG4gICAqIEByZXR1cm5zIGEgdG9rZW4gcmVwcmVzZW50ZWQgYXMgYSBzdHJpbmcgYXJyYXlcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ2V0QXpzKHJlZ2lvbj86IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gVG9rZW4uYXNMaXN0KG5ldyBGbkdldEFacyhyZWdpb24pKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OkltcG9ydFZhbHVlYGAgcmV0dXJucyB0aGUgdmFsdWUgb2YgYW4gb3V0cHV0XG4gICAqIGV4cG9ydGVkIGJ5IGFub3RoZXIgc3RhY2suIFlvdSB0eXBpY2FsbHkgdXNlIHRoaXMgZnVuY3Rpb24gdG8gY3JlYXRlXG4gICAqIGNyb3NzLXN0YWNrIHJlZmVyZW5jZXMuIEluIHRoZSBmb2xsb3dpbmcgZXhhbXBsZSB0ZW1wbGF0ZSBzbmlwcGV0cywgU3RhY2sgQVxuICAgKiBleHBvcnRzIFZQQyBzZWN1cml0eSBncm91cCB2YWx1ZXMgYW5kIFN0YWNrIEIgaW1wb3J0cyB0aGVtLlxuICAgKiBAcGFyYW0gc2hhcmVkVmFsdWVUb0ltcG9ydCBUaGUgc3RhY2sgb3V0cHV0IHZhbHVlIHRoYXQgeW91IHdhbnQgdG8gaW1wb3J0LlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGltcG9ydFZhbHVlKHNoYXJlZFZhbHVlVG9JbXBvcnQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIG5ldyBGbkltcG9ydFZhbHVlKHNoYXJlZFZhbHVlVG9JbXBvcnQpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpGaW5kSW5NYXBgYCByZXR1cm5zIHRoZSB2YWx1ZSBjb3JyZXNwb25kaW5nIHRvXG4gICAqIGtleXMgaW4gYSB0d28tbGV2ZWwgbWFwIHRoYXQgaXMgZGVjbGFyZWQgaW4gdGhlIE1hcHBpbmdzIHNlY3Rpb24uXG4gICAqIEByZXR1cm5zIGEgdG9rZW4gcmVwcmVzZW50ZWQgYXMgYSBzdHJpbmdcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZmluZEluTWFwKG1hcE5hbWU6IHN0cmluZywgdG9wTGV2ZWxLZXk6IHN0cmluZywgc2Vjb25kTGV2ZWxLZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIG5ldyBGbkZpbmRJbk1hcChtYXBOYW1lLCB0b3BMZXZlbEtleSwgc2Vjb25kTGV2ZWxLZXkpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIGFsbCB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbnMgZXZhbHVhdGUgdG8gdHJ1ZSwgb3IgcmV0dXJuc1xuICAgKiBmYWxzZSBpZiBhbnkgb25lIG9mIHRoZSBjb25kaXRpb25zIGV2YWx1YXRlcyB0byBmYWxzZS4gYGBGbjo6QW5kYGAgYWN0cyBhc1xuICAgKiBhbiBBTkQgb3BlcmF0b3IuIFRoZSBtaW5pbXVtIG51bWJlciBvZiBjb25kaXRpb25zIHRoYXQgeW91IGNhbiBpbmNsdWRlIGlzXG4gICAqIDIsIGFuZCB0aGUgbWF4aW11bSBpcyAxMC5cbiAgICogQHBhcmFtIGNvbmRpdGlvbnMgY29uZGl0aW9ucyB0byBBTkRcbiAgICogQHJldHVybnMgYW4gRm5Db25kaXRpb24gdG9rZW5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29uZGl0aW9uQW5kKC4uLmNvbmRpdGlvbnM6IElDZm5Db25kaXRpb25FeHByZXNzaW9uW10pOiBJQ2ZuQ29uZGl0aW9uRXhwcmVzc2lvbiB7XG4gICAgcmV0dXJuIG5ldyBGbkFuZCguLi5jb25kaXRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wYXJlcyBpZiB0d28gdmFsdWVzIGFyZSBlcXVhbC4gUmV0dXJucyB0cnVlIGlmIHRoZSB0d28gdmFsdWVzIGFyZSBlcXVhbFxuICAgKiBvciBmYWxzZSBpZiB0aGV5IGFyZW4ndC5cbiAgICogQHBhcmFtIGxocyBBIHZhbHVlIG9mIGFueSB0eXBlIHRoYXQgeW91IHdhbnQgdG8gY29tcGFyZS5cbiAgICogQHBhcmFtIHJocyBBIHZhbHVlIG9mIGFueSB0eXBlIHRoYXQgeW91IHdhbnQgdG8gY29tcGFyZS5cbiAgICogQHJldHVybnMgYW4gRm5Db25kaXRpb24gdG9rZW5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29uZGl0aW9uRXF1YWxzKGxoczogYW55LCByaHM6IGFueSk6IElDZm5Db25kaXRpb25FeHByZXNzaW9uIHtcbiAgICByZXR1cm4gbmV3IEZuRXF1YWxzKGxocywgcmhzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIG9uZSB2YWx1ZSBpZiB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbiBldmFsdWF0ZXMgdG8gdHJ1ZSBhbmQgYW5vdGhlclxuICAgKiB2YWx1ZSBpZiB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbiBldmFsdWF0ZXMgdG8gZmFsc2UuIEN1cnJlbnRseSwgQVdTXG4gICAqIENsb3VkRm9ybWF0aW9uIHN1cHBvcnRzIHRoZSBgYEZuOjpJZmBgIGludHJpbnNpYyBmdW5jdGlvbiBpbiB0aGUgbWV0YWRhdGFcbiAgICogYXR0cmlidXRlLCB1cGRhdGUgcG9saWN5IGF0dHJpYnV0ZSwgYW5kIHByb3BlcnR5IHZhbHVlcyBpbiB0aGUgUmVzb3VyY2VzXG4gICAqIHNlY3Rpb24gYW5kIE91dHB1dHMgc2VjdGlvbnMgb2YgYS