UNPKG

@tai-kun/surrealdb

Version:

The SurrealDB SDK for JavaScript

693 lines (692 loc) 87.6 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/cbor/decoder.ts import { CborMaxDepthReachedError, CborSyntaxError, CborTooLittleDataError, CborUnsafeMapKeyError, SurrealValueError, unreachable } from "../errors/index.mjs"; import { utf8 } from "../utils/index.mjs"; import { getFloat16 } from "./_float.mjs"; import { ianaReviver } from "./_iana.mjs"; import { AI_EIGHT_BYTES, AI_FOUR_BYTES, AI_INDEFINITE_NUM_BYTES, AI_ONE_BYTE, AI_SIMPLE_FALSE, AI_SIMPLE_NULL, AI_SIMPLE_TRUE, AI_SIMPLE_UNDEFINED, AI_TWO_BYTES, BREAK, JS_MAX_SAFE_UNSIGNED_BIG_INTEGER, MT_ARRAY, MT_BYTE_STRING, MT_MAP, MT_NEGATIVE_INTEGER, MT_SIMPLE_FLOAT, MT_TAG, MT_UNSIGNED_INTEGER, MT_UTF8_STRING, Simple } from "./spec.mjs"; import Tagged from "./tagged.mjs"; var PARENT_ROOT = 0; var PARENT_STR = 1; var PARENT_ARR = 2; var PARENT_OBJ = 3; var PARENT_MAP = 4; var PARENT_TAG = 5; var FRAGMENT_STR = 0; var HUMANIZED_DATA_ITEM = { [MT_UNSIGNED_INTEGER]: "unsigned integer", [MT_NEGATIVE_INTEGER]: "negative integer", [MT_BYTE_STRING]: "byte string", [MT_UTF8_STRING]: "utf8 string", [MT_ARRAY]: "array", [MT_MAP]: "map", [MT_TAG]: "tagged item", [MT_SIMPLE_FLOAT]: "simple/float" }; var NONE = Symbol.for("@tai-kun/surrealdb/cbor/none"); var CONTINUE = Symbol.for("@tai-kun/surrealdb/cbor/continue"); var __Decoder = class __Decoder { constructor(options = {}) { const { mapType = "Object", reviver, maxDepth = 64, isSafeMapKey = /* @__PURE__ */ __name((k) => k !== "__proto__" && k !== "constructor", "isSafeMapKey"), isSafeObjectKey = /* @__PURE__ */ __name((k) => k !== "__proto__" && k !== "constructor", "isSafeObjectKey") } = options; this.mapType = mapType; this.maxDepth = maxDepth; this.revivers = toRevivers(reviver); this.revivers.tagged.push(compatReviver, ianaReviver); this.isSafeMapKey = isSafeMapKey; this.isSafeObjectKey = isSafeObjectKey; this.depth = 0; this.parents = [ this.parent = { $: PARENT_ROOT, put(val) { if (val === BREAK) { throw new CborSyntaxError( `The "break" stop code was encountered outside of a indefinite-length data item.` ); } this.val = val; return false; }, out() { return this.val; }, val: void 0 } ]; this.fragment = null; } putValue(value) { let done = false; while (done = this.parent.put(value)) { this.end(); value = this.parents.pop().out(); this.parent = this.parents[this.parents.length - 1]; } } begin(parent) { if (parent.$ !== PARENT_STR && ++this.depth >= this.maxDepth) { throw new CborMaxDepthReachedError(this.maxDepth); } this.parents.push(this.parent = parent); } end() { if (this.parent.$ !== PARENT_STR) { this.depth -= 1; } } process(input) { let offset = 0; const fragment = this.fragment; if (fragment !== null) { switch (fragment.$) { case FRAGMENT_STR: { const remaining = fragment.size - fragment.offset; const chunk = input.subarray(offset, offset += remaining); fragment.data.set(chunk, fragment.offset); if (chunk.length < remaining) { fragment.offset += chunk.length; return; } let value = fragment.data; if (fragment.mt === MT_UTF8_STRING) { value = utf8.decode(value); } this.putValue(value); this.fragment = null; break; } default: unreachable(fragment); } } const view = new DataView(input.buffer, input.byteOffset, input.byteLength); const viewLength = view.byteLength; while (offset < viewLength) { const ib = view.getUint8(offset++); let mt = ib >> 5; let ai = ib & 31; let value; let isSimple = false; let payloadLength = 0; switch (ai) { // # Short Data Item (24 <= ai <= 27) // +--------------+--------------------------------+---------------------------+-------------------------------------+ // | Byte count | 1 byte (CBOR data item header) | 1, 2, 4 or 8 Bytes | 0 ~ 2^64-1 Bytes | // +--------------+------------+-------------------+---------------------------+-------------------------------------+ // | Structure | Major type | Additional info | Additional info (Content) | Payload | // +--------------+------------+-------------------+---------------------------+----------+--------------------------+ // | Bit count | 3 Bits | 5 Bits | 8, 16, 32 or 64 Bits | 8 Bits | ... | // +--------------+------------+-------------------+---------------------------+----------+--------------------------+ // | Unsigned Int | 0 | 24, 25, 26, 27 | 0 ~ 2^64-1 (Value) | N/A | // +--------------+------------+-------------------+---------------------------+-------------------------------------+ // | Negative Int | 1 | 24, 25, 26, 27 | 0 ~ 2^64-1 | N/A | // +--------------+------------+-------------------+---------------------------+----------+---------+----------------+ // | Bytes / Text | 2, 3 | 24, 25, 26, 27 | count := 0 ~ 2^64-1 | bytes[0] | ... | bytes[<count>] | // +--------------+------------+-------------------+---------------------------+----------+---------+----------------+ // | Array / Map | 4, 5 | 24, 25, 26, 27 | 0 ~ 2^64-1 [items] | N/A (Subsequent data items / pairs) | // +--------------+------------+-------------------+---------------------------+-------------------------------------+ // | Tag | 6 | 24, 25, 26, 27 | 0 ~ 2^64-1 (Value) | N/A (A subsequent data item) | // +--------------+------------+-------------------+---------------------------+-------------------------------------+ // | Float | 7 | 25, 26, 27 | (IEEE 754 Float) | N/A | // +--------------+------------+-------------------+---------------------------+-------------------------------------+ case AI_ONE_BYTE: payloadLength = 1; value = view.getUint8(offset); if (mt === MT_SIMPLE_FLOAT) { if (value < 32) { throw new CborSyntaxError( "2-byte sequence followed by a byte less than 0x20 is being issued after the header 0xf8." ); } isSimple = true; } break; case AI_TWO_BYTES: payloadLength = 2; value = mt === MT_SIMPLE_FLOAT ? getFloat16(view, offset) : view.getUint16(offset); break; case AI_FOUR_BYTES: payloadLength = 4; value = mt === MT_SIMPLE_FLOAT ? view.getFloat32(offset) : view.getUint32(offset); break; case AI_EIGHT_BYTES: payloadLength = 8; if (mt === MT_SIMPLE_FLOAT) { value = view.getFloat64(offset); } else { value = view.getBigUint64(offset); if (mt === MT_NEGATIVE_INTEGER) { if (value <= JS_MAX_SAFE_UNSIGNED_BIG_INTEGER - 1n) { value = Number(value); } } else if (value <= JS_MAX_SAFE_UNSIGNED_BIG_INTEGER) { value = Number(value); } } break; // # Long Data Item (ai == 31) // +--------------+--------------------------------+--------------------------------------+ // | Byte count | 1 byte (CBOR data item header) | 0 ~ ? Bytes | // +--------------+------------+-------------------+--------------------------------------+ // | Structure | Major type | Additional info | Payload | // +--------------+------------+-------------------+----------+---------------------------+ // | Bit count | 3 Bits | 5 Bits | 8 Bits | ... | // +--------------+------------+-------------------+----------+-----+---------------------+ // | Bytes / Text | 2, 3 | 31 | bytes[0] | ... | Break (Non-payload) | // +--------------+------------+-------------------+----------+-----+---------------------+ // | Array / Map | 4, 5 | 31 | N/A (Subsequent data items / pairs) | // +--------------+------------+-------------------+--------------------------------------+ // | Break | 7 | 31 | N/A | // +--------------+------------+-------------------+--------------------------------------+ case AI_INDEFINITE_NUM_BYTES: switch (mt) { case MT_UNSIGNED_INTEGER: case MT_NEGATIVE_INTEGER: case MT_TAG: throw new CborSyntaxError( `The data item \`${HUMANIZED_DATA_ITEM[mt]}\` has indefinite-length bytes.` ); case MT_SIMPLE_FLOAT: if ((this.parent.$ === PARENT_ARR || this.parent.$ === PARENT_OBJ || this.parent.$ === PARENT_MAP) && this.parent.len !== Infinity) { throw new CborSyntaxError( `The definite-length data item \`${HUMANIZED_DATA_ITEM[mt]}\`contains the "break" stop code.` ); } value = BREAK; break; case MT_BYTE_STRING: case MT_UTF8_STRING: if (this.parent.$ === PARENT_STR && mt === this.parent.mt) { throw new CborSyntaxError( "The payload of the indefinite-length data item `" + HUMANIZED_DATA_ITEM[mt] + "` contains the same type." ); } value = Infinity; break; // case MT_ARRAY: // case MT_MAP: default: value = Infinity; } break; // # Invalid Data Item (28 <= ai <= 30) // +--------------+--------------------------------+ // | Byte count | 1 byte (CBOR data item header) | // +--------------+------------+-------------------+ // | Structure | Major type | Additional info | // +--------------+------------+-------------------+ // | Bit count | 3 Bits | 5 Bits | // +--------------+------------+-------------------+ // | N/A | 0 ~ 7 | 28 ~ 30 | // +--------------+------------+-------------------+ case 28: case 29: case 30: throw new CborSyntaxError( `The additional info ${ai} is reserved for future additions to the CBOR format.` ); // # Tiny Data Item (0 <= ai <= 23) // +--------------+--------------------------------+-------------------------------------+ // | Byte count | 1 byte (CBOR data item header) | 0 ~ 23 Bytes | // +--------------+------------+-------------------+-------------------------------------+ // | Structure | Major type | Additional info | Payload | // +--------------+------------+-------------------+----------+--------------------------+ // | Bit count | 3 Bits | 5 Bits | 8 Bits | ... | // +--------------+------------+-------------------+----------+--------------------------+ // | Unsigned Int | 0 | 0 ~ 23 (Value) | N/A | // +--------------+------------+-------------------+-------------------------------------+ // | Negative Int | 1 | 0 ~ 23 | N/A | // +--------------+------------+-------------------+----------+---------+----------------+ // | Bytes / Text | 2, 3 | count := 0 ~ 23 | bytes[0] | ... | bytes[<count>] | // +--------------+------------+-------------------+----------+---------+----------------+ // | Array / Map | 4, 5 | 0 ~ 23 [items] | N/A (Subsequent data items / pairs) | // +--------------+------------+-------------------+-------------------------------------+ // | Tag | 6 | 0 ~ 23 (Value) | N/A (A subsequent data item) | // +--------------+------------+-------------------+-------------------------------------+ // | Simple | 7 | 0 ~ 19 (Value) | N/A | // +--------------+------------+-------------------+-------------------------------------+ // | Boolean | 7 | 20, 21 | N/A | // +--------------+------------+-------------------+-------------------------------------+ // | Nullable | 7 | 22, 23 | N/A | // +--------------+------------+-------------------+-------------------------------------+ // 0 ~ 23 default: value = ai; isSimple = true; } offset += payloadLength; switch (mt) { case MT_UNSIGNED_INTEGER: break; case MT_NEGATIVE_INTEGER: value = typeof value === "number" ? -1 - value : -1n - value; break; case MT_BYTE_STRING: if (ai === AI_INDEFINITE_NUM_BYTES) { this.begin({ $: PARENT_STR, mt, put(val) { if (val === BREAK) { return true; } if (val instanceof Uint8Array) { this.acc.push(val); this.size += val.length; return false; } unreachable(val); }, out() { const data = new Uint8Array(this.size); for (let offset2 = 0, chunk; chunk = this.acc.shift(); ) { data.set(chunk, offset2); offset2 += chunk.length; } return data; }, size: 0, acc: [] }); continue; } else { payloadLength = value; value = input.subarray(offset, offset += payloadLength); if (value.length < payloadLength) { const data = new Uint8Array(payloadLength); data.set(value); this.fragment = { $: FRAGMENT_STR, mt, data, size: data.length, offset: value.length }; return; } } break; case MT_UTF8_STRING: if (ai === AI_INDEFINITE_NUM_BYTES) { this.begin({ $: PARENT_STR, mt, put(val) { if (val === BREAK) { return true; } if (typeof val === "string") { this.acc += val; return false; } unreachable(val); }, out() { return this.acc; }, acc: "" }); continue; } else { payloadLength = value; value = input.subarray(offset, offset += payloadLength); if (value.length < payloadLength) { const data = new Uint8Array(payloadLength); data.set(value); this.fragment = { $: FRAGMENT_STR, mt, data, size: data.length, offset: value.length }; return; } value = utf8.decode(value); } break; case MT_ARRAY: if (ai === AI_INDEFINITE_NUM_BYTES) { this.begin({ $: PARENT_ARR, put(val) { if (val === BREAK) { return true; } this.acc.push(val); return false; }, out() { return this.acc; }, len: Infinity, idx: NaN, acc: [] }); continue; } else if (value !== 0) { this.begin({ $: PARENT_ARR, put(val) { this.acc.push(val); return ++this.idx === this.len; }, out() { return this.acc; }, len: value, idx: 0, acc: [] }); continue; } else { value = []; } break; case MT_MAP: if (this.mapType === "Object") { if (ai === AI_INDEFINITE_NUM_BYTES) { this.begin({ $: PARENT_OBJ, put(val) { if (val === BREAK) { return true; } if (this.key === NONE) { if (typeof val !== "string" && typeof val !== "number" || !this.v8n(val, this.acc)) { throw new CborUnsafeMapKeyError(val); } this.key = val; } else { this.acc[this.key] = val; this.key = NONE; } return false; }, out() { if (this.key === NONE) { return this.acc; } throw new CborTooLittleDataError({ cause: { key: this.key } }); }, v8n: this.isSafeObjectKey, len: Infinity, idx: Infinity, key: NONE, acc: {} }); continue; } else if (value !== 0) { this.begin({ $: PARENT_OBJ, put(val) { if (this.key === NONE) { if (typeof val !== "string" && typeof val !== "number" || !this.v8n(val, this.acc)) { throw new CborUnsafeMapKeyError(val); } this.key = val; } else { this.acc[this.key] = val; this.key = NONE; this.idx += 1; } return this.idx === this.len; }, out() { if (this.key === NONE) { return this.acc; } throw new CborTooLittleDataError({ cause: { key: this.key } }); }, v8n: this.isSafeObjectKey, len: value, idx: 0, key: NONE, acc: {} }); continue; } else { value = {}; } } else if (this.mapType === "Map") { if (ai === AI_INDEFINITE_NUM_BYTES) { this.begin({ $: PARENT_MAP, put(val) { if (val === BREAK) { return true; } if (this.key === NONE) { if (!this.v8n(val, this.acc)) { throw new CborUnsafeMapKeyError(val); } this.key = val; } else { this.acc.set(this.key, val); this.key = NONE; } return false; }, out() { if (this.key === NONE) { return this.acc; } throw new CborTooLittleDataError({ cause: { key: this.key } }); }, v8n: this.isSafeMapKey, len: Infinity, idx: Infinity, key: NONE, acc: /* @__PURE__ */ new Map() }); continue; } else if (value !== 0) { this.begin({ $: PARENT_MAP, put(val) { if (this.key === NONE) { if (!this.v8n(val, this.acc)) { throw new CborUnsafeMapKeyError(val); } this.key = val; } else { this.acc.set(this.key, val); this.key = NONE; this.idx += 1; } return this.idx === this.len; }, out() { if (this.key === NONE) { return this.acc; } throw new CborTooLittleDataError({ cause: { key: this.key } }); }, v8n: this.isSafeMapKey, len: value, idx: 0, key: NONE, acc: /* @__PURE__ */ new Map() }); continue; } else { value = /* @__PURE__ */ new Map(); } } else { throw new SurrealValueError( ['"Object"', '"Object"'], this.mapType ); } break; case MT_TAG: this.begin({ $: PARENT_TAG, put(val) { this.val = val; return true; }, out() { return reviveValue(this.fns, new Tagged(this.tag, this.val)); }, fns: this.revivers.tagged, tag: value, val: void 0 }); continue; case MT_SIMPLE_FLOAT: if (isSimple) { switch (value) { case AI_SIMPLE_FALSE: value = false; break; case AI_SIMPLE_TRUE: value = true; break; case AI_SIMPLE_NULL: value = null; break; case AI_SIMPLE_UNDEFINED: value = void 0; break; default: value = reviveValue( this.revivers.simple, new Simple(value) ); } } break; default: unreachable(mt); } if (this.parent.$ === PARENT_STR && mt !== this.parent.mt && value !== BREAK) { throw new CborSyntaxError( "The payload of the data item `" + HUMANIZED_DATA_ITEM[this.parent.mt] + `\` contains a mismatched data item \`${HUMANIZED_DATA_ITEM[mt]}\`.` ); } this.putValue(value); } } output() { if (this.parent.$ !== PARENT_ROOT || this.fragment) { throw new CborTooLittleDataError({ cause: { parents: this.parents, fragment: this.fragment } }); } return this.parent.out(); } }; __name(__Decoder, "_Decoder"); var _Decoder = __Decoder; function reviveValue(revivers, value) { for (let i = 0, len = revivers.length, ret; i < len; i++) { if ((ret = revivers[i](value)) !== CONTINUE) { return ret; } } return value; } __name(reviveValue, "reviveValue"); function toRevivers(reviver) { if (!reviver) { return { tagged: [], simple: [] }; } if (typeof reviver === "function") { return { tagged: [reviver], simple: [reviver] }; } if (Array.isArray(reviver)) { const tagged = []; const simple = []; for (const r of reviver) { if (typeof r === "function") { tagged.push(r); simple.push(r); } else { r.tagged && tagged.push(r.tagged); r.simple && simple.push(r.simple); } } return { tagged, simple }; } return { tagged: reviver.tagged ? [reviver.tagged] : [], simple: reviver.simple ? [reviver.simple] : [] }; } __name(toRevivers, "toRevivers"); function compatReviver(t) { if (t.tag === 6 && t.value === null) { return; } return CONTINUE; } __name(compatReviver, "compatReviver"); export { CONTINUE, _Decoder }; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2Nib3IvZGVjb2Rlci50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHtcbiAgQ2Jvck1heERlcHRoUmVhY2hlZEVycm9yLFxuICBDYm9yU3ludGF4RXJyb3IsXG4gIENib3JUb29MaXR0bGVEYXRhRXJyb3IsXG4gIC8vIENib3JUb29NdWNoRGF0YUVycm9yLFxuICBDYm9yVW5zYWZlTWFwS2V5RXJyb3IsXG4gIFN1cnJlYWxWYWx1ZUVycm9yLFxuICB1bnJlYWNoYWJsZSxcbn0gZnJvbSBcIkB0YWkta3VuL3N1cnJlYWxkYi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgVWludDhBcnJheUxpa2UgfSBmcm9tIFwiQHRhaS1rdW4vc3VycmVhbGRiL3R5cGVzXCI7XG5pbXBvcnQgeyB1dGY4IH0gZnJvbSBcIkB0YWkta3VuL3N1cnJlYWxkYi91dGlsc1wiO1xuaW1wb3J0IHsgZ2V0RmxvYXQxNiB9IGZyb20gXCIuL19mbG9hdFwiO1xuaW1wb3J0IHsgaWFuYVJldml2ZXIgfSBmcm9tIFwiLi9faWFuYVwiO1xuaW1wb3J0IHtcbiAgdHlwZSBBZGRpdGlvbmFsSW5mbyxcbiAgQUlfRUlHSFRfQllURVMsXG4gIEFJX0ZPVVJfQllURVMsXG4gIEFJX0lOREVGSU5JVEVfTlVNX0JZVEVTLFxuICBBSV9PTkVfQllURSxcbiAgQUlfU0lNUExFX0ZBTFNFLFxuICBBSV9TSU1QTEVfTlVMTCxcbiAgQUlfU0lNUExFX1RSVUUsXG4gIEFJX1NJTVBMRV9VTkRFRklORUQsXG4gIEFJX1RXT19CWVRFUyxcbiAgQlJFQUssXG4gIEpTX01BWF9TQUZFX1VOU0lHTkVEX0JJR19JTlRFR0VSLFxuICB0eXBlIE1ham9yVHlwZSxcbiAgTVRfQVJSQVksXG4gIE1UX0JZVEVfU1RSSU5HLFxuICBNVF9NQVAsXG4gIE1UX05FR0FUSVZFX0lOVEVHRVIsXG4gIE1UX1NJTVBMRV9GTE9BVCxcbiAgTVRfVEFHLFxuICBNVF9VTlNJR05FRF9JTlRFR0VSLFxuICBNVF9VVEY4X1NUUklORyxcbiAgU2ltcGxlLFxufSBmcm9tIFwiLi9zcGVjXCI7XG5pbXBvcnQgVGFnZ2VkIGZyb20gXCIuL3RhZ2dlZFwiO1xuXG50eXBlIElucHV0VmFsdWUgPSB1bmtub3duO1xuXG5jb25zdCBQQVJFTlRfUk9PVCA9IDA7XG5jb25zdCBQQVJFTlRfU1RSID0gMTtcbmNvbnN0IFBBUkVOVF9BUlIgPSAyO1xuY29uc3QgUEFSRU5UX09CSiA9IDM7XG5jb25zdCBQQVJFTlRfTUFQID0gNDtcbmNvbnN0IFBBUkVOVF9UQUcgPSA1O1xuXG5uYW1lc3BhY2UgUGFyZW50IHtcbiAgZXhwb3J0IHR5cGUgUm9vdCA9IHtcbiAgICByZWFkb25seSAkOiB0eXBlb2YgUEFSRU5UX1JPT1Q7XG4gICAgcmVhZG9ubHkgcHV0OiAodmFsOiBJbnB1dFZhbHVlKSA9PiBmYWxzZTtcbiAgICByZWFkb25seSBvdXQ6ICgpID0+IHVua25vd247XG4gICAgdmFsOiB1bmtub3duO1xuICB9O1xuXG4gIGV4cG9ydCBuYW1lc3BhY2UgU3RyIHtcbiAgICBleHBvcnQgdHlwZSBCeXRlID0ge1xuICAgICAgcmVhZG9ubHkgJDogdHlwZW9mIFBBUkVOVF9TVFI7XG4gICAgICByZWFkb25seSBtdDogdHlwZW9mIE1UX0JZVEVfU1RSSU5HO1xuICAgICAgcmVhZG9ubHkgcHV0OiAodmFsOiBJbnB1dFZhbHVlKSA9PiBib29sZWFuO1xuICAgICAgcmVhZG9ubHkgb3V0OiAoKSA9PiBVaW50OEFycmF5O1xuICAgICAgcmVhZG9ubHkgYWNjOiBVaW50OEFycmF5W107XG4gICAgICBzaXplOiBudW1iZXI7XG4gICAgfTtcblxuICAgIGV4cG9ydCB0eXBlIFV0ZjggPSB7XG4gICAgICByZWFkb25seSAkOiB0eXBlb2YgUEFSRU5UX1NUUjtcbiAgICAgIHJlYWRvbmx5IG10OiB0eXBlb2YgTVRfVVRGOF9TVFJJTkc7XG4gICAgICByZWFkb25seSBwdXQ6ICh2YWw6IElucHV0VmFsdWUpID0+IGJvb2xlYW47XG4gICAgICByZWFkb25seSBvdXQ6ICgpID0+IHN0cmluZztcbiAgICAgIGFjYzogc3RyaW5nO1xuICAgIH07XG4gIH1cblxuICBleHBvcnQgdHlwZSBTdHIgPVxuICAgIHwgU3RyLkJ5dGVcbiAgICB8IFN0ci5VdGY4O1xuXG4gIGV4cG9ydCB0eXBlIEFyciA9IHtcbiAgICByZWFkb25seSAkOiB0eXBlb2YgUEFSRU5UX0FSUjtcbiAgICByZWFkb25seSBwdXQ6ICh2YWw6IElucHV0VmFsdWUpID0+IGJvb2xlYW47XG4gICAgcmVhZG9ubHkgb3V0OiAoKSA9PiB1bmtub3duW107XG4gICAgcmVhZG9ubHkgYWNjOiB1bmtub3duW107XG4gICAgcmVhZG9ubHkgbGVuOiBudW1iZXI7XG4gICAgaWR4OiBudW1iZXI7XG4gIH07XG5cbiAgZXhwb3J0IG5hbWVzcGFjZSBPYmoge1xuICAgIGV4cG9ydCB0eXBlIE9iaiA9IHtcbiAgICAgIHJlYWRvbmx5ICQ6IHR5cGVvZiBQQVJFTlRfT0JKO1xuICAgICAgcmVhZG9ubHkgcHV0OiAodmFsOiBJbnB1dFZhbHVlKSA9PiBib29sZWFuO1xuICAgICAgcmVhZG9ubHkgb3V0OiAoKSA9PiB7IFtwOiBzdHJpbmddOiB1bmtub3duIH07XG4gICAgICByZWFkb25seSBhY2M6IHsgW3A6IHN0cmluZ106IHVua25vd24gfTtcbiAgICAgIHJlYWRvbmx5IHY4bjogSXNTYWZlT2JqZWN0S2V5O1xuICAgICAgcmVhZG9ubHkgbGVuOiBudW1iZXI7XG4gICAgICBpZHg6IG51bWJlcjtcbiAgICAgIGtleTogc3RyaW5nIHwgbnVtYmVyIHwgdHlwZW9mIE5PTkU7XG4gICAgfTtcblxuICAgIGV4cG9ydCB0eXBlIE1hcSA9IHtcbiAgICAgIHJlYWRvbmx5ICQ6IHR5cGVvZiBQQVJFTlRfTUFQO1xuICAgICAgcmVhZG9ubHkgcHV0OiAodmFsOiBJbnB1dFZhbHVlKSA9PiBib29sZWFuO1xuICAgICAgcmVhZG9ubHkgb3V0OiAoKSA9PiBNYXA8dW5rbm93biwgdW5rbm93bj47XG4gICAgICByZWFkb25seSBhY2M6IE1hcDx1bmtub3duLCB1bmtub3duPjtcbiAgICAgIHJlYWRvbmx5IHY4bjogSXNTYWZlTWFwS2V5O1xuICAgICAgcmVhZG9ubHkgbGVuOiBudW1iZXI7XG4gICAgICBpZHg6IG51bWJlcjtcbiAgICAgIGtleTogdW5rbm93biB8IHR5cGVvZiBOT05FO1xuICAgIH07XG4gIH1cblxuICBleHBvcnQgdHlwZSBPYmogPVxuICAgIHwgT2JqLk9ialxuICAgIHwgT2JqLk1hcTtcblxuICBleHBvcnQgdHlwZSBUYWcgPSB7XG4gICAgcmVhZG9ubHkgJDogdHlwZW9mIFBBUkVOVF9UQUc7XG4gICAgcmVhZG9ubHkgcHV0OiAodmFsOiBJbnB1dFZhbHVlKSA9PiBib29sZWFuO1xuICAgIHJlYWRvbmx5IG91dDogKCkgPT4gdW5rbm93bjtcbiAgICByZWFkb25seSBmbnM6IHJlYWRvbmx5IFRhZ2dlZEl0ZW1SZXZpdmVyW107XG4gICAgcmVhZG9ubHkgdGFnOiBudW1iZXIgfCBiaWdpbnQ7XG4gICAgdmFsOiB1bmtub3duO1xuICB9O1xufVxuXG50eXBlIFBhcmVudCA9XG4gIHwgUGFyZW50LlJvb3RcbiAgfCBQYXJlbnQuU3RyXG4gIHwgUGFyZW50LkFyclxuICB8IFBhcmVudC5PYmpcbiAgfCBQYXJlbnQuVGFnO1xuXG5jb25zdCBGUkFHTUVOVF9TVFIgPSAwO1xuXG5uYW1lc3BhY2UgRnJhZ21lbnQge1xuICBleHBvcnQgdHlwZSBTdHIgPSB7XG4gICAgcmVhZG9ubHkgJDogdHlwZW9mIEZSQUdNRU5UX1NUUjtcbiAgICByZWFkb25seSBtdDogdHlwZW9mIE1UX0JZVEVfU1RSSU5HIHwgdHlwZW9mIE1UX1VURjhfU1RSSU5HO1xuICAgIHJlYWRvbmx5IGRhdGE6IFVpbnQ4QXJyYXk7XG4gICAgcmVhZG9ubHkgc2l6ZTogbnVtYmVyO1xuICAgIG9mZnNldDogbnVtYmVyO1xuICB9O1xufVxuXG50eXBlIEZyYWdtZW50ID1cbiAgfCBGcmFnbWVudC5TdHJcbiAgfCBuZXZlcjsgLy8gXHUzMDUzXHUzMDUzXHUzMDZCXHU4RkZEXHU1MkEwXG5cbmNvbnN0IEhVTUFOSVpFRF9EQVRBX0lURU0gPSB7XG4gIFtNVF9VTlNJR05FRF9JTlRFR0VSXTogXCJ1bnNpZ25lZCBpbnRlZ2VyXCIsXG4gIFtNVF9ORUdBVElWRV9JTlRFR0VSXTogXCJuZWdhdGl2ZSBpbnRlZ2VyXCIsXG4gIFtNVF9CWVRFX1NUUklOR106IFwiYnl0ZSBzdHJpbmdcIixcbiAgW01UX1VURjhfU1RSSU5HXTogXCJ1dGY4IHN0cmluZ1wiLFxuICBbTVRfQVJSQVldOiBcImFycmF5XCIsXG4gIFtNVF9NQVBdOiBcIm1hcFwiLFxuICBbTVRfVEFHXTogXCJ0YWdnZWQgaXRlbVwiLFxuICBbTVRfU0lNUExFX0ZMT0FUXTogXCJzaW1wbGUvZmxvYXRcIixcbn07XG5cbmNvbnN0IE5PTkUgPSBTeW1ib2wuZm9yKFwiQHRhaS1rdW4vc3VycmVhbGRiL2Nib3Ivbm9uZVwiKTtcblxuZXhwb3J0IGNvbnN0IENPTlRJTlVFID0gU3ltYm9sLmZvcihcIkB0YWkta3VuL3N1cnJlYWxkYi9jYm9yL2NvbnRpbnVlXCIpO1xuXG5leHBvcnQgdHlwZSBUYWdnZWRJdGVtUmV2aXZlciA9ICh0YWdnZWQ6IFRhZ2dlZCkgPT4gdW5rbm93biB8IHR5cGVvZiBDT05USU5VRTtcblxuZXhwb3J0IHR5cGUgU2ltcGxlSXRlbVJldml2ZXIgPSAoc2ltcGxlOiBTaW1wbGUpID0+IHVua25vd24gfCB0eXBlb2YgQ09OVElOVUU7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmV2aXZlck9iamVjdCB7XG4gIHJlYWRvbmx5IHRhZ2dlZD86IFRhZ2dlZEl0ZW1SZXZpdmVyIHwgdW5kZWZpbmVkO1xuICByZWFkb25seSBzaW1wbGU/OiBTaW1wbGVJdGVtUmV2aXZlciB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgUmV2aXZlciA9ICh2YWx1ZTogVGFnZ2VkIHwgU2ltcGxlKSA9PiB1bmtub3duIHwgdHlwZW9mIENPTlRJTlVFO1xuXG5leHBvcnQgdHlwZSBJc1NhZmVNYXBLZXkgPSAoXG4gIGtleTogdW5rbm93bixcbiAgbWFwOiBNYXA8dW5rbm93biwgdW5rbm93bj4sXG4pID0+IGJvb2xlYW47XG5cbmV4cG9ydCB0eXBlIElzU2FmZU9iamVjdEtleSA9IChcbiAga2V5OiBzdHJpbmcgfCBudW1iZXIsXG4gIG9iajogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4pID0+IGJvb2xlYW47XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVjb2Rlck9wdGlvbnMge1xuICByZWFkb25seSBpc1NhZmVNYXBLZXk/OiBJc1NhZmVNYXBLZXkgfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IGlzU2FmZU9iamVjdEtleT86IElzU2FmZU9iamVjdEtleSB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgbWFwVHlwZT86IFwiT2JqZWN0XCIgfCBcIk1hcFwiIHwgdW5kZWZpbmVkO1xuICByZWFkb25seSBtYXhEZXB0aD86IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgcmV2aXZlcj86XG4gICAgfCBSZXZpdmVyXG4gICAgfCBSZXZpdmVyT2JqZWN0XG4gICAgfCByZWFkb25seSAoUmV2aXZlciB8IFJldml2ZXJPYmplY3QpW11cbiAgICB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGNsYXNzIF9EZWNvZGVyIHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IG1hcFR5cGU6IFwiT2JqZWN0XCIgfCBcIk1hcFwiO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgbWF4RGVwdGg6IG51bWJlcjtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJldml2ZXJzOiB7XG4gICAgdGFnZ2VkOiBUYWdnZWRJdGVtUmV2aXZlcltdO1xuICAgIHNpbXBsZTogU2ltcGxlSXRlbVJldml2ZXJbXTtcbiAgfTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlzU2FmZU1hcEtleTogKFxuICAgIGtleTogdW5rbm93bixcbiAgICBtYXA6IE1hcDx1bmtub3duLCB1bmtub3duPixcbiAgKSA9PiBib29sZWFuO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNTYWZlT2JqZWN0S2V5OiAoXG4gICAga2V5OiBzdHJpbmcgfCBudW1iZXIsXG4gICAgb2JqOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgKSA9PiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IERlY29kZXJPcHRpb25zIHwgdW5kZWZpbmVkID0ge30pIHtcbiAgICBjb25zdCB7XG4gICAgICBtYXBUeXBlID0gXCJPYmplY3RcIixcbiAgICAgIHJldml2ZXIsXG4gICAgICBtYXhEZXB0aCA9IDY0LFxuICAgICAgaXNTYWZlTWFwS2V5ID0gayA9PiBrICE9PSBcIl9fcHJvdG9fX1wiICYmIGsgIT09IFwiY29uc3RydWN0b3JcIixcbiAgICAgIGlzU2FmZU9iamVjdEtleSA9IGsgPT4gayAhPT0gXCJfX3Byb3RvX19cIiAmJiBrICE9PSBcImNvbnN0cnVjdG9yXCIsXG4gICAgfSA9IG9wdGlvbnM7XG4gICAgdGhpcy5tYXBUeXBlID0gbWFwVHlwZTtcbiAgICB0aGlzLm1heERlcHRoID0gbWF4RGVwdGg7XG4gICAgdGhpcy5yZXZpdmVycyA9IHRvUmV2aXZlcnMocmV2aXZlcik7XG4gICAgdGhpcy5yZXZpdmVycy50YWdnZWQucHVzaChjb21wYXRSZXZpdmVyLCBpYW5hUmV2aXZlcik7XG4gICAgdGhpcy5pc1NhZmVNYXBLZXkgPSBpc1NhZmVNYXBLZXk7XG4gICAgdGhpcy5pc1NhZmVPYmplY3RLZXkgPSBpc1NhZmVPYmplY3RLZXk7XG5cbiAgICB0aGlzLmRlcHRoID0gMDtcbiAgICB0aGlzLnBhcmVudHMgPSBbXG4gICAgICB0aGlzLnBhcmVudCA9IHtcbiAgICAgICAgJDogUEFSRU5UX1JPT1QsXG4gICAgICAgIHB1dCh2YWwpIHtcbiAgICAgICAgICBpZiAodmFsID09PSBCUkVBSykge1xuICAgICAgICAgICAgLy8gaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzg5NDkuaHRtbCNzZWN0aW9uLWFwcGVuZGl4LmYtNC40XG4gICAgICAgICAgICB0aHJvdyBuZXcgQ2JvclN5bnRheEVycm9yKFxuICAgICAgICAgICAgICBgVGhlIFwiYnJlYWtcIiBzdG9wIGNvZGUgd2FzIGVuY291bnRlcmVkIG91dHNpZGUgb2YgYFxuICAgICAgICAgICAgICAgICsgXCJhIGluZGVmaW5pdGUtbGVuZ3RoIGRhdGEgaXRlbS5cIixcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy52YWwgPSB2YWw7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgICBvdXQoKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMudmFsO1xuICAgICAgICB9LFxuICAgICAgICB2YWw6IHVuZGVmaW5lZCxcbiAgICAgIH0sXG4gICAgXTtcbiAgICB0aGlzLmZyYWdtZW50ID0gbnVsbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBkZXB0aDogbnVtYmVyO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcGFyZW50czogW1BhcmVudC5Sb290LCAuLi5FeGNsdWRlPFBhcmVudCwgUGFyZW50LlJvb3Q+W11dO1xuICBwcm90ZWN0ZWQgcGFyZW50OiBQYXJlbnQ7XG4gIHByb3RlY3RlZCBmcmFnbWVudDogRnJhZ21lbnQgfCBudWxsO1xuXG4gIHByb3RlY3RlZCBwdXRWYWx1ZSh2YWx1ZTogSW5wdXRWYWx1ZSk6IHZvaWQge1xuICAgIC8vIEB0cy1pZ25vcmUgKFRTNjEzMyk6IFx1NEY1NVx1NjU0NVx1MzA0Qlx1MzBBOFx1MzBFOVx1MzBGQ1x1MzA2Qlx1MzA2QVx1MzA4QlxuICAgIGxldCBkb25lID0gZmFsc2U7XG5cbiAgICB3aGlsZSAoKGRvbmUgPSB0aGlzLnBhcmVudC5wdXQodmFsdWUpKSkge1xuICAgICAgdGhpcy5lbmQoKTtcbiAgICAgIHZhbHVlID0gdGhpcy5wYXJlbnRzLnBvcCgpIS5vdXQoKTtcbiAgICAgIHRoaXMucGFyZW50ID0gdGhpcy5wYXJlbnRzW3RoaXMucGFyZW50cy5sZW5ndGggLSAxXSE7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGJlZ2luKHBhcmVudDogRXhjbHVkZTxQYXJlbnQsIFBhcmVudC5Sb290Pik6IHZvaWQge1xuICAgIGlmIChwYXJlbnQuJCAhPT0gUEFSRU5UX1NUUiAmJiArK3RoaXMuZGVwdGggPj0gdGhpcy5tYXhEZXB0aCkge1xuICAgICAgdGhyb3cgbmV3IENib3JNYXhEZXB0aFJlYWNoZWRFcnJvcih0aGlzLm1heERlcHRoKTtcbiAgICB9XG5cbiAgICB0aGlzLnBhcmVudHMucHVzaCh0aGlzLnBhcmVudCA9IHBhcmVudCk7XG4gIH1cblxuICBwcml2YXRlIGVuZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5wYXJlbnQuJCAhPT0gUEFSRU5UX1NUUikge1xuICAgICAgdGhpcy5kZXB0aCAtPSAxO1xuICAgIH1cbiAgfVxuXG4gIHByb2Nlc3MoaW5wdXQ6IFVpbnQ4QXJyYXlMaWtlKTogdm9pZCB7XG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgY29uc3QgZnJhZ21lbnQgPSB0aGlzLmZyYWdtZW50O1xuXG4gICAgaWYgKGZyYWdtZW50ICE9PSBudWxsKSB7XG4gICAgICBzd2l0Y2ggKGZyYWdtZW50LiQpIHtcbiAgICAgICAgY2FzZSBGUkFHTUVOVF9TVFI6IHtcbiAgICAgICAgICBjb25zdCByZW1haW5pbmcgPSBmcmFnbWVudC5zaXplIC0gZnJhZ21lbnQub2Zmc2V0O1xuICAgICAgICAgIGNvbnN0IGNodW5rID0gaW5wdXQuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKz0gcmVtYWluaW5nKTtcbiAgICAgICAgICBmcmFnbWVudC5kYXRhLnNldChjaHVuaywgZnJhZ21lbnQub2Zmc2V0KTtcblxuICAgICAgICAgIGlmIChjaHVuay5sZW5ndGggPCByZW1haW5pbmcpIHtcbiAgICAgICAgICAgIGZyYWdtZW50Lm9mZnNldCArPSBjaHVuay5sZW5ndGg7XG4gICAgICAgICAgICByZXR1cm47IC8vIGlucHV0IFx1MzA2RVx1NjcwMFx1NUY4Q1x1MzA2Qlx1NTIzMFx1OTA1NFx1MzA1N1x1MzA2Nlx1MzA0NFx1MzA4Qlx1MzA2RVx1MzA2N1x1NjVFOVx1NjcxRlx1MzBFQVx1MzBCRlx1MzBGQ1x1MzBGM1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGxldCB2YWx1ZTogc3RyaW5nIHwgVWludDhBcnJheUxpa2UgPSBmcmFnbWVudC5kYXRhO1xuXG4gICAgICAgICAgaWYgKGZyYWdtZW50Lm10ID09PSBNVF9VVEY4X1NUUklORykge1xuICAgICAgICAgICAgdmFsdWUgPSB1dGY4LmRlY29kZSh2YWx1ZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5wdXRWYWx1ZSh2YWx1ZSk7XG4gICAgICAgICAgdGhpcy5mcmFnbWVudCA9IG51bGw7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHVucmVhY2hhYmxlKGZyYWdtZW50IGFzIG5ldmVyKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KGlucHV0LmJ1ZmZlciwgaW5wdXQuYnl0ZU9mZnNldCwgaW5wdXQuYnl0ZUxlbmd0aCk7XG4gICAgY29uc3Qgdmlld0xlbmd0aCA9IHZpZXcuYnl0ZUxlbmd0aDtcblxuICAgIHdoaWxlIChvZmZzZXQgPCB2aWV3TGVuZ3RoKSB7XG4gICAgICBjb25zdCBpYiA9IHZpZXcuZ2V0VWludDgob2Zmc2V0KyspO1xuICAgICAgbGV0IG10ID0gKGliID4+IDUpIGFzIE1ham9yVHlwZTtcbiAgICAgIGxldCBhaSA9IChpYiAmIDB4MWYpIGFzIEFkZGl0aW9uYWxJbmZvO1xuICAgICAgbGV0IHZhbHVlO1xuICAgICAgbGV0IGlzU2ltcGxlID0gZmFsc2U7IC8vIE5vdCBhIGZsb2F0XG4gICAgICBsZXQgcGF5bG9hZExlbmd0aCA9IDA7XG5cbiAgICAgIHN3aXRjaCAoYWkpIHtcbiAgICAgICAgLy8gIyBTaG9ydCBEYXRhIEl0ZW0gKDI0IDw9IGFpIDw9IDI3KVxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXG4gICAgICAgIC8vIHwgQnl0ZSBjb3VudCAgIHwgMSBieXRlIChDQk9SIGRhdGEgaXRlbSBoZWFkZXIpIHwgICAgMSwgMiwgNCBvciA4IEJ5dGVzICAgICB8ICAgICAgICAgIDAgfiAyXjY0LTEgQnl0ZXMgICAgICAgICAgIHxcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tK1xuICAgICAgICAvLyB8IFN0cnVjdHVyZSAgICB8IE1ham9yIHR5cGUgfCAgQWRkaXRpb25hbCBpbmZvICB8IEFkZGl0aW9uYWwgaW5mbyAoQ29udGVudCkgfCAgICAgICAgICAgICAgICBQYXlsb2FkICAgICAgICAgICAgICB8XG4gICAgICAgIC8vICstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBCaXQgY291bnQgICAgfCAgIDMgQml0cyAgIHwgICAgICA1IEJpdHMgICAgICAgfCAgIDgsIDE2LCAzMiBvciA2NCBCaXRzICAgIHwgIDggQml0cyAgfCAgICAgICAgICAgLi4uICAgICAgICAgICAgfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXG4gICAgICAgIC8vIHwgVW5zaWduZWQgSW50IHwgICAgIDAgICAgICB8ICAyNCwgMjUsIDI2LCAyNyAgIHwgICAgIDAgfiAyXjY0LTEgKFZhbHVlKSAgICB8ICAgICAgICAgICAgICAgICBOL0EgICAgICAgICAgICAgICAgIHxcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tK1xuICAgICAgICAvLyB8IE5lZ2F0aXZlIEludCB8ICAgICAxICAgICAgfCAgMjQsIDI1LCAyNiwgMjcgICB8ICAgICAgICAgMCB+IDJeNjQtMSAgICAgICAgfCAgICAgICAgICAgICAgICAgTi9BICAgICAgICAgICAgICAgICB8XG4gICAgICAgIC8vICstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLSstLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBCeXRlcyAvIFRleHQgfCAgICAyLCAzICAgIHwgIDI0LCAyNSwgMjYsIDI3ICAgfCAgIGNvdW50IDo9IDAgfiAyXjY0LTEgICAgIHwgYnl0ZXNbMF0gfCAgIC4uLiAgIHwgYnl0ZXNbPGNvdW50Pl0gfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0rLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rXG4gICAgICAgIC8vIHwgQXJyYXkgLyBNYXAgIHwgICAgNCwgNSAgICB8ICAyNCwgMjUsIDI2LCAyNyAgIHwgICAgMCB+IDJeNjQtMSBbaXRlbXNdICAgICB8IE4vQSAoU3Vic2VxdWVudCBkYXRhIGl0ZW1zIC8gcGFpcnMpIHxcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tK1xuICAgICAgICAvLyB8IFRhZyAgICAgICAgICB8ICAgICA2ICAgICAgfCAgMjQsIDI1LCAyNiwgMjcgICB8ICAgIDAgfiAyXjY0LTEgKFZhbHVlKSAgICAgfCAgICAgTi9BIChBIHN1YnNlcXVlbnQgZGF0YSBpdGVtKSAgICB8XG4gICAgICAgIC8vICstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBGbG9hdCAgICAgICAgfCAgICAgNyAgICAgIHwgICAgMjUsIDI2LCAyNyAgICAgfCAgICAgKElFRUUgNzU0IEZsb2F0KSAgICAgIHwgICAgICAgICAgICAgICAgIE4vQSAgICAgICAgICAgICAgICAgfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXG5cbiAgICAgICAgY2FzZSBBSV9PTkVfQllURTogLy8gMjRcbiAgICAgICAgICBwYXlsb2FkTGVuZ3RoID0gMTtcbiAgICAgICAgICB2YWx1ZSA9IHZpZXcuZ2V0VWludDgob2Zmc2V0KTtcblxuICAgICAgICAgIGlmIChtdCA9PT0gTVRfU0lNUExFX0ZMT0FUKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgPCAweDIwKSB7XG4gICAgICAgICAgICAgIC8vIFx1MzBBOFx1MzBGM1x1MzBCM1x1MzBGQ1x1MzBDMFx1MzBGQ1x1MzA2Rlx1MzAwMTB4ZjggKE1ham9yIFR5cGU6IDcsIEFkZGl0aW9uYWwgSW5mbzogMjQpIFx1MzA2N1x1NTlDQlx1MzA3RVx1MzA4QVx1MzAwMVxuICAgICAgICAgICAgICAvLyAweDIwIFx1NjcyQVx1NkU4MFx1MzA2RVx1MzBEMFx1MzBBNFx1MzBDOFx1MzA2N1x1N0Q5QVx1MzA0RiAyIFx1MzBEMFx1MzBBNFx1MzBDOFx1MzBCN1x1MzBGQ1x1MzBCMVx1MzBGM1x1MzBCOVx1MzA5Mlx1NzY3QVx1ODg0Q1x1MzA1N1x1MzA2Nlx1MzA2Rlx1MzA2QVx1MzA4OVx1MzA2QVx1MzA0NFx1MzAwMlxuICAgICAgICAgICAgICAvLyBodHRwczovL3d3dy5yZmMtZWRpdG9yLm9yZy9yZmMvcmZjODk0OS5odG1sI3NlY3Rpb24tMy4zLTVcbiAgICAgICAgICAgICAgLy8gaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzg5NDkuaHRtbCNzZWN0aW9uLWFwcGVuZGl4LmYtNC4yXG4gICAgICAgICAgICAgIHRocm93IG5ldyBDYm9yU3ludGF4RXJyb3IoXG4gICAgICAgICAgICAgICAgXCIyLWJ5dGUgc2VxdWVuY2UgZm9sbG93ZWQgYnkgYSBieXRlIGxlc3MgdGhhbiAweDIwIGlzIGJlaW5nXCJcbiAgICAgICAgICAgICAgICAgICsgXCIgaXNzdWVkIGFmdGVyIHRoZSBoZWFkZXIgMHhmOC5cIixcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaXNTaW1wbGUgPSB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgQUlfVFdPX0JZVEVTOiAvLyAyNVxuICAgICAgICAgIHBheWxvYWRMZW5ndGggPSAyO1xuICAgICAgICAgIHZhbHVlID0gbXQgPT09IE1UX1NJTVBMRV9GTE9BVFxuICAgICAgICAgICAgPyBnZXRGbG9hdDE2KHZpZXcsIG9mZnNldClcbiAgICAgICAgICAgIDogdmlldy5nZXRVaW50MTYob2Zmc2V0KTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIEFJX0ZPVVJfQllURVM6IC8vIDI2XG4gICAgICAgICAgcGF5bG9hZExlbmd0aCA9IDQ7XG4gICAgICAgICAgdmFsdWUgPSBtdCA9PT0gTVRfU0lNUExFX0ZMT0FUXG4gICAgICAgICAgICA/IHZpZXcuZ2V0RmxvYXQzMihvZmZzZXQpXG4gICAgICAgICAgICA6IHZpZXcuZ2V0VWludDMyKG9mZnNldCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBBSV9FSUdIVF9CWVRFUzogLy8gMjdcbiAgICAgICAgICBwYXlsb2FkTGVuZ3RoID0gODtcblxuICAgICAgICAgIGlmIChtdCA9PT0gTVRfU0lNUExFX0ZMT0FUKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZpZXcuZ2V0RmxvYXQ2NChvZmZzZXQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZpZXcuZ2V0QmlnVWludDY0KG9mZnNldCk7XG5cbiAgICAgICAgICAgIGlmIChtdCA9PT0gTVRfTkVHQVRJVkVfSU5URUdFUikge1xuICAgICAgICAgICAgICAvLyBcdThDQTBcdTMwNkVcdTUwMjRcdTMwNkYgLTEgXHUzMDRCXHUzMDg5IHZhbHVlIFx1MzA5Mlx1NUYxNVx1MzA0NFx1MzA1Rlx1NjU3MFx1MzA2QVx1MzA2RVx1MzA2N1x1MzAwMVx1NjcwMFx1NTkyN1x1NTAyNFx1MzA4OFx1MzA4QSAxIFx1NEVFNVx1NEUwQVx1NUMwRlx1MzA1NVx1MzA0Rlx1MzA2QVx1MzA0NFx1MzA2OFxuICAgICAgICAgICAgICAvLyBOdW1iZXIgXHUzMDZCXHUzMDZGXHUzMDZBXHUzMDhDXHUzMDZBXHUzMDQ0XHUzMDAyXG4gICAgICAgICAgICAgIGlmICh2YWx1ZSA8PSBKU19NQVhfU0FGRV9VTlNJR05FRF9CSUdfSU5URUdFUiAtIDFuKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBOdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlIDw9IEpTX01BWF9TQUZFX1VOU0lHTkVEX0JJR19JTlRFR0VSKSB7XG4gICAgICAgICAgICAgIHZhbHVlID0gTnVtYmVyKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBicmVhaztcblxuICAgICAgICAvLyAjIExvbmcgRGF0YSBJdGVtIChhaSA9PSAzMSlcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tK1xuICAgICAgICAvLyB8IEJ5dGUgY291bnQgICB8IDEgYnl0ZSAoQ0JPUiBkYXRhIGl0ZW0gaGVhZGVyKSB8ICAgICAgICAgICAgICAwIH4gPyBCeXRlcyAgICAgICAgICAgICB8XG4gICAgICAgIC8vICstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBTdHJ1Y3R1cmUgICAgfCBNYWpvciB0eXBlIHwgIEFkZGl0aW9uYWwgaW5mbyAgfCAgICAgICAgICAgICAgICBQYXlsb2FkICAgICAgICAgICAgICAgfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXG4gICAgICAgIC8vIHwgQml0IGNvdW50ICAgIHwgICAzIEJpdHMgICB8ICAgICAgNSBCaXRzICAgICAgIHwgIDggQml0cyAgfCAgICAgICAgICAgIC4uLiAgICAgICAgICAgIHxcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0rLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tK1xuICAgICAgICAvLyB8IEJ5dGVzIC8gVGV4dCB8ICAgIDIsIDMgICAgfCAgICAgICAgMzEgICAgICAgICB8IGJ5dGVzWzBdIHwgLi4uIHwgQnJlYWsgKE5vbi1wYXlsb2FkKSB8XG4gICAgICAgIC8vICstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tKy0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBBcnJheSAvIE1hcCAgfCAgICA0LCA1ICAgIHwgICAgICAgIDMxICAgICAgICAgfCBOL0EgKFN1YnNlcXVlbnQgZGF0YSBpdGVtcyAvIHBhaXJzKSAgfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXG4gICAgICAgIC8vIHwgQnJlYWsgICAgICAgIHwgICAgIDcgICAgICB8ICAgICAgICAzMSAgICAgICAgIHwgICAgICAgICAgICAgICAgICBOL0EgICAgICAgICAgICAgICAgIHxcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tK1xuXG4gICAgICAgIGNhc2UgQUlfSU5ERUZJTklURV9OVU1fQllURVM6IC8vIDMxXG4gICAgICAgICAgc3dpdGNoIChtdCkge1xuICAgICAgICAgICAgY2FzZSBNVF9VTlNJR05FRF9JTlRFR0VSOlxuICAgICAgICAgICAgY2FzZSBNVF9ORUdBVElWRV9JTlRFR0VSOlxuICAgICAgICAgICAgY2FzZSBNVF9UQUc6XG4gICAgICAgICAgICAgIC8vIGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL3JmYy9yZmM4OTQ5Lmh0bWwjc2VjdGlvbi1hcHBlbmRpeC5mLTQuNVxuICAgICAgICAgICAgICB0aHJvdyBuZXcgQ2JvclN5bnRheEVycm9yKFxuICAgICAgICAgICAgICAgIGBUaGUgZGF0YSBpdGVtIFxcYCR7SFVNQU5JWkVEX0RBVEFfSVRFTVttdF19XFxgIGhhcyBgXG4gICAgICAgICAgICAgICAgICArIFwiaW5kZWZpbml0ZS1sZW5ndGggYnl0ZXMuXCIsXG4gICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGNhc2UgTVRfU0lNUExFX0ZMT0FUOlxuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgKHRoaXMucGFyZW50LiQgPT09IFBBUkVOVF9BUlJcbiAgICAgICAgICAgICAgICAgIHx8IHRoaXMucGFyZW50LiQgPT09IFBBUkVOVF9PQkpcbiAgICAgICAgICAgICAgICAgIHx8IHRoaXMucGFyZW50LiQgPT09IFBBUkVOVF9NQVApXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5wYXJlbnQubGVuICE9PSBJbmZpbml0eVxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQ2JvclN5bnRheEVycm9yKFxuICAgICAgICAgICAgICAgICAgYFRoZSBkZWZpbml0ZS1sZW5ndGggZGF0YSBpdGVtIFxcYCR7SFVNQU5JWkVEX0RBVEFfSVRFTVttdF19XFxgYFxuICAgICAgICAgICAgICAgICAgICArIGBjb250YWlucyB0aGUgXCJicmVha1wiIHN0b3AgY29kZS5gLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICB2YWx1ZSA9IEJSRUFLO1xuICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSBNVF9CWVRFX1NUUklORzpcbiAgICAgICAgICAgIGNhc2UgTVRfVVRGOF9TVFJJTkc6XG4gICAgICAgICAgICAgIGlmICh0aGlzLnBhcmVudC4kID09PSBQQVJFTlRfU1RSICYmIG10ID09PSB0aGlzLnBhcmVudC5tdCkge1xuICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL3JmYy9yZmM4OTQ5Lmh0bWwjc2VjdGlvbi1hcHBlbmRpeC5mLTQuM1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBDYm9yU3ludGF4RXJyb3IoXG4gICAgICAgICAgICAgICAgICBcIlRoZSBwYXlsb2FkIG9mIHRoZSBpbmRlZmluaXRlLWxlbmd0aCBkYXRhIGl0ZW0gYFwiXG4gICAgICAgICAgICAgICAgICAgICsgSFVNQU5JWkVEX0RBVEFfSVRFTVttdF0gKyBcImAgY29udGFpbnMgdGhlIHNhbWUgdHlwZS5cIixcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdmFsdWUgPSBJbmZpbml0eTtcbiAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIC8vIGNhc2UgTVRfQVJSQVk6XG4gICAgICAgICAgICAvLyBjYXNlIE1UX01BUDpcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHZhbHVlID0gSW5maW5pdHk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgLy8gIyBJbnZhbGlkIERhdGEgSXRlbSAoMjggPD0gYWkgPD0gMzApXG4gICAgICAgIC8vICstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBCeXRlIGNvdW50ICAgfCAxIGJ5dGUgKENCT1IgZGF0YSBpdGVtIGhlYWRlcikgfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rXG4gICAgICAgIC8vIHwgU3RydWN0dXJlICAgIHwgTWFqb3IgdHlwZSB8ICBBZGRpdGlvbmFsIGluZm8gIHxcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tK1xuICAgICAgICAvLyB8IEJpdCBjb3VudCAgICB8ICAgMyBCaXRzICAgfCAgICAgIDUgQml0cyAgICAgICB8XG4gICAgICAgIC8vICstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBOL0EgICAgICAgICAgfCAgIDAgfiA3ICAgIHwgICAgICAyOCB+IDMwICAgICAgfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rXG5cbiAgICAgICAgY2FzZSAyODpcbiAgICAgICAgY2FzZSAyOTpcbiAgICAgICAgY2FzZSAzMDpcbiAgICAgICAgICAvLyBodHRwczovL3d3dy5yZmMtZWRpdG9yLm9yZy9yZmMvcmZjODk0OS5odG1sI3NlY3Rpb24tMy0zLjZcbiAgICAgICAgICB0aHJvdyBuZXcgQ2JvclN5bnRheEVycm9yKFxuICAgICAgICAgICAgYFRoZSBhZGRpdGlvbmFsIGluZm8gJHthaX0gaXMgcmVzZXJ2ZWQgZm9yIGZ1dHVyZSBhZGRpdGlvbnMgdG8gdGhlIGBcbiAgICAgICAgICAgICAgKyBcIkNCT1IgZm9ybWF0LlwiLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgLy8gIyBUaW55IERhdGEgSXRlbSAoMCA8PSBhaSA8PSAyMylcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXG4gICAgICAgIC8vIHwgQnl0ZSBjb3VudCAgIHwgMSBieXRlIChDQk9SIGRhdGEgaXRlbSBoZWFkZXIpIHwgICAgICAgICAgICAgMCB+IDIzIEJ5dGVzICAgICAgICAgICAgfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBTdHJ1Y3R1cmUgICAgfCBNYWpvciB0eXBlIHwgIEFkZGl0aW9uYWwgaW5mbyAgfCAgICAgICAgICAgICAgIFBheWxvYWQgICAgICAgICAgICAgICB8XG4gICAgICAgIC8vICstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tK1xuICAgICAgICAvLyB8IEJpdCBjb3VudCAgICB8ICAgMyBCaXRzICAgfCAgICAgIDUgQml0cyAgICAgICB8ICA4IEJpdHMgIHwgICAgICAgICAgIC4uLiAgICAgICAgICAgIHxcbiAgICAgICAgLy8gKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rXG4gICAgICAgIC8vIHwgVW5zaWduZWQgSW50IHwgICAgIDAgICAgICB8ICAgMCB+IDIzIChWYWx1ZSkgIHwgICAgICAgICAgICAgICAgIE4vQSAgICAgICAgICAgICAgICAgfFxuICAgICAgICAvLyArLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLStcbiAgICAgICAgLy8gfCBOZWdhdGl2ZSBJbnQgfCAgICAgMSAgICAgIHwgICAgICAwIH4gMj