UNPKG

@selfage/message

Version:

Runtime lib for generated messages to parse, copy, serialize and deserialize messages.

222 lines 29.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.initBuffer = initBuffer; exports.toBufferFromValue = toBufferFromValue; exports.toBufferFromMessage = toBufferFromMessage; exports.serializeMessage = serializeMessage; exports.toEnumFromNumber = toEnumFromNumber; exports.toValueFromBinary = toValueFromBinary; exports.toMessageFromBinary = toMessageFromBinary; exports.deserializeMessage = deserializeMessage; const descriptor_1 = require("./descriptor"); // Binary format example. // From {1: 1, 2: true, 3: {}, 4: {1: 1}, 5: "a", 6: [1]} // To <6 (Uint32 for number of fields)><1 (Uint32 for index)><1 (Float64 for number value)><2 (Uint32 for index)><1 (Uint8 for boolean value)><3 (Uint32 for index)><0 (Uint32 for byte size)><4 (Uint32 for index)><12 (Uint32 for byte size)><1 (Uint32 for index)><1 (Float64 for number value)><5 (Uint32 for index)><1 (Uint32 for byte length)><97 (Uint8 for UTF8 encoding)><6 (Uint32 for index)><1 (Uint32 for array size)><1 (Float64 for number value)> // // Requirements: // 1. Index, enum value, and array length must be < 2^32. // 2. Number of fields, and string byte length must be < 2^32 - 1 (NOTE!). // 3. Field index and enum value must be > 0. // // Handling `undefined` and `null`: // 1. If a field is undefined/null, it's ignored when serialized. // 2. If an element of an array is undefined/null, it will be kept as undefined in the array. // // Maximum byte size by default is 16MB, but can be changed globally using `initBuffer(maxBytes: number)`. let UINT32_VALUE_FOR_UNDEFINED = 4294967295; let BOOLEAN_VALUE_FOR_UNDEFINED = 2; let RESERVED_UINT8_ARRAY; let DATA_VIEW_OF_RESERVED_ARRAY; let TEXT_ENCODER = new TextEncoder(); let TEXT_DECODER = new TextDecoder(); function initBuffer(maxBytes = 1024 * 1024 * 16) { RESERVED_UINT8_ARRAY = new Uint8Array(maxBytes); DATA_VIEW_OF_RESERVED_ARRAY = new DataView(RESERVED_UINT8_ARRAY.buffer); } initBuffer(); function toBufferFromValue(value, field, uint8Array, dataView, byteOffset) { if (field.primitiveType) { switch (field.primitiveType) { case descriptor_1.PrimitiveType.NUMBER: if (value == null) { dataView.setFloat64(byteOffset, NaN, true); } else { dataView.setFloat64(byteOffset, value, true); } byteOffset += 8; break; case descriptor_1.PrimitiveType.BOOLEAN: if (value == null) { dataView.setUint8(byteOffset, BOOLEAN_VALUE_FOR_UNDEFINED); } else { dataView.setUint8(byteOffset, value); } byteOffset += 1; break; case descriptor_1.PrimitiveType.STRING: if (value == null) { dataView.setUint32(byteOffset, UINT32_VALUE_FOR_UNDEFINED, true); byteOffset += 4; } else { let res = TEXT_ENCODER.encodeInto(value, uint8Array.subarray(byteOffset + 4)); dataView.setUint32(byteOffset, res.written, true); byteOffset += 4 + res.written; } break; } } else if (field.enumType) { if (value == null) { dataView.setUint32(byteOffset, 0, true); } else { dataView.setUint32(byteOffset, value, true); } byteOffset += 4; } else { // message type byteOffset = toBufferFromMessage(value, field.messageType, uint8Array, dataView, byteOffset); } return byteOffset; } function toBufferFromMessage(message, descriptor, uint8Array, dataView, byteOffset) { if (!message) { dataView.setUint32(byteOffset, UINT32_VALUE_FOR_UNDEFINED, true); return byteOffset + 4; } let numOfFields = 0; let byteOffsetForNumOfFields = byteOffset; byteOffset += 4; for (let field of descriptor.fields) { if (message[field.name] == null) { continue; } numOfFields += 1; dataView.setUint32(byteOffset, field.index, true); byteOffset += 4; if (field.isArray) { dataView.setUint32(byteOffset, message[field.name].length, true); byteOffset += 4; for (let value of message[field.name]) { byteOffset = toBufferFromValue(value, field, uint8Array, dataView, byteOffset); } } else { byteOffset = toBufferFromValue(message[field.name], field, uint8Array, dataView, byteOffset); } } dataView.setUint32(byteOffsetForNumOfFields, numOfFields, true); return byteOffset; } function serializeMessage(message, descriptor) { let byteOffset = toBufferFromMessage(message, descriptor, RESERVED_UINT8_ARRAY, DATA_VIEW_OF_RESERVED_ARRAY, 0); return RESERVED_UINT8_ARRAY.slice(0, byteOffset); } function toEnumFromNumber(sourceValue, enumType) { let found = enumType.values.find((enumValue) => { return enumValue.value === sourceValue; }); if (found === undefined) { return undefined; } else { return sourceValue; } } function toValueFromBinary(dataView, byteOffset, field) { let value; if (field.primitiveType) { switch (field.primitiveType) { case descriptor_1.PrimitiveType.NUMBER: value = dataView.getFloat64(byteOffset, true); if (isNaN(value)) { value = undefined; } byteOffset += 8; break; case descriptor_1.PrimitiveType.BOOLEAN: value = dataView.getUint8(byteOffset); if (value === BOOLEAN_VALUE_FOR_UNDEFINED) { value = undefined; } else { value = Boolean(value); } byteOffset += 1; break; case descriptor_1.PrimitiveType.STRING: let stringByteLength = dataView.getUint32(byteOffset, true); byteOffset += 4; if (stringByteLength === UINT32_VALUE_FOR_UNDEFINED) { value = undefined; } else { value = TEXT_DECODER.decode(new Uint8Array(dataView.buffer, dataView.byteOffset + byteOffset, stringByteLength)); byteOffset += stringByteLength; } break; } } else if (field.enumType) { let enumSourceValue = dataView.getUint32(byteOffset, true); byteOffset += 4; value = toEnumFromNumber(enumSourceValue, field.enumType); } else { // message type let messageAndByteOffset = toMessageFromBinary(dataView, byteOffset, field.messageType); value = messageAndByteOffset.message; byteOffset = messageAndByteOffset.byteOffset; } return { value, byteOffset }; } function toMessageFromBinary(dataView, byteOffset, descriptor) { let numOfFields = dataView.getUint32(byteOffset, true); byteOffset += 4; if (numOfFields === UINT32_VALUE_FOR_UNDEFINED) { return { byteOffset, }; } let message = {}; let i = 0; for (let j = 0; j < numOfFields; j++) { let index = dataView.getUint32(byteOffset, true); byteOffset += 4; while (descriptor.fields[i].index < index) { i++; } if (index !== descriptor.fields[i].index) { throw new Error(`Index ${index} is not found in the message descriptor of ${descriptor.name}.`); } let field = descriptor.fields[i]; if (field.isArray) { let arrayLength = dataView.getUint32(byteOffset, true); byteOffset += 4; let arrayField = new Array(); message[field.name] = arrayField; for (let m = 0; m < arrayLength; m++) { let valueAndByteOffset = toValueFromBinary(dataView, byteOffset, field); arrayField.push(valueAndByteOffset.value); byteOffset = valueAndByteOffset.byteOffset; } } else { let valueAndByteOffset = toValueFromBinary(dataView, byteOffset, field); message[field.name] = valueAndByteOffset.value; byteOffset = valueAndByteOffset.byteOffset; } } return { message, byteOffset }; } function deserializeMessage(binary, descriptor) { if (!binary) { return undefined; } return toMessageFromBinary(new DataView(binary.buffer, binary.byteOffset, binary.byteLength), 0, descriptor).message; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VyaWFsaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNlcmlhbGl6ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUE2QkEsZ0NBR0M7QUFJRCw4Q0F5REM7QUFFRCxrREFnREM7QUFFRCw0Q0FZQztBQUVELDRDQVlDO0FBRUQsOENBd0RDO0FBRUQsa0RBNENDO0FBRUQsZ0RBWUM7QUFqU0QsNkNBS3NCO0FBRXRCLHlCQUF5QjtBQUN6Qix5REFBeUQ7QUFDekQsa2NBQWtjO0FBQ2xjLEVBQUU7QUFDRixnQkFBZ0I7QUFDaEIsMkRBQTJEO0FBQzNELDRFQUE0RTtBQUM1RSwrQ0FBK0M7QUFDL0MsRUFBRTtBQUNGLG1DQUFtQztBQUNuQyxtRUFBbUU7QUFDbkUsK0ZBQStGO0FBQy9GLEVBQUU7QUFDRiwwR0FBMEc7QUFFMUcsSUFBSSwwQkFBMEIsR0FBRyxVQUFVLENBQUM7QUFDNUMsSUFBSSwyQkFBMkIsR0FBRyxDQUFDLENBQUM7QUFDcEMsSUFBSSxvQkFBZ0MsQ0FBQztBQUNyQyxJQUFJLDJCQUFxQyxDQUFDO0FBQzFDLElBQUksWUFBWSxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7QUFDckMsSUFBSSxZQUFZLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztBQUVyQyxTQUFnQixVQUFVLENBQUMsUUFBUSxHQUFHLElBQUksR0FBRyxJQUFJLEdBQUcsRUFBRTtJQUNwRCxvQkFBb0IsR0FBRyxJQUFJLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNoRCwyQkFBMkIsR0FBRyxJQUFJLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMxRSxDQUFDO0FBRUQsVUFBVSxFQUFFLENBQUM7QUFFYixTQUFnQixpQkFBaUIsQ0FDL0IsS0FBVSxFQUNWLEtBQW1CLEVBQ25CLFVBQXNCLEVBQ3RCLFFBQWtCLEVBQ2xCLFVBQWtCO0lBRWxCLElBQUksS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3hCLFFBQVEsS0FB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QyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDO1lBQ2pDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxXQUFXLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDckMsSUFBSSxrQkFBa0IsR0FBRyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN4RSxVQUFVLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMxQyxVQUFVLEdBQUcsa0JBQWtCLENBQUMsVUFBVSxDQUFDO1lBQzdDLENBQUM7UUFDSCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksa0JBQWtCLEdBQUcsaUJBQWlCLENBQUMsUUFBUSxFQUFFLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN4RSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLGtCQUFrQixDQUFDLEtBQUssQ0FBQztZQUMvQyxVQUFVLEdBQUcsa0JBQWtCLENBQUMsVUFBVSxDQUFDO1FBQzdDLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQztBQUNqQyxDQUFDO0FBRUQsU0FBZ0Isa0JBQWtCLENBQ2hDLE1BQXFDLEVBQ3JDLFVBQWdDO0lBRWhDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNaLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLG1CQUFtQixDQUN4QixJQUFJLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUNqRSxDQUFDLEVBQ0QsVUFBVSxDQUNYLENBQUMsT0FBTyxDQUFDO0FBQ1osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEVudW1EZXNjcmlwdG9yLFxuICBNZXNzYWdlRGVzY3JpcHRvcixcbiAgTWVzc2FnZUZpZWxkLFxuICBQcmltaXRpdmVUeXBlLFxufSBmcm9tIFwiLi9kZXNjcmlwdG9yXCI7XG5cbi8vIEJpbmFyeSBmb3JtYXQgZXhhbXBsZS5cbi8vIEZyb20gezE6IDEsIDI6IHRydWUsIDM6IHt9LCA0OiB7MTogMX0sIDU6IFwiYVwiLCA2OiBbMV19XG4vLyBUbyA8NiAoVWludDMyIGZvciBudW1iZXIgb2YgZmllbGRzKT48MSAoVWludDMyIGZvciBpbmRleCk+PDEgKEZsb2F0NjQgZm9yIG51bWJlciB2YWx1ZSk+PDIgKFVpbnQzMiBmb3IgaW5kZXgpPjwxIChVaW50OCBmb3IgYm9vbGVhbiB2YWx1ZSk+PDMgKFVpbnQzMiBmb3IgaW5kZXgpPjwwIChVaW50MzIgZm9yIGJ5dGUgc2l6ZSk+PDQgKFVpbnQzMiBmb3IgaW5kZXgpPjwxMiAoVWludDMyIGZvciBieXRlIHNpemUpPjwxIChVaW50MzIgZm9yIGluZGV4KT48MSAoRmxvYXQ2NCBmb3IgbnVtYmVyIHZhbHVlKT48NSAoVWludDMyIGZvciBpbmRleCk+PDEgKFVpbnQzMiBmb3IgYnl0ZSBsZW5ndGgpPjw5NyAoVWludDggZm9yIFVURjggZW5jb2RpbmcpPjw2IChVaW50MzIgZm9yIGluZGV4KT48MSAoVWludDMyIGZvciBhcnJheSBzaXplKT48MSAoRmxvYXQ2NCBmb3IgbnVtYmVyIHZhbHVlKT5cbi8vXG4vLyBSZXF1aXJlbWVudHM6XG4vLyAgIDEuIEluZGV4LCBlbnVtIHZhbHVlLCBhbmQgYXJyYXkgbGVuZ3RoIG11c3QgYmUgPCAyXjMyLlxuLy8gICAyLiBOdW1iZXIgb2YgZmllbGRzLCBhbmQgc3RyaW5nIGJ5dGUgbGVuZ3RoIG11c3QgYmUgPCAyXjMyIC0gMSAoTk9URSEpLlxuLy8gICAzLiBGaWVsZCBpbmRleCBhbmQgZW51bSB2YWx1ZSBtdXN0IGJlID4gMC5cbi8vXG4vLyBIYW5kbGluZyBgdW5kZWZpbmVkYCBhbmQgYG51bGxgOlxuLy8gICAxLiBJZiBhIGZpZWxkIGlzIHVuZGVmaW5lZC9udWxsLCBpdCdzIGlnbm9yZWQgd2hlbiBzZXJpYWxpemVkLlxuLy8gICAyLiBJZiBhbiBlbGVtZW50IG9mIGFuIGFycmF5IGlzIHVuZGVmaW5lZC9udWxsLCBpdCB3aWxsIGJlIGtlcHQgYXMgdW5kZWZpbmVkIGluIHRoZSBhcnJheS5cbi8vXG4vLyBNYXhpbXVtIGJ5dGUgc2l6ZSBieSBkZWZhdWx0IGlzIDE2TUIsIGJ1dCBjYW4gYmUgY2hhbmdlZCBnbG9iYWxseSB1c2luZyBgaW5pdEJ1ZmZlcihtYXhCeXRlczogbnVtYmVyKWAuXG5cbmxldCBVSU5UMzJfVkFMVUVfRk9SX1VOREVGSU5FRCA9IDQyOTQ5NjcyOTU7XG5sZXQgQk9PTEVBTl9WQUxVRV9GT1JfVU5ERUZJTkVEID0gMjtcbmxldCBSRVNFUlZFRF9VSU5UOF9BUlJBWTogVWludDhBcnJheTtcbmxldCBEQVRBX1ZJRVdfT0ZfUkVTRVJWRURfQVJSQVk6IERhdGFWaWV3O1xubGV0IFRFWFRfRU5DT0RFUiA9IG5ldyBUZXh0RW5jb2RlcigpO1xubGV0IFRFWFRfREVDT0RFUiA9IG5ldyBUZXh0RGVjb2RlcigpO1xuXG5leHBvcnQgZnVuY3Rpb24gaW5pdEJ1ZmZlcihtYXhCeXRlcyA9IDEwMjQgKiAxMDI0ICogMTYpOiB2b2lkIHtcbiAgUkVTRVJWRURfVUlOVDhfQVJSQVkgPSBuZXcgVWludDhBcnJheShtYXhCeXRlcyk7XG4gIERBVEFfVklFV19PRl9SRVNFUlZFRF9BUlJBWSA9IG5ldyBEYXRhVmlldyhSRVNFUlZFRF9VSU5UOF9BUlJBWS5idWZmZXIpO1xufVxuXG5pbml0QnVmZmVyKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiB0b0J1ZmZlckZyb21WYWx1ZShcbiAgdmFsdWU6IGFueSxcbiAgZmllbGQ6IE1lc3NhZ2VGaWVsZCxcbiAgdWludDhBcnJheTogVWludDhBcnJheSxcbiAgZGF0YVZpZXc6IERhdGFWaWV3LFxuICBieXRlT2Zmc2V0OiBudW1iZXIsXG4pOiBudW1iZXIge1xuICBpZiAoZmllbGQucHJpbWl0aXZlVHlwZSkge1xuICAgIHN3aXRjaCAoZmllbGQucHJpbWl0aXZlVHlwZSkge1xuICAgICAgY2FzZSBQcmltaXRpdmVUeXBlLk5VTUJFUjpcbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICBkYXRhVmlldy5zZXRGbG9hdDY0KGJ5dGVPZmZzZXQsIE5hTiwgdHJ1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGF0YVZpZXcuc2V0RmxvYXQ2NChieXRlT2Zmc2V0LCB2YWx1ZSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgYnl0ZU9mZnNldCArPSA4O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUHJpbWl0aXZlVHlwZS5CT09MRUFOOlxuICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgICAgIGRhdGFWaWV3LnNldFVpbnQ4KGJ5dGVPZmZzZXQsIEJPT0xFQU5fVkFMVUVfRk9SX1VOREVGSU5FRCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGF0YVZpZXcuc2V0VWludDgoYnl0ZU9mZnNldCwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGJ5dGVPZmZzZXQgKz0gMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFByaW1pdGl2ZVR5cGUuU1RSSU5HOlxuICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgICAgIGRhdGFWaWV3LnNldFVpbnQzMihieXRlT2Zmc2V0LCBVSU5UMzJfVkFMVUVfRk9SX1VOREVGSU5FRCwgdHJ1ZSk7XG4gICAgICAgICAgYnl0ZU9mZnNldCArPSA0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxldCByZXMgPSBURVhUX0VOQ09ERVIuZW5jb2RlSW50byhcbiAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgdWludDhBcnJheS5zdWJhcnJheShieXRlT2Zmc2V0ICsgNCksXG4gICAgICAgICAgKTtcbiAgICAgICAgICBkYXRhVmlldy5zZXRVaW50MzIoYnl0ZU9mZnNldCwgcmVzLndyaXR0ZW4sIHRydWUpO1xuICAgICAgICAgIGJ5dGVPZmZzZXQgKz0gNCArIHJlcy53cml0dGVuO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfSBlbHNlIGlmIChmaWVsZC5lbnVtVHlwZSkge1xuICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICBkYXRhVmlldy5zZXRVaW50MzIoYnl0ZU9mZnNldCwgMCwgdHJ1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRhdGFWaWV3LnNldFVpbnQzMihieXRlT2Zmc2V0LCB2YWx1ZSwgdHJ1ZSk7XG4gICAgfVxuICAgIGJ5dGVPZmZzZXQgKz0gNDtcbiAgfSBlbHNlIHtcbiAgICAvLyBtZXNzYWdlIHR5cGVcbiAgICBieXRlT2Zmc2V0ID0gdG9CdWZmZXJGcm9tTWVzc2FnZShcbiAgICAgIHZhbHVlLFxuICAgICAgZmllbGQubWVzc2FnZVR5cGUsXG4gICAgICB1aW50OEFycmF5LFxuICAgICAgZGF0YVZpZXcsXG4gICAgICBieXRlT2Zmc2V0LFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIGJ5dGVPZmZzZXQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b0J1ZmZlckZyb21NZXNzYWdlKFxuICBtZXNzYWdlOiBhbnksXG4gIGRlc2NyaXB0b3I6IE1lc3NhZ2VEZXNjcmlwdG9yPGFueT4sXG4gIHVpbnQ4QXJyYXk6IFVpbnQ4QXJyYXksXG4gIGRhdGFWaWV3OiBEYXRhVmlldyxcbiAgYnl0ZU9mZnNldDogbnVtYmVyLFxuKTogbnVtYmVyIHtcbiAgaWYgKCFtZXNzYWdlKSB7XG4gICAgZGF0YVZpZXcuc2V0VWludDMyKGJ5dGVPZmZzZXQsIFVJTlQzMl9WQUxVRV9GT1JfVU5ERUZJTkVELCB0cnVlKTtcbiAgICByZXR1cm4gYnl0ZU9mZnNldCArIDQ7XG4gIH1cblxuICBsZXQgbnVtT2ZGaWVsZHMgPSAwO1xuICBsZXQgYnl0ZU9mZnNldEZvck51bU9mRmllbGRzID0gYnl0ZU9mZnNldDtcbiAgYnl0ZU9mZnNldCArPSA0O1xuICBmb3IgKGxldCBmaWVsZCBvZiBkZXNjcmlwdG9yLmZpZWxkcykge1xuICAgIGlmIChtZXNzYWdlW2ZpZWxkLm5hbWVdID09IG51bGwpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBudW1PZkZpZWxkcyArPSAxO1xuXG4gICAgZGF0YVZpZXcuc2V0VWludDMyKGJ5dGVPZmZzZXQsIGZpZWxkLmluZGV4LCB0cnVlKTtcbiAgICBieXRlT2Zmc2V0ICs9IDQ7XG5cbiAgICBpZiAoZmllbGQuaXNBcnJheSkge1xuICAgICAgZGF0YVZpZXcuc2V0VWludDMyKGJ5dGVPZmZzZXQsIG1lc3NhZ2VbZmllbGQubmFtZV0ubGVuZ3RoLCB0cnVlKTtcbiAgICAgIGJ5dGVPZmZzZXQgKz0gNDtcbiAgICAgIGZvciAobGV0IHZhbHVlIG9mIG1lc3NhZ2VbZmllbGQubmFtZV0pIHtcbiAgICAgICAgYnl0ZU9mZnNldCA9IHRvQnVmZmVyRnJvbVZhbHVlKFxuICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgIGZpZWxkLFxuICAgICAgICAgIHVpbnQ4QXJyYXksXG4gICAgICAgICAgZGF0YVZpZXcsXG4gICAgICAgICAgYnl0ZU9mZnNldCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYnl0ZU9mZnNldCA9IHRvQnVmZmVyRnJvbVZhbHVlKFxuICAgICAgICBtZXNzYWdlW2ZpZWxkLm5hbWVdLFxuICAgICAgICBmaWVsZCxcbiAgICAgICAgdWludDhBcnJheSxcbiAgICAgICAgZGF0YVZpZXcsXG4gICAgICAgIGJ5dGVPZmZzZXQsXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBkYXRhVmlldy5zZXRVaW50MzIoYnl0ZU9mZnNldEZvck51bU9mRmllbGRzLCBudW1PZkZpZWxkcywgdHJ1ZSk7XG4gIHJldHVybiBieXRlT2Zmc2V0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplTWVzc2FnZTxUPihcbiAgbWVzc2FnZTogVCxcbiAgZGVzY3JpcHRvcjogTWVzc2FnZURlc2NyaXB0b3I8VD4sXG4pOiBVaW50OEFycmF5IHtcbiAgbGV0IGJ5dGVPZmZzZXQgPSB0b0J1ZmZlckZyb21NZXNzYWdlKFxuICAgIG1lc3NhZ2UsXG4gICAgZGVzY3JpcHRvcixcbiAgICBSRVNFUlZFRF9VSU5UOF9BUlJBWSxcbiAgICBEQVRBX1ZJRVdfT0ZfUkVTRVJWRURfQVJSQVksXG4gICAgMCxcbiAgKTtcbiAgcmV0dXJuIFJFU0VSVkVEX1VJTlQ4X0FSUkFZLnNsaWNlKDAsIGJ5dGVPZmZzZXQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9FbnVtRnJvbU51bWJlcihcbiAgc291cmNlVmFsdWU6IG51bWJlcixcbiAgZW51bVR5cGU6IEVudW1EZXNjcmlwdG9yPGFueT4sXG4pOiBudW1iZXIge1xuICBsZXQgZm91bmQgPSBlbnVtVHlwZS52YWx1ZXMuZmluZCgoZW51bVZhbHVlKTogYm9vbGVhbiA9PiB7XG4gICAgcmV0dXJuIGVudW1WYWx1ZS52YWx1ZSA9PT0gc291cmNlVmFsdWU7XG4gIH0pO1xuICBpZiAoZm91bmQgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHNvdXJjZVZhbHVlO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b1ZhbHVlRnJvbUJpbmFyeShcbiAgZGF0YVZpZXc6IERhdGFWaWV3LFxuICBieXRlT2Zmc2V0OiBudW1iZXIsXG4gIGZpZWxkOiBNZXNzYWdlRmllbGQsXG4pOiB7IHZhbHVlOiBhbnk7IGJ5dGVPZmZzZXQ6IG51bWJlciB9IHtcbiAgbGV0IHZhbHVlOiBhbnk7XG4gIGlmIChmaWVsZC5wcmltaXRpdmVUeXBlKSB7XG4gICAgc3dpdGNoIChmaWVsZC5wcmltaXRpdmVUeXBlKSB7XG4gICAgICBjYXNlIFByaW1pdGl2ZVR5cGUuTlVNQkVSOlxuICAgICAgICB2YWx1ZSA9IGRhdGFWaWV3LmdldEZsb2F0NjQoYnl0ZU9mZnNldCwgdHJ1ZSk7XG4gICAgICAgIGlmIChpc05hTih2YWx1ZSkpIHtcbiAgICAgICAgICB2YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBieXRlT2Zmc2V0ICs9IDg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQcmltaXRpdmVUeXBlLkJPT0xFQU46XG4gICAgICAgIHZhbHVlID0gZGF0YVZpZXcuZ2V0VWludDgoYnl0ZU9mZnNldCk7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gQk9PTEVBTl9WQUxVRV9GT1JfVU5ERUZJTkVEKSB7XG4gICAgICAgICAgdmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsdWUgPSBCb29sZWFuKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBieXRlT2Zmc2V0ICs9IDE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQcmltaXRpdmVUeXBlLlNUUklORzpcbiAgICAgICAgbGV0IHN0cmluZ0J5dGVMZW5ndGggPSBkYXRhVmlldy5nZXRVaW50MzIoYnl0ZU9mZnNldCwgdHJ1ZSk7XG4gICAgICAgIGJ5dGVPZmZzZXQgKz0gNDtcbiAgICAgICAgaWYgKHN0cmluZ0J5dGVMZW5ndGggPT09IFVJTlQzMl9WQUxVRV9GT1JfVU5ERUZJTkVEKSB7XG4gICAgICAgICAgdmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsdWUgPSBURVhUX0RFQ09ERVIuZGVjb2RlKFxuICAgICAgICAgICAgbmV3IFVpbnQ4QXJyYXkoXG4gICAgICAgICAgICAgIGRhdGFWaWV3LmJ1ZmZlcixcbiAgICAgICAgICAgICAgZGF0YVZpZXcuYnl0ZU9mZnNldCArIGJ5dGVPZmZzZXQsXG4gICAgICAgICAgICAgIHN0cmluZ0J5dGVMZW5ndGgsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICk7XG4gICAgICAgICAgYnl0ZU9mZnNldCArPSBzdHJpbmdCeXRlTGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfSBlbHNlIGlmIChmaWVsZC5lbnVtVHlwZSkge1xuICAgIGxldCBlbnVtU291cmNlVmFsdWUgPSBkYXRhVmlldy5nZXRVaW50MzIoYnl0ZU9mZnNldCwgdHJ1ZSk7XG4gICAgYnl0ZU9mZnNldCArPSA0O1xuICAgIHZhbHVlID0gdG9FbnVtRnJvbU51bWJlcihlbnVtU291cmNlVmFsdWUsIGZpZWxkLmVudW1UeXBlKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBtZXNzYWdlIHR5cGVcbiAgICBsZXQgbWVzc2FnZUFuZEJ5dGVPZmZzZXQgPSB0b01lc3NhZ2VGcm9tQmluYXJ5KFxuICAgICAgZGF0YVZpZXcsXG4gICAgICBieXRlT2Zmc2V0LFxuICAgICAgZmllbGQubWVzc2FnZVR5cGUsXG4gICAgKTtcbiAgICB2YWx1ZSA9IG1lc3NhZ2VBbmRCeXRlT2Zmc2V0Lm1lc3NhZ2U7XG4gICAgYnl0ZU9mZnNldCA9IG1lc3NhZ2VBbmRCeXRlT2Zmc2V0LmJ5dGVPZmZzZXQ7XG4gIH1cbiAgcmV0dXJuIHsgdmFsdWUsIGJ5dGVPZmZzZXQgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvTWVzc2FnZUZyb21CaW5hcnk8VD4oXG4gIGRhdGFWaWV3OiBEYXRhVmlldyxcbiAgYnl0ZU9mZnNldDogbnVtYmVyLFxuICBkZXNjcmlwdG9yOiBNZXNzYWdlRGVzY3JpcHRvcjxUPixcbik6IHsgbWVzc2FnZT86IFQ7IGJ5dGVPZmZzZXQ6IG51bWJlciB9IHtcbiAgbGV0IG51bU9mRmllbGRzID0gZGF0YVZpZXcuZ2V0VWludDMyKGJ5dGVPZmZzZXQsIHRydWUpO1xuICBieXRlT2Zmc2V0ICs9IDQ7XG4gIGlmIChudW1PZkZpZWxkcyA9PT0gVUlOVDMyX1ZBTFVFX0ZPUl9VTkRFRklORUQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYnl0ZU9mZnNldCxcbiAgICB9O1xuICB9XG5cbiAgbGV0IG1lc3NhZ2U6IGFueSA9IHt9O1xuICBsZXQgaSA9IDA7XG4gIGZvciAobGV0IGogPSAwOyBqIDwgbnVtT2ZGaWVsZHM7IGorKykge1xuICAgIGxldCBpbmRleCA9IGRhdGFWaWV3LmdldFVpbnQzMihieXRlT2Zmc2V0LCB0cnVlKTtcbiAgICBieXRlT2Zmc2V0ICs9IDQ7XG4gICAgd2hpbGUgKGRlc2NyaXB0b3IuZmllbGRzW2ldLmluZGV4IDwgaW5kZXgpIHtcbiAgICAgIGkrKztcbiAgICB9XG4gICAgaWYgKGluZGV4ICE9PSBkZXNjcmlwdG9yLmZpZWxkc1tpXS5pbmRleCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSW5kZXggJHtpbmRleH0gaXMgbm90IGZvdW5kIGluIHRoZSBtZXNzYWdlIGRlc2NyaXB0b3Igb2YgJHtkZXNjcmlwdG9yLm5hbWV9LmAsXG4gICAgICApO1xuICAgIH1cbiAgICBsZXQgZmllbGQgPSBkZXNjcmlwdG9yLmZpZWxkc1tpXTtcbiAgICBpZiAoZmllbGQuaXNBcnJheSkge1xuICAgICAgbGV0IGFycmF5TGVuZ3RoID0gZGF0YVZpZXcuZ2V0VWludDMyKGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgICAgYnl0ZU9mZnNldCArPSA0O1xuICAgICAgbGV0IGFycmF5RmllbGQgPSBuZXcgQXJyYXk8YW55PigpO1xuICAgICAgbWVzc2FnZVtmaWVsZC5uYW1lXSA9IGFycmF5RmllbGQ7XG4gICAgICBmb3IgKGxldCBtID0gMDsgbSA8IGFycmF5TGVuZ3RoOyBtKyspIHtcbiAgICAgICAgbGV0IHZhbHVlQW5kQnl0ZU9mZnNldCA9IHRvVmFsdWVGcm9tQmluYXJ5KGRhdGFWaWV3LCBieXRlT2Zmc2V0LCBmaWVsZCk7XG4gICAgICAgIGFycmF5RmllbGQucHVzaCh2YWx1ZUFuZEJ5dGVPZmZzZXQudmFsdWUpO1xuICAgICAgICBieXRlT2Zmc2V0ID0gdmFsdWVBbmRCeXRlT2Zmc2V0LmJ5dGVPZmZzZXQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCB2YWx1ZUFuZEJ5dGVPZmZzZXQgPSB0b1ZhbHVlRnJvbUJpbmFyeShkYXRhVmlldywgYnl0ZU9mZnNldCwgZmllbGQpO1xuICAgICAgbWVzc2FnZVtmaWVsZC5uYW1lXSA9IHZhbHVlQW5kQnl0ZU9mZnNldC52YWx1ZTtcbiAgICAgIGJ5dGVPZmZzZXQgPSB2YWx1ZUFuZEJ5dGVPZmZzZXQuYnl0ZU9mZnNldDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHsgbWVzc2FnZSwgYnl0ZU9mZnNldCB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVzZXJpYWxpemVNZXNzYWdlPFQ+KFxuICBiaW5hcnk6IFVpbnQ4QXJyYXkgfCB1bmRlZmluZWQgfCBudWxsLFxuICBkZXNjcmlwdG9yOiBNZXNzYWdlRGVzY3JpcHRvcjxUPixcbik6IFQge1xuICBpZiAoIWJpbmFyeSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIHRvTWVzc2FnZUZyb21CaW5hcnkoXG4gICAgbmV3IERhdGFWaWV3KGJpbmFyeS5idWZmZXIsIGJpbmFyeS5ieXRlT2Zmc2V0LCBiaW5hcnkuYnl0ZUxlbmd0aCksXG4gICAgMCxcbiAgICBkZXNjcmlwdG9yLFxuICApLm1lc3NhZ2U7XG59XG4iXX0=