@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
201 lines • 21.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const string_fragments_1 = require("../string-fragments");
const token_1 = require("../token");
// Details for encoding and decoding Tokens into native types; should not be exported
exports.BEGIN_STRING_TOKEN_MARKER = '${Token[';
exports.BEGIN_LIST_TOKEN_MARKER = '#{Token[';
exports.END_TOKEN_MARKER = ']}';
exports.VALID_KEY_CHARS = 'a-zA-Z0-9:._-';
const QUOTED_BEGIN_STRING_TOKEN_MARKER = regexQuote(exports.BEGIN_STRING_TOKEN_MARKER);
const QUOTED_BEGIN_LIST_TOKEN_MARKER = regexQuote(exports.BEGIN_LIST_TOKEN_MARKER);
const QUOTED_END_TOKEN_MARKER = regexQuote(exports.END_TOKEN_MARKER);
const STRING_TOKEN_REGEX = new RegExp(`${QUOTED_BEGIN_STRING_TOKEN_MARKER}([${exports.VALID_KEY_CHARS}]+)${QUOTED_END_TOKEN_MARKER}`, 'g');
const LIST_TOKEN_REGEX = new RegExp(`${QUOTED_BEGIN_LIST_TOKEN_MARKER}([${exports.VALID_KEY_CHARS}]+)${QUOTED_END_TOKEN_MARKER}`, 'g');
/**
* A string with markers in it that can be resolved to external values
*/
class TokenString {
constructor(str, re) {
this.str = str;
this.re = re;
}
/**
* Returns a `TokenString` for this string.
*/
static forString(s) {
return new TokenString(s, STRING_TOKEN_REGEX);
}
/**
* Returns a `TokenString` for this string (must be the first string element of the list)
*/
static forListToken(s) {
return new TokenString(s, LIST_TOKEN_REGEX);
}
/**
* Split string on markers, substituting markers with Tokens
*/
split(lookup) {
const ret = new string_fragments_1.TokenizedStringFragments();
let rest = 0;
this.re.lastIndex = 0; // Reset
let m = this.re.exec(this.str);
while (m) {
if (m.index > rest) {
ret.addLiteral(this.str.substring(rest, m.index));
}
ret.addToken(lookup(m[1]));
rest = this.re.lastIndex;
m = this.re.exec(this.str);
}
if (rest < this.str.length) {
ret.addLiteral(this.str.substring(rest));
}
return ret;
}
/**
* Indicates if this string includes tokens.
*/
test() {
this.re.lastIndex = 0; // Reset
return this.re.test(this.str);
}
}
exports.TokenString = TokenString;
/**
* Quote a string for use in a regex
*/
function regexQuote(s) {
return s.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&");
}
exports.regexQuote = regexQuote;
/**
* Concatenator that disregards the input
*
* Can be used when traversing the tokens is important, but the
* result isn't.
*/
class NullConcat {
join(_left, _right) {
return undefined;
}
}
exports.NullConcat = NullConcat;
function containsListTokenElement(xs) {
return xs.some(x => typeof (x) === 'string' && TokenString.forListToken(x).test());
}
exports.containsListTokenElement = containsListTokenElement;
/**
* Returns true if obj is a token (i.e. has the resolve() method or is a string
* that includes token markers), or it's a listifictaion of a Token string.
*
* @param obj The object to test.
*/
function unresolved(obj) {
if (typeof (obj) === 'string') {
return TokenString.forString(obj).test();
}
else if (typeof obj === 'number') {
return extractTokenDouble(obj) !== undefined;
}
else if (Array.isArray(obj) && obj.length === 1) {
return typeof (obj[0]) === 'string' && TokenString.forListToken(obj[0]).test();
}
else {
return token_1.isResolvableObject(obj);
}
}
exports.unresolved = unresolved;
/**
* Bit pattern in the top 16 bits of a double to indicate a Token
*
* An IEEE double in LE memory order looks like this (grouped
* into octets, then grouped into 32-bit words):
*
* mmmmmmmm.mmmmmmmm.mmmmmmmm.mmmmmmmm | mmmmmmmm.mmmmmmmm.EEEEmmmm.sEEEEEEE
*
* - m: mantissa (52 bits)
* - E: exponent (11 bits)
* - s: sign (1 bit)
*
* We put the following marker into the top 16 bits (exponent and sign), and
* use the mantissa part to encode the token index. To save some bit twiddling
* we use all top 16 bits for the tag. That loses us 4 mantissa bits to store
* information in but we still have 48, which is going to be plenty for any
* number of tokens to be created during the lifetime of any CDK application.
*
* Can't have all bits set because that makes a NaN, so unset the least
* significant exponent bit.
*
* Currently not supporting BE architectures.
*/
// tslint:disable-next-line:no-bitwise
const DOUBLE_TOKEN_MARKER_BITS = 0xFBFF << 16;
/**
* Highest encodable number
*/
const MAX_ENCODABLE_INTEGER = Math.pow(2, 48) - 1;
/**
* Get 2^32 as a number, so we can do multiplication and div instead of bit shifting
*
* Necessary because in JavaScript, bit operations implicitly convert
* to int32 and we need them to work on "int64"s.
*
* So instead of x >> 32, we do Math.floor(x / 2^32), and vice versa.
*/
const BITS32 = Math.pow(2, 32);
/**
* Return a special Double value that encodes the given nonnegative integer
*
* We use this to encode Token ordinals.
*/
function createTokenDouble(x) {
if (Math.floor(x) !== x || x < 0) {
throw new Error('Can only encode positive integers');
}
if (x > MAX_ENCODABLE_INTEGER) {
throw new Error(`Got an index too large to encode: ${x}`);
}
const buf = new ArrayBuffer(8);
const ints = new Uint32Array(buf);
// tslint:disable:no-bitwise
ints[0] = x & 0x0000FFFFFFFF; // Bottom 32 bits of number
// This needs an "x >> 32" but that will make it a 32-bit number instead
// of a 64-bit number.
ints[1] = (shr32(x) & 0xFFFF) | DOUBLE_TOKEN_MARKER_BITS; // Top 16 bits of number and the mask
// tslint:enable:no-bitwise
return (new Float64Array(buf))[0];
}
exports.createTokenDouble = createTokenDouble;
/**
* Shift a 64-bit int right 32 bits
*/
function shr32(x) {
return Math.floor(x / BITS32);
}
/**
* Shift a 64-bit left 32 bits
*/
function shl32(x) {
return x * BITS32;
}
/**
* Extract the encoded integer out of the special Double value
*
* Returns undefined if the float is a not an encoded token.
*/
function extractTokenDouble(encoded) {
const buf = new ArrayBuffer(8);
(new Float64Array(buf))[0] = encoded;
const ints = new Uint32Array(buf);
// tslint:disable:no-bitwise
if ((ints[1] & 0xFFFF0000) !== DOUBLE_TOKEN_MARKER_BITS) {
return undefined;
}
// Must use + instead of | here (bitwise operations
// will force 32-bits integer arithmetic, + will not).
return ints[0] + shl32(ints[1] & 0xFFFF);
// tslint:enable:no-bitwise
}
exports.extractTokenDouble = extractTokenDouble;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5jb2RpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJlbmNvZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLDBEQUErRDtBQUMvRCxvQ0FBOEM7QUFFOUMscUZBQXFGO0FBRXhFLFFBQUEseUJBQXlCLEdBQUcsVUFBVSxDQUFDO0FBQ3ZDLFFBQUEsdUJBQXVCLEdBQUcsVUFBVSxDQUFDO0FBQ3JDLFFBQUEsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0FBRXhCLFFBQUEsZUFBZSxHQUFHLGVBQWUsQ0FBQztBQUUvQyxNQUFNLGdDQUFnQyxHQUFHLFVBQVUsQ0FBQyxpQ0FBeUIsQ0FBQyxDQUFDO0FBQy9FLE1BQU0sOEJBQThCLEdBQUcsVUFBVSxDQUFDLCtCQUF1QixDQUFDLENBQUM7QUFDM0UsTUFBTSx1QkFBdUIsR0FBRyxVQUFVLENBQUMsd0JBQWdCLENBQUMsQ0FBQztBQUU3RCxNQUFNLGtCQUFrQixHQUFHLElBQUksTUFBTSxDQUFDLEdBQUcsZ0NBQWdDLEtBQUssdUJBQWUsTUFBTSx1QkFBdUIsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ25JLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxNQUFNLENBQUMsR0FBRyw4QkFBOEIsS0FBSyx1QkFBZSxNQUFNLHVCQUF1QixFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFFL0g7O0dBRUc7QUFDSCxNQUFhLFdBQVc7SUFldEIsWUFBNkIsR0FBVyxFQUFtQixFQUFVO1FBQXhDLFFBQUcsR0FBSCxHQUFHLENBQVE7UUFBbUIsT0FBRSxHQUFGLEVBQUUsQ0FBUTtJQUNyRSxDQUFDO0lBZkQ7O09BRUc7SUFDSSxNQUFNLENBQUMsU0FBUyxDQUFDLENBQVM7UUFDL0IsT0FBTyxJQUFJLFdBQVcsQ0FBQyxDQUFDLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsWUFBWSxDQUFDLENBQVM7UUFDbEMsT0FBTyxJQUFJLFdBQVcs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d0JBQXdCLENBQUMsQ0FBQyxxQ0FBcUM7SUFDL0YsMkJBQTJCO0lBRTNCLE9BQU8sQ0FBQyxJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BDLENBQUM7QUFwQkQsOENBb0JDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLEtBQUssQ0FBQyxDQUFTO0lBQ3RCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDaEMsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxLQUFLLENBQUMsQ0FBUztJQUN0QixPQUFPLENBQUMsR0FBRyxNQUFNLENBQUM7QUFDcEIsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQixrQkFBa0IsQ0FBQyxPQUFlO0lBQ2hELE1BQU0sR0FBRyxHQUFHLElBQUksV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9CLENBQUMsSUFBSSxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUM7SUFFckMsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFbEMsNEJBQTRCO0lBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLEtBQUssd0JBQXdCLEVBQUU7UUFDdkQsT0FBTyxTQUFTLENBQUM7S0FDbEI7SUFFRCxtREFBbUQ7SUFDbkQsc0RBQXNEO0lBQ3RELE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7SUFDekMsMkJBQTJCO0FBQzdCLENBQUM7QUFmRCxnREFlQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElSZXNvbHZhYmxlIH0gZnJvbSBcIi4uL3Jlc29sdmFibGVcIjtcbmltcG9ydCB7IElGcmFnbWVudENvbmNhdGVuYXRvciB9IGZyb20gXCIuLi9yZXNvbHZhYmxlXCI7XG5pbXBvcnQgeyBUb2tlbml6ZWRTdHJpbmdGcmFnbWVudHMgfSBmcm9tIFwiLi4vc3RyaW5nLWZyYWdtZW50c1wiO1xuaW1wb3J0IHsgaXNSZXNvbHZhYmxlT2JqZWN0IH0gZnJvbSBcIi4uL3Rva2VuXCI7XG5cbi8vIERldGFpbHMgZm9yIGVuY29kaW5nIGFuZCBkZWNvZGluZyBUb2tlbnMgaW50byBuYXRpdmUgdHlwZXM7IHNob3VsZCBub3QgYmUgZXhwb3J0ZWRcblxuZXhwb3J0IGNvbnN0IEJFR0lOX1NUUklOR19UT0tFTl9NQVJLRVIgPSAnJHtUb2tlblsnO1xuZXhwb3J0IGNvbnN0IEJFR0lOX0xJU1RfVE9LRU5fTUFSS0VSID0gJyN7VG9rZW5bJztcbmV4cG9ydCBjb25zdCBFTkRfVE9LRU5fTUFSS0VSID0gJ119JztcblxuZXhwb3J0IGNvbnN0IFZBTElEX0tFWV9DSEFSUyA9ICdhLXpBLVowLTk6Ll8tJztcblxuY29uc3QgUVVPVEVEX0JFR0lOX1NUUklOR19UT0tFTl9NQVJLRVIgPSByZWdleFF1b3RlKEJFR0lOX1NUUklOR19UT0tFTl9NQVJLRVIpO1xuY29uc3QgUVVPVEVEX0JFR0lOX0xJU1RfVE9LRU5fTUFSS0VSID0gcmVnZXhRdW90ZShCRUdJTl9MSVNUX1RPS0VOX01BUktFUik7XG5jb25zdCBRVU9URURfRU5EX1RPS0VOX01BUktFUiA9IHJlZ2V4UXVvdGUoRU5EX1RPS0VOX01BUktFUik7XG5cbmNvbnN0IFNUUklOR19UT0tFTl9SRUdFWCA9IG5ldyBSZWdFeHAoYCR7UVVPVEVEX0JFR0lOX1NUUklOR19UT0tFTl9NQVJLRVJ9KFske1ZBTElEX0tFWV9DSEFSU31dKykke1FVT1RFRF9FTkRfVE9LRU5fTUFSS0VSfWAsICdnJyk7XG5jb25zdCBMSVNUX1RPS0VOX1JFR0VYID0gbmV3IFJlZ0V4cChgJHtRVU9URURfQkVHSU5fTElTVF9UT0tFTl9NQVJLRVJ9KFske1ZBTElEX0tFWV9DSEFSU31dKykke1FVT1RFRF9FTkRfVE9LRU5fTUFSS0VSfWAsICdnJyk7XG5cbi8qKlxuICogQSBzdHJpbmcgd2l0aCBtYXJrZXJzIGluIGl0IHRoYXQgY2FuIGJlIHJlc29sdmVkIHRvIGV4dGVybmFsIHZhbHVlc1xuICovXG5leHBvcnQgY2xhc3MgVG9rZW5TdHJpbmcge1xuICAvKipcbiAgICogUmV0dXJucyBhIGBUb2tlblN0cmluZ2AgZm9yIHRoaXMgc3RyaW5nLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmb3JTdHJpbmcoczogc3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBUb2tlblN0cmluZyhzLCBTVFJJTkdfVE9LRU5fUkVHRVgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBgVG9rZW5TdHJpbmdgIGZvciB0aGlzIHN0cmluZyAobXVzdCBiZSB0aGUgZmlyc3Qgc3RyaW5nIGVsZW1lbnQgb2YgdGhlIGxpc3QpXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZvckxpc3RUb2tlbihzOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IFRva2VuU3RyaW5nKHMsIExJU1RfVE9LRU5fUkVHRVgpO1xuICB9XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBzdHI6IHN0cmluZywgcHJpdmF0ZSByZWFkb25seSByZTogUmVnRXhwKSB7XG4gIH1cblxuICAvKipcbiAgICogU3BsaXQgc3RyaW5nIG9uIG1hcmtlcnMsIHN1YnN0aXR1dGluZyBtYXJrZXJzIHdpdGggVG9rZW5zXG4gICAqL1xuICBwdWJsaWMgc3BsaXQobG9va3VwOiAoaWQ6IHN0cmluZykgPT4gSVJlc29sdmFibGUpOiBUb2tlbml6ZWRTdHJpbmdGcmFnbWVudHMge1xuICAgIGNvbnN0IHJldCA9IG5ldyBUb2tlbml6ZWRTdHJpbmdGcmFnbWVudHMoKTtcblxuICAgIGxldCByZXN0ID0gMDtcbiAgICB0aGlzLnJlLmxhc3RJbmRleCA9IDA7IC8vIFJlc2V0XG4gICAgbGV0IG0gPSB0aGlzLnJlLmV4ZWModGhpcy5zdHIpO1xuICAgIHdoaWxlIChtKSB7XG4gICAgICBpZiAobS5pbmRleCA+IHJlc3QpIHtcbiAgICAgICAgcmV0LmFkZExpdGVyYWwodGhpcy5zdHIuc3Vic3RyaW5nKHJlc3QsIG0uaW5kZXgpKTtcbiAgICAgIH1cblxuICAgICAgcmV0LmFkZFRva2VuKGxvb2t1cChtWzFdKSk7XG5cbiAgICAgIHJlc3QgPSB0aGlzLnJlLmxhc3RJbmRleDtcbiAgICAgIG0gPSB0aGlzLnJlLmV4ZWModGhpcy5zdHIpO1xuICAgIH1cblxuICAgIGlmIChyZXN0IDwgdGhpcy5zdHIubGVuZ3RoKSB7XG4gICAgICByZXQuYWRkTGl0ZXJhbCh0aGlzLnN0ci5zdWJzdHJpbmcocmVzdCkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIGlmIHRoaXMgc3RyaW5nIGluY2x1ZGVzIHRva2Vucy5cbiAgICovXG4gIHB1YmxpYyB0ZXN0KCk6IGJvb2xlYW4ge1xuICAgIHRoaXMucmUubGFzdEluZGV4ID0gMDsgLy8gUmVzZXRcbiAgICByZXR1cm4gdGhpcy5yZS50ZXN0KHRoaXMuc3RyKTtcbiAgfVxufVxuXG4vKipcbiAqIFF1b3RlIGEgc3RyaW5nIGZvciB1c2UgaW4gYSByZWdleFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnZXhRdW90ZShzOiBzdHJpbmcpIHtcbiAgcmV0dXJuIHMucmVwbGFjZSgvWy4/KiteJFtcXF1cXFxcKCl7fXwtXS9nLCBcIlxcXFwkJlwiKTtcbn1cblxuLyoqXG4gKiBDb25jYXRlbmF0b3IgdGhhdCBkaXNyZWdhcmRzIHRoZSBpbnB1dFxuICpcbiAqIENhbiBiZSB1c2VkIHdoZW4gdHJhdmVyc2luZyB0aGUgdG9rZW5zIGlzIGltcG9ydGFudCwgYnV0IHRoZVxuICogcmVzdWx0IGlzbid0LlxuICovXG5leHBvcnQgY2xhc3MgTnVsbENvbmNhdCBpbXBsZW1lbnRzIElGcmFnbWVudENvbmNhdGVuYXRvciB7XG4gIHB1YmxpYyBqb2luKF9sZWZ0OiBhbnkgfCB1bmRlZmluZWQsIF9yaWdodDogYW55IHwgdW5kZWZpbmVkKTogYW55IHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0xpc3RUb2tlbkVsZW1lbnQoeHM6IGFueVtdKSB7XG4gIHJldHVybiB4cy5zb21lKHggPT4gdHlwZW9mKHgpID09PSAnc3RyaW5nJyAmJiBUb2tlblN0cmluZy5mb3JMaXN0VG9rZW4oeCkudGVzdCgpKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgb2JqIGlzIGEgdG9rZW4gKGkuZS4gaGFzIHRoZSByZXNvbHZlKCkgbWV0aG9kIG9yIGlzIGEgc3RyaW5nXG4gKiB0aGF0IGluY2x1ZGVzIHRva2VuIG1hcmtlcnMpLCBvciBpdCdzIGEgbGlzdGlmaWN0YWlvbiBvZiBhIFRva2VuIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gb2JqIFRoZSBvYmplY3QgdG8gdGVzdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVucmVzb2x2ZWQob2JqOiBhbnkpOiBib29sZWFuIHtcbiAgaWYgKHR5cGVvZihvYmopID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBUb2tlblN0cmluZy5mb3JTdHJpbmcob2JqKS50ZXN0KCk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG9iaiA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gZXh0cmFjdFRva2VuRG91YmxlKG9iaikgIT09IHVuZGVmaW5lZDtcbiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iaikgJiYgb2JqLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiB0eXBlb2Yob2JqWzBdKSA9PT0gJ3N0cmluZycgJiYgVG9rZW5TdHJpbmcuZm9yTGlzdFRva2VuKG9ialswXSkudGVzdCgpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBpc1Jlc29sdmFibGVPYmplY3Qob2JqKTtcbiAgfVxufVxuXG4vKipcbiAqIEJpdCBwYXR0ZXJuIGluIHRoZSB0b3AgMTYgYml0cyBvZiBhIGRvdWJsZSB0byBpbmRpY2F0ZSBhIFRva2VuXG4gKlxuICogQW4gSUVFRSBkb3VibGUgaW4gTEUgbWVtb3J5IG9yZGVyIGxvb2tzIGxpa2UgdGhpcyAoZ3JvdXBlZFxuICogaW50byBvY3RldHMsIHRoZW4gZ3JvdXBlZCBpbnRvIDMyLWJpdCB3b3Jkcyk6XG4gKlxuICogbW1tbW1tbW0ubW1tbW1tbW0ubW1tbW1tbW0ubW1tbW1tbW0gfCBtbW1tbW1tbS5tbW1tbW1tbS5FRUVFbW1tbS5zRUVFRUVFRVxuICpcbiAqIC0gbTogbWFudGlzc2EgKDUyIGJpdHMpXG4gKiAtIEU6IGV4cG9uZW50ICgxMSBiaXRzKVxuICogLSBzOiBzaWduICgxIGJpdClcbiAqXG4gKiBXZSBwdXQgdGhlIGZvbGxvd2luZyBtYXJrZXIgaW50byB0aGUgdG9wIDE2IGJpdHMgKGV4cG9uZW50IGFuZCBzaWduKSwgYW5kXG4gKiB1c2UgdGhlIG1hbnRpc3NhIHBhcnQgdG8gZW5jb2RlIHRoZSB0b2tlbiBpbmRleC4gVG8gc2F2ZSBzb21lIGJpdCB0d2lkZGxpbmdcbiAqIHdlIHVzZSBhbGwgdG9wIDE2IGJpdHMgZm9yIHRoZSB0YWcuIFRoYXQgbG9zZXMgdXMgNCBtYW50aXNzYSBiaXRzIHRvIHN0b3JlXG4gKiBpbmZvcm1hdGlvbiBpbiBidXQgd2Ugc3RpbGwgaGF2ZSA0OCwgd2hpY2ggaXMgZ29pbmcgdG8gYmUgcGxlbnR5IGZvciBhbnlcbiAqIG51bWJlciBvZiB0b2tlbnMgdG8gYmUgY3JlYXRlZCBkdXJpbmcgdGhlIGxpZmV0aW1lIG9mIGFueSBDREsgYXBwbGljYXRpb24uXG4gKlxuICogQ2FuJ3QgaGF2ZSBhbGwgYml0cyBzZXQgYmVjYXVzZSB0aGF0IG1ha2VzIGEgTmFOLCBzbyB1bnNldCB0aGUgbGVhc3RcbiAqIHNpZ25pZmljYW50IGV4cG9uZW50IGJpdC5cbiAqXG4gKiBDdXJyZW50bHkgbm90IHN1cHBvcnRpbmcgQkUgYXJjaGl0ZWN0dXJlcy5cbiAqL1xuLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWJpdHdpc2VcbmNvbnN0IERPVUJMRV9UT0tFTl9NQVJLRVJfQklUUyA9IDB4RkJGRiA8PCAxNjtcblxuLyoqXG4gKiBIaWdoZXN0IGVuY29kYWJsZSBudW1iZXJcbiAqL1xuY29uc3QgTUFYX0VOQ09EQUJMRV9JTlRFR0VSID0gTWF0aC5wb3coMiwgNDgpIC0gMTtcblxuLyoqXG4gKiBHZXQgMl4zMiBhcyBhIG51bWJlciwgc28gd2UgY2FuIGRvIG11bHRpcGxpY2F0aW9uIGFuZCBkaXYgaW5zdGVhZCBvZiBiaXQgc2hpZnRpbmdcbiAqXG4gKiBOZWNlc3NhcnkgYmVjYXVzZSBpbiBKYXZhU2NyaXB0LCBiaXQgb3BlcmF0aW9ucyBpbXBsaWNpdGx5IGNvbnZlcnRcbiAqIHRvIGludDMyIGFuZCB3ZSBuZWVkIHRoZW0gdG8gd29yayBvbiBcImludDY0XCJzLlxuICpcbiAqIFNvIGluc3RlYWQgb2YgeCA+PiAzMiwgd2UgZG8gTWF0aC5mbG9vcih4IC8gMl4zMiksIGFuZCB2aWNlIHZlcnNhLlxuICovXG5jb25zdCBCSVRTMzIgPSBNYXRoLnBvdygyLCAzMik7XG5cbi8qKlxuICogUmV0dXJuIGEgc3BlY2lhbCBEb3VibGUgdmFsdWUgdGhhdCBlbmNvZGVzIHRoZSBnaXZlbiBub25uZWdhdGl2ZSBpbnRlZ2VyXG4gKlxuICogV2UgdXNlIHRoaXMgdG8gZW5jb2RlIFRva2VuIG9yZGluYWxzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVG9rZW5Eb3VibGUoeDogbnVtYmVyKSB7XG4gIGlmIChNYXRoLmZsb29yKHgpICE9PSB4IHx8IHggPCAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gb25seSBlbmNvZGUgcG9zaXRpdmUgaW50ZWdlcnMnKTtcbiAgfVxuICBpZiAoeCA+IE1BWF9FTkNPREFCTEVfSU5URUdFUikge1xuICAgIHRocm93IG5ldyBFcnJvcihgR290IGFuIGluZGV4IHRvbyBsYXJnZSB0byBlbmNvZGU6ICR7eH1gKTtcbiAgfVxuXG4gIGNvbnN0IGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgY29uc3QgaW50cyA9IG5ldyBVaW50MzJBcnJheShidWYpO1xuXG4gIC8vIHRzbGludDpkaXNhYmxlOm5vLWJpdHdpc2VcbiAgaW50c1swXSA9ICB4ICYgMHgwMDAwRkZGRkZGRkY7IC8vIEJvdHRvbSAzMiBiaXRzIG9mIG51bWJlclxuXG4gIC8vIFRoaXMgbmVlZHMgYW4gXCJ4ID4+IDMyXCIgYnV0IHRoYXQgd2lsbCBtYWtlIGl0IGEgMzItYml0IG51bWJlciBpbnN0ZWFkXG4gIC8vIG9mIGEgNjQtYml0IG51bWJlci5cbiAgaW50c1sxXSA9IChzaHIzMih4KSAmIDB4RkZGRikgfCBET1VCTEVfVE9LRU5fTUFSS0VSX0JJVFM7IC8vIFRvcCAxNiBiaXRzIG9mIG51bWJlciBhbmQgdGhlIG1hc2tcbiAgLy8gdHNsaW50OmVuYWJsZTpuby1iaXR3aXNlXG5cbiAgcmV0dXJuIChuZXcgRmxvYXQ2NEFycmF5KGJ1ZikpWzBdO1xufVxuXG4vKipcbiAqIFNoaWZ0IGEgNjQtYml0IGludCByaWdodCAzMiBiaXRzXG4gKi9cbmZ1bmN0aW9uIHNocjMyKHg6IG51bWJlcikge1xuICByZXR1cm4gTWF0aC5mbG9vcih4IC8gQklUUzMyKTtcbn1cblxuLyoqXG4gKiBTaGlmdCBhIDY0LWJpdCBsZWZ0IDMyIGJpdHNcbiAqL1xuZnVuY3Rpb24gc2hsMzIoeDogbnVtYmVyKSB7XG4gIHJldHVybiB4ICogQklUUzMyO1xufVxuXG4vKipcbiAqIEV4dHJhY3QgdGhlIGVuY29kZWQgaW50ZWdlciBvdXQgb2YgdGhlIHNwZWNpYWwgRG91YmxlIHZhbHVlXG4gKlxuICogUmV0dXJucyB1bmRlZmluZWQgaWYgdGhlIGZsb2F0IGlzIGEgbm90IGFuIGVuY29kZWQgdG9rZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0VG9rZW5Eb3VibGUoZW5jb2RlZDogbnVtYmVyKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAobmV3IEZsb2F0NjRBcnJheShidWYpKVswXSA9IGVuY29kZWQ7XG5cbiAgY29uc3QgaW50cyA9IG5ldyBVaW50MzJBcnJheShidWYpO1xuXG4gIC8vIHRzbGludDpkaXNhYmxlOm5vLWJpdHdpc2VcbiAgaWYgKChpbnRzWzFdICYgMHhGRkZGMDAwMCkgIT09IERPVUJMRV9UT0tFTl9NQVJLRVJfQklUUykge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBNdXN0IHVzZSArIGluc3RlYWQgb2YgfCBoZXJlIChiaXR3aXNlIG9wZXJhdGlvbnNcbiAgLy8gd2lsbCBmb3JjZSAzMi1iaXRzIGludGVnZXIgYXJpdGhtZXRpYywgKyB3aWxsIG5vdCkuXG4gIHJldHVybiBpbnRzWzBdICsgc2hsMzIoaW50c1sxXSAmIDB4RkZGRik7XG4gIC8vIHRzbGludDplbmFibGU6bm8tYml0d2lzZVxufVxuIl19