@developerwellness/angular-typed-forms
Version:
283 lines • 42.7 kB
JavaScript
import { InjectionToken } from '@angular/core';
import { FormArray, FormControl, FormGroup, } from '@angular/forms';
function createTypedFormArray(controls, validatorOrOpts, asyncValidator) {
return new TypedFormArray(controls, validatorOrOpts, asyncValidator);
}
class TypedFormArrayIterator {
constructor(_formArray) {
this._formArray = _formArray;
this._index = 0;
}
next() {
if (this._index < this._formArray.length) {
const control = this._formArray.controls[this._index];
this._index++;
return {
value: control,
done: false,
};
}
return {
value: null,
done: true,
};
}
}
class TypedFormArray extends FormArray {
constructor(controls, validatorOrOpts, asyncValidator) {
super(controls, validatorOrOpts, asyncValidator);
}
add(value) {
super.push(createTypedControls(value));
}
[Symbol.iterator]() {
return new TypedFormArrayIterator(this);
}
}
function createTypedFormControl(formState, validatorOrOpts, asyncValidator) {
return new TypedFormControl(formState, validatorOrOpts, asyncValidator);
}
class TypedFormControl extends FormControl {
constructor(formState, validatorOrOpts, asyncValidator) {
super(formState, validatorOrOpts, asyncValidator);
}
setValue(value, options) {
super.setValue(value, options);
}
patchValue(value, options) {
super.patchValue(value, options);
}
reset(formState, options) {
super.reset(formState, options);
}
}
function createTypedFormGroup(controls, validatorOrOpts, asyncValidator) {
return new TypedFormGroup(controls, validatorOrOpts, asyncValidator);
}
export class TypedFormGroup extends FormGroup {
constructor(controls, validatorOrOpts, asyncValidator) {
super(controls, validatorOrOpts, asyncValidator);
}
setReadonly(_value) { }
getValue() {
return this.value;
}
}
function _hasValueChanged(valueA, valueB) {
const result = !deepEquals(valueA.value, valueB);
return result;
}
function _isArray(value) {
return Array.isArray(value);
}
function _isObject(value) {
return !!(typeof value === 'object' && value);
}
function _shouldBeProcessedFactory(options) {
return (value) => !options.ignoreFields.includes(value);
}
function _containsErrors(value) {
if (!value?.errors)
return false;
return true;
}
function createTypedFormGroupControls(value, options) {
if (!value)
return null;
return Object.keys(value)
.map((key) => [key, createTypedControls(value[key], options, key)])
.reduce((formGroupControls, [key, formControl]) => ({
...formGroupControls,
[key]: formControl,
}), {});
}
function _isTypedFormModel(formValue) {
return (_isObject(formValue) &&
'value' in formValue &&
('validatorOrOpts' in formValue || 'asyncValidator' in formValue));
}
function createTypedControls(formValue, options = { ignoreFields: [] }, key) {
const shouldBeProcessed = _shouldBeProcessedFactory(options);
if (_isArray(formValue) && shouldBeProcessed(key)) {
return createTypedFormArray(formValue.map((item) => createTypedControls(item, options, key)));
}
else if (_isObject(formValue) &&
!_isTypedFormModel(formValue) &&
shouldBeProcessed(key)) {
return createTypedFormGroup(createTypedFormGroupControls(formValue, options));
}
else {
return _isTypedFormModel(formValue)
? createTypedFormControl(formValue.value, formValue.validatorOrOpts, formValue.asyncValidator)
: createTypedFormControl(formValue);
}
}
function removeFormArrayControls(formArray, formValue) {
forEach(new Array(formArray.length - formValue.length), () => {
formArray.removeAt(0, { emitEvent: false });
});
}
function updateTypedFormArray(formArray, formValue, options = { ignoreFields: [] }) {
if (formArray.length > formValue.length) {
removeFormArrayControls(formArray, formValue);
forEach(formArray.controls, (item, index) => {
updateTypedFormControls(item, formValue[index], options);
});
}
else {
forEach(formValue, (item, index) => {
if (formArray.controls[index]) {
updateTypedFormControls(formArray.controls[index], item, options);
}
else {
//Should be fixed with https://github.com/angular/angular/issues/20439#issuecomment-763976919
formArray.push(createTypedControls(item, options), { emitEvent: false });
}
});
}
}
function updateTypedFormGroup(formGroup, formValue, options = { ignoreFields: [] }) {
if (!formValue) {
Object.keys(formGroup.value)
.filter((key) => formGroup &&
formGroup.contains &&
formGroup.contains(key))
.map((key) => formGroup.get(key))
.forEach((itemControl) => {
itemControl.patchValue(null, { emitEvent: false });
});
}
else {
Object.keys(formValue)
.filter((key) => formGroup &&
formGroup.contains &&
formGroup.contains(key))
.map((key) => [formValue[key], formGroup.get(key), key])
.forEach(([item, itemControl, key]) => updateTypedFormControls(itemControl, item, options, key));
Object.keys(formValue)
.filter((key) => formGroup &&
formGroup.contains &&
!formGroup.contains(key))
.map((key) => [key, formValue[key]])
.forEach(([key, item]) => formGroup.addControl(key, createTypedControls(item, options, key), {
emitEvent: false,
}));
}
}
function updateTypedFormControl(formControl, formValue) {
if (_containsErrors(formValue)) {
const { errors } = formValue;
formControl.setErrors(errors);
}
else {
formControl.patchValue(formValue, { emitEvent: false });
formControl.setErrors(null);
}
}
function updateTypedFormControls(formControl, formValue, options = { ignoreFields: [] }, key) {
const _shouldBeIgnored = _shouldBeProcessedFactory(options);
if (_isArray(formValue || formControl.value) &&
_shouldBeIgnored(key) &&
_hasValueChanged(formControl, formValue)) {
updateTypedFormArray(formControl, formValue, options);
}
else if (_isObject(formControl.value || formControl.value) &&
_shouldBeIgnored(key) &&
_hasValueChanged(formControl, formValue) &&
formControl?.controls) {
updateTypedFormGroup(formControl, formValue, options);
}
else if (_hasValueChanged(formControl, formValue)) {
updateTypedFormControl(formControl, formValue);
}
}
const FORM_GROUP_PROP = 'formGroup';
const VALUE_PROP = 'value';
export function typedFormBuilderFactory(defaultValue, options = { ignoreFields: [] }) {
if (!defaultValue)
return null;
const formGroup = createTypedControls(defaultValue, options);
const controlValueProxyHandler = {
get: (target, prop) => {
if (target[prop] === undefined)
return undefined;
if (prop != FORM_GROUP_PROP) {
if (Array.isArray(target[prop])) {
return formGroup.get(prop);
}
else if (_isObject(target[prop])) {
return new Proxy(target[prop], controlValueProxyHandler);
}
return formGroup.get(prop);
}
return target[prop];
},
set: (target, prop, value) => {
if (prop !== FORM_GROUP_PROP) {
if (prop === VALUE_PROP) {
updateTypedFormControls(formGroup, value, options);
}
else {
updateTypedFormControls(formGroup.get(prop), value, options);
}
}
else {
target[prop] = value;
}
return true;
},
};
const formBuilder = new Proxy({
value: defaultValue,
}, controlValueProxyHandler);
formBuilder.formGroup = formGroup;
return formBuilder;
}
export const TYPED_FORM_BUILDER = new InjectionToken('TYPED_FORM_BUILDER');
function forEach(elements, callback, returnIf) {
let result = true;
const length = elements.length;
for (let index = 0; index < length; index++) {
result = callback(elements[index], index);
if (!!returnIf && returnIf(result)) {
return result;
}
}
if (returnIf) {
return result;
}
return false;
}
function deepEquals(objectA, objectB) {
if ((objectA === null || objectA === undefined) &&
(objectB === null || objectB === undefined))
return true;
if (!objectA || !objectB)
return false;
if (typeof objectA !== 'object' && typeof objectB !== 'object') {
return objectA === objectB;
}
if (Array.isArray(objectA) && Array.isArray(objectB)) {
if (objectA.length !== objectB.length)
return false;
return forEach(objectA, function (elementA, index) {
return deepEquals(elementA, objectB[index]);
}, function (result) {
return !result;
});
}
if (typeof objectA === 'object' && typeof objectB === 'object') {
if (Object.keys(objectA).length === 0 && Object.keys(objectA).length === 0)
return true;
return forEach(Object.keys(objectA), function (objectAKey) {
if (typeof objectB[objectAKey] !== undefined) {
return deepEquals(objectA[objectAKey], objectB[objectAKey]);
}
return false;
}, function (result) {
return !result;
});
}
return false;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJuYWxfYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2ludGVybmFsX2FwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9DLE9BQU8sRUFJTCxTQUFTLEVBQ1QsV0FBVyxFQUNYLFNBQVMsR0FFVixNQUFNLGdCQUFnQixDQUFDO0FBRXhCLFNBQVMsb0JBQW9CLENBQzNCLFFBQXdDLEVBQ3hDLGVBQTZFLEVBQzdFLGNBQTZEO0lBRTdELE9BQU8sSUFBSSxjQUFjLENBQU8sUUFBUSxFQUFFLGVBQWUsRUFBRSxjQUFjLENBQUMsQ0FBQztBQUM3RSxDQUFDO0FBUUQsTUFBTSxzQkFBc0I7SUFJMUIsWUFBb0IsVUFBb0M7UUFBcEMsZUFBVSxHQUFWLFVBQVUsQ0FBMEI7UUFEaEQsV0FBTSxHQUFHLENBQUMsQ0FBQztJQUN3QyxDQUFDO0lBQzVELElBQUk7UUFDRixJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUU7WUFDeEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNkLE9BQU87Z0JBQ0wsS0FBSyxFQUFFLE9BQXVDO2dCQUM5QyxJQUFJLEVBQUUsS0FBYzthQUNyQixDQUFDO1NBQ0g7UUFDRCxPQUFPO1lBQ0wsS0FBSyxFQUFFLElBQUk7WUFDWCxJQUFJLEVBQUUsSUFBYTtTQUNwQixDQUFDO0lBQ0osQ0FBQztDQUNGO0FBRUQsTUFBTSxjQUNKLFNBQVEsU0FBUztJQUdqQixZQUNFLFFBQXdDLEVBQ3hDLGVBSVEsRUFDUixjQUE2RDtRQUU3RCxLQUFLLENBQUMsUUFBUSxFQUFFLGVBQWUsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lB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T0FBTyxDQUFDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUNwRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssT0FBTyxDQUFDLE1BQU07WUFBRSxPQUFPLEtBQUssQ0FBQztRQUNwRCxPQUFPLE9BQU8sQ0FDWixPQUFPLEVBQ1AsVUFBVSxRQUFRLEVBQUUsS0FBSztZQUN2QixPQUFPLFVBQVUsQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDOUMsQ0FBQyxFQUNELFVBQVUsTUFBTTtZQUNkLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFDakIsQ0FBQyxDQUNGLENBQUM7S0FDSDtJQUNELElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRTtRQUM5RCxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQ3hFLE9BQU8sSUFBSSxDQUFDO1FBQ2QsT0FBTyxPQUFPLENBQ1osTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFDcEIsVUFBVSxVQUFVO1lBQ2xCLElBQUksT0FBTyxPQUFPLENBQUMsVUFBVSxDQUFDLEtBQUssU0FBUyxFQUFFO2dCQUM1QyxPQUFPLFVBQVUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7YUFDN0Q7WUFDRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUMsRUFDRCxVQUFVLE1BQU07WUFDZCxPQUFPLENBQUMsTUFBTSxDQUFDO1FBQ2pCLENBQUMsQ0FDRixDQUFDO0tBQ0g7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3Rpb25Ub2tlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQWJzdHJhY3RDb250cm9sLFxuICBBYnN0cmFjdENvbnRyb2xPcHRpb25zLFxuICBBc3luY1ZhbGlkYXRvckZuLFxuICBGb3JtQXJyYXksXG4gIEZvcm1Db250cm9sLFxuICBGb3JtR3JvdXAsXG4gIFZhbGlkYXRvckZuLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmZ1bmN0aW9uIGNyZWF0ZVR5cGVkRm9ybUFycmF5PFQsIEU+KFxuICBjb250cm9sczogSVR5cGVkQWJzdHJhY3RGb3JtQ29udHJvbDxUPltdLFxuICB2YWxpZGF0b3JPck9wdHM/OiBWYWxpZGF0b3JGbiB8IFZhbGlkYXRvckZuW10gfCBBYnN0cmFjdENvbnRyb2xPcHRpb25zIHwgbnVsbCxcbiAgYXN5bmNWYWxpZGF0b3I/OiBBc3luY1ZhbGlkYXRvckZuIHwgQXN5bmNWYWxpZGF0b3JGbltdIHwgbnVsbFxuKTogVHlwZWRGb3JtQXJyYXk8VCwgRT4ge1xuICByZXR1cm4gbmV3IFR5cGVkRm9ybUFycmF5PFQsIEU+KGNvbnRyb2xzLCB2YWxpZGF0b3JPck9wdHMsIGFzeW5jVmFsaWRhdG9yKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJVHlwZWRGb3JtQXJyYXk8X1QsIEUgPSBhbnk+XG4gIGV4dGVuZHMgSXRlcmFibGU8QWJzdHJhY3RDb250cm9sPixcbiAgICBGb3JtQXJyYXkge1xuICBhZGQodmFsdWU6IEUgfCBJVHlwZWRGb3JtTW9kZWw8RT4pO1xufVxuXG5jbGFzcyBUeXBlZEZvcm1BcnJheUl0ZXJhdG9yPEU+XG4gIGltcGxlbWVudHMgSXRlcmF0b3I8SVR5cGVkQWJzdHJhY3RGb3JtQ29udHJvbDxFPj5cbntcbiAgcHJpdmF0ZSBfaW5kZXggPSAwO1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9mb3JtQXJyYXk6IFR5cGVkRm9ybUFycmF5PGFueSwgYW55Pikge31cbiAgbmV4dCgpIHtcbiAgICBpZiAodGhpcy5faW5kZXggPCB0aGlzLl9mb3JtQXJyYXkubGVuZ3RoKSB7XG4gICAgICBjb25zdCBjb250cm9sID0gdGhpcy5fZm9ybUFycmF5LmNvbnRyb2xzW3RoaXMuX2luZGV4XTtcbiAgICAgIHRoaXMuX2luZGV4Kys7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZTogY29udHJvbCBhcyBJVHlwZWRBYnN0cmFjdEZvcm1Db250cm9sPEU+LFxuICAgICAgICBkb25lOiBmYWxzZSBhcyBjb25zdCxcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICB2YWx1ZTogbnVsbCxcbiAgICAgIGRvbmU6IHRydWUgYXMgY29uc3QsXG4gICAgfTtcbiAgfVxufVxuXG5jbGFzcyBUeXBlZEZvcm1BcnJheTxULCBFID0gYW55PlxuICBleHRlbmRzIEZvcm1BcnJheVxuICBpbXBsZW1lbnRzIElUeXBlZEZvcm1BcnJheTxULCBFPlxue1xuICBjb25zdHJ1Y3RvcihcbiAgICBjb250cm9sczogSVR5cGVkQWJzdHJhY3RGb3JtQ29udHJvbDxUPltdLFxuICAgIHZhbGlkYXRvck9yT3B0cz86XG4gICAgICB8IFZhbGlkYXRvckZuXG4gICAgICB8IFZhbGlkYXRvckZuW11cbiAgICAgIHwgQWJzdHJhY3RDb250cm9sT3B0aW9uc1xuICAgICAgfCBudWxsLFxuICAgIGFzeW5jVmFsaWRhdG9yPzogQXN5bmNWYWxpZGF0b3JGbiB8IEFzeW5jVmFsaWRhdG9yRm5bXSB8IG51bGxcbiAgKSB7XG4gICAgc3VwZXIoY29udHJvbHMsIHZhbGlkYXRvck9yT3B0cywgYXN5bmNWYWxpZGF0b3IpO1xuICB9XG5cbiAgYWRkKHZhbHVlOiBFKSB7XG4gICAgc3VwZXIucHVzaChjcmVhdGVUeXBlZENvbnRyb2xzKHZhbHVlKSk7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpOiBJdGVyYXRvcjxJVHlwZWRBYnN0cmFjdEZvcm1Db250cm9sPEU+PiB7XG4gICAgcmV0dXJuIG5ldyBUeXBlZEZvcm1BcnJheUl0ZXJhdG9yPEU+KHRoaXMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVR5cGVkRm9ybUNvbnRyb2w8VD4oXG4gIGZvcm1TdGF0ZTogVCxcbiAgdmFsaWRhdG9yT3JPcHRzPzogVmFsaWRhdG9yRm4gfCBWYWxpZGF0b3JGbltdIHwgQWJzdHJhY3RDb250cm9sT3B0aW9ucyB8IG51bGwsXG4gIGFzeW5jVmFsaWRhdG9yPzogQXN5bmNWYWxpZGF0b3JGbiB8IEFzeW5jVmFsaWRhdG9yRm5bXSB8IG51bGxcbik6IFR5cGVkRm9ybUNvbnRyb2w8VD4ge1xuICByZXR1cm4gbmV3IFR5cGVkRm9ybUNvbnRyb2w8VD4oZm9ybVN0YXRlLCB2YWxpZGF0b3JPck9wdHMsIGFzeW5jVmFsaWRhdG9yKTtcbn1cblxuaW50ZXJmYWNlIElUeXBlZEFic3RyYWN0Rm9ybUNvbnRyb2w8VD4gZXh0ZW5kcyBBYnN0cmFjdENvbnRyb2wge1xuICB2YWx1ZTogVDtcbn1cblxuaW50ZXJmYWNlIElUeXBlZEZvcm1Db250cm9sPFQ+IGV4dGVuZHMgRm9ybUNvbnRyb2wge1xuICB2YWx1ZTogVDtcbn1cblxuY2xhc3MgVHlwZWRGb3JtQ29udHJvbDxUPiBleHRlbmRzIEZvcm1Db250cm9sIGltcGxlbWVudHMgSVR5cGVkRm9ybUNvbnRyb2w8VD4ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBmb3JtU3RhdGU6IFQsXG4gICAgdmFsaWRhdG9yT3JPcHRzPzpcbiAgICAgIHwgVmFsaWRhdG9yRm5cbiAgICAgIHwgVmFsaWRhdG9yRm5bXVxuICAgICAgfCBBYnN0cmFjdENvbnRyb2xPcHRpb25zXG4gICAgICB8IG51bGwsXG4gICAgYXN5bmNWYWxpZGF0b3I/OiBBc3luY1ZhbGlkYXRvckZuIHwgQXN5bmNWYWxpZGF0b3JGbltdIHwgbnVsbFxuICApIHtcbiAgICBzdXBlcihmb3JtU3RhdGUsIHZhbGlkYXRvck9yT3B0cywgYXN5bmNWYWxpZGF0b3IpO1xuICB9XG5cbiAgc2V0VmFsdWUoXG4gICAgdmFsdWU6IFQsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIG9ubHlTZWxmPzogYm9vbGVhbjtcbiAgICAgIGVtaXRFdmVudD86IGJvb2xlYW47XG4gICAgICBlbWl0TW9kZWxUb1ZpZXdDaGFuZ2U/OiBib29sZWFuO1xuICAgICAgZW1pdFZpZXdUb01vZGVsQ2hhbmdlPzogYm9vbGVhbjtcbiAgICB9XG4gICkge1xuICAgIHN1cGVyLnNldFZhbHVlKHZhbHVlLCBvcHRpb25zKTtcbiAgfVxuXG4gIHBhdGNoVmFsdWUoXG4gICAgdmFsdWU6IFQsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIG9ubHlTZWxmPzogYm9vbGVhbjtcbiAgICAgIGVtaXRFdmVudD86IGJvb2xlYW47XG4gICAgICBlbWl0TW9kZWxUb1ZpZXdDaGFuZ2U/OiBib29sZWFuO1xuICAgICAgZW1pdFZpZXdUb01vZGVsQ2hhbmdlPzogYm9vbGVhbjtcbiAgICB9XG4gICkge1xuICAgIHN1cGVyLnBhdGNoVmFsdWUodmFsdWUsIG9wdGlvbnMpO1xuICB9XG5cbiAgcmVzZXQoXG4gICAgZm9ybVN0YXRlPzogVCxcbiAgICBvcHRpb25zPzoge1xuICAgICAgb25seVNlbGY/OiBib29sZWFuO1xuICAgICAgZW1pdEV2ZW50PzogYm9vbGVhbjtcbiAgICB9XG4gICkge1xuICAgIHN1cGVyLnJlc2V0KGZvcm1TdGF0ZSwgb3B0aW9ucyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlVHlwZWRGb3JtR3JvdXA8VD4oXG4gIGNvbnRyb2xzOiBJVHlwZWRGb3JtR3JvdXBDb250cm9sczxUPixcbiAgdmFsaWRhdG9yT3JPcHRzPzogVmFsaWRhdG9yRm4gfCBWYWxpZGF0b3JGbltdIHwgQWJzdHJhY3RDb250cm9sT3B0aW9ucyB8IG51bGwsXG4gIGFzeW5jVmFsaWRhdG9yPzogQXN5bmNWYWxpZGF0b3JGbiB8IEFzeW5jVmFsaWRhdG9yRm5bXSB8IG51bGxcbik6IFR5cGVkRm9ybUdyb3VwPFQ+IHtcbiAgcmV0dXJuIG5ldyBUeXBlZEZvcm1Hcm91cDxUPihjb250cm9scywgdmFsaWRhdG9yT3JPcHRzLCBhc3luY1ZhbGlkYXRvcik7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVR5cGVkRm9ybUdyb3VwPFQ+IGV4dGVuZHMgRm9ybUdyb3VwIHtcbiAgY29udHJvbHM6IElUeXBlZEZvcm1Hcm91cENvbnRyb2xzPFQ+O1xuICBzZXRSZWFkb25seSh2YWx1ZTogYm9vbGVhbik7XG4gIGdldFZhbHVlKCk6IFQ7XG59XG5cbnR5cGUgSVR5cGVkRm9ybUdyb3VwQ29udHJvbHM8VD4gPSB7XG4gIFtQIGluIGtleW9mIFRdPzogVFtQXSBleHRlbmRzIChpbmZlciBFKVtdXG4gICAgPyBJVHlwZWRGb3JtQXJyYXk8VCwgRT5cbiAgICA6IFRbUF0gZXh0ZW5kcyBvYmplY3RcbiAgICA/IElUeXBlZEZvcm1Hcm91cDxUW1BdPlxuICAgIDogSVR5cGVkRm9ybUNvbnRyb2w8VFtQXT47XG59O1xuXG5leHBvcnQgY2xhc3MgVHlwZWRGb3JtR3JvdXA8VD4gZXh0ZW5kcyBGb3JtR3JvdXAgaW1wbGVtZW50cyBJVHlwZWRGb3JtR3JvdXA8VD4ge1xuICBjb250cm9sczogSVR5cGVkRm9ybUdyb3VwQ29udHJvbHM8VD47XG4gIGNvbnN0cnVjdG9yKFxuICAgIGNvbnRyb2xzOiBJVHlwZWRGb3JtR3JvdXBDb250cm9sczxUPixcbiAgICB2YWxpZGF0b3JPck9wdHM/OlxuICAgICAgfCBWYWxpZGF0b3JGblxuICAgICAgfCBWYWxpZGF0b3JGbltdXG4gICAgICB8IEFic3RyYWN0Q29udHJvbE9wdGlvbnNcbiAgICAgIHwgbnVsbCxcbiAgICBhc3luY1ZhbGlkYXRvcj86IEFzeW5jVmFsaWRhdG9yRm4gfCBBc3luY1ZhbGlkYXRvckZuW10gfCBudWxsXG4gICkge1xuICAgIHN1cGVyKGNvbnRyb2xzLCB2YWxpZGF0b3JPck9wdHMsIGFzeW5jVmFsaWRhdG9yKTtcbiAgfVxuICBzZXRSZWFkb25seShfdmFsdWU6IGJvb2xlYW4pIHt9XG4gIGdldFZhbHVlKCk6IFQge1xuICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICB9XG59XG5cbmludGVyZmFjZSBDcmVhdGVUeXBlZENvbnRyb2xzT3B0aW9ucyB7XG4gIGlnbm9yZUZpZWxkczogc3RyaW5nW107XG59XG5cbmZ1bmN0aW9uIF9oYXNWYWx1ZUNoYW5nZWQ8VD4odmFsdWVBOiBJVHlwZWRBYnN0cmFjdEZvcm1Db250cm9sPFQ+LCB2YWx1ZUI6IFQpIHtcbiAgY29uc3QgcmVzdWx0ID0gIWRlZXBFcXVhbHModmFsdWVBLnZhbHVlLCB2YWx1ZUIpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBfaXNBcnJheSh2YWx1ZTogYW55KTogdmFsdWUgaXMgYW55W10ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIF9pc09iamVjdCh2YWx1ZTogYW55KSB7XG4gIHJldHVybiAhISh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX3Nob3VsZEJlUHJvY2Vzc2VkRmFjdG9yeShvcHRpb25zOiBDcmVhdGVUeXBlZENvbnRyb2xzT3B0aW9ucykge1xuICByZXR1cm4gKHZhbHVlOiBzdHJpbmcpID0+ICFvcHRpb25zLmlnbm9yZUZpZWxkcy5pbmNsdWRlcyh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIF9jb250YWluc0Vycm9ycyh2YWx1ZSkge1xuICBpZiAoIXZhbHVlPy5lcnJvcnMpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVR5cGVkRm9ybUdyb3VwQ29udHJvbHM8VD4oXG4gIHZhbHVlOiBULFxuICBvcHRpb25zOiBDcmVhdGVUeXBlZENvbnRyb2xzT3B0aW9uc1xuKTogSVR5cGVkRm9ybUdyb3VwQ29udHJvbHM8VD4ge1xuICBpZiAoIXZhbHVlKSByZXR1cm4gbnVsbDtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKHZhbHVlKVxuICAgIC5tYXAoKGtleTogc3RyaW5nKSA9PiBba2V5LCBjcmVhdGVUeXBlZENvbnRyb2xzKHZhbHVlW2tleV0sIG9wdGlvbnMsIGtleSldKVxuICAgIC5yZWR1Y2UoXG4gICAgICAoXG4gICAgICAgIGZvcm1Hcm91cENvbnRyb2xzLFxuICAgICAgICBba2V5LCBmb3JtQ29udHJvbF06IFtzdHJpbmcsIElUeXBlZEZvcm1Db250cm9sPGFueT5dXG4gICAgICApID0+ICh7XG4gICAgICAgIC4uLmZvcm1Hcm91cENvbnRyb2xzLFxuICAgICAgICBba2V5XTogZm9ybUNvbnRyb2wsXG4gICAgICB9KSxcbiAgICAgIHt9XG4gICAgKTtcbn1cblxuZnVuY3Rpb24gX2lzVHlwZWRGb3JtTW9kZWw8VD4oXG4gIGZvcm1WYWx1ZTogVCB8IElUeXBlZEZvcm1Nb2RlbFZhbHVlPFQ+XG4pOiBmb3JtVmFsdWUgaXMgSVR5cGVkRm9ybU1vZGVsVmFsdWU8VD4ge1xuICByZXR1cm4gKFxuICAgIF9pc09iamVjdChmb3JtVmFsdWUpICYmXG4gICAgJ3ZhbHVlJyBpbiBmb3JtVmFsdWUgJiZcbiAgICAoJ3ZhbGlkYXRvck9yT3B0cycgaW4gZm9ybVZhbHVlIHx8ICdhc3luY1ZhbGlkYXRvcicgaW4gZm9ybVZhbHVlKVxuICApO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVUeXBlZENvbnRyb2xzPFQ+KFxuICBmb3JtVmFsdWU6IFQgfCBJVHlwZWRGb3JtTW9kZWw8VD4sXG4gIG9wdGlvbnM6IENyZWF0ZVR5cGVkQ29udHJvbHNPcHRpb25zID0geyBpZ25vcmVGaWVsZHM6IFtdIH0sXG4gIGtleT86IHN0cmluZ1xuKTogSVR5cGVkQWJzdHJhY3RGb3JtQ29udHJvbDxUPiB7XG4gIGNvbnN0IHNob3VsZEJlUHJvY2Vzc2VkID0gX3Nob3VsZEJlUHJvY2Vzc2VkRmFjdG9yeShvcHRpb25zKTtcbiAgaWYgKF9pc0FycmF5KGZvcm1WYWx1ZSkgJiYgc2hvdWxkQmVQcm9jZXNzZWQoa2V5KSkge1xuICAgIHJldHVybiBjcmVhdGVUeXBlZEZvcm1BcnJheShcbiAgICAgIGZvcm1WYWx1ZS5tYXAoKGl0ZW0pID0+IGNyZWF0ZVR5cGVkQ29udHJvbHMoaXRlbSwgb3B0aW9ucywga2V5KSlcbiAgICApO1xuICB9IGVsc2UgaWYgKFxuICAgIF9pc09iamVjdChmb3JtVmFsdWUpICYmXG4gICAgIV9pc1R5cGVkRm9ybU1vZGVsKGZvcm1WYWx1ZSkgJiZcbiAgICBzaG91bGRCZVByb2Nlc3NlZChrZXkpXG4gICkge1xuICAgIHJldHVybiBjcmVhdGVUeXBlZEZvcm1Hcm91cChcbiAgICAgIGNyZWF0ZVR5cGVkRm9ybUdyb3VwQ29udHJvbHMoZm9ybVZhbHVlLCBvcHRpb25zKVxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIF9pc1R5cGVkRm9ybU1vZGVsKGZvcm1WYWx1ZSlcbiAgICAgID8gY3JlYXRlVHlwZWRGb3JtQ29udHJvbChcbiAgICAgICAgICBmb3JtVmFsdWUudmFsdWUsXG4gICAgICAgICAgZm9ybVZhbHVlLnZhbGlkYXRvck9yT3B0cyxcbiAgICAgICAgICBmb3JtVmFsdWUuYXN5bmNWYWxpZGF0b3JcbiAgICAgICAgKVxuICAgICAgOiBjcmVhdGVUeXBlZEZvcm1Db250cm9sKGZvcm1WYWx1ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlRm9ybUFycmF5Q29udHJvbHM8VD4oXG4gIGZvcm1BcnJheTogSVR5cGVkRm9ybUFycmF5PFQ+LFxuICBmb3JtVmFsdWU6IFRbXVxuKSB7XG4gIGZvckVhY2gobmV3IEFycmF5KGZvcm1BcnJheS5sZW5ndGggLSBmb3JtVmFsdWUubGVuZ3RoKSwgKCkgPT4ge1xuICAgIGZvcm1BcnJheS5yZW1vdmVBdCgwLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVUeXBlZEZvcm1BcnJheTxUPihcbiAgZm9ybUFycmF5OiBJVHlwZWRGb3JtQXJyYXk8VCwgYW55PixcbiAgZm9ybVZhbHVlOiBUW10sXG4gIG9wdGlvbnM6IENyZWF0ZVR5cGVkQ29udHJvbHNPcHRpb25zID0geyBpZ25vcmVGaWVsZHM6IFtdIH1cbikge1xuICBpZiAoZm9ybUFycmF5Lmxlbmd0aCA+IGZvcm1WYWx1ZS5sZW5ndGgpIHtcbiAgICByZW1vdmVGb3JtQXJyYXlDb250cm9scyhmb3JtQXJyYXksIGZvcm1WYWx1ZSk7XG4gICAgZm9yRWFjaChmb3JtQXJyYXkuY29udHJvbHMsIChpdGVtLCBpbmRleCkgPT4ge1xuICAgICAgdXBkYXRlVHlwZWRGb3JtQ29udHJvbHMoXG4gICAgICAgIGl0ZW0gYXMgSVR5cGVkQWJzdHJhY3RGb3JtQ29udHJvbDxUPixcbiAgICAgICAgZm9ybVZhbHVlW2luZGV4XSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBmb3JFYWNoKGZvcm1WYWx1ZSwgKGl0ZW0sIGluZGV4KSA9PiB7XG4gICAgICBpZiAoZm9ybUFycmF5LmNvbnRyb2xzW2luZGV4XSkge1xuICAgICAgICB1cGRhdGVUeXBlZEZvcm1Db250cm9scyhcbiAgICAgICAgICBmb3JtQXJyYXkuY29udHJvbHNbaW5kZXhdIGFzIElUeXBlZEFic3RyYWN0Rm9ybUNvbnRyb2w8VD4sXG4gICAgICAgICAgaXRlbSxcbiAgICAgICAgICBvcHRpb25zXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvL1Nob3VsZCBiZSBmaXhlZCB3aXRoIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvaXNzdWVzLzIwNDM5I2lzc3VlY29tbWVudC03NjM5NzY5MTlcbiAgICAgICAgKGZvcm1BcnJheSBhcyBJVHlwZWRGb3JtQXJyYXk8VD4pLnB1c2goXG4gICAgICAgICAgY3JlYXRlVHlwZWRDb250cm9scyhpdGVtLCBvcHRpb25zKSxcbiAgICAgICAgICB7IGVtaXRFdmVudDogZmFsc2UgfVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVR5cGVkRm9ybUdyb3VwPFQ+KFxuICBmb3JtR3JvdXA6IElUeXBlZEZvcm1Hcm91cDxUPixcbiAgZm9ybVZhbHVlOiBULFxuICBvcHRpb25zOiBDcmVhdGVUeXBlZENvbnRyb2xzT3B0aW9ucyA9IHsgaWdub3JlRmllbGRzOiBbXSB9XG4pIHtcbiAgaWYgKCFmb3JtVmFsdWUpIHtcbiAgICBPYmplY3Qua2V5cyhmb3JtR3JvdXAudmFsdWUpXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAoa2V5KSA9PlxuICAgICAgICAgIGZvcm1Hcm91cCAmJlxuICAgICAgICAgIChmb3JtR3JvdXAgYXMgSVR5cGVkRm9ybUdyb3VwPFQ+KS5jb250YWlucyAmJlxuICAgICAgICAgIChmb3JtR3JvdXAgYXMgSVR5cGVkRm9ybUdyb3VwPFQ+KS5jb250YWlucyhrZXkpXG4gICAgICApXG4gICAgICAubWFwKChrZXkpID0+IGZvcm1Hcm91cC5nZXQoa2V5KSlcbiAgICAgIC5mb3JFYWNoKChpdGVtQ29udHJvbCkgPT4ge1xuICAgICAgICBpdGVtQ29udHJvbC5wYXRjaFZhbHVlKG51bGwsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIE9iamVjdC5rZXlzKGZvcm1WYWx1ZSlcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChrZXkpID0+XG4gICAgICAgICAgZm9ybUdyb3VwICYmXG4gICAgICAgICAgKGZvcm1Hcm91cCBhcyBJVHlwZWRGb3JtR3JvdXA8VD4pLmNvbnRhaW5zICYmXG4gICAgICAgICAgKGZvcm1Hcm91cCBhcyBJVHlwZWRGb3JtR3JvdXA8VD4pLmNvbnRhaW5zKGtleSlcbiAgICAgIClcbiAgICAgIC5tYXAoKGtleSkgPT4gW2Zvcm1WYWx1ZVtrZXldLCBmb3JtR3JvdXAuZ2V0KGtleSksIGtleV0pXG4gICAgICAuZm9yRWFjaCgoW2l0ZW0sIGl0ZW1Db250cm9sLCBrZXldKSA9PlxuICAgICAgICB1cGRhdGVUeXBlZEZvcm1Db250cm9scyhpdGVtQ29udHJvbCwgaXRlbSwgb3B0aW9ucywga2V5KVxuICAgICAgKTtcbiAgICBPYmplY3Qua2V5cyhmb3JtVmFsdWUpXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAoa2V5KSA9PlxuICAgICAgICAgIGZvcm1Hcm91cCAmJlxuICAgICAgICAgIChmb3JtR3JvdXAgYXMgSVR5cGVkRm9ybUdyb3VwPFQ+KS5jb250YWlucyAmJlxuICAgICAgICAgICEoZm9ybUdyb3VwIGFzIElUeXBlZEZvcm1Hcm91cDxUPikuY29udGFpbnMoa2V5KVxuICAgICAgKVxuICAgICAgLm1hcCgoa2V5KSA9PiBba2V5LCBmb3JtVmFsdWVba2V5XV0pXG4gICAgICAuZm9yRWFjaCgoW2tleSwgaXRlbV0pID0+XG4gICAgICAgIChmb3JtR3JvdXAgYXMgSVR5cGVkRm9ybUdyb3VwPFQ+KS5hZGRDb250cm9sKFxuICAgICAgICAgIGtleSxcbiAgICAgICAgICBjcmVhdGVUeXBlZENvbnRyb2xzKGl0ZW0sIG9wdGlvbnMsIGtleSksXG4gICAgICAgICAge1xuICAgICAgICAgICAgZW1pdEV2ZW50OiBmYWxzZSxcbiAgICAgICAgICB9XG4gICAgICAgIClcbiAgICAgICk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlVHlwZWRGb3JtQ29udHJvbDxUPihcbiAgZm9ybUNvbnRyb2w6IElUeXBlZEZvcm1Db250cm9sPFQ+LFxuICBmb3JtVmFsdWU6IFRcbikge1xuICBpZiAoX2NvbnRhaW5zRXJyb3JzKGZvcm1WYWx1ZSkpIHtcbiAgICBjb25zdCB7IGVycm9ycyB9ID0gZm9ybVZhbHVlIGFzIGFueTtcbiAgICBmb3JtQ29udHJvbC5zZXRFcnJvcnMoZXJyb3JzKTtcbiAgfSBlbHNlIHtcbiAgICBmb3JtQ29udHJvbC5wYXRjaFZhbHVlKGZvcm1WYWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIGZvcm1Db250cm9sLnNldEVycm9ycyhudWxsKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVUeXBlZEZvcm1Db250cm9sczxUPihcbiAgZm9ybUNvbnRyb2w6IElUeXBlZEFic3RyYWN0Rm9ybUNvbnRyb2w8VD4sXG4gIGZvcm1WYWx1ZTogVCB8IFRbXSxcbiAgb3B0aW9uczogQ3JlYXRlVHlwZWRDb250cm9sc09wdGlvbnMgPSB7IGlnbm9yZUZpZWxkczogW10gfSxcbiAga2V5Pzogc3RyaW5nXG4pIHtcbiAgY29uc3QgX3Nob3VsZEJlSWdub3JlZCA9IF9zaG91bGRCZVByb2Nlc3NlZEZhY3Rvcnkob3B0aW9ucyk7XG4gIGlmIChcbiAgICBfaXNBcnJheShmb3JtVmFsdWUgfHwgZm9ybUNvbnRyb2wudmFsdWUpICYmXG4gICAgX3Nob3VsZEJlSWdub3JlZChrZXkpICYmXG4gICAgX2hhc1ZhbHVlQ2hhbmdlZChmb3JtQ29udHJvbCwgZm9ybVZhbHVlKVxuICApIHtcbiAgICB1cGRhdGVUeXBlZEZvcm1BcnJheShcbiAgICAgIGZvcm1Db250cm9sIGFzIElUeXBlZEZvcm1BcnJheTxUPixcbiAgICAgIGZvcm1WYWx1ZSBhcyBUW10sXG4gICAgICBvcHRpb25zXG4gICAgKTtcbiAgfSBlbHNlIGlmIChcbiAgICBfaXNPYmplY3QoZm9ybUNvbnRyb2wudmFsdWUgfHwgZm9ybUNvbnRyb2wudmFsdWUpICYmXG4gICAgX3Nob3VsZEJlSWdub3JlZChrZXkpICYmXG4gICAgX2hhc1ZhbHVlQ2hhbmdlZChmb3JtQ29udHJvbCwgZm9ybVZhbHVlKSAmJlxuICAgIChmb3JtQ29udHJvbCBhcyBJVHlwZWRGb3JtR3JvdXA8VD4pPy5jb250cm9sc1xuICApIHtcbiAgICB1cGRhdGVUeXBlZEZvcm1Hcm91cChmb3JtQ29udHJvbCBhcyBJVHlwZWRGb3JtR3JvdXA8VD4sIGZvcm1WYWx1ZSwgb3B0aW9ucyk7XG4gIH0gZWxzZSBpZiAoX2hhc1ZhbHVlQ2hhbmdlZChmb3JtQ29udHJvbCwgZm9ybVZhbHVlKSkge1xuICAgIHVwZGF0ZVR5cGVkRm9ybUNvbnRyb2woZm9ybUNvbnRyb2wgYXMgSVR5cGVkRm9ybUNvbnRyb2w8VD4sIGZvcm1WYWx1ZSk7XG4gIH1cbn1cblxuY29uc3QgRk9STV9HUk9VUF9QUk9QID0gJ2Zvcm1Hcm91cCc7XG5jb25zdCBWQUxVRV9QUk9QID0gJ3ZhbHVlJztcblxudHlwZSBJVHlwZWRGb3JtQnVpbGRlck9wdGlvbnMgPSBDcmVhdGVUeXBlZENvbnRyb2xzT3B0aW9ucztcbnR5cGUgSVR5cGVkRm9ybU1vZGVsVmFsdWU8VD4gPSB7XG4gIHZhbHVlOiBUO1xuICB2YWxpZGF0b3JPck9wdHM/OiBWYWxpZGF0b3JGbiB8IFZhbGlkYXRvckZuW10gfCBBYnN0cmFjdENvbnRyb2xPcHRpb25zIHwgbnVsbDtcbiAgYXN5bmNWYWxpZGF0b3I/OiBBc3luY1ZhbGlkYXRvckZuIHwgQXN5bmNWYWxpZGF0b3JGbltdIHwgbnVsbDtcbn07XG5leHBvcnQgdHlwZSBJVHlwZWRGb3JtTW9kZWw8VD4gPSB7XG4gIFtQIGluIGtleW9mIFRdOiBUW1BdIHwgSVR5cGVkRm9ybU1vZGVsVmFsdWU8VFtQXT4gfCBJVHlwZWRGb3JtTW9kZWw8VFtQXT47XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gdHlwZWRGb3JtQnVpbGRlckZhY3Rvcnk8VCBleHRlbmRzIG9iamVjdD4oXG4gIGRlZmF1bHRWYWx1ZTogSVR5cGVkRm9ybU1vZGVsPFQ+LFxuICBvcHRpb25zOiBJVHlwZWRGb3JtQnVpbGRlck9wdGlvbnMgPSB7IGlnbm9yZUZpZWxkczogW10gfVxuKTogSVR5cGVkRm9ybUJ1aWxkZXI8VD4gfCBudWxsIHtcbiAgaWYgKCFkZWZhdWx0VmFsdWUpIHJldHVybiBudWxsO1xuICBjb25zdCBmb3JtR3JvdXAgPSBjcmVhdGVUeXBlZENvbnRyb2xzPFQ+KGRlZmF1bHRWYWx1ZSwgb3B0aW9ucyk7XG4gIGNvbnN0IGNvbnRyb2xWYWx1ZVByb3h5SGFuZGxlciA9IHtcbiAgICBnZXQ6ICh0YXJnZXQsIHByb3ApID0+IHtcbiAgICAgIGlmICh0YXJnZXRbcHJvcF0gPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGlmIChwcm9wICE9IEZPUk1fR1JPVVBfUFJPUCkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh0YXJnZXRbcHJvcF0pKSB7XG4gICAgICAgICAgcmV0dXJuIGZvcm1Hcm91cC5nZXQocHJvcCk7XG4gICAgICAgIH0gZWxzZSBpZiAoX2lzT2JqZWN0KHRhcmdldFtwcm9wXSkpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFByb3h5KHRhcmdldFtwcm9wXSwgY29udHJvbFZhbHVlUHJveHlIYW5kbGVyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm9ybUdyb3VwLmdldChwcm9wKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0YXJnZXRbcHJvcF07XG4gICAgfSxcbiAgICBzZXQ6ICh0YXJnZXQsIHByb3AsIHZhbHVlKSA9PiB7XG4gICAgICBpZiAocHJvcCAhPT0gRk9STV9HUk9VUF9QUk9QKSB7XG4gICAgICAgIGlmIChwcm9wID09PSBWQUxVRV9QUk9QKSB7XG4gICAgICAgICAgdXBkYXRlVHlwZWRGb3JtQ29udHJvbHMoZm9ybUdyb3VwLCB2YWx1ZSwgb3B0aW9ucyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdXBkYXRlVHlwZWRGb3JtQ29udHJvbHMoXG4gICAgICAgICAgICBmb3JtR3JvdXAuZ2V0KHByb3ApIGFzIElUeXBlZEFic3RyYWN0Rm9ybUNvbnRyb2w8VD4sXG4gICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0YXJnZXRbcHJvcF0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gIH07XG4gIGNvbnN0IGZvcm1CdWlsZGVyID0gbmV3IFByb3h5KFxuICAgIHtcbiAgICAgIHZhbHVlOiBkZWZhdWx0VmFsdWUsXG4gICAgfSxcbiAgICBjb250cm9sVmFsdWVQcm94eUhhbmRsZXJcbiAgKTtcbiAgZm9ybUJ1aWxkZXIuZm9ybUdyb3VwID0gZm9ybUdyb3VwO1xuICByZXR1cm4gZm9ybUJ1aWxkZXI7XG59XG5cbmV4cG9ydCBjb25zdCBUWVBFRF9GT1JNX0JVSUxERVI6IEluamVjdGlvblRva2VuPElUeXBlZEZvcm1CdWlsZGVyPGFueT4+ID1cbiAgbmV3IEluamVjdGlvblRva2VuPElUeXBlZEZvcm1CdWlsZGVyPGFueT4+KCdUWVBFRF9GT1JNX0JVSUxERVInKTtcblxuZnVuY3Rpb24gZm9yRWFjaDxUPihcbiAgZWxlbWVudHM6IFRbXSxcbiAgY2FsbGJhY2s6IChpdGVtOiBULCBpbmRleDogbnVtYmVyKSA9PiBhbnksXG4gIHJldHVybklmPzogYW55XG4pOiBib29sZWFuIHwgdm9pZCB7XG4gIGxldCByZXN1bHQgPSB0cnVlO1xuICBjb25zdCBsZW5ndGggPSBlbGVtZW50cy5sZW5ndGg7XG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICByZXN1bHQgPSBjYWxsYmFjayhlbGVtZW50c1tpbmRleF0sIGluZGV4KTtcbiAgICBpZiAoISFyZXR1cm5JZiAmJiByZXR1cm5JZihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuICBpZiAocmV0dXJuSWYpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZGVlcEVxdWFscyhvYmplY3RBLCBvYmplY3RCKSB7XG4gIGlmIChcbiAgICAob2JqZWN0QSA9PT0gbnVsbCB8fCBvYmplY3RBID09PSB1bmRlZmluZWQpICYmXG4gICAgKG9iamVjdEIgPT09IG51bGwgfHwgb2JqZWN0QiA9PT0gdW5kZWZpbmVkKVxuICApXG4gICAgcmV0dXJuIHRydWU7XG4gIGlmICghb2JqZWN0QSB8fCAhb2JqZWN0QikgcmV0dXJuIGZhbHNlO1xuICBpZiAodHlwZW9mIG9iamVjdEEgIT09ICdvYmplY3QnICYmIHR5cGVvZiBvYmplY3RCICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBvYmplY3RBID09PSBvYmplY3RCO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KG9iamVjdEEpICYmIEFycmF5LmlzQXJyYXkob2JqZWN0QikpIHtcbiAgICBpZiAob2JqZWN0QS5sZW5ndGggIT09IG9iamVjdEIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIGZvckVhY2goXG4gICAgICBvYmplY3RBLFxuICAgICAgZnVuY3Rpb24gKGVsZW1lbnRBLCBpbmRleCkge1xuICAgICAgICByZXR1cm4gZGVlcEVxdWFscyhlbGVtZW50QSwgb2JqZWN0QltpbmRleF0pO1xuICAgICAgfSxcbiAgICAgIGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuICFyZXN1bHQ7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuICBpZiAodHlwZW9mIG9iamVjdEEgPT09ICdvYmplY3QnICYmIHR5cGVvZiBvYmplY3RCID09PSAnb2JqZWN0Jykge1xuICAgIGlmIChPYmplY3Qua2V5cyhvYmplY3RBKS5sZW5ndGggPT09IDAgJiYgT2JqZWN0LmtleXMob2JqZWN0QSkubGVuZ3RoID09PSAwKVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIGZvckVhY2goXG4gICAgICBPYmplY3Qua2V5cyhvYmplY3RBKSxcbiAgICAgIGZ1bmN0aW9uIChvYmplY3RBS2V5KSB7XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0QltvYmplY3RBS2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmV0dXJuIGRlZXBFcXVhbHMob2JqZWN0QVtvYmplY3RBS2V5XSwgb2JqZWN0QltvYmplY3RBS2V5XSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSxcbiAgICAgIGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuICFyZXN1bHQ7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbnR5cGUgSVR5cGVkRm9ybUJ1aWxkZXJWYWx1ZTxUPiA9IHtcbiAgW1AgaW4ga2V5b2YgVF0/OiBUW1BdIGV4dGVuZHMgKGluZmVyIEUpW11cbiAgICA/IElUeXBlZEZvcm1BcnJheTxUW1BdLCBFPiB8IFRbUF1cbiAgICA6IFRbUF0gZXh0ZW5kcyBvYmplY3RcbiAgICA/IElUeXBlZEZvcm1CdWlsZGVyVmFsdWU8VFtQXT5cbiAgICA6IElUeXBlZEZvcm1Db250cm9sPFRbUF0+IHwgVFtQXTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVR5cGVkRm9ybUJ1aWxkZXI8VD4ge1xuICB2YWx1ZTogSVR5cGVkRm9ybUJ1aWxkZXJWYWx1ZTxUPjtcbiAgZm9ybUdyb3VwOiBJVHlwZWRGb3JtR3JvdXA8VD47XG59XG4iXX0=