UNPKG

@selfage/message

Version:

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

222 lines 30 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 (i < descriptor.fields.length && 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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ZURlc2NyaXB0b3IsXG4gIE1lc3NhZ2VGaWVsZCxcbiAgUHJpbWl0aXZlVHlwZSxcbn0gZnJvbSBcIi4vZGVzY3JpcHRvclwiO1xuXG4vLyBCaW5hcnkgZm9ybWF0IGV4YW1wbGUuXG4vLyBGcm9tIHsxOiAxLCAyOiB0cnVlLCAzOiB7fSwgNDogezE6IDF9LCA1OiBcImFcIiwgNjogWzFdfVxuLy8gVG8gPDYgKFVpbnQzMiBmb3IgbnVtYmVyIG9mIGZpZWxkcyk+PDEgKFVpbnQzMiBmb3IgaW5kZXgpPjwxIChGbG9hdDY0IGZvciBudW1iZXIgdmFsdWUpPjwyIChVaW50MzIgZm9yIGluZGV4KT48MSAoVWludDggZm9yIGJvb2xlYW4gdmFsdWUpPjwzIChVaW50MzIgZm9yIGluZGV4KT48MCAoVWludDMyIGZvciBieXRlIHNpemUpPjw0IChVaW50MzIgZm9yIGluZGV4KT48MTIgKFVpbnQzMiBmb3IgYnl0ZSBzaXplKT48MSAoVWludDMyIGZvciBpbmRleCk+PDEgKEZsb2F0NjQgZm9yIG51bWJlciB2YWx1ZSk+PDUgKFVpbnQzMiBmb3IgaW5kZXgpPjwxIChVaW50MzIgZm9yIGJ5dGUgbGVuZ3RoKT48OTcgKFVpbnQ4IGZvciBVVEY4IGVuY29kaW5nKT48NiAoVWludDMyIGZvciBpbmRleCk+PDEgKFVpbnQzMiBmb3IgYXJyYXkgc2l6ZSk+PDEgKEZsb2F0NjQgZm9yIG51bWJlciB2YWx1ZSk+XG4vL1xuLy8gUmVxdWlyZW1lbnRzOlxuLy8gICAxLiBJbmRleCwgZW51bSB2YWx1ZSwgYW5kIGFycmF5IGxlbmd0aCBtdXN0IGJlIDwgMl4zMi5cbi8vICAgMi4gTnVtYmVyIG9mIGZpZWxkcywgYW5kIHN0cmluZyBieXRlIGxlbmd0aCBtdXN0IGJlIDwgMl4zMiAtIDEgKE5PVEUhKS5cbi8vICAgMy4gRmllbGQgaW5kZXggYW5kIGVudW0gdmFsdWUgbXVzdCBiZSA+IDAuXG4vL1xuLy8gSGFuZGxpbmcgYHVuZGVmaW5lZGAgYW5kIGBudWxsYDpcbi8vICAgMS4gSWYgYSBmaWVsZCBpcyB1bmRlZmluZWQvbnVsbCwgaXQncyBpZ25vcmVkIHdoZW4gc2VyaWFsaXplZC5cbi8vICAgMi4gSWYgYW4gZWxlbWVudCBvZiBhbiBhcnJheSBpcyB1bmRlZmluZWQvbnVsbCwgaXQgd2lsbCBiZSBrZXB0IGFzIHVuZGVmaW5lZCBpbiB0aGUgYXJyYXkuXG4vL1xuLy8gTWF4aW11bSBieXRlIHNpemUgYnkgZGVmYXVsdCBpcyAxNk1CLCBidXQgY2FuIGJlIGNoYW5nZWQgZ2xvYmFsbHkgdXNpbmcgYGluaXRCdWZmZXIobWF4Qnl0ZXM6IG51bWJlcilgLlxuXG5sZXQgVUlOVDMyX1ZBTFVFX0ZPUl9VTkRFRklORUQgPSA0Mjk0OTY3Mjk1O1xubGV0IEJPT0xFQU5fVkFMVUVfRk9SX1VOREVGSU5FRCA9IDI7XG5sZXQgUkVTRVJWRURfVUlOVDhfQVJSQVk6IFVpbnQ4QXJyYXk7XG5sZXQgREFUQV9WSUVXX09GX1JFU0VSVkVEX0FSUkFZOiBEYXRhVmlldztcbmxldCBURVhUX0VOQ09ERVIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbmxldCBURVhUX0RFQ09ERVIgPSBuZXcgVGV4dERlY29kZXIoKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGluaXRCdWZmZXIobWF4Qnl0ZXMgPSAxMDI0ICogMTAyNCAqIDE2KTogdm9pZCB7XG4gIFJFU0VSVkVEX1VJTlQ4X0FSUkFZID0gbmV3IFVpbnQ4QXJyYXkobWF4Qnl0ZXMpO1xuICBEQVRBX1ZJRVdfT0ZfUkVTRVJWRURfQVJSQVkgPSBuZXcgRGF0YVZpZXcoUkVTRVJWRURfVUlOVDhfQVJSQVkuYnVmZmVyKTtcbn1cblxuaW5pdEJ1ZmZlcigpO1xuXG5leHBvcnQgZnVuY3Rpb24gdG9CdWZmZXJGcm9tVmFsdWUoXG4gIHZhbHVlOiBhbnksXG4gIGZpZWxkOiBNZXNzYWdlRmllbGQsXG4gIHVpbnQ4QXJyYXk6IFVpbnQ4QXJyYXksXG4gIGRhdGFWaWV3OiBEYXRhVmlldyxcbiAgYnl0ZU9mZnNldDogbnVtYmVyLFxuKTogbnVtYmVyIHtcbiAgaWYgKGZpZWxkLnByaW1pdGl2ZVR5cGUpIHtcbiAgICBzd2l0Y2ggKGZpZWxkLnByaW1pdGl2ZVR5cGUpIHtcbiAgICAgIGNhc2UgUHJpbWl0aXZlVHlwZS5OVU1CRVI6XG4gICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgZGF0YVZpZXcuc2V0RmxvYXQ2NChieXRlT2Zmc2V0LCBOYU4sIHRydWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRhdGFWaWV3LnNldEZsb2F0NjQoYnl0ZU9mZnNldCwgdmFsdWUsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGJ5dGVPZmZzZXQgKz0gODtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFByaW1pdGl2ZVR5cGUuQk9PTEVBTjpcbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICBkYXRhVmlldy5zZXRVaW50OChieXRlT2Zmc2V0LCBCT09MRUFOX1ZBTFVFX0ZPUl9VTkRFRklORUQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRhdGFWaWV3LnNldFVpbnQ4KGJ5dGVPZmZzZXQsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBieXRlT2Zmc2V0ICs9IDE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBQcmltaXRpdmVUeXBlLlNUUklORzpcbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICBkYXRhVmlldy5zZXRVaW50MzIoYnl0ZU9mZnNldCwgVUlOVDMyX1ZBTFVFX0ZPUl9VTkRFRklORUQsIHRydWUpO1xuICAgICAgICAgIGJ5dGVPZmZzZXQgKz0gNDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsZXQgcmVzID0gVEVYVF9FTkNPREVSLmVuY29kZUludG8oXG4gICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgIHVpbnQ4QXJyYXkuc3ViYXJyYXkoYnl0ZU9mZnNldCArIDQpLFxuICAgICAgICAgICk7XG4gICAgICAgICAgZGF0YVZpZXcuc2V0VWludDMyKGJ5dGVPZmZzZXQsIHJlcy53cml0dGVuLCB0cnVlKTtcbiAgICAgICAgICBieXRlT2Zmc2V0ICs9IDQgKyByZXMud3JpdHRlbjtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH0gZWxzZSBpZiAoZmllbGQuZW51bVR5cGUpIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgZGF0YVZpZXcuc2V0VWludDMyKGJ5dGVPZmZzZXQsIDAsIHRydWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkYXRhVmlldy5zZXRVaW50MzIoYnl0ZU9mZnNldCwgdmFsdWUsIHRydWUpO1xuICAgIH1cbiAgICBieXRlT2Zmc2V0ICs9IDQ7XG4gIH0gZWxzZSB7XG4gICAgLy8gbWVzc2FnZSB0eXBlXG4gICAgYnl0ZU9mZnNldCA9IHRvQnVmZmVyRnJvbU1lc3NhZ2UoXG4gICAgICB2YWx1ZSxcbiAgICAgIGZpZWxkLm1lc3NhZ2VUeXBlLFxuICAgICAgdWludDhBcnJheSxcbiAgICAgIGRhdGFWaWV3LFxuICAgICAgYnl0ZU9mZnNldCxcbiAgICApO1xuICB9XG4gIHJldHVybiBieXRlT2Zmc2V0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9CdWZmZXJGcm9tTWVzc2FnZShcbiAgbWVzc2FnZTogYW55LFxuICBkZXNjcmlwdG9yOiBNZXNzYWdlRGVzY3JpcHRvcjxhbnk+LFxuICB1aW50OEFycmF5OiBVaW50OEFycmF5LFxuICBkYXRhVmlldzogRGF0YVZpZXcsXG4gIGJ5dGVPZmZzZXQ6IG51bWJlcixcbik6IG51bWJlciB7XG4gIGlmICghbWVzc2FnZSkge1xuICAgIGRhdGFWaWV3LnNldFVpbnQzMihieXRlT2Zmc2V0LCBVSU5UMzJfVkFMVUVfRk9SX1VOREVGSU5FRCwgdHJ1ZSk7XG4gICAgcmV0dXJuIGJ5dGVPZmZzZXQgKyA0O1xuICB9XG5cbiAgbGV0IG51bU9mRmllbGRzID0gMDtcbiAgbGV0IGJ5dGVPZmZzZXRGb3JOdW1PZkZpZWxkcyA9IGJ5dGVPZmZzZXQ7XG4gIGJ5dGVPZmZzZXQgKz0gNDtcbiAgZm9yIChsZXQgZmllbGQgb2YgZGVzY3JpcHRvci5maWVsZHMpIHtcbiAgICBpZiAobWVzc2FnZVtmaWVsZC5uYW1lXSA9PSBudWxsKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgbnVtT2ZGaWVsZHMgKz0gMTtcblxuICAgIGRhdGFWaWV3LnNldFVpbnQzMihieXRlT2Zmc2V0LCBmaWVsZC5pbmRleCwgdHJ1ZSk7XG4gICAgYnl0ZU9mZnNldCArPSA0O1xuXG4gICAgaWYgKGZpZWxkLmlzQXJyYXkpIHtcbiAgICAgIGRhdGFWaWV3LnNldFVpbnQzMihieXRlT2Zmc2V0LCBtZXNzYWdlW2ZpZWxkLm5hbWVdLmxlbmd0aCwgdHJ1ZSk7XG4gICAgICBieXRlT2Zmc2V0ICs9IDQ7XG4gICAgICBmb3IgKGxldCB2YWx1ZSBvZiBtZXNzYWdlW2ZpZWxkLm5hbWVdKSB7XG4gICAgICAgIGJ5dGVPZmZzZXQgPSB0b0J1ZmZlckZyb21WYWx1ZShcbiAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICBmaWVsZCxcbiAgICAgICAgICB1aW50OEFycmF5LFxuICAgICAgICAgIGRhdGFWaWV3LFxuICAgICAgICAgIGJ5dGVPZmZzZXQsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGJ5dGVPZmZzZXQgPSB0b0J1ZmZlckZyb21WYWx1ZShcbiAgICAgICAgbWVzc2FnZVtmaWVsZC5uYW1lXSxcbiAgICAgICAgZmllbGQsXG4gICAgICAgIHVpbnQ4QXJyYXksXG4gICAgICAgIGRhdGFWaWV3LFxuICAgICAgICBieXRlT2Zmc2V0LFxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgZGF0YVZpZXcuc2V0VWludDMyKGJ5dGVPZmZzZXRGb3JOdW1PZkZpZWxkcywgbnVtT2ZGaWVsZHMsIHRydWUpO1xuICByZXR1cm4gYnl0ZU9mZnNldDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNlcmlhbGl6ZU1lc3NhZ2U8VD4oXG4gIG1lc3NhZ2U6IFQsXG4gIGRlc2NyaXB0b3I6IE1lc3NhZ2VEZXNjcmlwdG9yPFQ+LFxuKTogVWludDhBcnJheSB7XG4gIGxldCBieXRlT2Zmc2V0ID0gdG9CdWZmZXJGcm9tTWVzc2FnZShcbiAgICBtZXNzYWdlLFxuICAgIGRlc2NyaXB0b3IsXG4gICAgUkVTRVJWRURfVUlOVDhfQVJSQVksXG4gICAgREFUQV9WSUVXX09GX1JFU0VSVkVEX0FSUkFZLFxuICAgIDAsXG4gICk7XG4gIHJldHVybiBSRVNFUlZFRF9VSU5UOF9BUlJBWS5zbGljZSgwLCBieXRlT2Zmc2V0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvRW51bUZyb21OdW1iZXIoXG4gIHNvdXJjZVZhbHVlOiBudW1iZXIsXG4gIGVudW1UeXBlOiBFbnVtRGVzY3JpcHRvcjxhbnk+LFxuKTogbnVtYmVyIHtcbiAgbGV0IGZvdW5kID0gZW51bVR5cGUudmFsdWVzLmZpbmQoKGVudW1WYWx1ZSk6IGJvb2xlYW4gPT4ge1xuICAgIHJldHVybiBlbnVtVmFsdWUudmFsdWUgPT09IHNvdXJjZVZhbHVlO1xuICB9KTtcbiAgaWYgKGZvdW5kID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzb3VyY2VWYWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9WYWx1ZUZyb21CaW5hcnkoXG4gIGRhdGFWaWV3OiBEYXRhVmlldyxcbiAgYnl0ZU9mZnNldDogbnVtYmVyLFxuICBmaWVsZDogTWVzc2FnZUZpZWxkLFxuKTogeyB2YWx1ZTogYW55OyBieXRlT2Zmc2V0OiBudW1iZXIgfSB7XG4gIGxldCB2YWx1ZTogYW55O1xuICBpZiAoZmllbGQucHJpbWl0aXZlVHlwZSkge1xuICAgIHN3aXRjaCAoZmllbGQucHJpbWl0aXZlVHlwZSkge1xuICAgICAgY2FzZSBQcmltaXRpdmVUeXBlLk5VTUJFUjpcbiAgICAgICAgdmFsdWUgPSBkYXRhVmlldy5nZXRGbG9hdDY0KGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgICAgICBpZiAoaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgdmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgYnl0ZU9mZnNldCArPSA4O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUHJpbWl0aXZlVHlwZS5CT09MRUFOOlxuICAgICAgICB2YWx1ZSA9IGRhdGFWaWV3LmdldFVpbnQ4KGJ5dGVPZmZzZXQpO1xuICAgICAgICBpZiAodmFsdWUgPT09IEJPT0xFQU5fVkFMVUVfRk9SX1VOREVGSU5FRCkge1xuICAgICAgICAgIHZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlID0gQm9vbGVhbih2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgYnl0ZU9mZnNldCArPSAxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUHJpbWl0aXZlVHlwZS5TVFJJTkc6XG4gICAgICAgIGxldCBzdHJpbmdCeXRlTGVuZ3RoID0gZGF0YVZpZXcuZ2V0VWludDMyKGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgICAgICBieXRlT2Zmc2V0ICs9IDQ7XG4gICAgICAgIGlmIChzdHJpbmdCeXRlTGVuZ3RoID09PSBVSU5UMzJfVkFMVUVfRk9SX1VOREVGSU5FRCkge1xuICAgICAgICAgIHZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlID0gVEVYVF9ERUNPREVSLmRlY29kZShcbiAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KFxuICAgICAgICAgICAgICBkYXRhVmlldy5idWZmZXIsXG4gICAgICAgICAgICAgIGRhdGFWaWV3LmJ5dGVPZmZzZXQgKyBieXRlT2Zmc2V0LFxuICAgICAgICAgICAgICBzdHJpbmdCeXRlTGVuZ3RoLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJ5dGVPZmZzZXQgKz0gc3RyaW5nQnl0ZUxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH0gZWxzZSBpZiAoZmllbGQuZW51bVR5cGUpIHtcbiAgICBsZXQgZW51bVNvdXJjZVZhbHVlID0gZGF0YVZpZXcuZ2V0VWludDMyKGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgIGJ5dGVPZmZzZXQgKz0gNDtcbiAgICB2YWx1ZSA9IHRvRW51bUZyb21OdW1iZXIoZW51bVNvdXJjZVZhbHVlLCBmaWVsZC5lbnVtVHlwZSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gbWVzc2FnZSB0eXBlXG4gICAgbGV0IG1lc3NhZ2VBbmRCeXRlT2Zmc2V0ID0gdG9NZXNzYWdlRnJvbUJpbmFyeShcbiAgICAgIGRhdGFWaWV3LFxuICAgICAgYnl0ZU9mZnNldCxcbiAgICAgIGZpZWxkLm1lc3NhZ2VUeXBlLFxuICAgICk7XG4gICAgdmFsdWUgPSBtZXNzYWdlQW5kQnl0ZU9mZnNldC5tZXNzYWdlO1xuICAgIGJ5dGVPZmZzZXQgPSBtZXNzYWdlQW5kQnl0ZU9mZnNldC5ieXRlT2Zmc2V0O1xuICB9XG4gIHJldHVybiB7IHZhbHVlLCBieXRlT2Zmc2V0IH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b01lc3NhZ2VGcm9tQmluYXJ5PFQ+KFxuICBkYXRhVmlldzogRGF0YVZpZXcsXG4gIGJ5dGVPZmZzZXQ6IG51bWJlcixcbiAgZGVzY3JpcHRvcjogTWVzc2FnZURlc2NyaXB0b3I8VD4sXG4pOiB7IG1lc3NhZ2U/OiBUOyBieXRlT2Zmc2V0OiBudW1iZXIgfSB7XG4gIGxldCBudW1PZkZpZWxkcyA9IGRhdGFWaWV3LmdldFVpbnQzMihieXRlT2Zmc2V0LCB0cnVlKTtcbiAgYnl0ZU9mZnNldCArPSA0O1xuICBpZiAobnVtT2ZGaWVsZHMgPT09IFVJTlQzMl9WQUxVRV9GT1JfVU5ERUZJTkVEKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGJ5dGVPZmZzZXQsXG4gICAgfTtcbiAgfVxuXG4gIGxldCBtZXNzYWdlOiBhbnkgPSB7fTtcbiAgbGV0IGkgPSAwO1xuICBmb3IgKGxldCBqID0gMDsgaiA8IG51bU9mRmllbGRzOyBqKyspIHtcbiAgICBsZXQgaW5kZXggPSBkYXRhVmlldy5nZXRVaW50MzIoYnl0ZU9mZnNldCwgdHJ1ZSk7XG4gICAgYnl0ZU9mZnNldCArPSA0O1xuICAgIHdoaWxlIChpIDwgZGVzY3JpcHRvci5maWVsZHMubGVuZ3RoICYmIGRlc2NyaXB0b3IuZmllbGRzW2ldLmluZGV4IDwgaW5kZXgpIHtcbiAgICAgIGkrKztcbiAgICB9XG4gICAgaWYgKGluZGV4ICE9PSBkZXNjcmlwdG9yLmZpZWxkc1tpXS5pbmRleCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgSW5kZXggJHtpbmRleH0gaXMgbm90IGZvdW5kIGluIHRoZSBtZXNzYWdlIGRlc2NyaXB0b3Igb2YgJHtkZXNjcmlwdG9yLm5hbWV9LmAsXG4gICAgICApO1xuICAgIH1cbiAgICBsZXQgZmllbGQgPSBkZXNjcmlwdG9yLmZpZWxkc1tpXTtcbiAgICBpZiAoZmllbGQuaXNBcnJheSkge1xuICAgICAgbGV0IGFycmF5TGVuZ3RoID0gZGF0YVZpZXcuZ2V0VWludDMyKGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgICAgYnl0ZU9mZnNldCArPSA0O1xuICAgICAgbGV0IGFycmF5RmllbGQgPSBuZXcgQXJyYXk8YW55PigpO1xuICAgICAgbWVzc2FnZVtmaWVsZC5uYW1lXSA9IGFycmF5RmllbGQ7XG4gICAgICBmb3IgKGxldCBtID0gMDsgbSA8IGFycmF5TGVuZ3RoOyBtKyspIHtcbiAgICAgICAgbGV0IHZhbHVlQW5kQnl0ZU9mZnNldCA9IHRvVmFsdWVGcm9tQmluYXJ5KGRhdGFWaWV3LCBieXRlT2Zmc2V0LCBmaWVsZCk7XG4gICAgICAgIGFycmF5RmllbGQucHVzaCh2YWx1ZUFuZEJ5dGVPZmZzZXQudmFsdWUpO1xuICAgICAgICBieXRlT2Zmc2V0ID0gdmFsdWVBbmRCeXRlT2Zmc2V0LmJ5dGVPZmZzZXQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCB2YWx1ZUFuZEJ5dGVPZmZzZXQgPSB0b1ZhbHVlRnJvbUJpbmFyeShkYXRhVmlldywgYnl0ZU9mZnNldCwgZmllbGQpO1xuICAgICAgbWVzc2FnZVtmaWVsZC5uYW1lXSA9IHZhbHVlQW5kQnl0ZU9mZnNldC52YWx1ZTtcbiAgICAgIGJ5dGVPZmZzZXQgPSB2YWx1ZUFuZEJ5dGVPZmZzZXQuYnl0ZU9mZnNldDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHsgbWVzc2FnZSwgYnl0ZU9mZnNldCB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVzZXJpYWxpemVNZXNzYWdlPFQ+KFxuICBiaW5hcnk6IFVpbnQ4QXJyYXkgfCB1bmRlZmluZWQgfCBudWxsLFxuICBkZXNjcmlwdG9yOiBNZXNzYWdlRGVzY3JpcHRvcjxUPixcbik6IFQge1xuICBpZiAoIWJpbmFyeSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIHRvTWVzc2FnZUZyb21CaW5hcnkoXG4gICAgbmV3IERhdGFWaWV3KGJpbmFyeS5idWZmZXIsIGJpbmFyeS5ieXRlT2Zmc2V0LCBiaW5hcnkuYnl0ZUxlbmd0aCksXG4gICAgMCxcbiAgICBkZXNjcmlwdG9yLFxuICApLm1lc3NhZ2U7XG59XG4iXX0=