1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.Fn = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const cloudformation_lang_1 = require("./private/cloudformation-lang");
|
8 | const intrinsic_1 = require("./private/intrinsic");
|
9 | const reference_1 = require("./reference");
|
10 | const stack_trace_1 = require("./stack-trace");
|
11 | const token_1 = require("./token");
|
12 | /* eslint-disable max-len */
|
13 | /**
|
14 | * CloudFormation intrinsic functions.
|
15 | * http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
|
16 | */
|
17 | class Fn {
|
18 | constructor() { }
|
19 | /**
|
20 | * The ``Ref`` intrinsic function returns the value of the specified parameter or resource.
|
21 | * Note that it doesn't validate the logicalName, it mainly serves paremeter/resource reference defined in a ``CfnInclude`` template.
|
22 | * @param logicalName The logical name of a parameter/resource for which you want to retrieve its value.
|
23 | */
|
24 | static ref(logicalName) {
|
25 | return new FnRef(logicalName).toString();
|
26 | }
|
27 | /**
|
28 | * The ``Fn::GetAtt`` intrinsic function returns the value of an attribute
|
29 | * from a resource in the template.
|
30 | * @param logicalNameOfResource The logical name (also called logical ID) of
|
31 | * the resource that contains the attribute that you want.
|
32 | * @param attributeName The name of the resource-specific attribute whose
|
33 | * value you want. See the resource's reference page for details about the
|
34 | * attributes available for that resource type.
|
35 | * @returns an IResolvable object
|
36 | */
|
37 | static getAtt(logicalNameOfResource, attributeName) {
|
38 | return new FnGetAtt(logicalNameOfResource, attributeName);
|
39 | }
|
40 | /**
|
41 | * The intrinsic function ``Fn::Join`` appends a set of values into a single
|
42 | * value, separated by the specified delimiter. If a delimiter is the empty
|
43 | * string, the set of values are concatenated with no delimiter.
|
44 | * @param delimiter The value you want to occur between fragments. The
|
45 | * delimiter will occur between fragments only. It will not terminate the
|
46 | * final value.
|
47 | * @param listOfValues The list of values you want combined.
|
48 | * @returns a token represented as a string
|
49 | */
|
50 | static join(delimiter, listOfValues) {
|
51 | if (listOfValues.length === 0) {
|
52 | throw new Error('FnJoin requires at least one value to be provided');
|
53 | }
|
54 | return new FnJoin(delimiter, listOfValues).toString();
|
55 | }
|
56 | /**
|
57 | * Split a string token into a token list of string values.
|
58 | *
|
59 | * Specify the location of splits with a delimiter such as ',' (a comma).
|
60 | * Renders to the `Fn::Split` intrinsic function.
|
61 | *
|
62 | * Lists with unknown lengths (default)
|
63 | * -------------------------------------
|
64 | *
|
65 | * Since this function is used to work with deploy-time values, if `assumedLength`
|
66 | * is not given the CDK cannot know the length of the resulting list at synthesis time.
|
67 | * This brings the following restrictions:
|
68 | *
|
69 | * - You must use `Fn.select(i, list)` to pick elements out of the list (you must not use
|
70 | * `list[i]`).
|
71 | * - You cannot add elements to the list, remove elements from the list,
|
72 | * combine two such lists together, or take a slice of the list.
|
73 | * - You cannot pass the list to constructs that do any of the above.
|
74 | *
|
75 | * The only valid operation with such a tokenized list is to pass it unmodified to a
|
76 | * CloudFormation Resource construct.
|
77 | *
|
78 | * Lists with assumed lengths
|
79 | * --------------------------
|
80 | *
|
81 | * Pass `assumedLength` if you know the length of the list that will be
|
82 | * produced by splitting. The actual list length at deploy time may be
|
83 | * *longer* than the number you pass, but not *shorter*.
|
84 | *
|
85 | * The returned list will look like:
|
86 | *
|
87 | * ```
|
88 | * [Fn.select(0, split), Fn.select(1, split), Fn.select(2, split), ...]
|
89 | * ```
|
90 | *
|
91 | * The restrictions from the section "Lists with unknown lengths" will now be lifted,
|
92 | * at the expense of having to know and fix the length of the list.
|
93 | *
|
94 | * @param delimiter A string value that determines where the source string is divided.
|
95 | * @param source The string value that you want to split.
|
96 | * @param assumedLength The length of the list that will be produced by splitting
|
97 | * @returns a token represented as a string array
|
98 | */
|
99 | static split(delimiter, source, assumedLength) {
|
100 | // short-circut if source is not a token
|
101 | if (!token_1.Token.isUnresolved(source)) {
|
102 | return source.split(delimiter);
|
103 | }
|
104 | if (token_1.Token.isUnresolved(delimiter)) {
|
105 | // Limitation of CloudFormation
|
106 | throw new Error('Fn.split: \'delimiter\' may not be a token value');
|
107 | }
|
108 | const split = token_1.Token.asList(new FnSplit(delimiter, source));
|
109 | if (assumedLength === undefined) {
|
110 | return split;
|
111 | }
|
112 | if (token_1.Token.isUnresolved(assumedLength)) {
|
113 | throw new Error('Fn.split: \'assumedLength\' may not be a token value');
|
114 | }
|
115 | return range(assumedLength).map(i => Fn.select(i, split));
|
116 | }
|
117 | /**
|
118 | * The intrinsic function ``Fn::Select`` returns a single object from a list of objects by index.
|
119 | * @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.
|
120 | * @param array The list of objects to select from. This list must not be null, nor can it have null entries.
|
121 | * @returns a token represented as a string
|
122 | */
|
123 | static select(index, array) {
|
124 | if (!token_1.Token.isUnresolved(index) && !token_1.Token.isUnresolved(array) && !array.some(token_1.Token.isUnresolved)) {
|
125 | return array[index];
|
126 | }
|
127 | return new FnSelect(index, array).toString();
|
128 | }
|
129 | /**
|
130 | * The intrinsic function ``Fn::Sub`` substitutes variables in an input string
|
131 | * with values that you specify. In your templates, you can use this function
|
132 | * to construct commands or outputs that include values that aren't available
|
133 | * until you create or update a stack.
|
134 | * @param body A string with variables that AWS CloudFormation substitutes
|
135 | * with their associated values at runtime. Write variables as ${MyVarName}.
|
136 | * Variables can be template parameter names, resource logical IDs, resource
|
137 | * attributes, or a variable in a key-value map. If you specify only template
|
138 | * parameter names, resource logical IDs, and resource attributes, don't
|
139 | * specify a key-value map.
|
140 | * @param variables The name of a variable that you included in the String
|
141 | * parameter. The value that AWS CloudFormation substitutes for the associated
|
142 | * variable name at runtime.
|
143 | * @returns a token represented as a string
|
144 | */
|
145 | static sub(body, variables) {
|
146 | return new FnSub(body, variables).toString();
|
147 | }
|
148 | /**
|
149 | * The intrinsic function ``Fn::Base64`` returns the Base64 representation of
|
150 | * the input string. This function is typically used to pass encoded data to
|
151 | * Amazon EC2 instances by way of the UserData property.
|
152 | * @param data The string value you want to convert to Base64.
|
153 | * @returns a token represented as a string
|
154 | */
|
155 | static base64(data) {
|
156 | return new FnBase64(data).toString();
|
157 | }
|
158 | /**
|
159 | * The intrinsic function ``Fn::Cidr`` returns the specified Cidr address block.
|
160 | * @param ipBlock The user-specified default Cidr address block.
|
161 | * @param count The number of subnets' Cidr block wanted. Count can be 1 to 256.
|
162 | * @param sizeMask The digit covered in the subnet.
|
163 | * @returns a token represented as a string
|
164 | */
|
165 | static cidr(ipBlock, count, sizeMask) {
|
166 | return token_1.Token.asList(new FnCidr(ipBlock, count, sizeMask));
|
167 | }
|
168 | /**
|
169 | * Given an url, parse the domain name
|
170 | * @param url the url to parse
|
171 | */
|
172 | static parseDomainName(url) {
|
173 | const noHttps = Fn.select(1, Fn.split('//', url));
|
174 | return Fn.select(0, Fn.split('/', noHttps));
|
175 | }
|
176 | /**
|
177 | * The intrinsic function ``Fn::GetAZs`` returns an array that lists
|
178 | * Availability Zones for a specified region. Because customers have access to
|
179 | * different Availability Zones, the intrinsic function ``Fn::GetAZs`` enables
|
180 | * template authors to write templates that adapt to the calling user's
|
181 | * access. That way you don't have to hard-code a full list of Availability
|
182 | * Zones for a specified region.
|
183 | * @param region The name of the region for which you want to get the
|
184 | * Availability Zones. You can use the AWS::Region pseudo parameter to specify
|
185 | * the region in which the stack is created. Specifying an empty string is
|
186 | * equivalent to specifying AWS::Region.
|
187 | * @returns a token represented as a string array
|
188 | */
|
189 | static getAzs(region) {
|
190 | return token_1.Token.asList(new FnGetAZs(region));
|
191 | }
|
192 | /**
|
193 | * The intrinsic function ``Fn::ImportValue`` returns the value of an output
|
194 | * exported by another stack. You typically use this function to create
|
195 | * cross-stack references. In the following example template snippets, Stack A
|
196 | * exports VPC security group values and Stack B imports them.
|
197 | * @param sharedValueToImport The stack output value that you want to import.
|
198 | * @returns a token represented as a string
|
199 | */
|
200 | static importValue(sharedValueToImport) {
|
201 | return new FnImportValue(sharedValueToImport).toString();
|
202 | }
|
203 | /**
|
204 | * Like `Fn.importValue`, but import a list with a known length
|
205 | *
|
206 | * If you explicitly want a list with an unknown length, call `Fn.split(',',
|
207 | * Fn.importValue(exportName))`. See the documentation of `Fn.split` to read
|
208 | * more about the limitations of using lists of unknown length.
|
209 | *
|
210 | * `Fn.importListValue(exportName, assumedLength)` is the same as
|
211 | * `Fn.split(',', Fn.importValue(exportName), assumedLength)`,
|
212 | * but easier to read and impossible to forget to pass `assumedLength`.
|
213 | */
|
214 | static importListValue(sharedValueToImport, assumedLength, delimiter = ',') {
|
215 | return Fn.split(delimiter, Fn.importValue(sharedValueToImport), assumedLength);
|
216 | }
|
217 | /**
|
218 | * The intrinsic function ``Fn::FindInMap`` returns the value corresponding to
|
219 | * keys in a two-level map that is declared in the Mappings section.
|
220 | * @returns a token represented as a string
|
221 | */
|
222 | static findInMap(mapName, topLevelKey, secondLevelKey) {
|
223 | return Fn._findInMap(mapName, topLevelKey, secondLevelKey).toString();
|
224 | }
|
225 | /**
|
226 | * An additional function used in CfnParser,
|
227 | * as Fn::FindInMap does not always return a string.
|
228 | *
|
229 | * @internal
|
230 | */
|
231 | static _findInMap(mapName, topLevelKey, secondLevelKey) {
|
232 | return new FnFindInMap(mapName, topLevelKey, secondLevelKey);
|
233 | }
|
234 | /**
|
235 | * Creates a token representing the ``Fn::Transform`` expression
|
236 | * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-transform.html
|
237 | * @param macroName The name of the macro to perform the processing
|
238 | * @param parameters The parameters to be passed to the macro
|
239 | * @returns a token representing the transform expression
|
240 | */
|
241 | static transform(macroName, parameters) {
|
242 | return new FnTransform(macroName, parameters);
|
243 | }
|
244 | /**
|
245 | * Returns true if all the specified conditions evaluate to true, or returns
|
246 | * false if any one of the conditions evaluates to false. ``Fn::And`` acts as
|
247 | * an AND operator. The minimum number of conditions that you can include is
|
248 | * 1.
|
249 | * @param conditions conditions to AND
|
250 | * @returns an FnCondition token
|
251 | */
|
252 | static conditionAnd(...conditions) {
|
253 | try {
|
254 | jsiiDeprecationWarnings._aws_cdk_core_ICfnConditionExpression(conditions);
|
255 | }
|
256 | catch (error) {
|
257 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
258 | Error.captureStackTrace(error, this.conditionAnd);
|
259 | }
|
260 | throw error;
|
261 | }
|
262 | if (conditions.length === 0) {
|
263 | throw new Error('Fn.conditionAnd() needs at least one argument');
|
264 | }
|
265 | if (conditions.length === 1) {
|
266 | return conditions[0];
|
267 | }
|
268 | return Fn.conditionAnd(..._inGroupsOf(conditions, 10).map(group => new FnAnd(...group)));
|
269 | }
|
270 | /**
|
271 | * Compares if two values are equal. Returns true if the two values are equal
|
272 | * or false if they aren't.
|
273 | * @param lhs A value of any type that you want to compare.
|
274 | * @param rhs A value of any type that you want to compare.
|
275 | * @returns an FnCondition token
|
276 | */
|
277 | static conditionEquals(lhs, rhs) {
|
278 | return new FnEquals(lhs, rhs);
|
279 | }
|
280 | /**
|
281 | * Returns one value if the specified condition evaluates to true and another
|
282 | * value if the specified condition evaluates to false. Currently, AWS
|
283 | * CloudFormation supports the ``Fn::If`` intrinsic function in the metadata
|
284 | * attribute, update policy attribute, and property values in the Resources
|
285 | * section and Outputs sections of a template. You can use the AWS::NoValue
|
286 | * pseudo parameter as a return value to remove the corresponding property.
|
287 | * @param conditionId A reference to a condition in the Conditions section. Use
|
288 | * the condition's name to reference it.
|
289 | * @param valueIfTrue A value to be returned if the specified condition
|
290 | * evaluates to true.
|
291 | * @param valueIfFalse A value to be returned if the specified condition
|
292 | * evaluates to false.
|
293 | * @returns an FnCondition token
|
294 | */
|
295 | static conditionIf(conditionId, valueIfTrue, valueIfFalse) {
|
296 | return new FnIf(conditionId, valueIfTrue, valueIfFalse);
|
297 | }
|
298 | /**
|
299 | * Returns true for a condition that evaluates to false or returns false for a
|
300 | * condition that evaluates to true. ``Fn::Not`` acts as a NOT operator.
|
301 | * @param condition A condition such as ``Fn::Equals`` that evaluates to true
|
302 | * or false.
|
303 | * @returns an FnCondition token
|
304 | */
|
305 | static conditionNot(condition) {
|
306 | try {
|
307 | jsiiDeprecationWarnings._aws_cdk_core_ICfnConditionExpression(condition);
|
308 | }
|
309 | catch (error) {
|
310 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
311 | Error.captureStackTrace(error, this.conditionNot);
|
312 | }
|
313 | throw error;
|
314 | }
|
315 | return new FnNot(condition);
|
316 | }
|
317 | /**
|
318 | * Returns true if any one of the specified conditions evaluate to true, or
|
319 | * returns false if all of the conditions evaluates to false. ``Fn::Or`` acts
|
320 | * as an OR operator. The minimum number of conditions that you can include is
|
321 | * 1.
|
322 | * @param conditions conditions that evaluates to true or false.
|
323 | * @returns an FnCondition token
|
324 | */
|
325 | static conditionOr(...conditions) {
|
326 | try {
|
327 | jsiiDeprecationWarnings._aws_cdk_core_ICfnConditionExpression(conditions);
|
328 | }
|
329 | catch (error) {
|
330 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
331 | Error.captureStackTrace(error, this.conditionOr);
|
332 | }
|
333 | throw error;
|
334 | }
|
335 | if (conditions.length === 0) {
|
336 | throw new Error('Fn.conditionOr() needs at least one argument');
|
337 | }
|
338 | if (conditions.length === 1) {
|
339 | return conditions[0];
|
340 | }
|
341 | return Fn.conditionOr(..._inGroupsOf(conditions, 10).map(group => new FnOr(...group)));
|
342 | }
|
343 | /**
|
344 | * Returns true if a specified string matches at least one value in a list of
|
345 | * strings.
|
346 | * @param listOfStrings A list of strings, such as "A", "B", "C".
|
347 | * @param value A string, such as "A", that you want to compare against a list of strings.
|
348 | * @returns an FnCondition token
|
349 | */
|
350 | static conditionContains(listOfStrings, value) {
|
351 | return new FnContains(listOfStrings, value);
|
352 | }
|
353 | /**
|
354 | * Returns true if a specified string matches all values in a list.
|
355 | * @param listOfStrings A list of strings, such as "A", "B", "C".
|
356 | * @param value A string, such as "A", that you want to compare against a list
|
357 | * of strings.
|
358 | * @returns an FnCondition token
|
359 | */
|
360 | static conditionEachMemberEquals(listOfStrings, value) {
|
361 | return new FnEachMemberEquals(listOfStrings, value);
|
362 | }
|
363 | /**
|
364 | * Returns true if each member in a list of strings matches at least one value
|
365 | * in a second list of strings.
|
366 | * @param stringsToCheck A list of strings, such as "A", "B", "C". AWS
|
367 | * CloudFormation checks whether each member in the strings_to_check parameter
|
368 | * is in the strings_to_match parameter.
|
369 | * @param stringsToMatch A list of strings, such as "A", "B", "C". Each member
|
370 | * in the strings_to_match parameter is compared against the members of the
|
371 | * strings_to_check parameter.
|
372 | * @returns an FnCondition token
|
373 | */
|
374 | static conditionEachMemberIn(stringsToCheck, stringsToMatch) {
|
375 | return new FnEachMemberIn(stringsToCheck, stringsToMatch);
|
376 | }
|
377 | /**
|
378 | * Returns all values for a specified parameter type.
|
379 | * @param parameterType An AWS-specific parameter type, such as
|
380 | * AWS::EC2::SecurityGroup::Id or AWS::EC2::VPC::Id. For more information, see
|
381 | * Parameters in the AWS CloudFormation User Guide.
|
382 | * @returns a token represented as a string array
|
383 | */
|
384 | static refAll(parameterType) {
|
385 | return token_1.Token.asList(new FnRefAll(parameterType));
|
386 | }
|
387 | /**
|
388 | * Returns an attribute value or list of values for a specific parameter and
|
389 | * attribute.
|
390 | * @param parameterOrLogicalId The name of a parameter for which you want to
|
391 | * retrieve attribute values. The parameter must be declared in the Parameters
|
392 | * section of the template.
|
393 | * @param attribute The name of an attribute from which you want to retrieve a
|
394 | * value.
|
395 | * @returns a token represented as a string
|
396 | */
|
397 | static valueOf(parameterOrLogicalId, attribute) {
|
398 | return new FnValueOf(parameterOrLogicalId, attribute).toString();
|
399 | }
|
400 | /**
|
401 | * Returns a list of all attribute values for a given parameter type and
|
402 | * attribute.
|
403 | * @param parameterType An AWS-specific parameter type, such as
|
404 | * AWS::EC2::SecurityGroup::Id or AWS::EC2::VPC::Id. For more information, see
|
405 | * Parameters in the AWS CloudFormation User Guide.
|
406 | * @param attribute The name of an attribute from which you want to retrieve a
|
407 | * value. For more information about attributes, see Supported Attributes.
|
408 | * @returns a token represented as a string array
|
409 | */
|
410 | static valueOfAll(parameterType, attribute) {
|
411 | return token_1.Token.asList(new FnValueOfAll(parameterType, attribute));
|
412 | }
|
413 | }
|
414 | exports.Fn = Fn;
|
415 | _a = JSII_RTTI_SYMBOL_1;
|
416 | Fn[_a] = { fqn: "@aws-cdk/core.Fn", version: "1.204.0" };
|
417 | /**
|
418 | * Base class for tokens that represent CloudFormation intrinsic functions.
|
419 | */
|
420 | class FnBase extends intrinsic_1.Intrinsic {
|
421 | constructor(name, value) {
|
422 | super({ [name]: value });
|
423 | }
|
424 | }
|
425 | /**
|
426 | * The intrinsic function ``Ref`` returns the value of the specified parameter or resource.
|
427 | * When you specify a parameter's logical name, it returns the value of the parameter.
|
428 | * When you specify a resource's logical name, it returns a value that you can typically use to refer to that resource, such as a physical ID.
|
429 | */
|
430 | class FnRef extends FnBase {
|
431 | /**
|
432 | * Creates an ``Ref`` function.
|
433 | * @param logicalName The logical name of a parameter/resource for which you want to retrieve its value.
|
434 | */
|
435 | constructor(logicalName) {
|
436 | super('Ref', logicalName);
|
437 | }
|
438 | }
|
439 | /**
|
440 | * The intrinsic function ``Fn::FindInMap`` returns the value corresponding to keys in a two-level
|
441 | * map that is declared in the Mappings section.
|
442 | */
|
443 | class FnFindInMap extends FnBase {
|
444 | /**
|
445 | * Creates an ``Fn::FindInMap`` function.
|
446 | * @param mapName The logical name of a mapping declared in the Mappings section that contains the keys and values.
|
447 | * @param topLevelKey The top-level key name. Its value is a list of key-value pairs.
|
448 | * @param secondLevelKey The second-level key name, which is set to one of the keys from the list assigned to TopLevelKey.
|
449 | */
|
450 | constructor(mapName, topLevelKey, secondLevelKey) {
|
451 | super('Fn::FindInMap', [mapName, topLevelKey, secondLevelKey]);
|
452 | }
|
453 | }
|
454 | /**
|
455 | * The intrinsic function ``Fn::Transform`` specifies a macro to perform custom processing on part of a stack template.
|
456 | */
|
457 | class FnTransform extends FnBase {
|
458 | /**
|
459 | * creates an ``Fn::Transform`` function.
|
460 | * @param macroName The name of the macro to be invoked
|
461 | * @param parameters the parameters to pass to it
|
462 | */
|
463 | constructor(macroName, parameters) {
|
464 | super('Fn::Transform', { Name: macroName, Parameters: parameters });
|
465 | }
|
466 | }
|
467 | /**
|
468 | * The ``Fn::GetAtt`` intrinsic function returns the value of an attribute from a resource in the template.
|
469 | */
|
470 | class FnGetAtt extends FnBase {
|
471 | /**
|
472 | * Creates a ``Fn::GetAtt`` function.
|
473 | * @param logicalNameOfResource The logical name (also called logical ID) of the resource that contains the attribute that you want.
|
474 | * @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.
|
475 | */
|
476 | constructor(logicalNameOfResource, attributeName) {
|
477 | super('Fn::GetAtt', [logicalNameOfResource, attributeName]);
|
478 | }
|
479 | }
|
480 | /**
|
481 | * The intrinsic function ``Fn::GetAZs`` returns an array that lists Availability Zones for a
|
482 | * specified region. Because customers have access to different Availability Zones, the intrinsic
|
483 | * function ``Fn::GetAZs`` enables template authors to write templates that adapt to the calling
|
484 | * user's access. That way you don't have to hard-code a full list of Availability Zones for a
|
485 | * specified region.
|
486 | */
|
487 | class FnGetAZs extends FnBase {
|
488 | /**
|
489 | * Creates an ``Fn::GetAZs`` function.
|
490 | * @param region The name of the region for which you want to get the Availability Zones.
|
491 | * You can use the AWS::Region pseudo parameter to specify the region in
|
492 | * which the stack is created. Specifying an empty string is equivalent to
|
493 | * specifying AWS::Region.
|
494 | */
|
495 | constructor(region) {
|
496 | super('Fn::GetAZs', region || '');
|
497 | }
|
498 | }
|
499 | /**
|
500 | * The intrinsic function ``Fn::ImportValue`` returns the value of an output exported by another stack.
|
501 | * You typically use this function to create cross-stack references. In the following example
|
502 | * template snippets, Stack A exports VPC security group values and Stack B imports them.
|
503 | */
|
504 | class FnImportValue extends FnBase {
|
505 | /**
|
506 | * Creates an ``Fn::ImportValue`` function.
|
507 | * @param sharedValueToImport The stack output value that you want to import.
|
508 | */
|
509 | constructor(sharedValueToImport) {
|
510 | super('Fn::ImportValue', sharedValueToImport);
|
511 | }
|
512 | }
|
513 | /**
|
514 | * The intrinsic function ``Fn::Select`` returns a single object from a list of objects by index.
|
515 | */
|
516 | class FnSelect extends FnBase {
|
517 | /**
|
518 | * Creates an ``Fn::Select`` function.
|
519 | * @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.
|
520 | * @param array The list of objects to select from. This list must not be null, nor can it have null entries.
|
521 | */
|
522 | constructor(index, array) {
|
523 | super('Fn::Select', [index, array]);
|
524 | }
|
525 | }
|
526 | /**
|
527 | * To split a string into a list of string values so that you can select an element from the
|
528 | * resulting string list, use the ``Fn::Split`` intrinsic function. Specify the location of splits
|
529 | * with a delimiter, such as , (a comma). After you split a string, use the ``Fn::Select`` function
|
530 | * to pick a specific element.
|
531 | */
|
532 | class FnSplit extends FnBase {
|
533 | /**
|
534 | * Create an ``Fn::Split`` function.
|
535 | * @param delimiter A string value that determines where the source string is divided.
|
536 | * @param source The string value that you want to split.
|
537 | */
|
538 | constructor(delimiter, source) {
|
539 | super('Fn::Split', [delimiter, source]);
|
540 | }
|
541 | }
|
542 | /**
|
543 | * The intrinsic function ``Fn::Sub`` substitutes variables in an input string with values that
|
544 | * you specify. In your templates, you can use this function to construct commands or outputs
|
545 | * that include values that aren't available until you create or update a stack.
|
546 | */
|
547 | class FnSub extends FnBase {
|
548 | /**
|
549 | * Creates an ``Fn::Sub`` function.
|
550 | * @param body A string with variables that AWS CloudFormation substitutes with their
|
551 | * associated values at runtime. Write variables as ${MyVarName}. Variables
|
552 | * can be template parameter names, resource logical IDs, resource attributes,
|
553 | * or a variable in a key-value map. If you specify only template parameter names,
|
554 | * resource logical IDs, and resource attributes, don't specify a key-value map.
|
555 | * @param variables The name of a variable that you included in the String parameter.
|
556 | * The value that AWS CloudFormation substitutes for the associated variable name at runtime.
|
557 | */
|
558 | constructor(body, variables) {
|
559 | super('Fn::Sub', variables ? [body, variables] : body);
|
560 | }
|
561 | }
|
562 | /**
|
563 | * The intrinsic function ``Fn::Base64`` returns the Base64 representation of the input string.
|
564 | * This function is typically used to pass encoded data to Amazon EC2 instances by way of
|
565 | * the UserData property.
|
566 | */
|
567 | class FnBase64 extends FnBase {
|
568 | /**
|
569 | * Creates an ``Fn::Base64`` function.
|
570 | * @param data The string value you want to convert to Base64.
|
571 | */
|
572 | constructor(data) {
|
573 | super('Fn::Base64', data);
|
574 | }
|
575 | }
|
576 | /**
|
577 | * The intrinsic function ``Fn::Cidr`` returns the specified Cidr address block.
|
578 | */
|
579 | class FnCidr extends FnBase {
|
580 | /**
|
581 | * Creates an ``Fn::Cidr`` function.
|
582 | * @param ipBlock The user-specified default Cidr address block.
|
583 | * @param count The number of subnets' Cidr block wanted. Count can be 1 to 256.
|
584 | * @param sizeMask The digit covered in the subnet.
|
585 | */
|
586 | constructor(ipBlock, count, sizeMask) {
|
587 | if (count < 1 || count > 256) {
|
588 | throw new Error(`Fn::Cidr's count attribute must be betwen 1 and 256, ${count} was provided.`);
|
589 | }
|
590 | super('Fn::Cidr', [ipBlock, count, sizeMask]);
|
591 | }
|
592 | }
|
593 | class FnConditionBase extends intrinsic_1.Intrinsic {
|
594 | constructor(type, value) {
|
595 | super({ [type]: value });
|
596 | this.disambiguator = true;
|
597 | }
|
598 | }
|
599 | /**
|
600 | * Returns true if all the specified conditions evaluate to true, or returns false if any one
|
601 | * of the conditions evaluates to false. ``Fn::And`` acts as an AND operator. The minimum number of
|
602 | * conditions that you can include is 2, and the maximum is 10.
|
603 | */
|
604 | class FnAnd extends FnConditionBase {
|
605 | constructor(...condition) {
|
606 | super('Fn::And', condition);
|
607 | }
|
608 | }
|
609 | /**
|
610 | * Compares if two values are equal. Returns true if the two values are equal or false
|
611 | * if they aren't.
|
612 | */
|
613 | class FnEquals extends FnConditionBase {
|
614 | /**
|
615 | * Creates an ``Fn::Equals`` condition function.
|
616 | * @param lhs A value of any type that you want to compare.
|
617 | * @param rhs A value of any type that you want to compare.
|
618 | */
|
619 | constructor(lhs, rhs) {
|
620 | super('Fn::Equals', [lhs, rhs]);
|
621 | }
|
622 | }
|
623 | /**
|
624 | * Returns one value if the specified condition evaluates to true and another value if the
|
625 | * specified condition evaluates to false. Currently, AWS CloudFormation supports the ``Fn::If``
|
626 | * intrinsic function in the metadata attribute, update policy attribute, and property values
|
627 | * in the Resources section and Outputs sections of a template. You can use the AWS::NoValue
|
628 | * pseudo parameter as a return value to remove the corresponding property.
|
629 | */
|
630 | class FnIf extends FnConditionBase {
|
631 | /**
|
632 | * Creates an ``Fn::If`` condition function.
|
633 | * @param condition A reference to a condition in the Conditions section. Use the condition's name to reference it.
|
634 | * @param valueIfTrue A value to be returned if the specified condition evaluates to true.
|
635 | * @param valueIfFalse A value to be returned if the specified condition evaluates to false.
|
636 | */
|
637 | constructor(condition, valueIfTrue, valueIfFalse) {
|
638 | super('Fn::If', [condition, valueIfTrue, valueIfFalse]);
|
639 | }
|
640 | }
|
641 | /**
|
642 | * Returns true for a condition that evaluates to false or returns false for a condition that evaluates to true.
|
643 | * ``Fn::Not`` acts as a NOT operator.
|
644 | */
|
645 | class FnNot extends FnConditionBase {
|
646 | /**
|
647 | * Creates an ``Fn::Not`` condition function.
|
648 | * @param condition A condition such as ``Fn::Equals`` that evaluates to true or false.
|
649 | */
|
650 | constructor(condition) {
|
651 | super('Fn::Not', [condition]);
|
652 | }
|
653 | }
|
654 | /**
|
655 | * Returns true if any one of the specified conditions evaluate to true, or returns false if
|
656 | * all of the conditions evaluates to false. ``Fn::Or`` acts as an OR operator. The minimum number
|
657 | * of conditions that you can include is 2, and the maximum is 10.
|
658 | */
|
659 | class FnOr extends FnConditionBase {
|
660 | /**
|
661 | * Creates an ``Fn::Or`` condition function.
|
662 | * @param condition A condition that evaluates to true or false.
|
663 | */
|
664 | constructor(...condition) {
|
665 | super('Fn::Or', condition);
|
666 | }
|
667 | }
|
668 | /**
|
669 | * Returns true if a specified string matches at least one value in a list of strings.
|
670 | */
|
671 | class FnContains extends FnConditionBase {
|
672 | /**
|
673 | * Creates an ``Fn::Contains`` function.
|
674 | * @param listOfStrings A list of strings, such as "A", "B", "C".
|
675 | * @param value A string, such as "A", that you want to compare against a list of strings.
|
676 | */
|
677 | constructor(listOfStrings, value) {
|
678 | super('Fn::Contains', [listOfStrings, value]);
|
679 | }
|
680 | }
|
681 | /**
|
682 | * Returns true if a specified string matches all values in a list.
|
683 | */
|
684 | class FnEachMemberEquals extends FnConditionBase {
|
685 | /**
|
686 | * Creates an ``Fn::EachMemberEquals`` function.
|
687 | * @param listOfStrings A list of strings, such as "A", "B", "C".
|
688 | * @param value A string, such as "A", that you want to compare against a list of strings.
|
689 | */
|
690 | constructor(listOfStrings, value) {
|
691 | super('Fn::EachMemberEquals', [listOfStrings, value]);
|
692 | }
|
693 | }
|
694 | /**
|
695 | * Returns true if each member in a list of strings matches at least one value in a second
|
696 | * list of strings.
|
697 | */
|
698 | class FnEachMemberIn extends FnConditionBase {
|
699 | /**
|
700 | * Creates an ``Fn::EachMemberIn`` function.
|
701 | * @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.
|
702 | * @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.
|
703 | */
|
704 | constructor(stringsToCheck, stringsToMatch) {
|
705 | super('Fn::EachMemberIn', [stringsToCheck, stringsToMatch]);
|
706 | }
|
707 | }
|
708 | /**
|
709 | * Returns all values for a specified parameter type.
|
710 | */
|
711 | class FnRefAll extends FnBase {
|
712 | /**
|
713 | * Creates an ``Fn::RefAll`` function.
|
714 | * @param parameterType An AWS-specific parameter type, such as AWS::EC2::SecurityGroup::Id or
|
715 | * AWS::EC2::VPC::Id. For more information, see Parameters in the AWS
|
716 | * CloudFormation User Guide.
|
717 | */
|
718 | constructor(parameterType) {
|
719 | super('Fn::RefAll', parameterType);
|
720 | }
|
721 | }
|
722 | /**
|
723 | * Returns an attribute value or list of values for a specific parameter and attribute.
|
724 | */
|
725 | class FnValueOf extends FnBase {
|
726 | /**
|
727 | * Creates an ``Fn::ValueOf`` function.
|
728 | * @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.
|
729 | * @param attribute The name of an attribute from which you want to retrieve a value.
|
730 | */
|
731 | constructor(parameterOrLogicalId, attribute) {
|
732 | super('Fn::ValueOf', [parameterOrLogicalId, attribute]);
|
733 | }
|
734 | }
|
735 | /**
|
736 | * Returns a list of all attribute values for a given parameter type and attribute.
|
737 | */
|
738 | class FnValueOfAll extends FnBase {
|
739 | /**
|
740 | * Creates an ``Fn::ValueOfAll`` function.
|
741 | * @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.
|
742 | * @param attribute The name of an attribute from which you want to retrieve a value. For more information about attributes, see Supported Attributes.
|
743 | */
|
744 | constructor(parameterType, attribute) {
|
745 | super('Fn::ValueOfAll', [parameterType, attribute]);
|
746 | }
|
747 | }
|
748 | /**
|
749 | * The intrinsic function ``Fn::Join`` appends a set of values into a single value, separated by
|
750 | * the specified delimiter. If a delimiter is the empty string, the set of values are concatenated
|
751 | * with no delimiter.
|
752 | */
|
753 | class FnJoin {
|
754 | /**
|
755 | * Creates an ``Fn::Join`` function.
|
756 | * @param delimiter The value you want to occur between fragments. The delimiter will occur between fragments only.
|
757 | * It will not terminate the final value.
|
758 | * @param listOfValues The list of values you want combined.
|
759 | */
|
760 | constructor(delimiter, listOfValues) {
|
761 | if (listOfValues.length === 0) {
|
762 | throw new Error('FnJoin requires at least one value to be provided');
|
763 | }
|
764 | this.delimiter = delimiter;
|
765 | this.listOfValues = listOfValues;
|
766 | this.creationStack = stack_trace_1.captureStackTrace();
|
767 | }
|
768 | resolve(context) {
|
769 | if (token_1.Token.isUnresolved(this.listOfValues)) {
|
770 | // This is a list token, don't try to do smart things with it.
|
771 | return { 'Fn::Join': [this.delimiter, this.listOfValues] };
|
772 | }
|
773 | const resolved = this.resolveValues(context);
|
774 | if (resolved.length === 1) {
|
775 | return resolved[0];
|
776 | }
|
777 | return { 'Fn::Join': [this.delimiter, resolved] };
|
778 | }
|
779 | toString() {
|
780 | return token_1.Token.asString(this, { displayHint: 'Fn::Join' });
|
781 | }
|
782 | toJSON() {
|
783 | return '<Fn::Join>';
|
784 | }
|
785 | /**
|
786 | * Optimization: if an Fn::Join is nested in another one and they share the same delimiter, then flatten it up. Also,
|
787 | * if two concatenated elements are literal strings (not tokens), then pre-concatenate them with the delimiter, to
|
788 | * generate shorter output.
|
789 | */
|
790 | resolveValues(context) {
|
791 | const resolvedValues = this.listOfValues.map(x => reference_1.Reference.isReference(x) ? x : context.resolve(x));
|
792 | return cloudformation_lang_1.minimalCloudFormationJoin(this.delimiter, resolvedValues);
|
793 | }
|
794 | }
|
795 | function _inGroupsOf(array, maxGroup) {
|
796 | const result = new Array();
|
797 | for (let i = 0; i < array.length; i += maxGroup) {
|
798 | result.push(array.slice(i, i + maxGroup));
|
799 | }
|
800 | return result;
|
801 | }
|
802 | function range(n) {
|
803 | const ret = [];
|
804 | for (let i = 0; i < n; i++) {
|
805 | ret.push(i);
|
806 | }
|
807 | return ret;
|
808 | }
|
809 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2ZuLWZuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2ZuLWZuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUNBLHVFQUEwRTtBQUMxRSxtREFBZ0Q7QUFDaEQsMkNBQXdDO0FBRXhDLCtDQUFrRDtBQUNsRCxtQ0FBZ0M7QUFFaEMsNEJBQTRCO0FBRTVCOzs7R0FHRztBQUNILE1BQWEsRUFBRTtJQWdaYixpQkFBeUI7SUEvWXpCOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsR0FBRyxDQUFDLFdBQW1CO1FBQ25DLE9BQU8sSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDMUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxNQUFNLENBQUMsTUFBTSxDQUFDLHFCQUE2QixFQUFFLGFBQXFCO1FBQ3ZFLE9BQU8sSUFBSSxRQUFRLENBQUMscUJBQXFCLEVBQUUsYUFBYSxDQUFDLENBQUM7S0FDM0Q7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQWlCLEVBQUUsWUFBc0I7UUFDMUQsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLG1EQUFtRCxDQUFDLENBQUM7U0FDdEU7UUFFRCxPQUFPLElBQUksTUFBTSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztLQUN2RDtJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0EwQ0c7SUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQWlCLEVBQUUsTUFBYyxFQUFFLGFBQXNCO1FBQzNFLHdDQUF3QztRQUN4QyxJQUFJLENBQUMsYUFBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUMvQixPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDaEM7UUFFRCxJQUFJLGFB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QUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUM7S0FDM0M7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBRUQsU0FBUyxLQUFLLENBQUMsQ0FBUztJQUN0QixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFDZixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQzFCLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDYjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElDZm5Db25kaXRpb25FeHByZXNzaW9uLCBJQ2ZuUnVsZUNvbmRpdGlvbkV4cHJlc3Npb24gfSBmcm9tICcuL2Nmbi1jb25kaXRpb24nO1xuaW1wb3J0IHsgbWluaW1hbENsb3VkRm9ybWF0aW9uSm9pbiB9IGZyb20gJy4vcHJpdmF0ZS9jbG91ZGZvcm1hdGlvbi1sYW5nJztcbmltcG9ydCB7IEludHJpbnNpYyB9IGZyb20gJy4vcHJpdmF0ZS9pbnRyaW5zaWMnO1xuaW1wb3J0IHsgUmVmZXJlbmNlIH0gZnJvbSAnLi9yZWZlcmVuY2UnO1xuaW1wb3J0IHsgSVJlc29sdmFibGUsIElSZXNvbHZlQ29udGV4dCB9IGZyb20gJy4vcmVzb2x2YWJsZSc7XG5pbXBvcnQgeyBjYXB0dXJlU3RhY2tUcmFjZSB9IGZyb20gJy4vc3RhY2stdHJhY2UnO1xuaW1wb3J0IHsgVG9rZW4gfSBmcm9tICcuL3Rva2VuJztcblxuLyogZXNsaW50LWRpc2FibGUgbWF4LWxlbiAqL1xuXG4vKipcbiAqIENsb3VkRm9ybWF0aW9uIGludHJpbnNpYyBmdW5jdGlvbnMuXG4gKiBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2ludHJpbnNpYy1mdW5jdGlvbi1yZWZlcmVuY2UuaHRtbFxuICovXG5leHBvcnQgY2xhc3MgRm4ge1xuICAvKipcbiAgICogVGhlIGBgUmVmYGAgaW50cmluc2ljIGZ1bmN0aW9uIHJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgcGFyYW1ldGVyIG9yIHJlc291cmNlLlxuICAgKiBOb3RlIHRoYXQgaXQgZG9lc24ndCB2YWxpZGF0ZSB0aGUgbG9naWNhbE5hbWUsIGl0IG1haW5seSBzZXJ2ZXMgcGFyZW1ldGVyL3Jlc291cmNlIHJlZmVyZW5jZSBkZWZpbmVkIGluIGEgYGBDZm5JbmNsdWRlYGAgdGVtcGxhdGUuXG4gICAqIEBwYXJhbSBsb2dpY2FsTmFtZSBUaGUgbG9naWNhbCBuYW1lIG9mIGEgcGFyYW1ldGVyL3Jlc291cmNlIGZvciB3aGljaCB5b3Ugd2FudCB0byByZXRyaWV2ZSBpdHMgdmFsdWUuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlZihsb2dpY2FsTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IEZuUmVmKGxvZ2ljYWxOYW1lKS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBgYEZuOjpHZXRBdHRgYCBpbnRyaW5zaWMgZnVuY3Rpb24gcmV0dXJucyB0aGUgdmFsdWUgb2YgYW4gYXR0cmlidXRlXG4gICAqIGZyb20gYSByZXNvdXJjZSBpbiB0aGUgdGVtcGxhdGUuXG4gICAqIEBwYXJhbSBsb2dpY2FsTmFtZU9mUmVzb3VyY2UgVGhlIGxvZ2ljYWwgbmFtZSAoYWxzbyBjYWxsZWQgbG9naWNhbCBJRCkgb2ZcbiAgICogdGhlIHJlc291cmNlIHRoYXQgY29udGFpbnMgdGhlIGF0dHJpYnV0ZSB0aGF0IHlvdSB3YW50LlxuICAgKiBAcGFyYW0gYXR0cmlidXRlTmFtZSBUaGUgbmFtZSBvZiB0aGUgcmVzb3VyY2Utc3BlY2lmaWMgYXR0cmlidXRlIHdob3NlXG4gICAqIHZhbHVlIHlvdSB3YW50LiBTZWUgdGhlIHJlc291cmNlJ3MgcmVmZXJlbmNlIHBhZ2UgZm9yIGRldGFpbHMgYWJvdXQgdGhlXG4gICAqIGF0dHJpYnV0ZXMgYXZhaWxhYmxlIGZvciB0aGF0IHJlc291cmNlIHR5cGUuXG4gICAqIEByZXR1cm5zIGFuIElSZXNvbHZhYmxlIG9iamVjdFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBnZXRBdHQobG9naWNhbE5hbWVPZlJlc291cmNlOiBzdHJpbmcsIGF0dHJpYnV0ZU5hbWU6IHN0cmluZyk6IElSZXNvbHZhYmxlIHtcbiAgICByZXR1cm4gbmV3IEZuR2V0QXR0KGxvZ2ljYWxOYW1lT2ZSZXNvdXJjZSwgYXR0cmlidXRlTmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpKb2luYGAgYXBwZW5kcyBhIHNldCBvZiB2YWx1ZXMgaW50byBhIHNpbmdsZVxuICAgKiB2YWx1ZSwgc2VwYXJhdGVkIGJ5IHRoZSBzcGVjaWZpZWQgZGVsaW1pdGVyLiBJZiBhIGRlbGltaXRlciBpcyB0aGUgZW1wdHlcbiAgICogc3RyaW5nLCB0aGUgc2V0IG9mIHZhbHVlcyBhcmUgY29uY2F0ZW5hdGVkIHdpdGggbm8gZGVsaW1pdGVyLlxuICAgKiBAcGFyYW0gZGVsaW1pdGVyIFRoZSB2YWx1ZSB5b3Ugd2FudCB0byBvY2N1ciBiZXR3ZWVuIGZyYWdtZW50cy4gVGhlXG4gICAqIGRlbGltaXRlciB3aWxsIG9jY3VyIGJldHdlZW4gZnJhZ21lbnRzIG9ubHkuIEl0IHdpbGwgbm90IHRlcm1pbmF0ZSB0aGVcbiAgICogZmluYWwgdmFsdWUuXG4gICAqIEBwYXJhbSBsaXN0T2ZWYWx1ZXMgVGhlIGxpc3Qgb2YgdmFsdWVzIHlvdSB3YW50IGNvbWJpbmVkLlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGpvaW4oZGVsaW1pdGVyOiBzdHJpbmcsIGxpc3RPZlZhbHVlczogc3RyaW5nW10pOiBzdHJpbmcge1xuICAgIGlmIChsaXN0T2ZWYWx1ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZuSm9pbiByZXF1aXJlcyBhdCBsZWFzdCBvbmUgdmFsdWUgdG8gYmUgcHJvdmlkZWQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEZuSm9pbihkZWxpbWl0ZXIsIGxpc3RPZlZhbHVlcykudG9TdHJpbmcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdCBhIHN0cmluZyB0b2tlbiBpbnRvIGEgdG9rZW4gbGlzdCBvZiBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBTcGVjaWZ5IHRoZSBsb2NhdGlvbiBvZiBzcGxpdHMgd2l0aCBhIGRlbGltaXRlciBzdWNoIGFzICcsJyAoYSBjb21tYSkuXG4gICAqIFJlbmRlcnMgdG8gdGhlIGBGbjo6U3BsaXRgIGludHJpbnNpYyBmdW5jdGlvbi5cbiAgICpcbiAgICogTGlzdHMgd2l0aCB1bmtub3duIGxlbmd0aHMgKGRlZmF1bHQpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICpcbiAgICogU2luY2UgdGhpcyBmdW5jdGlvbiBpcyB1c2VkIHRvIHdvcmsgd2l0aCBkZXBsb3ktdGltZSB2YWx1ZXMsIGlmIGBhc3N1bWVkTGVuZ3RoYFxuICAgKiBpcyBub3QgZ2l2ZW4gdGhlIENESyBjYW5ub3Qga25vdyB0aGUgbGVuZ3RoIG9mIHRoZSByZXN1bHRpbmcgbGlzdCBhdCBzeW50aGVzaXMgdGltZS5cbiAgICogVGhpcyBicmluZ3MgdGhlIGZvbGxvd2luZyByZXN0cmljdGlvbnM6XG4gICAqXG4gICAqIC0gWW91IG11c3QgdXNlIGBGbi5zZWxlY3QoaSwgbGlzdClgIHRvIHBpY2sgZWxlbWVudHMgb3V0IG9mIHRoZSBsaXN0ICh5b3UgbXVzdCBub3QgdXNlXG4gICAqICAgYGxpc3RbaV1gKS5cbiAgICogLSBZb3UgY2Fubm90IGFkZCBlbGVtZW50cyB0byB0aGUgbGlzdCwgcmVtb3ZlIGVsZW1lbnRzIGZyb20gdGhlIGxpc3QsXG4gICAqICAgY29tYmluZSB0d28gc3VjaCBsaXN0cyB0b2dldGhlciwgb3IgdGFrZSBhIHNsaWNlIG9mIHRoZSBsaXN0LlxuICAgKiAtIFlvdSBjYW5ub3QgcGFzcyB0aGUgbGlzdCB0byBjb25zdHJ1Y3RzIHRoYXQgZG8gYW55IG9mIHRoZSBhYm92ZS5cbiAgICpcbiAgICogVGhlIG9ubHkgdmFsaWQgb3BlcmF0aW9uIHdpdGggc3VjaCBhIHRva2VuaXplZCBsaXN0IGlzIHRvIHBhc3MgaXQgdW5tb2RpZmllZCB0byBhXG4gICAqIENsb3VkRm9ybWF0aW9uIFJlc291cmNlIGNvbnN0cnVjdC5cbiAgICpcbiAgICogTGlzdHMgd2l0aCBhc3N1bWVkIGxlbmd0aHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICpcbiAgICogUGFzcyBgYXNzdW1lZExlbmd0aGAgaWYgeW91IGtub3cgdGhlIGxlbmd0aCBvZiB0aGUgbGlzdCB0aGF0IHdpbGwgYmVcbiAgICogcHJvZHVjZWQgYnkgc3BsaXR0aW5nLiBUaGUgYWN0dWFsIGxpc3QgbGVuZ3RoIGF0IGRlcGxveSB0aW1lIG1heSBiZVxuICAgKiAqbG9uZ2VyKiB0aGFuIHRoZSBudW1iZXIgeW91IHBhc3MsIGJ1dCBub3QgKnNob3J0ZXIqLlxuICAgKlxuICAgKiBUaGUgcmV0dXJuZWQgbGlzdCB3aWxsIGxvb2sgbGlrZTpcbiAgICpcbiAgICogYGBgXG4gICAqIFtGbi5zZWxlY3QoMCwgc3BsaXQpLCBGbi5zZWxlY3QoMSwgc3BsaXQpLCBGbi5zZWxlY3QoMiwgc3BsaXQpLCAuLi5dXG4gICAqIGBgYFxuICAgKlxuICAgKiBUaGUgcmVzdHJpY3Rpb25zIGZyb20gdGhlIHNlY3Rpb24gXCJMaXN0cyB3aXRoIHVua25vd24gbGVuZ3Roc1wiIHdpbGwgbm93IGJlIGxpZnRlZCxcbiAgICogYXQgdGhlIGV4cGVuc2Ugb2YgaGF2aW5nIHRvIGtub3cgYW5kIGZpeCB0aGUgbGVuZ3RoIG9mIHRoZSBsaXN0LlxuICAgKlxuICAgKiBAcGFyYW0gZGVsaW1pdGVyIEEgc3RyaW5nIHZhbHVlIHRoYXQgZGV0ZXJtaW5lcyB3aGVyZSB0aGUgc291cmNlIHN0cmluZyBpcyBkaXZpZGVkLlxuICAgKiBAcGFyYW0gc291cmNlIFRoZSBzdHJpbmcgdmFsdWUgdGhhdCB5b3Ugd2FudCB0byBzcGxpdC5cbiAgICogQHBhcmFtIGFzc3VtZWRMZW5ndGggVGhlIGxlbmd0aCBvZiB0aGUgbGlzdCB0aGF0IHdpbGwgYmUgcHJvZHVjZWQgYnkgc3BsaXR0aW5nXG4gICAqIEByZXR1cm5zIGEgdG9rZW4gcmVwcmVzZW50ZWQgYXMgYSBzdHJpbmcgYXJyYXlcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgc3BsaXQoZGVsaW1pdGVyOiBzdHJpbmcsIHNvdXJjZTogc3RyaW5nLCBhc3N1bWVkTGVuZ3RoPzogbnVtYmVyKTogc3RyaW5nW10ge1xuICAgIC8vIHNob3J0LWNpcmN1dCBpZiBzb3VyY2UgaXMgbm90IGEgdG9rZW5cbiAgICBpZiAoIVRva2VuLmlzVW5yZXNvbHZlZChzb3VyY2UpKSB7XG4gICAgICByZXR1cm4gc291cmNlLnNwbGl0KGRlbGltaXRlcik7XG4gICAgfVxuXG4gICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZChkZWxpbWl0ZXIpKSB7XG4gICAgICAvLyBMaW1pdGF0aW9uIG9mIENsb3VkRm9ybWF0aW9uXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZuLnNwbGl0OiBcXCdkZWxpbWl0ZXJcXCcgbWF5IG5vdCBiZSBhIHRva2VuIHZhbHVlJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3BsaXQgPSBUb2tlbi5hc0xpc3QobmV3IEZuU3BsaXQoZGVsaW1pdGVyLCBzb3VyY2UpKTtcbiAgICBpZiAoYXNzdW1lZExlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gc3BsaXQ7XG4gICAgfVxuXG4gICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZChhc3N1bWVkTGVuZ3RoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGbi5zcGxpdDogXFwnYXNzdW1lZExlbmd0aFxcJyBtYXkgbm90IGJlIGEgdG9rZW4gdmFsdWUnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmFuZ2UoYXNzdW1lZExlbmd0aCkubWFwKGkgPT4gRm4uc2VsZWN0KGksIHNwbGl0KSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpTZWxlY3RgYCByZXR1cm5zIGEgc2luZ2xlIG9iamVjdCBmcm9tIGEgbGlzdCBvZiBvYmplY3RzIGJ5IGluZGV4LlxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBvYmplY3QgdG8gcmV0cmlldmUuIFRoaXMgbXVzdCBiZSBhIHZhbHVlIGZyb20gemVybyB0byBOLTEsIHdoZXJlIE4gcmVwcmVzZW50cyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSBhcnJheS5cbiAgICogQHBhcmFtIGFycmF5IFRoZSBsaXN0IG9mIG9iamVjdHMgdG8gc2VsZWN0IGZyb20uIFRoaXMgbGlzdCBtdXN0IG5vdCBiZSBudWxsLCBub3IgY2FuIGl0IGhhdmUgbnVsbCBlbnRyaWVzLlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHNlbGVjdChpbmRleDogbnVtYmVyLCBhcnJheTogc3RyaW5nW10pOiBzdHJpbmcge1xuICAgIGlmICghVG9rZW4uaXNVbnJlc29sdmVkKGluZGV4KSAmJiAhVG9rZW4uaXNVbnJlc29sdmVkKGFycmF5KSAmJiAhYXJyYXkuc29tZShUb2tlbi5pc1VucmVzb2x2ZWQpKSB7XG4gICAgICByZXR1cm4gYXJyYXlbaW5kZXhdO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgRm5TZWxlY3QoaW5kZXgsIGFycmF5KS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6U3ViYGAgc3Vic3RpdHV0ZXMgdmFyaWFibGVzIGluIGFuIGlucHV0IHN0cmluZ1xuICAgKiB3aXRoIHZhbHVlcyB0aGF0IHlvdSBzcGVjaWZ5LiBJbiB5b3VyIHRlbXBsYXRlcywgeW91IGNhbiB1c2UgdGhpcyBmdW5jdGlvblxuICAgKiB0byBjb25zdHJ1Y3QgY29tbWFuZHMgb3Igb3V0cHV0cyB0aGF0IGluY2x1ZGUgdmFsdWVzIHRoYXQgYXJlbid0IGF2YWlsYWJsZVxuICAgKiB1bnRpbCB5b3UgY3JlYXRlIG9yIHVwZGF0ZSBhIHN0YWNrLlxuICAgKiBAcGFyYW0gYm9keSBBIHN0cmluZyB3aXRoIHZhcmlhYmxlcyB0aGF0IEFXUyBDbG91ZEZvcm1hdGlvbiBzdWJzdGl0dXRlc1xuICAgKiB3aXRoIHRoZWlyIGFzc29jaWF0ZWQgdmFsdWVzIGF0IHJ1bnRpbWUuIFdyaXRlIHZhcmlhYmxlcyBhcyAke015VmFyTmFtZX0uXG4gICAqIFZhcmlhYmxlcyBjYW4gYmUgdGVtcGxhdGUgcGFyYW1ldGVyIG5hbWVzLCByZXNvdXJjZSBsb2dpY2FsIElEcywgcmVzb3VyY2VcbiAgICogYXR0cmlidXRlcywgb3IgYSB2YXJpYWJsZSBpbiBhIGtleS12YWx1ZSBtYXAuIElmIHlvdSBzcGVjaWZ5IG9ubHkgdGVtcGxhdGVcbiAgICogcGFyYW1ldGVyIG5hbWVzLCByZXNvdXJjZSBsb2dpY2FsIElEcywgYW5kIHJlc291cmNlIGF0dHJpYnV0ZXMsIGRvbid0XG4gICAqIHNwZWNpZnkgYSBrZXktdmFsdWUgbWFwLlxuICAgKiBAcGFyYW0gdmFyaWFibGVzIFRoZSBuYW1lIG9mIGEgdmFyaWFibGUgdGhhdCB5b3UgaW5jbHVkZWQgaW4gdGhlIFN0cmluZ1xuICAgKiBwYXJhbWV0ZXIuIFRoZSB2YWx1ZSB0aGF0IEFXUyBDbG91ZEZvcm1hdGlvbiBzdWJzdGl0dXRlcyBmb3IgdGhlIGFzc29jaWF0ZWRcbiAgICogdmFyaWFibGUgbmFtZSBhdCBydW50aW1lLlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHN1Yihib2R5OiBzdHJpbmcsIHZhcmlhYmxlcz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0pOiBzdHJpbmcge1xuICAgIHJldHVybiBuZXcgRm5TdWIoYm9keSwgdmFyaWFibGVzKS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6QmFzZTY0YGAgcmV0dXJucyB0aGUgQmFzZTY0IHJlcHJlc2VudGF0aW9uIG9mXG4gICAqIHRoZSBpbnB1dCBzdHJpbmcuIFRoaXMgZnVuY3Rpb24gaXMgdHlwaWNhbGx5IHVzZWQgdG8gcGFzcyBlbmNvZGVkIGRhdGEgdG9cbiAgICogQW1hem9uIEVDMiBpbnN0YW5jZXMgYnkgd2F5IG9mIHRoZSBVc2VyRGF0YSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIGRhdGEgVGhlIHN0cmluZyB2YWx1ZSB5b3Ugd2FudCB0byBjb252ZXJ0IHRvIEJhc2U2NC5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZ1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBiYXNlNjQoZGF0YTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IEZuQmFzZTY0KGRhdGEpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpDaWRyYGAgcmV0dXJucyB0aGUgc3BlY2lmaWVkIENpZHIgYWRkcmVzcyBibG9jay5cbiAgICogQHBhcmFtIGlwQmxvY2sgIFRoZSB1c2VyLXNwZWNpZmllZCBkZWZhdWx0IENpZHIgYWRkcmVzcyBibG9jay5cbiAgICogQHBhcmFtIGNvdW50ICBUaGUgbnVtYmVyIG9mIHN1Ym5ldHMnIENpZHIgYmxvY2sgd2FudGVkLiBDb3VudCBjYW4gYmUgMSB0byAyNTYuXG4gICAqIEBwYXJhbSBzaXplTWFzayBUaGUgZGlnaXQgY292ZXJlZCBpbiB0aGUgc3VibmV0LlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNpZHIoaXBCbG9jazogc3RyaW5nLCBjb3VudDogbnVtYmVyLCBzaXplTWFzaz86IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gVG9rZW4uYXNMaXN0KG5ldyBGbkNpZHIoaXBCbG9jaywgY291bnQsIHNpemVNYXNrKSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYW4gdXJsLCBwYXJzZSB0aGUgZG9tYWluIG5hbWVcbiAgICogQHBhcmFtIHVybCB0aGUgdXJsIHRvIHBhcnNlXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHBhcnNlRG9tYWluTmFtZSh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3Qgbm9IdHRwcyA9IEZuLnNlbGVjdCgxLCBGbi5zcGxpdCgnLy8nLCB1cmwpKTtcbiAgICByZXR1cm4gRm4uc2VsZWN0KDAsIEZuLnNwbGl0KCcvJywgbm9IdHRwcykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6R2V0QVpzYGAgcmV0dXJucyBhbiBhcnJheSB0aGF0IGxpc3RzXG4gICAqIEF2YWlsYWJpbGl0eSBab25lcyBmb3IgYSBzcGVjaWZpZWQgcmVnaW9uLiBCZWNhdXNlIGN1c3RvbWVycyBoYXZlIGFjY2VzcyB0b1xuICAgKiBkaWZmZXJlbnQgQXZhaWxhYmlsaXR5IFpvbmVzLCB0aGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OkdldEFac2BgIGVuYWJsZXNcbiAgICogdGVtcGxhdGUgYXV0aG9ycyB0byB3cml0ZSB0ZW1wbGF0ZXMgdGhhdCBhZGFwdCB0byB0aGUgY2FsbGluZyB1c2VyJ3NcbiAgICogYWNjZXNzLiBUaGF0IHdheSB5b3UgZG9uJ3QgaGF2ZSB0byBoYXJkLWNvZGUgYSBmdWxsIGxpc3Qgb2YgQXZhaWxhYmlsaXR5XG4gICAqIFpvbmVzIGZvciBhIHNwZWNpZmllZCByZWdpb24uXG4gICAqIEBwYXJhbSByZWdpb24gVGhlIG5hbWUgb2YgdGhlIHJlZ2lvbiBmb3Igd2hpY2ggeW91IHdhbnQgdG8gZ2V0IHRoZVxuICAgKiBBdmFpbGFiaWxpdHkgWm9uZXMuIFlvdSBjYW4gdXNlIHRoZSBBV1M6OlJlZ2lvbiBwc2V1ZG8gcGFyYW1ldGVyIHRvIHNwZWNpZnlcbiAgICogdGhlIHJlZ2lvbiBpbiB3aGljaCB0aGUgc3RhY2sgaXMgY3JlYXRlZC4gU3BlY2lmeWluZyBhbiBlbXB0eSBzdHJpbmcgaXNcbiAgICogZXF1aXZhbGVudCB0byBzcGVjaWZ5aW5nIEFXUzo6UmVnaW9uLlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nIGFycmF5XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGdldEF6cyhyZWdpb24/OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIFRva2VuLmFzTGlzdChuZXcgRm5HZXRBWnMocmVnaW9uKSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpJbXBvcnRWYWx1ZWBgIHJldHVybnMgdGhlIHZhbHVlIG9mIGFuIG91dHB1dFxuICAgKiBleHBvcnRlZCBieSBhbm90aGVyIHN0YWNrLiBZb3UgdHlwaWNhbGx5IHVzZSB0aGlzIGZ1bmN0aW9uIHRvIGNyZWF0ZVxuICAgKiBjcm9zcy1zdGFjayByZWZlcmVuY2VzLiBJbiB0aGUgZm9sbG93aW5nIGV4YW1wbGUgdGVtcGxhdGUgc25pcHBldHMsIFN0YWNrIEFcbiAgICogZXhwb3J0cyBWUEMgc2VjdXJpdHkgZ3JvdXAgdmFsdWVzIGFuZCBTdGFjayBCIGltcG9ydHMgdGhlbS5cbiAgICogQHBhcmFtIHNoYXJlZFZhbHVlVG9JbXBvcnQgVGhlIHN0YWNrIG91dHB1dCB2YWx1ZSB0aGF0IHlvdSB3YW50IHRvIGltcG9ydC5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZ1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBpbXBvcnRWYWx1ZShzaGFyZWRWYWx1ZVRvSW1wb3J0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBuZXcgRm5JbXBvcnRWYWx1ZShzaGFyZWRWYWx1ZVRvSW1wb3J0KS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpa2UgYEZuLmltcG9ydFZhbHVlYCwgYnV0IGltcG9ydCBhIGxpc3Qgd2l0aCBhIGtub3duIGxlbmd0aFxuICAgKlxuICAgKiBJZiB5b3UgZXhwbGljaXRseSB3YW50IGEgbGlzdCB3aXRoIGFuIHVua25vd24gbGVuZ3RoLCBjYWxsIGBGbi5zcGxpdCgnLCcsXG4gICAqIEZuLmltcG9ydFZhbHVlKGV4cG9ydE5hbWUpKWAuIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBvZiBgRm4uc3BsaXRgIHRvIHJlYWRcbiAgICogbW9yZSBhYm91dCB0aGUgbGltaXRhdGlvbnMgb2YgdXNpbmcgbGlzdHMgb2YgdW5rbm93biBsZW5ndGguXG4gICAqXG4gICAqIGBGbi5pbXBvcnRMaXN0VmFsdWUoZXhwb3J0TmFtZSwgYXNzdW1lZExlbmd0aClgIGlzIHRoZSBzYW1lIGFzXG4gICAqIGBGbi5zcGxpdCgnLCcsIEZuLmltcG9ydFZhbHVlKGV4cG9ydE5hbWUpLCBhc3N1bWVkTGVuZ3RoKWAsXG4gICAqIGJ1dCBlYXNpZXIgdG8gcmVhZCBhbmQgaW1wb3NzaWJsZSB0byBmb3JnZXQgdG8gcGFzcyBgYXNzdW1lZExlbmd0aGAuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGltcG9ydExpc3RWYWx1ZShzaGFyZWRWYWx1ZVRvSW1wb3J0OiBzdHJpbmcsIGFzc3VtZWRMZW5ndGg6IG51bWJlciwgZGVsaW1pdGVyID0gJywnKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBGbi5zcGxpdChkZWxpbWl0ZXIsIEZuLmltcG9ydFZhbHVlKHNoYXJlZFZhbHVlVG9JbXBvcnQpLCBhc3N1bWVkTGVuZ3RoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OkZpbmRJbk1hcGBgIHJldHVybnMgdGhlIHZhbHVlIGNvcnJlc3BvbmRpbmcgdG9cbiAgICoga2V5cyBpbiBhIHR3by1sZXZlbCBtYXAgdGhhdCBpcyBkZWNsYXJlZCBpbiB0aGUgTWFwcGluZ3Mgc2VjdGlvbi5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZ1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmaW5kSW5NYXAobWFwTmFtZTogc3RyaW5nLCB0b3BMZXZlbEtleTogc3RyaW5nLCBzZWNvbmRMZXZlbEtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gRm4uX2ZpbmRJbk1hcChtYXBOYW1lLCB0b3BMZXZlbEtleSwgc2Vjb25kTGV2ZWxLZXkpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogQW4gYWRkaXRpb25hbCBmdW5jdGlvbiB1c2VkIGluIENmblBhcnNlcixcbiAgICogYXMgRm46OkZpbmRJbk1hcCBkb2VzIG5vdCBhbHdheXMgcmV0dXJuIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgX2ZpbmRJbk1hcChtYXBOYW1lOiBzdHJpbmcsIHRvcExldmVsS2V5OiBzdHJpbmcsIHNlY29uZExldmVsS2V5OiBzdHJpbmcpOiBJUmVzb2x2YWJsZSB7XG4gICAgcmV0dXJuIG5ldyBGbkZpbmRJbk1hcChtYXBOYW1lLCB0b3BMZXZlbEtleSwgc2Vjb25kTGV2ZWxLZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSB0b2tlbiByZXByZXNlbnRpbmcgdGhlIGBgRm46OlRyYW5zZm9ybWBgIGV4cHJlc3Npb25cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9pbnRyaW5zaWMtZnVuY3Rpb24tcmVmZXJlbmNlLXRyYW5zZm9ybS5odG1sXG4gICAqIEBwYXJhbSBtYWNyb05hbWUgVGhlIG5hbWUgb2YgdGhlIG1hY3JvIHRvIHBlcmZvcm0gdGhlIHByb2Nlc3NpbmdcbiAgICogQHBhcmFtIHBhcmFtZXRlcnMgVGhlIHBhcmFtZXRlcnMgdG8gYmUgcGFzc2VkIHRvIHRoZSBtYWNyb1xuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGluZyB0aGUgdHJhbnNmb3JtIGV4cHJlc3Npb25cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgdHJhbnNmb3JtKG1hY3JvTmFtZTogc3RyaW5nLCBwYXJhbWV0ZXJzOiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSk6IElSZXNvbHZhYmxlIHtcbiAgICByZXR1cm4gbmV3IEZuVHJhbnNmb3JtKG1hY3JvTmFtZSwgcGFyYW1ldGVycyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIGFsbCB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbnMgZXZhbHVhdGUgdG8gdHJ1ZSwgb3IgcmV0dXJuc1xuICAgKiBmYWxzZSBpZiBhbnkgb25lIG9mIHRoZSBjb25kaXRpb25zIGV2YWx1YXRlcyB0byBmYWxzZS4gYGBGbjo6QW5kYGAgYWN0cyBhc1xuICAgKiBhbiBBTkQgb3BlcmF0b3IuIFRoZSBtaW5pbXVtIG51bWJlciBvZiBjb25kaXRpb25zIHRoYXQgeW91IGNhbiBpbmNsdWRlIGlzXG4gICAqIDEuXG4gICAqIEBwYXJhbSBjb25kaXRpb25zIGNvbmRpdGlvbnMgdG8gQU5EXG4gICAqIEByZXR1cm5zIGFuIEZuQ29uZGl0aW9uIHRva2VuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbmRpdGlvbkFuZCguLi5jb25kaXRpb25zOiBJQ2ZuQ29uZGl0aW9uRXhwcmVzc2lvbltdKTogSUNmblJ1bGVDb25kaXRpb25FeHByZXNzaW9uIHtcbiAgICBpZiAoY29uZGl0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRm4uY29uZGl0aW9uQW5kKCkgbmVlZHMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50Jyk7XG4gICAgfVxuICAgIGlmIChjb25kaXRpb25zLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIGNvbmRpdGlvbnNbMF0gYXMgSUNmblJ1bGVDb25kaXRpb25FeHByZXNzaW9uO1xuICAgIH1cbiAgICByZXR1cm4gRm4uY29uZGl0aW9uQW5kKC4uLl9pbkdyb3Vwc09mKGNvbmRpdGlvbnMsIDEwKS5tYXAoZ3JvdXAgPT4gbmV3IEZuQW5kKC4uLmdyb3VwKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbXBhcmVzIGlmIHR3byB2YWx1ZXMgYXJlIGVxdWFsLiBSZXR1cm5zIHRydWUgaWYgdGhlIHR3byB2YWx1ZXMgYXJlIGVxdWFsXG4gICAqIG9yIGZhbHNlIGlmIHRoZXkgYXJlbid0LlxuICAgKiBAcGFyYW0gbGhzIEEgdmFsdWUgb2YgYW55IHR5cGUgdGhhdCB5b3Ugd2FudCB0byBjb21wYXJlLlxuICAgKiBAcGFyYW0gcmhzIEEgdmFsdWUgb2YgYW55IHR5cGUgdGhhdCB5b3Ugd2FudCB0byBjb21wYXJlLlxuICAgKiBAcmV0dXJucyBhbiBGbkNvbmRpdGlvbiB0b2tlblxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb25kaXRpb25FcXVhbHMobGhzOiBhbnksIHJoczogYW55KTogSUNmblJ1bGVDb25kaXRpb25FeHByZXNzaW9uIHtcbiAgICByZXR1cm4gbmV3IEZuRXF1YWxzKGxocywgcmhzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIG9uZSB2YWx1ZSBpZiB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbiBldmFsdWF0ZXMgdG8gdHJ1ZSBhbmQgYW5vdGhlclxuICAgKiB2YWx1ZSBpZiB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbiBldmFsdWF0ZXMgdG8gZmFsc2UuIEN1cnJlbnRseSwgQVdTXG4gICAqIENsb3VkRm9ybWF0aW9uIHN1cHBvcnRzIHRoZSBgYEZuOjpJZmBgIGludHJpbnNpYyBmdW5jdGlvbiBpbiB0aGUgbWV0YWRhdGFcbiAgICogYXR0cmlidXRlLCB1cGRhdGUgcG9saWN5IGF0dHJpYnV0ZSwgYW5kIHByb3BlcnR5IHZhbHVlcyBpbiB0aGUgUmVzb3VyY2VzXG4gICAqIHNlY3Rpb24gYW5kIE91dHB1dHMgc2VjdGlvbnMgb2YgYSB0ZW1wbGF0ZS4gWW91IGNhbiB1c2UgdGhlIEFXUzo6Tm9WYWx1ZVxuICAgKiBwc2V1ZG8gcGFyYW1ldGVyIGFzIGEgcmV0dXJuIHZhbHVlIHRvIHJlbW92ZSB0aGUgY29ycmVzcG9uZGluZyBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIGNvbmRpdGlvbklkIEEgcmVmZXJlbmNlIHRvIGEgY29uZGl0aW9uIGluIHRoZSBDb25kaXRpb25zIHNlY3Rpb24uIFVzZVxuICAgKiB0aGUgY29uZGl0aW9uJ3MgbmFtZSB0byByZWZlcmVuY2UgaXQuXG4gICAqIEBwYXJhbSB2YWx1ZUlmVHJ1ZSBBIHZhbHVlIHRvIGJlIHJldHVybmVkIGlmIHRoZSBzcGVjaWZpZWQgY29uZGl0aW9uXG4gICAqIGV2YWx1YXRlcyB0byB0cnVlLlxuICAgKiBAcGFyYW0gdmFsdWVJZkZhbHNlIEEgdmFsdWUgdG8gYmUgcmV0dXJuZWQgaWYgdGhlIHNwZWNpZmllZCBjb25kaXRpb25cbiAgICogZXZhbHVhdGVzIHRvIGZhbHNlLlxuICAgKiBAcmV0dXJucyBhbiBGbkNvbmRpdGlvbiB0b2tlblxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb25kaXRpb25JZihjb25kaXRpb25JZDogc3RyaW5nLCB2YWx1ZUlmVHJ1ZTogYW55LCB2YWx1ZUlmRmFsc2U6IGFueSk6IElDZm5SdWxlQ29uZGl0aW9uRXhwcmVzc2lvbiB7XG4gICAgcmV0dXJuIG5ldyBGbklmKGNvbmRpdGlvbklkLCB2YWx1ZUlmVHJ1ZSwgdmFsdWVJZkZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgZm9yIGEgY29uZGl0aW9uIHRoYXQgZXZhbHVhdGVzIHRvIGZhbHNlIG9yIHJldHVybnMgZmFsc2UgZm9yIGFcbiAgICogY29uZGl0aW9uIHRoYXQgZXZhbHVhdGVzIHRvIHRydWUuIGBgRm46Ok5vdGBgIGFjdHMgYXMgYSBOT1Qgb3BlcmF0b3IuXG4gICAqIEBwYXJhbSBjb25kaXRpb24gQSBjb25kaXRpb24gc3VjaCBhcyBgYEZuOjpFcXVhbHNgYCB0aGF0IGV2YWx1YXRlcyB0byB0cnVlXG4gICAqIG9yIGZhbHNlLlxuICAgKiBAcmV0dXJucyBhbiBGbkNvbmRpdGlvbiB0b2tlblxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb25kaXRpb25Ob3QoY29uZGl0aW9uOiBJQ2ZuQ29uZGl0aW9uRXhwcmVzc2lvbik6IElDZm5SdWxlQ29uZGl0aW9uRXhwcmVzc2lvbiB7XG4gICAgcmV0dXJuIG5ldyBGbk5vdChjb25kaXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiBhbnkgb25lIG9mIHRoZSBzcGVjaWZpZWQgY29uZGl0aW9ucyBldmFsdWF0ZSB0byB0cnVlLCBvclxuICAgKiByZXR1cm5zIGZhbHNlIGlmIGFsbCBvZiB0aGUgY29uZGl0aW9ucyBldmFsdWF0ZXMgdG8gZmFsc2UuIGBgRm46Ok9yYGAgYWN0c1xuICAgKiBhcyBhbiBPUiBvcGVyYXRvci4gVGhlIG1pbmltdW0gbnVtYmVyIG9mIGNvbmRpdGlvbnMgdGhhdCB5b3UgY2FuIGluY2x1ZGUgaXNcbiAgICogMS5cbiAgICogQHBhcmFtIGNvbmRpdGlvbnMgY29uZGl0aW9ucyB0aGF0IGV2YWx1YXRlcyB0byB0cnVlIG9yIGZhbHNlLlxuICAgKiBAcmV0dXJucyBhbiBGbkNvbmRpdGlvbiB0b2tlblxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb25kaXRpb25PciguLi5jb25kaXRpb25zOiBJQ2ZuQ29uZGl0aW9uRXhwcmVzc2lvbltdKTogSUNmblJ1bGVDb25kaXRpb25FeHByZXNzaW9uIHtcbiAgICBpZiAoY29uZGl0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRm4uY29uZGl0aW9uT3IoKSBuZWVkcyBhdCBsZWFzdCBvbmUgYXJndW1lbnQnKTtcbiAgICB9XG4gICAgaWYgKGNvbmRpdGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4gY29uZGl0aW9uc1swXSBhcyBJQ2ZuUnVsZUNvbmRpdGlvbkV4cHJlc3Npb247XG4gICAgfVxuICAgIHJldHVybiBGbi5jb25kaXRpb25PciguLi5faW5Hcm91cHNPZihjb25kaXRpb25zLCAxMCkubWFwKGdyb3VwID0+IG5ldyBGbk9yKC4uLmdyb3VwKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiBhIHNwZWNpZmllZCBzdHJpbmcgbWF0Y2hlcyBhdCBsZWFzdCBvbmUgdmFsdWUgaW4gYSBsaXN0IG9mXG4gICAqIHN0cmluZ3MuXG4gICAqIEBwYXJhbSBsaXN0T2ZTdHJpbmdzIEEgbGlzdCBvZiBzdHJpbmdzLCBzdWNoIGFzIFwiQVwiLCBcIkJcIiwgXCJDXCIuXG4gICAqIEBwYXJhbSB2YWx1ZSBBIHN0cmluZywgc3VjaCBhcyBcIkFcIiwgdGhhdCB5b3Ugd2FudCB0byBjb21wYXJlIGFnYWluc3QgYSBsaXN0IG9mIHN0cmluZ3MuXG4gICAqIEByZXR1cm5zIGFuIEZuQ29uZGl0aW9uIHRva2VuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbmRpdGlvbkNvbnRhaW5zKGxpc3RPZlN0cmluZ3M6IHN0cmluZ1tdLCB2YWx1ZTogc3RyaW5nKTogSUNmblJ1bGVDb25kaXRpb25FeHByZXNzaW9uIHtcbiAgICByZXR1cm4gbmV3IEZuQ29udGFpbnMobGlzdE9mU3RyaW5ncywgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiBhIHNwZWNpZmllZCBzdHJpbmcgbWF0Y2hlcyBhbGwgdmFsdWVzIGluIGEgbGlzdC5cbiAgICogQHBhcmFtIGxpc3RPZlN0cmluZ3MgQSBsaXN0IG9mIHN0cmluZ3MsIHN1Y2ggYXMgXCJBXCIsIFwiQlwiLCBcIkNcIi5cbiAgICogQHBhcmFtIHZhbHVlIEEgc3RyaW5nLCBzdWNoIGFzIFwiQVwiLCB0aGF0IHlvdSB3YW50IHRvIGNvbXBhcmUgYWdhaW5zdCBhIGxpc3RcbiAgICogb2Ygc3RyaW5ncy5cbiAgICogQHJldHVybnMgYW4gRm5Db25kaXRpb24gdG9rZW5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29uZGl0aW9uRWFjaE1lbWJlckVxdWFscyhsaXN0T2ZTdHJpbmdzOiBzdHJpbmdbXSwgdmFsdWU6IHN0cmluZyk6IElDZm5SdWxlQ29uZGl0aW9uRXhwcmVzc2lvbiB7XG4gICAgcmV0dXJuIG5ldyBGbkVhY2hNZW1iZXJFcXVhbHMobGlzdE9mU3RyaW5ncywgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiBlYWNoIG1lbWJlciBpbiBhIGxpc3Qgb2Ygc3RyaW5ncyBtYXRjaGVzIGF0IGxlYXN0IG9uZSB2YWx1ZVxuICAgKiBpbiBhIHNlY29uZCBsaXN0IG9mIHN0cmluZ3MuXG4gICAqIEBwYXJhbSBzdHJpbmdzVG9DaGVjayBBIGxpc3Qgb2Ygc3RyaW5ncywgc3VjaCBhcyBcIkFcIiwgXCJCXCIsIFwiQ1wiLiBBV1NcbiAgICogQ2xvdWRGb3JtYXRpb24gY2hlY2tzIHdoZXRoZXIgZWFjaCBtZW1iZXIgaW4gdGhlIHN0cmluZ3NfdG9fY2hlY2sgcGFyYW1ldGVyXG4gICAqIGlzIGluIHRoZSBzdHJpbmdzX3RvX21hdGNoIHBhcmFtZXRlci5cbiAgICogQHBhcmFtIHN0cmluZ3NUb01hdGNoIEEgbGlzdCBvZiBzdHJpbmdzLCBzdWNoIGFzIFwiQVwiLCBcIkJcIiwgXCJDXCIuIEVhY2ggbWVtYmVyXG4gICAqIGluIHRoZSBzdHJpbmdzX3RvX21hdGNoIHBhcmFtZXRlciBpcyBjb21wYXJlZCBhZ2FpbnN0IHRoZSBtZW1iZXJzIG9mIHRoZVxuICAgKiBzdHJpbmdzX3RvX2NoZWNrIHBhcmFtZXRlci5cbiAgICogQHJldHVybnMgYW4gRm5Db25kaXRpb24gdG9rZW5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29uZGl0aW9uRWFjaE1lbWJlckluKHN0cmluZ3NUb0NoZWNrOiBzdHJpbmdbXSwgc3RyaW5nc1RvTWF0Y2g6IHN0cmluZ1tdKTogSUNmblJ1bGVDb25kaXRpb25FeHByZXNzaW9uIHtcbiAgICByZXR1cm4gbmV3IEZuRWFjaE1lbWJlckluKHN0cmluZ3NUb0NoZWNrLCBzdHJpbmdzVG9NYXRjaCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbGwgdmFsdWVzIGZvciBhIHNwZWNpZmllZCBwYXJhbWV0ZXIgdHlwZS5cbiAgICogQHBhcmFtIHBhcmFtZXRlclR5cGUgQW4gQVdTLXNwZWNpZmljIHBhcmFtZXRlciB0eXBlLCBzdWNoIGFzXG4gICAqIEFXUzo6RUMyOjpTZWN1cml0eUdyb3VwOjpJZCBvciBBV1M6OkVDMjo6VlBDOjpJZC4gRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZVxuICAgKiBQYXJhbWV0ZXJzIGluIHRoZSBBV1MgQ2xvdWRGb3JtYXRpb24gVXNlciBHdWlkZS5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZyBhcnJheVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWZBbGwocGFyYW1ldGVyVHlwZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBUb2tlbi5hc0xpc3QobmV3IEZuUmVmQWxsKHBhcmFtZXRlclR5cGUpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIGF0dHJpYnV0ZSB2YWx1ZSBvciBsaXN0IG9mIHZhbHVlcyBmb3IgYSBzcGVjaWZpYyBwYXJhbWV0ZXIgYW5kXG4gICAqIGF0dHJpYnV0ZS5cbiAgICogQHBhcmFtIHBhcmFtZXRlck9yTG9naWNhbElkIFRoZSBuYW1lIG9mIGEgcGFyYW1ldGVyIGZvciB3aGljaCB5b3Ugd2FudCB0b1xuICAgKiByZXRyaWV2ZSBhdHRyaWJ1dGUgdmFsdWVzLiBUaGUgcGFyYW1ldGVyIG11c3QgYmUgZGVjbGFyZWQgaW4gdGhlIFBhcmFtZXRlcnNcbiAgICogc2VjdGlvbiBvZiB0aGUgdGVtcGxhdGUuXG4gICAqIEBwYXJhbSBhdHRyaWJ1dGUgVGhlIG5hbWUgb2YgYW4gYXR0cmlidXRlIGZyb20gd2hpY2ggeW91IHdhbnQgdG8gcmV0cmlldmUgYVxuICAgKiB2YWx1ZS5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZ1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyB2YWx1ZU9mKHBhcmFtZXRlck9yTG9naWNhbElkOiBzdHJpbmcsIGF0dHJpYnV0ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IEZuVmFsdWVPZihwYXJhbWV0ZXJPckxvZ2ljYWxJZCwgYXR0cmlidXRlKS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBsaXN0IG9mIGFsbCBhdHRyaWJ1dGUgdmFsdWVzIGZvciBhIGdpdmVuIHBhcmFtZXRlciB0eXBlIGFuZFxuICAgKiBhdHRyaWJ1dGUuXG4gICAqIEBwYXJhbSBwYXJhbWV0ZXJUeXBlIEFuIEFXUy1zcGVjaWZpYyBwYXJhbWV0ZXIgdHlwZSwgc3VjaCBhc1xuICAgKiBBV1M6OkVDMjo6U2VjdXJpdHlHcm91cDo6SWQgb3IgQVdTOjpFQzI6OlZQQzo6SWQuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWVcbiAgICogUGFyYW1ldGVycyBpbiB0aGUgQVdTIENsb3VkRm9ybWF0aW9uIFVzZXIgR3VpZGUuXG4gICAqIEBwYXJhbSBhdHRyaWJ1dGUgVGhlIG5hbWUgb2YgYW4gYXR0cmlidXRlIGZyb20gd2hpY2ggeW91IHdhbnQgdG8gcmV0cmlldmUgYVxuICAgKiB2YWx1ZS4gRm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgYXR0cmlidXRlcywgc2VlIFN1cHBvcnRlZCBBdHRyaWJ1dGVzLlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nIGFycmF5XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHZhbHVlT2ZBbGwocGFyYW1ldGVyVHlwZTogc3RyaW5nLCBhdHRyaWJ1dGU6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gVG9rZW4uYXNMaXN0KG5ldyBGblZhbHVlT2ZBbGwocGFyYW1ldGVyVHlwZSwgYXR0cmlidXRlKSk7XG4gIH1cblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKCkgeyB9XG59XG5cbi8qKlxuICogQmFzZSBjbGFzcyBmb3IgdG9rZW5zIHRoYXQgcmVwcmVzZW50IENsb3VkRm9ybWF0aW9uIGludHJpbnNpYyBmdW5jdGlvbnMuXG4gKi9cbmNsYXNzIEZuQmFzZSBleHRlbmRzIEludHJpbnNpYyB7XG4gIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIHN1cGVyKHsgW25hbWVdOiB2YWx1ZSB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBSZWZgYCByZXR1cm5zIHRoZSB2YWx1ZSBvZiB0aGUgc3BlY2lmaWVkIHBhcmFtZXRlciBvciByZXNvdXJjZS5cbiAqIFdoZW4geW91IHNwZWNpZnkgYSBwYXJhbWV0ZXIncyBsb2dpY2FsIG5hbWUsIGl0IHJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuXG4gKiBXaGVuIHlvdSBzcGVjaWZ5IGEgcmVzb3VyY2UncyBsb2dpY2FsIG5hbWUsIGl0IHJldHVybnMgYSB2YWx1ZSB0aGF0IHlvdSBjYW4gdHlwaWNhbGx5IHVzZSB0byByZWZlciB0byB0aGF0IHJlc291cmNlLCBzdWNoIGFzIGEgcGh5c2ljYWwgSUQuXG4gKi9cbmNsYXNzIEZuUmVmIGV4dGVuZHMgRm5CYXNlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYGBSZWZgYCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGxvZ2ljYWxOYW1lIFRoZSBsb2dpY2FsIG5hbWUgb2YgYSBwYXJhbWV0ZXIvcmVzb3VyY2UgZm9yIHdoaWNoIHlvdSB3YW50IHRvIHJldHJpZXZlIGl0cyB2YWx1ZS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGxvZ2ljYWxOYW1lOiBzdHJpbmcpIHtcbiAgICBzdXBlcignUmVmJywgbG9naWNhbE5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpGaW5kSW5NYXBgYCByZXR1cm5zIHRoZSB2YWx1ZSBjb3JyZXNwb25kaW5nIHRvIGtleXMgaW4gYSB0d28tbGV2ZWxcbiAqIG1hcCB0aGF0IGlzIGRlY2xhcmVkIGluIHRoZSBNYXBwaW5ncyBzZWN0aW9uLlxuICovXG5jbGFzcyBGbkZpbmRJbk1hcCBleHRlbmRzIEZuQmFzZSB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGBgRm46OkZpbmRJbk1hcGBgIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gbWFwTmFtZSBUaGUgbG9naWNhbCBuYW1lIG9mIGEgbWFwcGluZyBkZWNsYXJlZCBpbiB0aGUgTWFwcGluZ3Mgc2VjdGlvbiB0aGF0IGNvbnRhaW5zIHRoZSBrZXlzIGFuZCB2YWx1ZXMuXG4gICAqIEBwYXJhbSB0b3BMZXZlbEtleSBUaGUgdG9wLWxldmVsIGtleSBuYW1lLiBJdHMgdmFsdWUgaXMgYSBsaXN0IG9mIGtleS12YWx1ZSBwYWlycy5cbiAgICogQHBhcmFtIHNlY29uZExldmVsS2V5IFRoZSBzZWNvbmQtbGV2ZWwga2V5IG5hbWUsIHdoaWNoIGlzIHNldCB0byBvbmUgb2YgdGhlIGtleXMgZnJvbSB0aGUgbGlzdCBhc3NpZ25lZCB0byBUb3BMZXZlbEtleS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG1hcE5hbWU6IHN0cmluZywgdG9wTGV2ZWxLZXk6IGFueSwgc2Vjb25kTGV2ZWxLZXk6IGFueSkge1xuICAgIHN1cGVyKCdGbjo6RmluZEluTWFwJywgW21hcE5hbWUsIHRvcExldmVsS2V5LCBzZWNvbmRMZXZlbEtleV0pO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpUcmFuc2Zvcm1gYCBzcGVjaWZpZXMgYSBtYWNybyB0byBwZXJmb3JtIGN1c3RvbSBwcm9jZXNzaW5nIG9uIHBhcnQgb2YgYSBzdGFjayB0ZW1wbGF0ZS5cbiAqL1xuY2xhc3MgRm5UcmFuc2Zvcm0gZXh0ZW5kcyBGbkJhc2Uge1xuICAvKipcbiAgICogY3JlYXRlcyBhbiBgYEZuOjpUcmFuc2Zvcm1gYCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIG1hY3JvTmFtZSBUaGUgbmFtZSBvZiB0aGUgbWFjcm8gdG8gYmUgaW52b2tlZFxuICAgKiBAcGFyYW0gcGFyYW1ldGVycyB0aGUgcGFyYW1ldGVycyB0byBwYXNzIHRvIGl0XG4gICAqL1xuICBjb25zdHJ1Y3RvcihtYWNyb05hbWU6IHN0cmluZywgcGFyYW1ldGVyczogeyBbbmFtZTogc3RyaW5nXTogYW55IH0pIHtcbiAgICBzdXBlcignRm46OlRyYW5zZm9ybScsIHsgTmFtZTogbWFjcm9OYW1lLCBQYXJhbWV0ZXJzOiBwYXJhbWV0ZXJzIH0pO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGBgRm46OkdldEF0dGBgIGludHJpbnNpYyBmdW5jdGlvbiByZXR1cm5zIHRoZSB2YWx1ZSBvZiBhbiBhdHRyaWJ1dGUgZnJvbSBhIHJlc291cmNlIGluIHRoZSB0ZW1wbGF0ZS5cbiAqL1xuY2xhc3MgRm5HZXRBdHQgZXh0ZW5kcyBGbkJhc2Uge1xuICAvKipcbiAgICogQ3JlYXRlcyBhIGBgRm46OkdldEF0dGBgIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gbG9naWNhbE5hbWVPZlJlc291cmNlIFRoZSBsb2dpY2FsIG5hbWUgKGFsc28gY2FsbGVkIGxvZ2ljYWwgSUQpIG9mIHRoZSByZXNvdXJjZSB0aGF0IGNvbnRhaW5zIHRoZSBhdHRyaWJ1dGUgdGhhdCB5b3Ugd2FudC5cbiAgICogQHBhcmFtIGF0dHJpYnV0ZU5hbWUgVGhlIG5hbWUgb2YgdGhlIHJlc291cmNlLXNwZWNpZmljIGF0dHJpYnV0ZSB3aG9zZSB2YWx1ZSB5b3Ugd2FudC4gU2VlIHRoZSByZXNvdXJjZSdzIHJlZmVyZW5jZSBwYWdlIGZvciBkZXRhaWxzIGFib3V0IHRoZSBhdHRyaWJ1dGVzIGF2YWlsYWJsZSBmb3IgdGhhdCByZXNvdXJjZSB0eXBlLlxuICAgKi9cbiAgY29uc3RydWN0b3IobG9naWNhbE5hbWVPZlJlc291cmNlOiBzdHJpbmcsIGF0dHJpYnV0ZU5hbWU6IHN0cmluZykge1xuICAgIHN1cGVyKCdGbjo6R2V0QXR0JywgW2xvZ2ljYWxOYW1lT2ZSZXNvdXJjZSwgYXR0cmlidXRlTmFtZV0pO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpHZXRBWnNgYCByZXR1cm5zIGFuIGFycmF5IHRoYXQgbGlzdHMgQXZhaWxhYmlsaXR5IFpvbmVzIGZvciBhXG4gKiBzcGVjaWZpZWQgcmVnaW9uLiBCZWNhdXNlIGN1c3RvbWVycyBoYXZlIGFjY2VzcyB0byBkaWZmZXJlbnQgQXZhaWxhYmlsaXR5IFpvbmVzLCB0aGUgaW50cmluc2ljXG4gKiBmdW5jdGlvbiBgYEZuOjpHZXRBWnNgYCBlbmFibGVzIHRlbXBsYXRlIGF1dGhvcnMgdG8gd3JpdGUgdGVtcGxhdGVzIHRoYXQgYWRhcHQgdG8gdGhlIGNhbGxpbmdcbiAqIHVzZXIncyBhY2Nlc3MuIFRoYXQgd2F5IHlvdSBkb24ndCBoYXZlIHRvIGhhcmQtY29kZSBhIGZ1bGwgbGlzdCBvZiBBdmFpbGFiaWxpdHkgWm9uZXMgZm9yIGFcbiAqIHNwZWNpZmllZCByZWdpb24uXG4gKi9cbmNsYXNzIEZuR2V0QVpzIGV4dGVuZHMgRm5CYXNlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYGBGbjo6R2V0QVpzYGAgZnVuY3Rpb24uXG4gICAqIEBwYXJhbSByZWdpb24gVGhlIG5hbWUgb2YgdGhlIHJlZ2lvbiBmb3Igd2hpY2ggeW91IHdhbnQgdG8gZ2V0IHRoZSBBdmFpbGFiaWxpdHkgWm9uZXMuXG4gICAqICAgICAgICAgWW91IGNhbiB1c2UgdGhlIEFXUzo6UmVnaW9uIHBzZXVkbyBwYXJhbWV0ZXIgdG8gc3BlY2lmeSB0aGUgcmVnaW9uIGluXG4gICAqICAgICAgICAgd2hpY2ggdGhlIHN0YWNrIGlzIGNyZWF0ZWQuIFNwZWNpZnlpbmcgYW4gZW1wdHkgc3RyaW5nIGlzIGVxdWl2YWxlbnQgdG9cbiAgICogICAgICAgICBzcGVjaWZ5aW5nIEFXUzo6UmVnaW9uLlxuICAgKi9cbiAgY29uc3RydWN0b3IocmVnaW9uPzogc3RyaW5nKSB7XG4gICAgc3VwZXIoJ0ZuOjpHZXRBWnMnLCByZWdpb24gfHwgJycpO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpJbXBvcnRWYWx1ZWBgIHJldHVybnMgdGhlIHZhbHVlIG9mIGFuIG91dHB1dCBleHBvcnRlZCBieSBhbm90aGVyIHN0YWNrLlxuICogWW91IHR5cGljYWxseSB1c2UgdGhpcyBmdW5jdGlvbiB0byBjcmVhdGUgY3Jvc3Mtc3RhY2sgcmVmZXJlbmNlcy4gSW4gdGhlIGZvbGxvd2luZyBleGFtcGxlXG4gKiB0ZW1wbGF0ZSBzbmlwcGV0cywgU3RhY2sgQSBleHBvcnRzIFZQQyBzZWN1cml0eSBncm91cCB2YWx1ZXMgYW5kIFN0YWNrIEIgaW1wb3J0cyB0aGVtLlxuICovXG5jbGFzcyBGbkltcG9ydFZhbHVlIGV4dGVuZHMgRm5CYXNlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYGBGbjo6SW1wb3J0VmFsdWVgYCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIHNoYXJlZFZhbHVlVG9JbXBvcnQgVGhlIHN0YWNrIG91dHB1dCB2YWx1ZSB0aGF0IHlvdSB3YW50IHRvIGltcG9ydC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHNoYXJlZFZhbHVlVG9JbXBvcnQ6IHN0cmluZykge1xuICAgIHN1cGVyKCdGbjo6SW1wb3J0VmFsdWUnLCBzaGFyZWRWYWx1ZVRvSW1wb3J0KTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6U2VsZWN0YGAgcmV0dXJucyBhIHNpbmdsZSBvYmplY3QgZnJvbSBhIGxpc3Qgb2Ygb2JqZWN0cyBieSBpbmRleC5cbiAqL1xuY2xhc3MgRm5TZWxlY3QgZXh0ZW5kcyBGbkJhc2Uge1xuICAvKipcbiAgICogQ3JlYXRlcyBhbiBgYEZuOjpTZWxlY3RgYCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgb2JqZWN0IHRvIHJldHJpZXZlLiBUaGlzIG11c3QgYmUgYSB2YWx1ZSBmcm9tIHplcm8gdG8gTi0xLCB3aGVyZSBOIHJlcHJlc2VudHMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgYXJyYXkuXG4gICAqIEBwYXJhbSBhcnJheSBUaGUgbGlzdCBvZiBvYmplY3RzIHRvIHNlbGVjdCBmcm9tLiBUaGlzIGxpc3QgbXVzdCBub3QgYmUgbnVsbCwgbm9yIGNhbiBpdCBoYXZlIG51bGwgZW50cmllcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGluZGV4OiBudW1iZXIsIGFycmF5OiBhbnkpIHtcbiAgICBzdXBlcignRm46OlNlbGVjdCcsIFtpbmRleCwgYXJyYXldKTtcbiAgfVxufVxuXG4vKipcbiAqIFRvIHNwbGl0IGEgc3RyaW5nIGludG8gYSBsaXN0IG9mIHN0cmluZyB2YWx1ZXMgc28gdGhhdCB5b3UgY2FuIHNlbGVjdCBhbiBlbGVtZW50IGZyb20gdGhlXG4gKiByZXN1bHRpbmcgc3RyaW5nIGxpc3QsIHVzZSB0aGUgYGBGbjo6U3BsaXRgYCBpbnRyaW5zaWMgZnVuY3Rpb24uIFNwZWNpZnkgdGhlIGxvY2F0aW9uIG9mIHNwbGl0c1xuICogd2l0aCBhIGRlbGltaXRlciwgc3VjaCBhcyAsIChhIGNvbW1hKS4gQWZ0ZXIgeW91IHNwbGl0IGEgc3RyaW5nLCB1c2UgdGhlIGBgRm46OlNlbGVjdGBgIGZ1bmN0aW9uXG4gKiB0byBwaWNrIGEgc3BlY2lmaWMgZWxlbWVudC5cbiAqL1xuY2xhc3MgRm5TcGxpdCBleHRlbmRzIEZuQmFzZSB7XG4gIC8qKlxuICAgKiBDcmVhdGUgYW4gYGBGbjo6U3BsaXRgYCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGRlbGltaXRlciBBIHN0cmluZyB2YWx1ZSB0aGF0IGRldGVybWluZXMgd2hlcmUgdGhlIHNvdXJjZSBzdHJpbmcgaXMgZGl2aWRlZC5cbiAgICogQHBhcmFtIHNvdXJjZSBUaGUgc3RyaW5nIHZhbHVlIHRoYXQgeW91IHdhbnQgdG8gc3BsaXQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihkZWxpbWl0ZXI6IHN0cmluZywgc291cmNlOiBhbnkpIHtcbiAgICBzdXBlcignRm46OlNwbGl0JywgW2RlbGltaXRlciwgc291cmNlXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OlN1YmBgIHN1YnN0aXR1dGVzIHZhcmlhYmxlcyBpbiBhbiBpbnB1dCBzdHJpbmcgd2l0aCB2YWx1ZXMgdGhhdFxuICogeW91IHNwZWNpZnkuIEluIHlvdXIgdGVtcGxhdGVzLCB5b3UgY2FuIHVzZSB0aGlzIGZ1bmN0aW9uIHRvIGNvbnN0cnVjdCBjb21tYW5kcyBvciBvdXRwdXRzXG4gKiB0aGF0IGluY2x1ZGUgdmFsdWVzIHRoYXQgYXJlbid0IGF2YWlsYWJsZSB1bnRpbCB5b3UgY3JlYXRlIG9yIHVwZGF0ZSBhIHN0YWNrLlxuICovXG5jbGFzcyBGblN1YiBleHRlbmRzIEZuQmFzZSB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGBgRm46OlN1YmBgIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gYm9keSBBIHN0cmluZyB3aXRoIHZhcmlhYmxlcyB0aGF0IEFXUyBDbG91ZEZvcm1hdGlvbiBzdWJzdGl0dXRlcyB3aXRoIHRoZWlyXG4gICAqICAgICAgIGFzc29jaWF0ZWQgdmFsdWVzIGF0IHJ1bnRpbWUuIFdyaXRlIHZhcmlhYmxlcyBhcyAke015VmFyTmFtZX0uIFZhcmlhYmxlc1xuICAgKiAgICAgICBjYW4gYmUgdGVtcGxhdGUgcGFyYW1ldGVyIG5hbWVzLCByZXNvdXJjZSBsb2dpY2FsIElEcywgcmVzb3VyY2UgYXR0cmlidXRlcyxcbiAgICogICAgICAgb3IgYSB2YXJpYWJsZSBpbiBhIGtleS12YWx1ZSBtYXAuIElmIHlvdSBzcGVjaWZ5IG9ubHkgdGVtcGxhdGUgcGFyYW1ldGVyIG5hbWVzLFxuICAgKiAgICAgICByZXNvdXJjZSBsb2dpY2FsIElEcywgYW5kIHJlc291cmNlIGF0dHJpYnV0ZXMsIGRvbid0IHNwZWNpZnkgYSBrZXktdmFsdWUgbWFwLlxuICAgKiBAcGFyYW0gdmFyaWFibGVzIFRoZSBuYW1lIG9mIGEgdmFyaWFibGUgdGhhdCB5b3UgaW5jbHVkZWQgaW4gdGhlIFN0cmluZyBwYXJhbWV0ZXIuXG4gICAqICAgICAgICAgIFRoZSB2YWx1ZSB0aGF0IEFXUyBDbG91ZEZvcm1hdGlvbiBzdWJzdGl0dXRlcyBmb3IgdGhlIGFzc29jaWF0ZWQgdmFyaWFibGUgbmFtZSBhdCBydW50aW1lLlxuICAgKi9cbiAgY29uc3RydWN0b3IoYm9keTogc3RyaW5nLCB2YXJpYWJsZXM/OiB7IFtrZXk6IHN0cmluZ106IGFueSB9KSB7XG4gICAgc3VwZXIoJ0ZuOjpTdWInLCB2YXJpYWJsZXMgPyBbYm9keSwgdmFyaWFibGVzXSA6IGJvZHkpO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpCYXNlNjRgYCByZXR1cm5zIHRoZSBCYXNlNjQgcmVwcmVzZW50YXRpb24gb2YgdGhlIGlucHV0IHN0cmluZy5cbiAqIFRoaXMgZnVuY3Rpb24gaXMgdHlwaWNhbGx5IHVzZWQgdG8gcGFzcyBlbmNvZGVkIGRhdGEgdG8gQW1hem9uIEVDMiBpbnN0YW5jZXMgYnkgd2F5IG9mXG4gKiB0aGUgVXNlckRhdGEgcHJvcGVydHkuXG4gKi9cbmNsYXNzIEZuQmFzZTY0IGV4dGVuZHMgRm5CYXNlIHtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhbiBgYEZuOjpCYXNlNjRgYCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGRhdGEgVGhlIHN0cmluZyB2YWx1ZSB5b3Ugd2FudCB0byBjb252ZXJ0IHRvIEJhc2U2NC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGRhdGE6IGFueSkge1xuICAgIHN1cGVyKCdGbjo6QmFzZTY0JywgZGF0YSk7XG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OkNpZHJgYCByZXR1cm5zIHRoZSBzcGVjaWZpZWQgQ2lkciBhZGRyZXNzIGJsb2NrLlxuICovXG5jbGFzcyBGbkNpZHIgZXh0ZW5kcyBGbkJhc2Uge1xuICAvKipcbiAgICogQ3JlYXRlcyBhbiBgYEZuOjpDaWRyYGAgZnVuY3Rpb24uXG4gICAqIEBwYXJhbSBpcEJsb2NrICBUaGUgdXNlci1zcGVjaWZpZWQgZGVmYXVsdCBDaWRyIGFkZHJlc3MgYmxvY2suXG4gICAqIEBwYXJhbSBjb3VudCAgVGhlIG51bWJlciBvZiBzdWJuZXRzJyBDaWRyIGJsb2NrIHdhbnRlZC4gQ291bnQgY2FuIGJlIDEgdG8gMjU2LlxuICAgKiBAcGFyYW0gc2l6ZU1hc2sgVGhlIGRpZ2l0IGNvdmVyZWQgaW4gdGhlIHN1Ym5ldC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGlwQmxvY2s6IGFueSwgY291bnQ6IGFueSwgc2l6ZU1hc2s/OiBhbnkpIHtcbiAgICBpZiAoY291bnQgPCAxIHx8IGNvdW50ID4gMjU2KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZuOjpDaWRyJ3MgY291bnQgYXR0cmlidXRlIG11c3QgYmUgYmV0d2VuIDEgYW5kIDI1NiwgJHtjb3VudH0gd2FzIHByb3ZpZGVkLmApO1xuICAgIH1cbiAgICBzdXBlcignRm46OkNpZHInLCBbaXBCbG9jaywgY291bnQsIHNpemVNYXNrXSk7XG4gIH1cbn1cblxuY2xhc3MgRm5Db25kaXRpb25CYXNlIGV4dGVuZHMgSW50cmluc2ljIGltcGxlbWVudHMgSUNmblJ1bGVDb25kaXRpb25FeHByZXNzaW9uIHtcbiAgcmVhZG9ubHkgZGlzYW1iaWd1YXRvciA9IHRydWU7XG4gIGNvbnN0cnVjdG9yKHR5cGU6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIHN1cGVyKHsgW3R5cGVdOiB2YWx1ZSB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiBhbGwgdGhlIHNwZWNpZmllZCBjb25kaXRpb25zIGV2YWx1YXRlIHRvIHRydWUsIG9yIHJldHVybnMgZmFsc2UgaWYgYW55IG9uZVxuICogIG9mIHRoZSBjb25kaXRpb25zIGV2YWx1YXRlcyB0byBmYWxzZS4gYGBGbjo6QW5kYGAgYWN0cyBhcyBhbiBBTkQgb3BlcmF0b3IuIFRoZSBtaW5pbXVtIG51bWJlciBvZlxuICogY29uZGl0aW9ucyB0aGF0IHlvdSBjYW4gaW5jbHVkZSBpcyAyLCBhbmQgdGhlIG1heGltdW0gaXMgMTAuXG4gKi9cbmNsYXNzIEZuQW5kIGV4dGVuZHMgRm5Db25kaXRpb25CYXNlIHtcbiAgY29uc3RydWN0b3IoLi4uY29uZGl0aW9uOiBJQ2ZuQ29uZGl0aW9uRXhwcmVzc2lvbltdKSB7XG4gICAgc3VwZXIoJ0ZuOjpBbmQnLCBjb25kaXRpb24pO1xuICB9XG59XG5cbi8qKlxuICogQ29tcGFyZXMgaWYgdHdvIHZhbHVlcyBhcmUgZXF1YWwuIFJldHVybnMgdHJ1ZSBpZiB0aGUgdHdvIHZhbHVlcyBhcmUgZXF1YWwgb3IgZmFsc2VcbiAqIGlmIHRoZXkgYXJlbid0LlxuICovXG5jbGFzcyBGbkVxdWFscyBleHRlbmRzIEZuQ29uZGl0aW9uQmFzZSB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGBgRm46OkVxdWFsc2BgIGNvbmRpdGlvbiBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGxocyBBIHZhbHVlIG9mIGFueSB0eXBlIHRoYXQgeW91IHdhbnQgdG8gY29tcGFyZS5cbiAgICogQHBhcmFtIHJocyBBIHZhbHVlIG9mIGFueSB0eXBlIHRoYXQgeW91IHdhbnQgdG8gY29tcGFyZS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGxoczogYW55LCByaHM6IGFueSkge1xuICAgIHN1cGVyKCdGbjo6RXF1YWxzJywgW2xocywgcmhzXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIG9uZSB2YWx1ZSBpZiB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbiBldmFsdWF0ZXMgdG8gdHJ1ZSBhbmQgYW5vdGhlciB2YWx1ZSBpZiB0aGVcbiAqIHNwZWNpZmllZCBjb25kaXRpb24gZXZhbHVhdGVzIHRvIGZhbHNlLiBDdXJyZW50bHksIEFXUyBDbG91ZEZvcm1hdGlvbiBzdXBwb3J0cyB0aGUgYGBGbjo6SWZgYFxuICogaW50cmluc2ljIGZ1bmN0aW9uIGluIHRoZSBtZXRhZGF0YSBhdHRyaWJ1dGUsIHVwZGF0ZSBwb2xpY3kgYXR0cmlidXRlLCBhbmQgcHJvcGVydHkgdmFsdWVzXG4gKiBpbiB0aGUgUmVzb3VyY2VzIHNlY3Rpb24gYW5kIE91dHB1dHMgc2VjdGlvbnMgb2YgYSB0ZW1wbGF0ZS4gWW91IGNhbiB1c2UgdGhlIEFXUzo6Tm9WYWx1ZVxuICogcHNldWRvIHBhcmFtZXRlciBhcyBhIHJldHVybiB2YWx1ZSB0byByZW1vdmUgdGhlIGNvcnJlc3BvbmRpbmcgcHJvcGVydHkuXG4gKi9cbmNsYXNzIEZuSWYgZXh0ZW5kcyBGbkNvbmRpdGlvbkJhc2Uge1xuICAvKipcbiAgICogQ3JlYXRlcyBhbiBgYEZuOjpJZmBgIGNvbmRpdGlvbiBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGNvbmRpdGlvbiBBIHJlZmVyZW5jZSB0byBhIGNvbmRpdGlvbiBpbiB0aGUgQ29uZGl0aW9ucyBzZWN0aW9uLiBVc2UgdGhlIGNvbmRpdGlvbidzIG5hbWUgdG8gcmVmZXJlbmNlIGl0LlxuICAgKiBAcGFyYW0gdmFsdWVJZlRydWUgQSB2YWx1ZSB0byBiZSByZXR1cm5lZCBpZiB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbiBldmFsdWF0ZXMgdG8gdHJ1ZS5cbiAgICogQHBhcmFtIHZhbHVlSWZGYWxzZSBBIHZhbHVlIHRvIGJlIHJldHVybmVkIGlmIHRoZSBzcGVjaWZpZWQgY29uZGl0aW9uIGV2YWx1YXRlcyB0byBmYWxzZS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGNvbmRpdGlvbjogc3RyaW5nLCB2YWx1ZUlmVHJ1ZTogYW55LCB2YWx1ZUlmRmFsc2U6IGFueSkge1xuICAgIHN1cGVyKCdGbjo6SWYnLCBbY29uZGl0aW9uLCB2YWx1ZUlmVHJ1ZSwgdmFsdWVJZkZhbHNlXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgZm9yIGEgY29uZGl0aW9uIHRoYXQgZXZhbHVhdGVzIHRvIGZhbHNlIG9yIHJldHVybnMgZmFsc2UgZm9yIGEgY29uZGl0aW9uIHRoYXQgZXZhbHVhdGVzIHRvIHRydWUuXG4gKiBgYEZuOjpOb3RgYCBhY3RzIGFzIGEgTk9UIG9wZXJhdG9yLlxuICovXG5jbGFzcyBGbk5vdCBleHRlbmRzIEZuQ29uZGl0aW9uQmFzZSB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGBgRm46Ok5vdGBgIGNvbmRpdGlvbiBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGNvbmRpdGlvbiBBIGNvbmRpdGlvbiBzdWNoIGFzIGBgRm46OkVxdWFsc2BgIHRoYXQgZXZhbHVhdGVzIHRvIHRydWUgb3IgZmFsc2UuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihjb25kaXRpb246IElDZm5Db25kaXRpb25FeHByZXNzaW9uKSB7XG4gICAgc3VwZXIoJ0ZuOjpOb3QnLCBbY29uZGl0aW9uXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgYW55IG9uZSBvZiB0aGUgc3BlY2lmaWVkIGNvbmRpdGlvbnMgZXZhbHVhdGUgdG8gdHJ1ZSwgb3IgcmV0dXJucyBmYWxzZSBpZlxuICogYWxsIG9mIHRoZSBjb25kaXRpb25zIGV2YWx1YXRlcyB0byBmYWxzZS4gYGBGbjo6T3JgYCBhY3RzIGFzIGFuIE9SIG9wZXJhdG9yLiBUaGUgbWluaW11bSBudW1iZXJcbiAqIG9mIGNvbmRpdGlvbnMgdGhhdCB5b3UgY2FuIGluY2x1ZGUgaXMgMiwgYW5kIHRoZSBtYXhpbXVtIGlzIDEwLlxuICovXG5jbGFzcyBGbk9yIGV4dGVuZHMgRm5Db25kaXRpb25CYXNlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYGBGbjo6T3JgYCBjb25kaXRpb24gZnVuY3Rpb24uXG4gICAqIEBwYXJhbSBjb25kaXRpb24gQSBjb25kaXRpb24gdGhhdCBldmFsdWF0ZXMgdG8gdHJ1ZSBvciBmYWxzZS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKC4uLmNvbmRpdGlvbjogSUNmbkNvbmRpdGlvbkV4cHJlc3Npb25bXSkge1xuICAgIHN1cGVyKCdGbjo6T3InLCBjb25kaXRpb24pO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIGEgc3BlY2lmaWVkIHN0cmluZyBtYXRjaGVzIGF0IGxlYXN0IG9uZSB2YWx1ZSBpbiBhIGxpc3Qgb2Ygc3RyaW5ncy5cbiAqL1xuY2xhc3MgRm5Db250YWlucyBleHRlbmRzIEZuQ29uZGl0aW9uQmFzZSB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGBgRm46OkNvbnRhaW5zYGAgZnVuY3Rpb24uXG4gICAqIEBwYXJhbSBsaXN0T2ZTdHJpbmdzIEEgbGlzdCBvZiBzdHJpbmdzLCBzdWNoIGFzIFwiQVwiLCBcIkJcIiwgXCJDXCIuXG4gICAqIEBwYXJhbSB2YWx1ZSBBIHN0cmluZywgc3VjaCBhcyBcIkFcIiwgdGhhdCB5b3Ugd2FudCB0byBjb21wYXJlIGFnYWluc3QgYSBsaXN0IG9mIHN0cmluZ3MuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihsaXN0T2ZTdHJpbmdzOiBhbnksIHZhbHVlOiBzdHJpbmcpIHtcbiAgICBzdXBlcignRm46OkNvbnRhaW5zJywgW2xpc3RPZlN0cmluZ3MsIHZhbHVlXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgYSBzcGVjaWZpZWQgc3RyaW5nIG1hdGNoZXMgYWxsIHZhbHVlcyBpbiBhIGxpc3QuXG4gKi9cbmNsYXNzIEZuRWFjaE1lbWJlckVxdWFscyBleHRlbmRzIEZuQ29uZGl0aW9uQmFzZSB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGBgRm46OkVhY2hNZW1iZXJFcXVhbHNgYCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGxpc3RPZlN0cmluZ3MgQSBsaXN0IG9mIHN0cmluZ3MsIHN1Y2ggYXMgXCJBXCIsIFwiQlwiLCBcIkNcIi5cbiAgICogQHBhcmFtIHZhbHVlIEEgc3RyaW5nLCBzdWNoIGFzIFwiQVwiLCB0aGF0IHlvdSB3YW50IHRvIGNvbXBhcmUgYWdhaW5zdCBhIGxpc3Qgb2Ygc3RyaW5ncy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGxpc3RPZlN0cmluZ3M6IGFueSwgdmFsdWU6IHN0cmluZykge1xuICAgIHN1cGVyKCdGbjo6RWFjaE1lbWJlckVxdWFscycsIFtsaXN0T2ZTdHJpbmdzLCB2YWx1ZV0pO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIGVhY2ggbWVtYmVyIGluIGEgbGlzdCBvZiBzdHJpbmdzIG1hdGNoZXMgYXQgbGVhc3Qgb25lIHZhbHVlIGluIGEgc2Vjb25kXG4gKiBsaXN0IG9mIHN0cmluZ3MuXG4gKi9cbmNsYXNzIEZuRWFjaE1lbWJlckluIGV4dGVuZHMgRm5Db25kaXRpb25CYXNlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYGBGbjo6RWFjaE1lbWJlckluYGAgZnVuY3Rpb24uXG4gICAqIEBwYXJhbSBzdHJpbmdzVG9DaGVjayBBIGxpc3Qgb2Ygc3RyaW5ncywgc3VjaCBhcyBcIkFcIiwgXCJCXCIsIFwiQ1wiLiBBV1MgQ2xvdWRGb3JtYXRpb24gY2hlY2tzIHdoZXRoZXIgZWFjaCBtZW1iZXIgaW4gdGhlIHN0cmluZ3NfdG9fY2hlY2sgcGFyYW1ldGVyIGlzIGluIHRoZSBzdHJpbmdzX3RvX21hdGNoIHBhcmFtZXRlci5cbiAgICogQHBhcmFtIHN0cmluZ3NUb01hdGNoIEEgbGlzdCBvZiBzdHJpbmdzLCBzdWNoIGFzIFwiQVwiLCBcIkJcIiwgXCJDXCIuIEVhY2ggbWVtYmVyIGluIHRoZSBzdHJpbmdzX3RvX21hdGNoIHBhcmFtZXRlciBpcyBjb21wYXJlZCBhZ2FpbnN0IHRoZSBtZW1iZXJzIG9mIHRoZSBzdHJpbmdzX3RvX2NoZWNrIHBhcmFtZXRlci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHN0cmluZ3NUb0NoZWNrOiBzdHJpbmdbXSwgc3RyaW5nc1RvTWF0Y2g6IHN0cmluZ1tdKSB7XG4gICAgc3VwZXIoJ0ZuOjpFYWNoTWVtYmVySW4nLCBbc3RyaW5nc1RvQ2hlY2ssIHN0cmluZ3NUb01hdGNoXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGFsbCB2YWx1ZXMgZm9yIGEgc3BlY2lmaWVkIHBhcmFtZXRlciB0eXBlLlxuICovXG5jbGFzcyBGblJlZkFsbCBleHRlbmRzIEZuQmFzZSB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGBgRm46OlJlZkFsbGBgIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gcGFyYW1ldGVyVHlwZSBBbiBBV1Mtc3BlY2lmaWMgcGFyYW1ldGVyIHR5cGUsIHN1Y2ggYXMgQVdTOjpFQzI6OlNlY3VyaXR5R3JvdXA6OklkIG9yXG4gICAqICAgICAgICAgICAgQVdTOjpFQzI6OlZQQzo6SWQuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWUgUGFyYW1ldGVycyBpbiB0aGUgQVdTXG4gICAqICAgICAgICAgICAgQ2xvdWRGb3JtYXRpb24gVXNlciBHdWlkZS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHBhcmFtZXRlclR5cGU6IHN0cmluZykge1xuICAgIHN1cGVyKCdGbjo6UmVmQWxsJywgcGFyYW1ldGVyVHlwZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGFuIGF0dHJpYnV0ZSB2YWx1ZSBvciBsaXN0IG9mIHZhbHVlcyBmb3IgYSBzcGVjaWZpYyBwYXJhbWV0ZXIgYW5kIGF0dHJpYnV0ZS5cbiAqL1xuY2xhc3MgRm5WYWx1ZU9mIGV4dGVuZHMgRm5CYXNlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYGBGbjo6VmFsdWVPZmBgIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gcGFyYW1ldGVyT3JMb2dpY2FsSWQgVGhlIG5hbWUgb2YgYSBwYXJhbWV0ZXIgZm9yIHdoaWNoIHlvdSB3YW50IHRvIHJldHJpZXZlIGF0dHJpYnV0ZSB2YWx1ZXMuIFRoZSBwYXJhbWV0ZXIgbXVzdCBiZSBkZWNsYXJlZCBpbiB0aGUgUGFyYW1ldGVycyBzZWN0aW9uIG9mIHRoZSB0ZW1wbGF0ZS5cbiAgICogQHBhcmFtIGF0dHJpYnV0ZSBUaGUgbmFtZSBvZiBhbiBhdHRyaWJ1dGUgZnJvbSB3aGljaCB5b3Ugd2FudCB0byByZXRyaWV2ZSBhIHZhbHVlLlxuICAgKi9cbiAgY29uc3RydWN0b3IocGFyYW1ldGVyT3JMb2dpY2FsSWQ6IHN0cmluZywgYXR0cmlidXRlOiBzdHJpbmcpIHtcbiAgICBzdXBlcignRm46OlZhbHVlT2YnLCBbcGFyYW1ldGVyT3JMb2dpY2FsSWQsIGF0dHJpYnV0ZV0pO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGxpc3Qgb2YgYWxsIGF0dHJpYnV0ZSB2YWx1ZXMgZm9yIGEgZ2l2ZW4gcGFyYW1ldGVyIHR5cGUgYW5kIGF0dHJpYnV0ZS5cbiAqL1xuY2xhc3MgRm5WYWx1ZU9mQWxsIGV4dGVuZHMgRm5CYXNlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYGBGbjo6VmFsdWVPZkFsbGBgIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gcGFyYW1ldGVyVHlwZSBBbiBBV1Mtc3BlY2lmaWMgcGFyYW1ldGVyIHR5cGUsIHN1Y2ggYXMgQVdTOjpFQzI6OlNlY3VyaXR5R3JvdXA6OklkIG9yIEFXUzo6RUMyOjpWUEM6OklkLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIFBhcmFtZXRlcnMgaW4gdGhlIEFXUyBDbG91ZEZvcm1hdGlvbiBVc2VyIEd1aWRlLlxuICAgKiBAcGFyYW0gYXR0cmlidXRlIFRoZSBuYW1lIG9mIGFuIGF0dHJpYnV0ZSBmcm9tIHdoaWNoIHlvdSB3YW50IHRvIHJldHJpZXZlIGEgdmFsdWUuIEZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGF0dHJpYnV0ZXMsIHNlZSBTdXBwb3J0ZWQgQXR0cmlidXRlcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHBhcmFtZXRlclR5cGU6IHN0cmluZywgYXR0cmlidXRlOiBzdHJpbmcpIHtcbiAgICBzdXBlcignRm46OlZhbHVlT2ZBbGwnLCBbcGFyYW1ldGVyVHlwZSwgYXR0cmlidXRlXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OkpvaW5gYCBhcHBlbmRzIGEgc2V0IG9mIHZhbHVlcyBpbnRvIGEgc2luZ2xlIHZhbHVlLCBzZXBhcmF0ZWQgYnlcbiAqIHRoZSBzcGVjaWZpZWQgZGVsaW1pdGVyLiBJZiBhIGRlbGltaXRlciBpcyB0aGUgZW1wdHkgc3RyaW5nLCB0aGUgc2V0IG9mIHZhbHVlcyBhcmUgY29uY2F0ZW5hdGVkXG4gKiB3aXRoIG5vIGRlbGltaXRlci5cbiAqL1xuY2xhc3MgRm5Kb2luIGltcGxlbWVudHMgSVJlc29sdmFibGUge1xuICBwdWJsaWMgcmVhZG9ubHkgY3JlYXRpb25TdGFjazogc3RyaW5nW107XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZWxpbWl0ZXI6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBsaXN0T2ZWYWx1ZXM6IGFueVtdO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGBgRm46OkpvaW5gYCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGRlbGltaXRlciBUaGUgdmFsdWUgeW91IHdhbnQgdG8gb2NjdXIgYmV0d2VlbiBmcmFnbWVudHMuIFRoZSBkZWxpbWl0ZXIgd2lsbCBvY2N1ciBiZXR3ZWVuIGZyYWdtZW50cyBvbmx5LlxuICAgKiAgICAgICAgICBJdCB3aWxsIG5vdCB0ZXJtaW5hdGUgdGhlIGZpbmFsIHZhbHVlLlxuICAgKiBAcGFyYW0gbGlzdE9mVmFsdWVzIFRoZSBsaXN0IG9mIHZhbHVlcyB5b3Ugd2FudCBjb21iaW5lZC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGRlbGltaXRlcjogc3RyaW5nLCBsaXN0T2ZWYWx1ZXM6IGFueVtdKSB7XG4gICAgaWYgKGxpc3RPZlZhbHVlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRm5Kb2luIHJlcXVpcmVzIGF0IGxlYXN0IG9uZSB2YWx1ZSB0byBiZSBwcm92aWRlZCcpO1xuICAgIH1cblxuICAgIHRoaXMuZGVsaW1pdGVyID0gZGVsaW1pdGVyO1xuICAgIHRoaXMubGlzdE9mVmFsdWVzID0gbGlzdE9mVmFsdWVzO1xuICAgIHRoaXMuY3JlYXRpb25TdGFjayA9IGNhcHR1cmVTdGFja1RyYWNlKCk7XG4gIH1cblxuICBwdWJsaWMgcmVzb2x2ZShjb250ZXh0OiBJUmVzb2x2ZUNvbnRleHQpOiBhbnkge1xuICAgIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQodGhpcy5saXN0T2ZWYWx1ZXMpKSB7XG4gICAgICAvLyBUaGlzIGlzIGEgbGlzdCB0b2tlbiwgZG9uJ3QgdHJ5IHRvIGRvIHNtYXJ0IHRoaW5ncyB3aXRoIGl0LlxuICAgICAgcmV0dXJuIHsgJ0ZuOjpKb2luJzogW3RoaXMuZGVsaW1pdGVyLCB0aGlzLmxpc3RPZlZhbHVlc10gfTtcbiAgICB9XG4gICAgY29uc3QgcmVzb2x2ZWQgPSB0aGlzLnJlc29sdmVWYWx1ZXMoY29udGV4dCk7XG4gICAgaWYgKHJlc29sdmVkLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIHJlc29sdmVkWzBdO1xuICAgIH1cbiAgICByZXR1cm4geyAnRm46OkpvaW4nOiBbdGhpcy5kZWxpbWl0ZXIsIHJlc29sdmVkXSB9O1xuICB9XG5cbiAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBUb2tlbi5hc1N0cmluZyh0aGlzLCB7IGRpc3BsYXlIaW50OiAnRm46OkpvaW4nIH0pO1xuICB9XG5cbiAgcHVibGljIHRvSlNPTigpIHtcbiAgICByZXR1cm4gJzxGbjo6Sm9pbj4nO1xuICB9XG5cbiAgLyoqXG4gICAqIE9wdGltaXphdGlvbjogaWYgYW4gRm46OkpvaW4gaXMgbmVzdGVkIGluIGFub3RoZXIgb25lIGFuZCB0aGV5IHNoYXJlIHRoZSBzYW1lIGRlbGltaXRlciwgdGhlbiBmbGF0dGVuIGl0IHVwLiBBbHNvLFxuICAgKiBpZiB0d28gY29uY2F0ZW5hdGVkIGVsZW1lbnRzIGFyZSBsaXRlcmFsIHN0cmluZ3MgKG5vdCB0b2tlbnMpLCB0aGVuIHByZS1jb25jYXRlbmF0ZSB0aGVtIHdpdGggdGhlIGRlbGltaXRlciwgdG9cbiAgICogZ2VuZXJhdGUgc2hvcnRlciBvdXRwdXQuXG4gICAqL1xuICBwcml2YXRlIHJlc29sdmVWYWx1ZXMoY29udGV4dDogSVJlc29sdmVDb250ZXh0KSB7XG4gICAgY29uc3QgcmVzb2x2ZWRWYWx1ZXMgPSB0aGlzLmxpc3RPZlZhbHVlcy5tYXAoeCA9PiBSZWZlcmVuY2UuaXNSZWZlcmVuY2UoeCkgPyB4IDogY29udGV4dC5yZXNvbHZlKHgpKTtcbiAgICByZXR1cm4gbWluaW1hbENsb3VkRm9ybWF0aW9uSm9pbih0aGlzLmRlbGltaXRlciwgcmVzb2x2ZWRWYWx1ZXMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9pbkdyb3Vwc09mPFQ+KGFycmF5OiBUW10sIG1heEdyb3VwOiBudW1iZXIpOiBUW11bXSB7XG4gIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheTxUW10+KCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpICs9IG1heEdyb3VwKSB7XG4gICAgcmVzdWx0LnB1c2goYXJyYXkuc2xpY2UoaSwgaSArIG1heEdyb3VwKSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gcmFuZ2UobjogbnVtYmVyKTogbnVtYmVyW10ge1xuICBjb25zdCByZXQgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICByZXQucHVzaChpKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufSJdfQ== |
\ | No newline at end of file |