@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
168 lines • 18.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatAnalytics = exports.MetadataResource = void 0;
const zlib = require("zlib");
const region_info_1 = require("@aws-cdk/region-info");
const cfn_condition_1 = require("../cfn-condition");
const cfn_fn_1 = require("../cfn-fn");
const cfn_pseudo_1 = require("../cfn-pseudo");
const cfn_resource_1 = require("../cfn-resource");
const construct_compat_1 = require("../construct-compat");
const lazy_1 = require("../lazy");
const token_1 = require("../token");
const runtime_info_1 = require("./runtime-info");
/**
* Construct that will render the metadata resource
*/
class MetadataResource extends construct_compat_1.Construct {
constructor(scope, id) {
super(scope, id);
const metadataServiceExists = token_1.Token.isUnresolved(scope.region) || region_info_1.RegionInfo.get(scope.region).cdkMetadataResourceAvailable;
if (metadataServiceExists) {
const resource = new cfn_resource_1.CfnResource(this, 'Default', {
type: 'AWS::CDK::Metadata',
properties: {
Analytics: lazy_1.Lazy.string({ produce: () => formatAnalytics(runtime_info_1.constructInfoFromStack(scope)) }),
},
});
// In case we don't actually know the region, add a condition to determine it at deploy time
if (token_1.Token.isUnresolved(scope.region)) {
const condition = new cfn_condition_1.CfnCondition(this, 'Condition', {
expression: makeCdkMetadataAvailableCondition(),
});
// To not cause undue template changes
condition.overrideLogicalId('CDKMetadataAvailable');
resource.cfnOptions.condition = condition;
}
}
}
}
exports.MetadataResource = MetadataResource;
function makeCdkMetadataAvailableCondition() {
return cfn_fn_1.Fn.conditionOr(...region_info_1.RegionInfo.regions
.filter(ri => ri.cdkMetadataResourceAvailable)
.map(ri => cfn_fn_1.Fn.conditionEquals(cfn_pseudo_1.Aws.REGION, ri.name)));
}
/** Convenience type for arbitrarily-nested map */
class Trie extends Map {
}
/**
* Formats a list of construct fully-qualified names (FQNs) and versions into a (possibly compressed) prefix-encoded string.
*
* The list of ConstructInfos is logically formatted into:
* ${version}!${fqn} (e.g., "1.90.0!aws-cdk-lib.Stack")
* and then all of the construct-versions are grouped with common prefixes together, grouping common parts in '{}' and separating items with ','.
*
* Example:
* [1.90.0!aws-cdk-lib.Stack, 1.90.0!aws-cdk-lib.Construct, 1.90.0!aws-cdk-lib.service.Resource, 0.42.1!aws-cdk-lib-experiments.NewStuff]
* Becomes:
* 1.90.0!aws-cdk-lib.{Stack,Construct,service.Resource},0.42.1!aws-cdk-lib-experiments.NewStuff
*
* The whole thing is then either included directly as plaintext as:
* v2:plaintext:{prefixEncodedList}
* Or is compressed and base64-encoded, and then formatted as:
* v2:deflate64:{prefixEncodedListCompressedAndEncoded}
*
* Exported/visible for ease of testing.
*/
function formatAnalytics(infos) {
const trie = new Trie();
infos.forEach(info => insertFqnInTrie(`${info.version}!${info.fqn}`, trie));
const plaintextEncodedConstructs = prefixEncodeTrie(trie);
const compressedConstructsBuffer = zlib.gzipSync(Buffer.from(plaintextEncodedConstructs));
// set OS flag to "unknown" in order to ensure we get consistent results across operating systems
// see https://github.com/aws/aws-cdk/issues/15322
setGzipOperatingSystemToUnknown(compressedConstructsBuffer);
const compressedConstructs = compressedConstructsBuffer.toString('base64');
return `v2:deflate64:${compressedConstructs}`;
}
exports.formatAnalytics = formatAnalytics;
/**
* Splits after non-alphanumeric characters (e.g., '.', '/') in the FQN
* and insert each piece of the FQN in nested map (i.e., simple trie).
*/
function insertFqnInTrie(fqn, trie) {
for (const fqnPart of fqn.replace(/[^a-z0-9]/gi, '$& ').split(' ')) {
const nextLevelTreeRef = trie.get(fqnPart) ?? new Trie();
trie.set(fqnPart, nextLevelTreeRef);
trie = nextLevelTreeRef;
}
return trie;
}
/**
* Prefix-encodes a "trie-ish" structure, using '{}' to group and ',' to separate siblings.
*
* Example input:
* ABC,ABD,AEF
*
* Example trie:
* A --> B --> C
* | \--> D
* \--> E --> F
*
* Becomes:
* A{B{C,D},EF}
*/
function prefixEncodeTrie(trie) {
let prefixEncoded = '';
let isFirstEntryAtLevel = true;
[...trie.entries()].forEach(([key, value]) => {
if (!isFirstEntryAtLevel) {
prefixEncoded += ',';
}
isFirstEntryAtLevel = false;
prefixEncoded += key;
if (value.size > 1) {
prefixEncoded += '{';
prefixEncoded += prefixEncodeTrie(value);
prefixEncoded += '}';
}
else {
prefixEncoded += prefixEncodeTrie(value);
}
});
return prefixEncoded;
}
/**
* Sets the OS flag to "unknown" in order to ensure we get consistent results across operating systems.
*
* @see https://datatracker.ietf.org/doc/html/rfc1952#page-5
*
* +---+---+---+---+---+---+---+---+---+---+
* |ID1|ID2|CM |FLG| MTIME |XFL|OS |
* +---+---+---+---+---+---+---+---+---+---+
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
* +---+---+---+---+---+---+---+---+---+---+
*
* OS (Operating System)
* =====================
* This identifies the type of file system on which compression
* took place. This may be useful in determining end-of-line
* convention for text files. The currently defined values are
* as follows:
* 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
* 1 - Amiga
* 2 - VMS (or OpenVMS)
* 3 - Unix
* 4 - VM/CMS
* 5 - Atari TOS
* 6 - HPFS filesystem (OS/2, NT)
* 7 - Macintosh
* 8 - Z-System
* 9 - CP/M
* 10 - TOPS-20
* 11 - NTFS filesystem (NT)
* 12 - QDOS
* 13 - Acorn RISCOS
* 255 - unknown
*
* @param gzipBuffer A gzip buffer
*/
function setGzipOperatingSystemToUnknown(gzipBuffer) {
// check that this is indeed a gzip buffer (https://datatracker.ietf.org/doc/html/rfc1952#page-6)
if (gzipBuffer[0] !== 0x1f || gzipBuffer[1] !== 0x8b) {
throw new Error('Expecting a gzip buffer (must start with 0x1f8b)');
}
gzipBuffer[9] = 255;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0YWRhdGEtcmVzb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtZXRhZGF0YS1yZXNvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2QkFBNkI7QUFDN0Isc0RBQWtEO0FBQ2xELG9EQUFnRDtBQUNoRCxzQ0FBK0I7QUFDL0IsOENBQW9DO0FBQ3BDLGtEQUE4QztBQUM5QywwREFBZ0Q7QUFDaEQsa0NBQStCO0FBRS9CLG9DQUFpQztBQUNqQyxpREFBdUU7QUFFdkU7O0dBRUc7QUFDSCxNQUFhLGdCQUFpQixTQUFRLDRCQUFTO0lBQzdDLFlBQVksS0FBWSxFQUFFLEVBQVU7UUFDbEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixNQUFNLHFCQUFxQixHQUFHLGFBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLHdCQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyw0QkFBNEIsQ0FBQztRQUM1SCxJQUFJLHFCQUFxQixFQUFFO1lBQ3pCLE1BQU0sUUFBUSxHQUFHLElBQUksMEJBQVcsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFO2dCQUNoRCxJQUFJLEVBQUUsb0JBQW9CO2dCQUMxQixVQUFVLEVBQUU7b0JBQ1YsU0FBUyxFQUFFLFdBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDLHFDQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztpQkFDMUY7YUFDRixDQUFDLENBQUM7WUFFSCw0RkFBNEY7WUFDNUYsSUFBSSxhQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDcEMsTUFBTSxTQUFTLEdBQUcsSUFBSSw0QkFBWSxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUU7b0JBQ3BELFVBQVUsRUFBRSxpQ0FBaUMsRUFBRTtpQkFDaEQs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SSxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUMxQztJQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxhQUFhLENBQUM7QUFDdkIsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0NHO0FBQ0gsU0FBUywrQkFBK0IsQ0FBQyxVQUFrQjtJQUN6RCxpR0FBaUc7SUFDakcsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUU7UUFDcEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO0tBQ3JFO0lBRUQsVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgemxpYiBmcm9tICd6bGliJztcbmltcG9ydCB7IFJlZ2lvbkluZm8gfSBmcm9tICdAYXdzLWNkay9yZWdpb24taW5mbyc7XG5pbXBvcnQgeyBDZm5Db25kaXRpb24gfSBmcm9tICcuLi9jZm4tY29uZGl0aW9uJztcbmltcG9ydCB7IEZuIH0gZnJvbSAnLi4vY2ZuLWZuJztcbmltcG9ydCB7IEF3cyB9IGZyb20gJy4uL2Nmbi1wc2V1ZG8nO1xuaW1wb3J0IHsgQ2ZuUmVzb3VyY2UgfSBmcm9tICcuLi9jZm4tcmVzb3VyY2UnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnLi4vY29uc3RydWN0LWNvbXBhdCc7XG5pbXBvcnQgeyBMYXp5IH0gZnJvbSAnLi4vbGF6eSc7XG5pbXBvcnQgeyBTdGFjayB9IGZyb20gJy4uL3N0YWNrJztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi4vdG9rZW4nO1xuaW1wb3J0IHsgQ29uc3RydWN0SW5mbywgY29uc3RydWN0SW5mb0Zyb21TdGFjayB9IGZyb20gJy4vcnVudGltZS1pbmZvJztcblxuLyoqXG4gKiBDb25zdHJ1Y3QgdGhhdCB3aWxsIHJlbmRlciB0aGUgbWV0YWRhdGEgcmVzb3VyY2VcbiAqL1xuZXhwb3J0IGNsYXNzIE1ldGFkYXRhUmVzb3VyY2UgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBjb25zdHJ1Y3RvcihzY29wZTogU3RhY2ssIGlkOiBzdHJpbmcpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgbWV0YWRhdGFTZXJ2aWNlRXhpc3RzID0gVG9rZW4uaXNVbnJlc29sdmVkKHNjb3BlLnJlZ2lvbikgfHwgUmVnaW9uSW5mby5nZXQoc2NvcGUucmVnaW9uKS5jZGtNZXRhZGF0YVJlc291cmNlQXZhaWxhYmxlO1xuICAgIGlmIChtZXRhZGF0YVNlcnZpY2VFeGlzdHMpIHtcbiAgICAgIGNvbnN0IHJlc291cmNlID0gbmV3IENmblJlc291cmNlKHRoaXMsICdEZWZhdWx0Jywge1xuICAgICAgICB0eXBlOiAnQVdTOjpDREs6Ok1ldGFkYXRhJyxcbiAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgIEFuYWx5dGljczogTGF6eS5zdHJpbmcoeyBwcm9kdWNlOiAoKSA9PiBmb3JtYXRBbmFseXRpY3MoY29uc3RydWN0SW5mb0Zyb21TdGFjayhzY29wZSkpIH0pLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIEluIGNhc2Ugd2UgZG9uJ3QgYWN0dWFsbHkga25vdyB0aGUgcmVnaW9uLCBhZGQgYSBjb25kaXRpb24gdG8gZGV0ZXJtaW5lIGl0IGF0IGRlcGxveSB0aW1lXG4gICAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHNjb3BlLnJlZ2lvbikpIHtcbiAgICAgICAgY29uc3QgY29uZGl0aW9uID0gbmV3IENmbkNvbmRpdGlvbih0aGlzLCAnQ29uZGl0aW9uJywge1xuICAgICAgICAgIGV4cHJlc3Npb246IG1ha2VDZGtNZXRhZGF0YUF2YWlsYWJsZUNvbmRpdGlvbigpLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUbyBub3QgY2F1c2UgdW5kdWUgdGVtcGxhdGUgY2hhbmdlc1xuICAgICAgICBjb25kaXRpb24ub3ZlcnJpZGVMb2dpY2FsSWQoJ0NES01ldGFkYXRhQXZhaWxhYmxlJyk7XG5cbiAgICAgICAgcmVzb3VyY2UuY2ZuT3B0aW9ucy5jb25kaXRpb24gPSBjb25kaXRpb247XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VDZGtNZXRhZGF0YUF2YWlsYWJsZUNvbmRpdGlvbigpIHtcbiAgcmV0dXJuIEZuLmNvbmRpdGlvbk9yKC4uLlJlZ2lvbkluZm8ucmVnaW9uc1xuICAgIC5maWx0ZXIocmkgPT4gcmkuY2RrTWV0YWRhdGFSZXNvdXJjZUF2YWlsYWJsZSlcbiAgICAubWFwKHJpID0+IEZuLmNvbmRpdGlvbkVxdWFscyhBd3MuUkVHSU9OLCByaS5uYW1lKSkpO1xufVxuXG4vKiogQ29udmVuaWVuY2UgdHlwZSBmb3IgYXJiaXRyYXJpbHktbmVzdGVkIG1hcCAqL1xuY2xhc3MgVHJpZSBleHRlbmRzIE1hcDxzdHJpbmcsIFRyaWU+IHsgfVxuXG4vKipcbiAqIEZvcm1hdHMgYSBsaXN0IG9mIGNvbnN0cnVjdCBmdWxseS1xdWFsaWZpZWQgbmFtZXMgKEZRTnMpIGFuZCB2ZXJzaW9ucyBpbnRvIGEgKHBvc3NpYmx5IGNvbXByZXNzZWQpIHByZWZpeC1lbmNvZGVkIHN0cmluZy5cbiAqXG4gKiBUaGUgbGlzdCBvZiBDb25zdHJ1Y3RJbmZvcyBpcyBsb2dpY2FsbHkgZm9ybWF0dGVkIGludG86XG4gKiAke3ZlcnNpb259ISR7ZnFufSAoZS5nLiwgXCIxLjkwLjAhYXdzLWNkay1saWIuU3RhY2tcIilcbiAqIGFuZCB0aGVuIGFsbCBvZiB0aGUgY29uc3RydWN0LXZlcnNpb25zIGFyZSBncm91cGVkIHdpdGggY29tbW9uIHByZWZpeGVzIHRvZ2V0aGVyLCBncm91cGluZyBjb21tb24gcGFydHMgaW4gJ3t9JyBhbmQgc2VwYXJhdGluZyBpdGVtcyB3aXRoICcsJy5cbiAqXG4gKiBFeGFtcGxlOlxuICogWzEuOTAuMCFhd3MtY2RrLWxpYi5TdGFjaywgMS45MC4wIWF3cy1jZGstbGliLkNvbnN0cnVjdCwgMS45MC4wIWF3cy1jZGstbGliLnNlcnZpY2UuUmVzb3VyY2UsIDAuNDIuMSFhd3MtY2RrLWxpYi1leHBlcmltZW50cy5OZXdTdHVmZl1cbiAqIEJlY29tZXM6XG4gKiAxLjkwLjAhYXdzLWNkay1saWIue1N0YWNrLENvbnN0cnVjdCxzZXJ2aWNlLlJlc291cmNlfSwwLjQyLjEhYXdzLWNkay1saWItZXhwZXJpbWVudHMuTmV3U3R1ZmZcbiAqXG4gKiBUaGUgd2hvbGUgdGhpbmcgaXMgdGhlbiBlaXRoZXIgaW5jbHVkZWQgZGlyZWN0bHkgYXMgcGxhaW50ZXh0IGFzOlxuICogdjI6cGxhaW50ZXh0OntwcmVmaXhFbmNvZGVkTGlzdH1cbiAqIE9yIGlzIGNvbXByZXNzZWQgYW5kIGJhc2U2NC1lbmNvZGVkLCBhbmQgdGhlbiBmb3JtYXR0ZWQgYXM6XG4gKiB2MjpkZWZsYXRlNjQ6e3ByZWZpeEVuY29kZWRMaXN0Q29tcHJlc3NlZEFuZEVuY29kZWR9XG4gKlxuICogRXhwb3J0ZWQvdmlzaWJsZSBmb3IgZWFzZSBvZiB0ZXN0aW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0QW5hbHl0aWNzKGluZm9zOiBDb25zdHJ1Y3RJbmZvW10pIHtcbiAgY29uc3QgdHJpZSA9IG5ldyBUcmllKCk7XG4gIGluZm9zLmZvckVhY2goaW5mbyA9PiBpbnNlcnRGcW5JblRyaWUoYCR7aW5mby52ZXJzaW9ufSEke2luZm8uZnFufWAsIHRyaWUpKTtcblxuICBjb25zdCBwbGFpbnRleHRFbmNvZGVkQ29uc3RydWN0cyA9IHByZWZpeEVuY29kZVRyaWUodHJpZSk7XG4gIGNvbnN0IGNvbXByZXNzZWRDb25zdHJ1Y3RzQnVmZmVyID0gemxpYi5nemlwU3luYyhCdWZmZXIuZnJvbShwbGFpbnRleHRFbmNvZGVkQ29uc3RydWN0cykpO1xuXG4gIC8vIHNldCBPUyBmbGFnIHRvIFwidW5rbm93blwiIGluIG9yZGVyIHRvIGVuc3VyZSB3ZSBnZXQgY29uc2lzdGVudCByZXN1bHRzIGFjcm9zcyBvcGVyYXRpbmcgc3lzdGVtc1xuICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2lzc3Vlcy8xNTMyMlxuICBzZXRHemlwT3BlcmF0aW5nU3lzdGVtVG9Vbmtub3duKGNvbXByZXNzZWRDb25zdHJ1Y3RzQnVmZmVyKTtcblxuICBjb25zdCBjb21wcmVzc2VkQ29uc3RydWN0cyA9IGNvbXByZXNzZWRDb25zdHJ1Y3RzQnVmZmVyLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgcmV0dXJuIGB2MjpkZWZsYXRlNjQ6JHtjb21wcmVzc2VkQ29uc3RydWN0c31gO1xufVxuXG4vKipcbiAqIFNwbGl0cyBhZnRlciBub24tYWxwaGFudW1lcmljIGNoYXJhY3RlcnMgKGUuZy4sICcuJywgJy8nKSBpbiB0aGUgRlFOXG4gKiBhbmQgaW5zZXJ0IGVhY2ggcGllY2Ugb2YgdGhlIEZRTiBpbiBuZXN0ZWQgbWFwIChpLmUuLCBzaW1wbGUgdHJpZSkuXG4gKi9cbmZ1bmN0aW9uIGluc2VydEZxbkluVHJpZShmcW46IHN0cmluZywgdHJpZTogVHJpZSkge1xuICBmb3IgKGNvbnN0IGZxblBhcnQgb2YgZnFuLnJlcGxhY2UoL1teYS16MC05XS9naSwgJyQmICcpLnNwbGl0KCcgJykpIHtcbiAgICBjb25zdCBuZXh0TGV2ZWxUcmVlUmVmID0gdHJpZS5nZXQoZnFuUGFydCkgPz8gbmV3IFRyaWUoKTtcbiAgICB0cmllLnNldChmcW5QYXJ0LCBuZXh0TGV2ZWxUcmVlUmVmKTtcbiAgICB0cmllID0gbmV4dExldmVsVHJlZVJlZjtcbiAgfVxuICByZXR1cm4gdHJpZTtcbn1cblxuLyoqXG4gKiBQcmVmaXgtZW5jb2RlcyBhIFwidHJpZS1pc2hcIiBzdHJ1Y3R1cmUsIHVzaW5nICd7fScgdG8gZ3JvdXAgYW5kICcsJyB0byBzZXBhcmF0ZSBzaWJsaW5ncy5cbiAqXG4gKiBFeGFtcGxlIGlucHV0OlxuICogQUJDLEFCRCxBRUZcbiAqXG4gKiBFeGFtcGxlIHRyaWU6XG4gKiBBIC0tPiBCIC0tPiBDXG4gKiAgfCAgICAgXFwtLT4gRFxuICogIFxcLS0+IEUgLS0+IEZcbiAqXG4gKiBCZWNvbWVzOlxuICogQXtCe0MsRH0sRUZ9XG4gKi9cbmZ1bmN0aW9uIHByZWZpeEVuY29kZVRyaWUodHJpZTogVHJpZSkge1xuICBsZXQgcHJlZml4RW5jb2RlZCA9ICcnO1xuICBsZXQgaXNGaXJzdEVudHJ5QXRMZXZlbCA9IHRydWU7XG4gIFsuLi50cmllLmVudHJpZXMoKV0uZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgaWYgKCFpc0ZpcnN0RW50cnlBdExldmVsKSB7XG4gICAgICBwcmVmaXhFbmNvZGVkICs9ICcsJztcbiAgICB9XG4gICAgaXNGaXJzdEVudHJ5QXRMZXZlbCA9IGZhbHNlO1xuICAgIHByZWZpeEVuY29kZWQgKz0ga2V5O1xuICAgIGlmICh2YWx1ZS5zaXplID4gMSkge1xuICAgICAgcHJlZml4RW5jb2RlZCArPSAneyc7XG4gICAgICBwcmVmaXhFbmNvZGVkICs9IHByZWZpeEVuY29kZVRyaWUodmFsdWUpO1xuICAgICAgcHJlZml4RW5jb2RlZCArPSAnfSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByZWZpeEVuY29kZWQgKz0gcHJlZml4RW5jb2RlVHJpZSh2YWx1ZSk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHByZWZpeEVuY29kZWQ7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgT1MgZmxhZyB0byBcInVua25vd25cIiBpbiBvcmRlciB0byBlbnN1cmUgd2UgZ2V0IGNvbnNpc3RlbnQgcmVzdWx0cyBhY3Jvc3Mgb3BlcmF0aW5nIHN5c3RlbXMuXG4gKlxuICogQHNlZSBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL3JmYzE5NTIjcGFnZS01XG4gKlxuICogICArLS0tKy0tLSstLS0rLS0tKy0tLSstLS0rLS0tKy0tLSstLS0rLS0tK1xuICogICB8SUQxfElEMnxDTSB8RkxHfCAgICAgTVRJTUUgICAgIHxYRkx8T1MgfFxuICogICArLS0tKy0tLSstLS0rLS0tKy0tLSstLS0rLS0tKy0tLSstLS0rLS0tK1xuICogICB8IDAgfCAxIHwgMiB8IDMgfCA0IHwgNSB8IDYgfCA3IHwgOCB8IDkgfFxuICogICArLS0tKy0tLSstLS0rLS0tKy0tLSstLS0rLS0tKy0tLSstLS0rLS0tK1xuICpcbiAqIE9TIChPcGVyYXRpbmcgU3lzdGVtKVxuICogPT09PT09PT09PT09PT09PT09PT09XG4gKiBUaGlzIGlkZW50aWZpZXMgdGhlIHR5cGUgb2YgZmlsZSBzeXN0ZW0gb24gd2hpY2ggY29tcHJlc3Npb25cbiAqIHRvb2sgcGxhY2UuICBUaGlzIG1heSBiZSB1c2VmdWwgaW4gZGV0ZXJtaW5pbmcgZW5kLW9mLWxpbmVcbiAqIGNvbnZlbnRpb24gZm9yIHRleHQgZmlsZXMuICBUaGUgY3VycmVudGx5IGRlZmluZWQgdmFsdWVzIGFyZVxuICogYXMgZm9sbG93czpcbiAqICAgICAgMCAtIEZBVCBmaWxlc3lzdGVtIChNUy1ET1MsIE9TLzIsIE5UL1dpbjMyKVxuICogICAgICAxIC0gQW1pZ2FcbiAqICAgICAgMiAtIFZNUyAob3IgT3BlblZNUylcbiAqICAgICAgMyAtIFVuaXhcbiAqICAgICAgNCAtIFZNL0NNU1xuICogICAgICA1IC0gQXRhcmkgVE9TXG4gKiAgICAgIDYgLSBIUEZTIGZpbGVzeXN0ZW0gKE9TLzIsIE5UKVxuICogICAgICA3IC0gTWFjaW50b3NoXG4gKiAgICAgIDggLSBaLVN5c3RlbVxuICogICAgICA5IC0gQ1AvTVxuICogICAgIDEwIC0gVE9QUy0yMFxuICogICAgIDExIC0gTlRGUyBmaWxlc3lzdGVtIChOVClcbiAqICAgICAxMiAtIFFET1NcbiAqICAgICAxMyAtIEFjb3JuIFJJU0NPU1xuICogICAgMjU1IC0gdW5rbm93blxuICpcbiAqIEBwYXJhbSBnemlwQnVmZmVyIEEgZ3ppcCBidWZmZXJcbiAqL1xuZnVuY3Rpb24gc2V0R3ppcE9wZXJhdGluZ1N5c3RlbVRvVW5rbm93bihnemlwQnVmZmVyOiBCdWZmZXIpIHtcbiAgLy8gY2hlY2sgdGhhdCB0aGlzIGlzIGluZGVlZCBhIGd6aXAgYnVmZmVyIChodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL3JmYzE5NTIjcGFnZS02KVxuICBpZiAoZ3ppcEJ1ZmZlclswXSAhPT0gMHgxZiB8fCBnemlwQnVmZmVyWzFdICE9PSAweDhiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RpbmcgYSBnemlwIGJ1ZmZlciAobXVzdCBzdGFydCB3aXRoIDB4MWY4YiknKTtcbiAgfVxuXG4gIGd6aXBCdWZmZXJbOV0gPSAyNTU7XG59Il19
;