@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
198 lines • 21.2 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.TokenMap = void 0;
const token_1 = require("../token");
const encoding_1 = require("./encoding");
const glob = global;
const STRING_SYMBOL = Symbol.for('@aws-cdk/core.TokenMap.STRING');
const LIST_SYMBOL = Symbol.for('@aws-cdk/core.TokenMap.LIST');
const NUMBER_SYMBOL = Symbol.for('@aws-cdk/core.TokenMap.NUMBER');
/**
* Central place where we keep a mapping from Tokens to their String representation
*
* The string representation is used to embed token into strings,
* and stored to be able to reverse that mapping.
*
* All instances of TokenStringMap share the same storage, so that this process
* works even when different copies of the library are loaded.
*/
class TokenMap {
constructor() {
this.stringTokenMap = new Map();
this.numberTokenMap = new Map();
/**
* Counter to assign unique IDs to tokens
*
* Start at a random number to prevent people from accidentally taking
* dependencies on token values between runs.
*
* This is most prominent in tests, where people will write:
*
* ```ts
* sha256(JSON.stringify({ ...some structure that can contain tokens ... }))
* ```
*
* This should have been:
*
* ```ts
* sha256(JSON.stringify(stack.resolve({ ...some structure that can contain tokens ... })))
* ```
*
* The hash value is hard to inspect for correctness. It will LOOK consistent
* during testing, but will break as soon as someone stringifies another
* token before the run.
*
* By changing the starting number for tokens, we ensure that the hash is almost
* guaranteed to be different during a few test runs, so the hashing of unresolved
* tokens can be detected.
*/
this.tokenCounter = Math.floor(Math.random() * 10);
}
/**
* Singleton instance of the token string map
*/
static instance() {
if (!glob.__cdkTokenMap) {
glob.__cdkTokenMap = new TokenMap();
}
return glob.__cdkTokenMap;
}
/**
* Generate a unique string for this Token, returning a key
*
* Every call for the same Token will produce a new unique string, no
* attempt is made to deduplicate. Token objects should cache the
* value themselves, if required.
*
* The token can choose (part of) its own representation string with a
* hint. This may be used to produce aesthetically pleasing and
* recognizable token representations for humans.
*/
registerString(token, displayHint) {
return cachedValue(token, STRING_SYMBOL, () => {
const key = this.registerStringKey(token, displayHint);
return `${encoding_1.BEGIN_STRING_TOKEN_MARKER}${key}${encoding_1.END_TOKEN_MARKER}`;
});
}
/**
* Generate a unique string for this Token, returning a key
*/
registerList(token, displayHint) {
return cachedValue(token, LIST_SYMBOL, () => {
const key = this.registerStringKey(token, displayHint);
return [`${encoding_1.BEGIN_LIST_TOKEN_MARKER}${key}${encoding_1.END_TOKEN_MARKER}`];
});
}
/**
* Create a unique number representation for this Token and return it
*/
registerNumber(token) {
return cachedValue(token, NUMBER_SYMBOL, () => {
return this.registerNumberKey(token);
});
}
/**
* Lookup a token from an encoded value
*/
tokenFromEncoding(x) {
if (token_1.isResolvableObject(x)) {
return x;
}
if (typeof x === 'string') {
return this.lookupString(x);
}
if (Array.isArray(x)) {
return this.lookupList(x);
}
if (token_1.Token.isUnresolved(x)) {
return x;
}
return undefined;
}
/**
* Reverse a string representation into a Token object
*/
lookupString(s) {
const fragments = this.splitString(s);
if (fragments.tokens.length > 0 && fragments.length === 1) {
return fragments.firstToken;
}
return undefined;
}
/**
* Reverse a string representation into a Token object
*/
lookupList(xs) {
if (xs.length !== 1) {
return undefined;
}
const str = encoding_1.TokenString.forListToken(xs[0]);
const fragments = str.split(this.lookupToken.bind(this));
if (fragments.length === 1) {
return fragments.firstToken;
}
return undefined;
}
/**
* Split a string into literals and Tokens
*/
splitString(s) {
const str = encoding_1.TokenString.forString(s);
return str.split(this.lookupToken.bind(this));
}
/**
* Reverse a number encoding into a Token, or undefined if the number wasn't a Token
*/
lookupNumberToken(x) {
const tokenIndex = encoding_1.extractTokenDouble(x);
if (tokenIndex === undefined) {
return undefined;
}
const t = this.numberTokenMap.get(tokenIndex);
if (t === undefined) {
throw new Error('Encoded representation of unknown number Token found');
}
return t;
}
/**
* Find a Token by key.
*
* This excludes the token markers.
*/
lookupToken(key) {
const token = this.stringTokenMap.get(key);
if (!token) {
throw new Error(`Unrecognized token key: ${key}`);
}
return token;
}
registerStringKey(token, displayHint) {
const counter = this.tokenCounter++;
const representation = (displayHint || 'TOKEN').replace(new RegExp(`[^${encoding_1.VALID_KEY_CHARS}]`, 'g'), '.');
const key = `${representation}.${counter}`;
this.stringTokenMap.set(key, token);
return key;
}
registerNumberKey(token) {
const counter = this.tokenCounter++;
const dbl = encoding_1.createTokenDouble(counter);
// Register in the number map, as well as a string representation of that token
// in the string map.
this.numberTokenMap.set(counter, token);
this.stringTokenMap.set(`${dbl}`, token);
return dbl;
}
}
exports.TokenMap = TokenMap;
/**
* Get a cached value for an object, storing it on the object in a symbol
*/
function cachedValue(x, sym, prod) {
let cached = x[sym];
if (cached === undefined) {
cached = prod();
Object.defineProperty(x, sym, { value: cached });
}
return cached;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tbWFwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidG9rZW4tbWFwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLG9DQUFxRDtBQUNyRCx5Q0FHb0I7QUFFcEIsTUFBTSxJQUFJLEdBQUcsTUFBYSxDQUFDO0FBRTNCLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FBQztBQUNsRSxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLENBQUM7QUFDOUQsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO0FBRWxFOzs7Ozs7OztHQVFHO0FBQ0gsTUFBYSxRQUFRO0lBQXJCO1FBV21CLG1CQUFjLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7UUFDaEQsbUJBQWMsR0FBRyxJQUFJLEdBQUcsRUFBdUIsQ0FBQztRQUVqRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztXQXlCRztRQUNLLGlCQUFZLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUEySHhELENBQUM7SUFsS0M7O09BRUc7SUFDSSxNQUFNLENBQUMsUUFBUTtRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUN2QixJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7U0FDckM7UUFDRCxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7S0FDM0I7SUFpQ0Q7Ozs7Ozs7Ozs7T0FVRztJQUNJLGNBQWMsQ0FBQyxLQUFrQixFQUFFLFdBQW9CO1FBQzVELE9BQU8sV0FBVyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsR0FBRyxFQUFFO1lBQzVDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7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O1FBQ3hDLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDekMsT0FBTyxHQUFHLENBQUM7S0FDWjtDQUNGO0FBbktELDRCQW1LQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxXQUFXLENBQXNCLENBQUksRUFBRSxHQUFXLEVBQUUsSUFBYTtJQUN4RSxJQUFJLE1BQU0sR0FBSSxDQUFTLENBQUMsR0FBVSxDQUFDLENBQUM7SUFDcEMsSUFBSSxNQUFNLEtBQUssU0FBUyxFQUFFO1FBQ3hCLE1BQU0sR0FBRyxJQUFJLEVBQUUsQ0FBQztRQUNoQixNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztLQUNsRDtJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJUmVzb2x2YWJsZSB9IGZyb20gJy4uL3Jlc29sdmFibGUnO1xuaW1wb3J0IHsgVG9rZW5pemVkU3RyaW5nRnJhZ21lbnRzIH0gZnJvbSAnLi4vc3RyaW5nLWZyYWdtZW50cyc7XG5pbXBvcnQgeyBpc1Jlc29sdmFibGVPYmplY3QsIFRva2VuIH0gZnJvbSAnLi4vdG9rZW4nO1xuaW1wb3J0IHtcbiAgQkVHSU5fTElTVF9UT0tFTl9NQVJLRVIsIEJFR0lOX1NUUklOR19UT0tFTl9NQVJLRVIsIGNyZWF0ZVRva2VuRG91YmxlLFxuICBFTkRfVE9LRU5fTUFSS0VSLCBleHRyYWN0VG9rZW5Eb3VibGUsIFRva2VuU3RyaW5nLCBWQUxJRF9LRVlfQ0hBUlMsXG59IGZyb20gJy4vZW5jb2RpbmcnO1xuXG5jb25zdCBnbG9iID0gZ2xvYmFsIGFzIGFueTtcblxuY29uc3QgU1RSSU5HX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUuVG9rZW5NYXAuU1RSSU5HJyk7XG5jb25zdCBMSVNUX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUuVG9rZW5NYXAuTElTVCcpO1xuY29uc3QgTlVNQkVSX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUuVG9rZW5NYXAuTlVNQkVSJyk7XG5cbi8qKlxuICogQ2VudHJhbCBwbGFjZSB3aGVyZSB3ZSBrZWVwIGEgbWFwcGluZyBmcm9tIFRva2VucyB0byB0aGVpciBTdHJpbmcgcmVwcmVzZW50YXRpb25cbiAqXG4gKiBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIGlzIHVzZWQgdG8gZW1iZWQgdG9rZW4gaW50byBzdHJpbmdzLFxuICogYW5kIHN0b3JlZCB0byBiZSBhYmxlIHRvIHJldmVyc2UgdGhhdCBtYXBwaW5nLlxuICpcbiAqIEFsbCBpbnN0YW5jZXMgb2YgVG9rZW5TdHJpbmdNYXAgc2hhcmUgdGhlIHNhbWUgc3RvcmFnZSwgc28gdGhhdCB0aGlzIHByb2Nlc3NcbiAqIHdvcmtzIGV2ZW4gd2hlbiBkaWZmZXJlbnQgY29waWVzIG9mIHRoZSBsaWJyYXJ5IGFyZSBsb2FkZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBUb2tlbk1hcCB7XG4gIC8qKlxuICAgKiBTaW5nbGV0b24gaW5zdGFuY2Ugb2YgdGhlIHRva2VuIHN0cmluZyBtYXBcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaW5zdGFuY2UoKTogVG9rZW5NYXAge1xuICAgIGlmICghZ2xvYi5fX2Nka1Rva2VuTWFwKSB7XG4gICAgICBnbG9iLl9fY2RrVG9rZW5NYXAgPSBuZXcgVG9rZW5NYXAoKTtcbiAgICB9XG4gICAgcmV0dXJuIGdsb2IuX19jZGtUb2tlbk1hcDtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgc3RyaW5nVG9rZW5NYXAgPSBuZXcgTWFwPHN0cmluZywgSVJlc29sdmFibGU+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbnVtYmVyVG9rZW5NYXAgPSBuZXcgTWFwPG51bWJlciwgSVJlc29sdmFibGU+KCk7XG5cbiAgLyoqXG4gICAqIENvdW50ZXIgdG8gYXNzaWduIHVuaXF1ZSBJRHMgdG8gdG9rZW5zXG4gICAqXG4gICAqIFN0YXJ0IGF0IGEgcmFuZG9tIG51bWJlciB0byBwcmV2ZW50IHBlb3BsZSBmcm9tIGFjY2lkZW50YWxseSB0YWtpbmdcbiAgICogZGVwZW5kZW5jaWVzIG9uIHRva2VuIHZhbHVlcyBiZXR3ZWVuIHJ1bnMuXG4gICAqXG4gICAqIFRoaXMgaXMgbW9zdCBwcm9taW5lbnQgaW4gdGVzdHMsIHdoZXJlIHBlb3BsZSB3aWxsIHdyaXRlOlxuICAgKlxuICAgKiBgYGB0c1xuICAgKiBzaGEyNTYoSlNPTi5zdHJpbmdpZnkoeyAuLi5zb21lIHN0cnVjdHVyZSB0aGF0IGNhbiBjb250YWluIHRva2VucyAuLi4gfSkpXG4gICAqIGBgYFxuICAgKlxuICAgKiBUaGlzIHNob3VsZCBoYXZlIGJlZW46XG4gICAqXG4gICAqIGBgYHRzXG4gICAqIHNoYTI1NihKU09OLnN0cmluZ2lmeShzdGFjay5yZXNvbHZlKHsgLi4uc29tZSBzdHJ1Y3R1cmUgdGhhdCBjYW4gY29udGFpbiB0b2tlbnMgLi4uIH0pKSlcbiAgICogYGBgXG4gICAqXG4gICAqIFRoZSBoYXNoIHZhbHVlIGlzIGhhcmQgdG8gaW5zcGVjdCBmb3IgY29ycmVjdG5lc3MuIEl0IHdpbGwgTE9PSyBjb25zaXN0ZW50XG4gICAqIGR1cmluZyB0ZXN0aW5nLCBidXQgd2lsbCBicmVhayBhcyBzb29uIGFzIHNvbWVvbmUgc3RyaW5naWZpZXMgYW5vdGhlclxuICAgKiB0b2tlbiBiZWZvcmUgdGhlIHJ1bi5cbiAgICpcbiAgICogQnkgY2hhbmdpbmcgdGhlIHN0YXJ0aW5nIG51bWJlciBmb3IgdG9rZW5zLCB3ZSBlbnN1cmUgdGhhdCB0aGUgaGFzaCBpcyBhbG1vc3RcbiAgICogZ3VhcmFudGVlZCB0byBiZSBkaWZmZXJlbnQgZHVyaW5nIGEgZmV3IHRlc3QgcnVucywgc28gdGhlIGhhc2hpbmcgb2YgdW5yZXNvbHZlZFxuICAgKiB0b2tlbnMgY2FuIGJlIGRldGVjdGVkLlxuICAgKi9cbiAgcHJpdmF0ZSB0b2tlbkNvdW50ZXIgPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAxMCk7XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIGEgdW5pcXVlIHN0cmluZyBmb3IgdGhpcyBUb2tlbiwgcmV0dXJuaW5nIGEga2V5XG4gICAqXG4gICAqIEV2ZXJ5IGNhbGwgZm9yIHRoZSBzYW1lIFRva2VuIHdpbGwgcHJvZHVjZSBhIG5ldyB1bmlxdWUgc3RyaW5nLCBub1xuICAgKiBhdHRlbXB0IGlzIG1hZGUgdG8gZGVkdXBsaWNhdGUuIFRva2VuIG9iamVjdHMgc2hvdWxkIGNhY2hlIHRoZVxuICAgKiB2YWx1ZSB0aGVtc2VsdmVzLCBpZiByZXF1aXJlZC5cbiAgICpcbiAgICogVGhlIHRva2VuIGNhbiBjaG9vc2UgKHBhcnQgb2YpIGl0cyBvd24gcmVwcmVzZW50YXRpb24gc3RyaW5nIHdpdGggYVxuICAgKiBoaW50LiBUaGlzIG1heSBiZSB1c2VkIHRvIHByb2R1Y2UgYWVzdGhldGljYWxseSBwbGVhc2luZyBhbmRcbiAgICogcmVjb2duaXphYmxlIHRva2VuIHJlcHJlc2VudGF0aW9ucyBmb3IgaHVtYW5zLlxuICAgKi9cbiAgcHVibGljIHJlZ2lzdGVyU3RyaW5nKHRva2VuOiBJUmVzb2x2YWJsZSwgZGlzcGxheUhpbnQ/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBjYWNoZWRWYWx1ZSh0b2tlbiwgU1RSSU5HX1NZTUJPTCwgKCkgPT4ge1xuICAgICAgY29uc3Qga2V5ID0gdGhpcy5yZWdpc3RlclN0cmluZ0tleSh0b2tlbiwgZGlzcGxheUhpbnQpO1xuICAgICAgcmV0dXJuIGAke0JFR0lOX1NUUklOR19UT0tFTl9NQVJLRVJ9JHtrZXl9JHtFTkRfVE9LRU5fTUFSS0VSfWA7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgYSB1bmlxdWUgc3RyaW5nIGZvciB0aGlzIFRva2VuLCByZXR1cm5pbmcgYSBrZXlcbiAgICovXG4gIHB1YmxpYyByZWdpc3Rlckxpc3QodG9rZW46IElSZXNvbHZhYmxlLCBkaXNwbGF5SGludD86IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gY2FjaGVkVmFsdWUodG9rZW4sIExJU1RfU1lNQk9MLCAoKSA9PiB7XG4gICAgICBjb25zdCBrZXkgPSB0aGlzLnJlZ2lzdGVyU3RyaW5nS2V5KHRva2VuLCBkaXNwbGF5SGludCk7XG4gICAgICByZXR1cm4gW2Ake0JFR0lOX0xJU1RfVE9LRU5fTUFSS0VSfSR7a2V5fSR7RU5EX1RPS0VOX01BUktFUn1gXTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSB1bmlxdWUgbnVtYmVyIHJlcHJlc2VudGF0aW9uIGZvciB0aGlzIFRva2VuIGFuZCByZXR1cm4gaXRcbiAgICovXG4gIHB1YmxpYyByZWdpc3Rlck51bWJlcih0b2tlbjogSVJlc29sdmFibGUpOiBudW1iZXIge1xuICAgIHJldHVybiBjYWNoZWRWYWx1ZSh0b2tlbiwgTlVNQkVSX1NZTUJPTCwgKCkgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMucmVnaXN0ZXJOdW1iZXJLZXkodG9rZW4pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIExvb2t1cCBhIHRva2VuIGZyb20gYW4gZW5jb2RlZCB2YWx1ZVxuICAgKi9cbiAgcHVibGljIHRva2VuRnJvbUVuY29kaW5nKHg6IGFueSk6IElSZXNvbHZhYmxlIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoaXNSZXNvbHZhYmxlT2JqZWN0KHgpKSB7IHJldHVybiB4OyB9XG4gICAgaWYgKHR5cGVvZiB4ID09PSAnc3RyaW5nJykgeyByZXR1cm4gdGhpcy5sb29rdXBTdHJpbmcoeCk7IH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh4KSkgeyByZXR1cm4gdGhpcy5sb29rdXBMaXN0KHgpOyB9XG4gICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZCh4KSkgeyByZXR1cm4geDsgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogUmV2ZXJzZSBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBpbnRvIGEgVG9rZW4gb2JqZWN0XG4gICAqL1xuICBwdWJsaWMgbG9va3VwU3RyaW5nKHM6IHN0cmluZyk6IElSZXNvbHZhYmxlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBmcmFnbWVudHMgPSB0aGlzLnNwbGl0U3RyaW5nKHMpO1xuICAgIGlmIChmcmFnbWVudHMudG9rZW5zLmxlbmd0aCA+IDAgJiYgZnJhZ21lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIGZyYWdtZW50cy5maXJzdFRva2VuO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldmVyc2UgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gaW50byBhIFRva2VuIG9iamVjdFxuICAgKi9cbiAgcHVibGljIGxvb2t1cExpc3QoeHM6IHN0cmluZ1tdKTogSVJlc29sdmFibGUgfCB1bmRlZmluZWQge1xuICAgIGlmICh4cy5sZW5ndGggIT09IDEpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfVxuICAgIGNvbnN0IHN0ciA9IFRva2VuU3RyaW5nLmZvckxpc3RUb2tlbih4c1swXSk7XG4gICAgY29uc3QgZnJhZ21lbnRzID0gc3RyLnNwbGl0KHRoaXMubG9va3VwVG9rZW4uYmluZCh0aGlzKSk7XG4gICAgaWYgKGZyYWdtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBmcmFnbWVudHMuZmlyc3RUb2tlbjtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdCBhIHN0cmluZyBpbnRvIGxpdGVyYWxzIGFuZCBUb2tlbnNcbiAgICovXG4gIHB1YmxpYyBzcGxpdFN0cmluZyhzOiBzdHJpbmcpOiBUb2tlbml6ZWRTdHJpbmdGcmFnbWVudHMge1xuICAgIGNvbnN0IHN0ciA9IFRva2VuU3RyaW5nLmZvclN0cmluZyhzKTtcbiAgICByZXR1cm4gc3RyLnNwbGl0KHRoaXMubG9va3VwVG9rZW4uYmluZCh0aGlzKSk7XG4gIH1cblxuICAvKipcbiAgICogUmV2ZXJzZSBhIG51bWJlciBlbmNvZGluZyBpbnRvIGEgVG9rZW4sIG9yIHVuZGVmaW5lZCBpZiB0aGUgbnVtYmVyIHdhc24ndCBhIFRva2VuXG4gICAqL1xuICBwdWJsaWMgbG9va3VwTnVtYmVyVG9rZW4oeDogbnVtYmVyKTogSVJlc29sdmFibGUgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHRva2VuSW5kZXggPSBleHRyYWN0VG9rZW5Eb3VibGUoeCk7XG4gICAgaWYgKHRva2VuSW5kZXggPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG4gICAgY29uc3QgdCA9IHRoaXMubnVtYmVyVG9rZW5NYXAuZ2V0KHRva2VuSW5kZXgpO1xuICAgIGlmICh0ID09PSB1bmRlZmluZWQpIHsgdGhyb3cgbmV3IEVycm9yKCdFbmNvZGVkIHJlcHJlc2VudGF0aW9uIG9mIHVua25vd24gbnVtYmVyIFRva2VuIGZvdW5kJyk7IH1cbiAgICByZXR1cm4gdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kIGEgVG9rZW4gYnkga2V5LlxuICAgKlxuICAgKiBUaGlzIGV4Y2x1ZGVzIHRoZSB0b2tlbiBtYXJrZXJzLlxuICAgKi9cbiAgcHVibGljIGxvb2t1cFRva2VuKGtleTogc3RyaW5nKTogSVJlc29sdmFibGUge1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5zdHJpbmdUb2tlbk1hcC5nZXQoa2V5KTtcbiAgICBpZiAoIXRva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVucmVjb2duaXplZCB0b2tlbiBrZXk6ICR7a2V5fWApO1xuICAgIH1cbiAgICByZXR1cm4gdG9rZW47XG4gIH1cblxuICBwcml2YXRlIHJlZ2lzdGVyU3RyaW5nS2V5KHRva2VuOiBJUmVzb2x2YWJsZSwgZGlzcGxheUhpbnQ/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvdW50ZXIgPSB0aGlzLnRva2VuQ291bnRlcisrO1xuICAgIGNvbnN0IHJlcHJlc2VudGF0aW9uID0gKGRpc3BsYXlIaW50IHx8ICdUT0tFTicpLnJlcGxhY2UobmV3IFJlZ0V4cChgW14ke1ZBTElEX0tFWV9DSEFSU31dYCwgJ2cnKSwgJy4nKTtcbiAgICBjb25zdCBrZXkgPSBgJHtyZXByZXNlbnRhdGlvbn0uJHtjb3VudGVyfWA7XG4gICAgdGhpcy5zdHJpbmdUb2tlbk1hcC5zZXQoa2V5LCB0b2tlbik7XG4gICAgcmV0dXJuIGtleTtcbiAgfVxuXG4gIHByaXZhdGUgcmVnaXN0ZXJOdW1iZXJLZXkodG9rZW46IElSZXNvbHZhYmxlKTogbnVtYmVyIHtcbiAgICBjb25zdCBjb3VudGVyID0gdGhpcy50b2tlbkNvdW50ZXIrKztcbiAgICBjb25zdCBkYmwgPSBjcmVhdGVUb2tlbkRvdWJsZShjb3VudGVyKTtcbiAgICAvLyBSZWdpc3RlciBpbiB0aGUgbnVtYmVyIG1hcCwgYXMgd2VsbCBhcyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGF0IHRva2VuXG4gICAgLy8gaW4gdGhlIHN0cmluZyBtYXAuXG4gICAgdGhpcy5udW1iZXJUb2tlbk1hcC5zZXQoY291bnRlciwgdG9rZW4pO1xuICAgIHRoaXMuc3RyaW5nVG9rZW5NYXAuc2V0KGAke2RibH1gLCB0b2tlbik7XG4gICAgcmV0dXJuIGRibDtcbiAgfVxufVxuXG4vKipcbiAqIEdldCBhIGNhY2hlZCB2YWx1ZSBmb3IgYW4gb2JqZWN0LCBzdG9yaW5nIGl0IG9uIHRoZSBvYmplY3QgaW4gYSBzeW1ib2xcbiAqL1xuZnVuY3Rpb24gY2FjaGVkVmFsdWU8QSBleHRlbmRzIG9iamVjdCwgQj4oeDogQSwgc3ltOiBzeW1ib2wsIHByb2Q6ICgpID0+IEIpIHtcbiAgbGV0IGNhY2hlZCA9ICh4IGFzIGFueSlbc3ltIGFzIGFueV07XG4gIGlmIChjYWNoZWQgPT09IHVuZGVmaW5lZCkge1xuICAgIGNhY2hlZCA9IHByb2QoKTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoeCwgc3ltLCB7IHZhbHVlOiBjYWNoZWQgfSk7XG4gIH1cbiAgcmV0dXJuIGNhY2hlZDtcbn1cbiJdfQ==
;