UNPKG

@openfisca/json-model

Version:

Library to handle informations extracted in JSON or YAML format from OpenFisca parameters, variables, etc

242 lines 30 kB
import { Instant, Period } from "../periods.js"; import { AstTransformer } from "./visitors.js"; class InstantOrPeriodMethod { constructor(instantOrPeriod, methodName) { this.instantOrPeriod = instantOrPeriod; this.methodName = methodName; } } class InstantOrPeriodEvaluator extends AstTransformer { constructor(period) { super(); this.period = period; } transform_Attribute(attribute) { const value = this.transform(attribute.value); const { output: valueOutput } = value; if (value.error === undefined) { if (valueOutput instanceof Instant) { switch (attribute.attr) { case "offset": case "period": // Method return { input: attribute, output: new InstantOrPeriodMethod(valueOutput, attribute.attr) }; default: { return { input: attribute, output: valueOutput, error: `Unknown instant attribute: ${attribute.attr}` }; } } } if (valueOutput instanceof Period) { switch (attribute.attr) { case "days": case "first_month": case "last_3_months": case "last_month": case "last_year": case "n_2": case "start": case "this_year": // Simple attribute return { input: attribute, output: valueOutput[attribute.attr] }; case "offset": // Method return { input: attribute, output: new InstantOrPeriodMethod(valueOutput, attribute.attr) }; default: { return { input: attribute, output: valueOutput, error: `Unknown period attribute: ${attribute.attr}` }; } } } } const result = this.reduceErrorByKey(attribute, { ...attribute, value: valueOutput }, { value: value.error }); return result.error === undefined ? { ...result, error: "Unhandled Attribute in evaluation of instant or period" } : result; } transform_Call(call) { const args = this.reduceMapErrors(call.args.map(arg => this.transform(arg))); const func = this.transform(call.func); const { output: funcOutput } = func; const keywords = this.reduceMapErrors(call.keywords.map(keyword => this.transform(keyword))); if (args.error === undefined && func.error === undefined && keywords.error === undefined) { if (funcOutput instanceof InstantOrPeriodMethod) { const { instantOrPeriod, methodName } = funcOutput; if (instantOrPeriod instanceof Instant) { switch (methodName) { case "offset": { console.assert(keywords.output.length === 0, "Unexpected keyword argument for Instant.offset() method"); return { input: call, output: instantOrPeriod.offset(...args.output) }; } case "period": { console.assert(keywords.output.length === 0, "Unexpected keyword argument for Instant.period() method"); return { input: call, output: instantOrPeriod.period(...args.output) }; } default: { return { input: call, output: instantOrPeriod, error: `Unknown instant method: ${methodName}` }; } } } if (instantOrPeriod instanceof Period) { switch (methodName) { case "offset": { console.assert(keywords.output.length === 0, "Unexpected keyword argument for Period.offset() method"); return { input: call, output: instantOrPeriod.offset(...args.output) }; } default: { return { input: call, output: instantOrPeriod, error: `Unknown period method: ${methodName}` }; } } } } } const result = this.reduceErrorByKey(call, { ...call, args: args.output, func: funcOutput, keywords: keywords.output }, { args: args.error, func: func.error, keywords: keywords.error }); return result.error === undefined ? { ...result, error: "Unhandled Call in evaluation of instant or period" } : result; } transform_Constant(constant) { return { input: constant, output: constant.value }; } transform_instant_or_period_expression(instantOrPeriodExpression) { const expression = this.transform(instantOrPeriodExpression.expression); return this.reduceErrorByKey(instantOrPeriodExpression, expression.output, { expression: expression.error }); } transform_period(period) { return { input: period, output: this.period }; } transform_UnaryOp(unaryOp) { const operand = this.transform(unaryOp.operand); if (operand.error === undefined) { switch (unaryOp.op.ast_class) { case "Invert": case "Not": break; case "UAdd": return { input: unaryOp, output: operand.output }; case "USub": return { input: unaryOp, output: -operand.output }; default: assertNever("unary operator", unaryOp.op); } } const result = this.reduceErrorByKey(unaryOp, { ...unaryOp, operand: operand.output }, { operand: operand.error }); return result.error === undefined ? { ...result, error: "Unhandled UnaryOp in evaluation of instant or period" } : result; } transformGenericOutputByKey(input, _outputByKey, _errorByKey) { return { input, output: new Instant(9999, 12, 31), error: `Missing instant or period transformer for ${input.ast_class}` }; } } function assertNever(type, value) { throw new Error(`Unexpected ${type}: ${JSON.stringify(value)}`); } export function evaluateOpenfiscaAstInstantOrPeriod(instantOrPeriod, period) { const instantOrPeriodEvaluator = new InstantOrPeriodEvaluator(period); const instantOrPeriodResult = instantOrPeriodEvaluator.transform(instantOrPeriod); if (instantOrPeriodResult.output instanceof InstantOrPeriodMethod) { // Error: Result output is a method instead of a instant or a period. return { input: instantOrPeriodResult.input, output: instantOrPeriodResult.output.instantOrPeriod, error: instantOrPeriodResult.error ?? "Evaluation of instant or period expression is a method instead of a value" }; } if (!(instantOrPeriodResult.output instanceof Instant) && !(instantOrPeriodResult.output instanceof Period) && !Number.isInteger(instantOrPeriodResult.output)) { // Error: Unexpected result output. return { input: instantOrPeriodResult.input, output: new Instant(9999, 12, 31), error: instantOrPeriodResult.error ?? "Unexpected result for evaluation of instant or period" }; } return instantOrPeriodResult; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJJbnN0YW50IiwiUGVyaW9kIiwiQXN0VHJhbnNmb3JtZXIiLCJJbnN0YW50T3JQZXJpb2RNZXRob2QiLCJjb25zdHJ1Y3RvciIsImluc3RhbnRPclBlcmlvZCIsIm1ldGhvZE5hbWUiLCJJbnN0YW50T3JQZXJpb2RFdmFsdWF0b3IiLCJwZXJpb2QiLCJ0cmFuc2Zvcm1fQXR0cmlidXRlIiwiYXR0cmlidXRlIiwidmFsdWUiLCJ0cmFuc2Zvcm0iLCJvdXRwdXQiLCJ2YWx1ZU91dHB1dCIsImVycm9yIiwidW5kZWZpbmVkIiwiYXR0ciIsImlucHV0IiwicmVzdWx0IiwicmVkdWNlRXJyb3JCeUtleSIsInRyYW5zZm9ybV9DYWxsIiwiY2FsbCIsImFyZ3MiLCJyZWR1Y2VNYXBFcnJvcnMiLCJtYXAiLCJhcmciLCJmdW5jIiwiZnVuY091dHB1dCIsImtleXdvcmRzIiwia2V5d29yZCIsImNvbnNvbGUiLCJhc3NlcnQiLCJsZW5ndGgiLCJvZmZzZXQiLCJ0cmFuc2Zvcm1fQ29uc3RhbnQiLCJjb25zdGFudCIsInRyYW5zZm9ybV9pbnN0YW50X29yX3BlcmlvZF9leHByZXNzaW9uIiwiaW5zdGFudE9yUGVyaW9kRXhwcmVzc2lvbiIsImV4cHJlc3Npb24iLCJ0cmFuc2Zvcm1fcGVyaW9kIiwidHJhbnNmb3JtX1VuYXJ5T3AiLCJ1bmFyeU9wIiwib3BlcmFuZCIsIm9wIiwiYXN0X2NsYXNzIiwiYXNzZXJ0TmV2ZXIiLCJ0cmFuc2Zvcm1HZW5lcmljT3V0cHV0QnlLZXkiLCJfb3V0cHV0QnlLZXkiLCJfZXJyb3JCeUtleSIsInR5cGUiLCJFcnJvciIsIkpTT04iLCJzdHJpbmdpZnkiLCJldmFsdWF0ZU9wZW5maXNjYUFzdEluc3RhbnRPclBlcmlvZCIsImluc3RhbnRPclBlcmlvZEV2YWx1YXRvciIsImluc3RhbnRPclBlcmlvZFJlc3VsdCIsIk51bWJlciIsImlzSW50ZWdlciJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hc3QvcGVyaW9kcy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbnN0YW50LCBQZXJpb2QsIFBlcmlvZFVuaXQgfSBmcm9tIFwiLi4vcGVyaW9kc1wiXG5cbmltcG9ydCB0eXBlIHtcbiAgT3BlbmZpc2NhQXN0SW5zdGFudE9yUGVyaW9kRXhwcmVzc2lvbixcbiAgT3BlbmZpc2NhQXN0Tm9kZSxcbiAgT3BlbmZpc2NhQXN0UGVyaW9kLFxuICBQeXRob25Bc3RBdHRyaWJ1dGUsXG4gIFB5dGhvbkFzdENhbGwsXG4gIFB5dGhvbkFzdENvbnN0YW50LFxuICBQeXRob25Bc3RLZXl3b3JkLFxuICBQeXRob25Bc3RVbmFyeU9wLFxufSBmcm9tIFwiLi9ub2Rlc1wiXG5pbXBvcnQgeyBBc3RUcmFuc2Zvcm1lciB9IGZyb20gXCIuL3Zpc2l0b3JzXCJcblxuY2xhc3MgSW5zdGFudE9yUGVyaW9kTWV0aG9kIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHJlYWRvbmx5IGluc3RhbnRPclBlcmlvZDogSW5zdGFudCB8IFBlcmlvZCxcbiAgICBwdWJsaWMgcmVhZG9ubHkgbWV0aG9kTmFtZTogc3RyaW5nLFxuICApIHt9XG59XG5cbmNsYXNzIEluc3RhbnRPclBlcmlvZEV2YWx1YXRvciBleHRlbmRzIEFzdFRyYW5zZm9ybWVyPFxuICBPcGVuZmlzY2FBc3ROb2RlLFxuICB1bmtub3duXG4+IHtcbiAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHBlcmlvZDogUGVyaW9kKSB7XG4gICAgc3VwZXIoKVxuICB9XG5cbiAgdHJhbnNmb3JtX0F0dHJpYnV0ZShhdHRyaWJ1dGU6IFB5dGhvbkFzdEF0dHJpYnV0ZSk6IHtcbiAgICBpbnB1dDogT3BlbmZpc2NhQXN0Tm9kZVxuICAgIG91dHB1dDogdW5rbm93blxuICAgIGVycm9yPzogdW5rbm93blxuICB9IHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMudHJhbnNmb3JtKGF0dHJpYnV0ZS52YWx1ZSlcbiAgICBjb25zdCB7IG91dHB1dDogdmFsdWVPdXRwdXQgfSA9IHZhbHVlXG5cbiAgICBpZiAodmFsdWUuZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHZhbHVlT3V0cHV0IGluc3RhbmNlb2YgSW5zdGFudCkge1xuICAgICAgICBzd2l0Y2ggKGF0dHJpYnV0ZS5hdHRyKSB7XG4gICAgICAgICAgY2FzZSBcIm9mZnNldFwiOlxuICAgICAgICAgIGNhc2UgXCJwZXJpb2RcIjpcbiAgICAgICAgICAgIC8vIE1ldGhvZFxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaW5wdXQ6IGF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAgb3V0cHV0OiBuZXcgSW5zdGFudE9yUGVyaW9kTWV0aG9kKHZhbHVlT3V0cHV0LCBhdHRyaWJ1dGUuYXR0ciksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgZGVmYXVsdDoge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaW5wdXQ6IGF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAgb3V0cHV0OiB2YWx1ZU91dHB1dCxcbiAgICAgICAgICAgICAgZXJyb3I6IGBVbmtub3duIGluc3RhbnQgYXR0cmlidXRlOiAke2F0dHJpYnV0ZS5hdHRyfWAsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodmFsdWVPdXRwdXQgaW5zdGFuY2VvZiBQZXJpb2QpIHtcbiAgICAgICAgc3dpdGNoIChhdHRyaWJ1dGUuYXR0cikge1xuICAgICAgICAgIGNhc2UgXCJkYXlzXCI6XG4gICAgICAgICAgY2FzZSBcImZpcnN0X21vbnRoXCI6XG4gICAgICAgICAgY2FzZSBcImxhc3RfM19tb250aHNcIjpcbiAgICAgICAgICBjYXNlIFwibGFzdF9tb250aFwiOlxuICAgICAgICAgIGNhc2UgXCJsYXN0X3llYXJcIjpcbiAgICAgICAgICBjYXNlIFwibl8yXCI6XG4gICAgICAgICAgY2FzZSBcInN0YXJ0XCI6XG4gICAgICAgICAgY2FzZSBcInRoaXNfeWVhclwiOlxuICAgICAgICAgICAgLy8gU2ltcGxlIGF0dHJpYnV0ZVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgaW5wdXQ6IGF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAgb3V0cHV0OiAodmFsdWVPdXRwdXQgYXMgdW5rbm93biBhcyB7IFthdHRyOiBzdHJpbmddOiB1bmtub3duIH0pW1xuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZS5hdHRyXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgY2FzZSBcIm9mZnNldFwiOlxuICAgICAgICAgICAgLy8gTWV0aG9kXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBpbnB1dDogYXR0cmlidXRlLFxuICAgICAgICAgICAgICBvdXRwdXQ6IG5ldyBJbnN0YW50T3JQZXJpb2RNZXRob2QodmFsdWVPdXRwdXQsIGF0dHJpYnV0ZS5hdHRyKSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBpbnB1dDogYXR0cmlidXRlLFxuICAgICAgICAgICAgICBvdXRwdXQ6IHZhbHVlT3V0cHV0LFxuICAgICAgICAgICAgICBlcnJvcjogYFVua25vd24gcGVyaW9kIGF0dHJpYnV0ZTogJHthdHRyaWJ1dGUuYXR0cn1gLFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMucmVkdWNlRXJyb3JCeUtleShcbiAgICAgIGF0dHJpYnV0ZSxcbiAgICAgIHtcbiAgICAgICAgLi4uYXR0cmlidXRlLFxuICAgICAgICB2YWx1ZTogdmFsdWVPdXRwdXQsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICB2YWx1ZTogdmFsdWUuZXJyb3IsXG4gICAgICB9LFxuICAgIClcbiAgICByZXR1cm4gcmVzdWx0LmVycm9yID09PSB1bmRlZmluZWRcbiAgICAgID8ge1xuICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICBlcnJvcjogXCJVbmhhbmRsZWQgQXR0cmlidXRlIGluIGV2YWx1YXRpb24gb2YgaW5zdGFudCBvciBwZXJpb2RcIixcbiAgICAgICAgfVxuICAgICAgOiByZXN1bHRcbiAgfVxuXG4gIHRyYW5zZm9ybV9DYWxsKGNhbGw6IFB5dGhvbkFzdENhbGwpOiB7XG4gICAgaW5wdXQ6IE9wZW5maXNjYUFzdE5vZGVcbiAgICBvdXRwdXQ6IHVua25vd25cbiAgICBlcnJvcj86IHVua25vd25cbiAgfSB7XG4gICAgY29uc3QgYXJncyA9IHRoaXMucmVkdWNlTWFwRXJyb3JzKFxuICAgICAgY2FsbC5hcmdzLm1hcCgoYXJnKSA9PiB0aGlzLnRyYW5zZm9ybShhcmcpKSxcbiAgICApXG4gICAgY29uc3QgZnVuYyA9IHRoaXMudHJhbnNmb3JtKGNhbGwuZnVuYylcbiAgICBjb25zdCB7IG91dHB1dDogZnVuY091dHB1dCB9ID0gZnVuY1xuICAgIGNvbnN0IGtleXdvcmRzID0gdGhpcy5yZWR1Y2VNYXBFcnJvcnMoXG4gICAgICBjYWxsLmtleXdvcmRzLm1hcCgoa2V5d29yZCkgPT4gdGhpcy50cmFuc2Zvcm0oa2V5d29yZCkpLFxuICAgICkgYXMge1xuICAgICAgaW5wdXQ6IE9wZW5maXNjYUFzdE5vZGVbXVxuICAgICAgb3V0cHV0OiBQeXRob25Bc3RLZXl3b3JkW11cbiAgICAgIGVycm9yPzogdW5rbm93blxuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGFyZ3MuZXJyb3IgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgZnVuYy5lcnJvciA9PT0gdW5kZWZpbmVkICYmXG4gICAgICBrZXl3b3Jkcy5lcnJvciA9PT0gdW5kZWZpbmVkXG4gICAgKSB7XG4gICAgICBpZiAoZnVuY091dHB1dCBpbnN0YW5jZW9mIEluc3RhbnRPclBlcmlvZE1ldGhvZCkge1xuICAgICAgICBjb25zdCB7IGluc3RhbnRPclBlcmlvZCwgbWV0aG9kTmFtZSB9ID0gZnVuY091dHB1dFxuICAgICAgICBpZiAoaW5zdGFudE9yUGVyaW9kIGluc3RhbmNlb2YgSW5zdGFudCkge1xuICAgICAgICAgIHN3aXRjaCAobWV0aG9kTmFtZSkge1xuICAgICAgICAgICAgY2FzZSBcIm9mZnNldFwiOiB7XG4gICAgICAgICAgICAgIGNvbnNvbGUuYXNzZXJ0KFxuICAgICAgICAgICAgICAgIGtleXdvcmRzLm91dHB1dC5sZW5ndGggPT09IDAsXG4gICAgICAgICAgICAgICAgXCJVbmV4cGVjdGVkIGtleXdvcmQgYXJndW1lbnQgZm9yIEluc3RhbnQub2Zmc2V0KCkgbWV0aG9kXCIsXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBpbnB1dDogY2FsbCxcbiAgICAgICAgICAgICAgICBvdXRwdXQ6IGluc3RhbnRPclBlcmlvZC5vZmZzZXQoXG4gICAgICAgICAgICAgICAgICAuLi4oYXJncy5vdXRwdXQgYXMgW1xuICAgICAgICAgICAgICAgICAgICBcImZpcnN0LW9mXCIgfCBcImxhc3Qtb2ZcIiB8IG51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgUGVyaW9kVW5pdCxcbiAgICAgICAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgXCJwZXJpb2RcIjoge1xuICAgICAgICAgICAgICBjb25zb2xlLmFzc2VydChcbiAgICAgICAgICAgICAgICBrZXl3b3Jkcy5vdXRwdXQubGVuZ3RoID09PSAwLFxuICAgICAgICAgICAgICAgIFwiVW5leHBlY3RlZCBrZXl3b3JkIGFyZ3VtZW50IGZvciBJbnN0YW50LnBlcmlvZCgpIG1ldGhvZFwiLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaW5wdXQ6IGNhbGwsXG4gICAgICAgICAgICAgICAgb3V0cHV0OiBpbnN0YW50T3JQZXJpb2QucGVyaW9kKFxuICAgICAgICAgICAgICAgICAgLi4uKGFyZ3Mub3V0cHV0IGFzIFtQZXJpb2RVbml0LCBudW1iZXJdKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaW5wdXQ6IGNhbGwsXG4gICAgICAgICAgICAgICAgb3V0cHV0OiBpbnN0YW50T3JQZXJpb2QsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGBVbmtub3duIGluc3RhbnQgbWV0aG9kOiAke21ldGhvZE5hbWV9YCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaW5zdGFudE9yUGVyaW9kIGluc3RhbmNlb2YgUGVyaW9kKSB7XG4gICAgICAgICAgc3dpdGNoIChtZXRob2ROYW1lKSB7XG4gICAgICAgICAgICBjYXNlIFwib2Zmc2V0XCI6IHtcbiAgICAgICAgICAgICAgY29uc29sZS5hc3NlcnQoXG4gICAgICAgICAgICAgICAga2V5d29yZHMub3V0cHV0Lmxlbmd0aCA9PT0gMCxcbiAgICAgICAgICAgICAgICBcIlVuZXhwZWN0ZWQga2V5d29yZCBhcmd1bWVudCBmb3IgUGVyaW9kLm9mZnNldCgpIG1ldGhvZFwiLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaW5wdXQ6IGNhbGwsXG4gICAgICAgICAgICAgICAgb3V0cHV0OiBpbnN0YW50T3JQZXJpb2Qub2Zmc2V0KFxuICAgICAgICAgICAgICAgICAgLi4uKGFyZ3Mub3V0cHV0IGFzIFtcbiAgICAgICAgICAgICAgICAgICAgXCJmaXJzdC1vZlwiIHwgXCJsYXN0LW9mXCIgfCBudW1iZXIsXG4gICAgICAgICAgICAgICAgICAgIFBlcmlvZFVuaXQgfCB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaW5wdXQ6IGNhbGwsXG4gICAgICAgICAgICAgICAgb3V0cHV0OiBpbnN0YW50T3JQZXJpb2QsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGBVbmtub3duIHBlcmlvZCBtZXRob2Q6ICR7bWV0aG9kTmFtZX1gLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gdGhpcy5yZWR1Y2VFcnJvckJ5S2V5KFxuICAgICAgY2FsbCxcbiAgICAgIHtcbiAgICAgICAgLi4uY2FsbCxcbiAgICAgICAgYXJnczogYXJncy5vdXRwdXQsXG4gICAgICAgIGZ1bmM6IGZ1bmNPdXRwdXQsXG4gICAgICAgIGtleXdvcmRzOiBrZXl3b3Jkcy5vdXRwdXQsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBhcmdzOiBhcmdzLmVycm9yLFxuICAgICAgICBmdW5jOiBmdW5jLmVycm9yLFxuICAgICAgICBrZXl3b3Jkczoga2V5d29yZHMuZXJyb3IsXG4gICAgICB9LFxuICAgIClcbiAgICByZXR1cm4gcmVzdWx0LmVycm9yID09PSB1bmRlZmluZWRcbiAgICAgID8ge1xuICAgICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgICBlcnJvcjogXCJVbmhhbmRsZWQgQ2FsbCBpbiBldmFsdWF0aW9uIG9mIGluc3RhbnQgb3IgcGVyaW9kXCIsXG4gICAgICAgIH1cbiAgICAgIDogcmVzdWx0XG4gIH1cblxuICB0cmFuc2Zvcm1fQ29uc3RhbnQoY29uc3RhbnQ6IFB5dGhvbkFzdENvbnN0YW50KToge1xuICAgIGlucHV0OiBPcGVuZmlzY2FBc3ROb2RlXG4gICAgb3V0cHV0OiB1bmtub3duXG4gICAgZXJyb3I/OiB1bmtub3duXG4gIH0ge1xuICAgIHJldHVybiB7IGlucHV0OiBjb25zdGFudCwgb3V0cHV0OiBjb25zdGFudC52YWx1ZSB9XG4gIH1cblxuICB0cmFuc2Zvcm1faW5zdGFudF9vcl9wZXJpb2RfZXhwcmVzc2lvbihcbiAgICBpbnN0YW50T3JQZXJpb2RFeHByZXNzaW9uOiBPcGVuZmlzY2FBc3RJbnN0YW50T3JQZXJpb2RFeHByZXNzaW9uLFxuICApOiB7XG4gICAgaW5wdXQ6IE9wZW5maXNjYUFzdE5vZGVcbiAgICBvdXRwdXQ6IHVua25vd25cbiAgICBlcnJvcj86IHVua25vd25cbiAgfSB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IHRoaXMudHJhbnNmb3JtKGluc3RhbnRPclBlcmlvZEV4cHJlc3Npb24uZXhwcmVzc2lvbilcbiAgICByZXR1cm4gdGhpcy5yZWR1Y2VFcnJvckJ5S2V5KGluc3RhbnRPclBlcmlvZEV4cHJlc3Npb24sIGV4cHJlc3Npb24ub3V0cHV0LCB7XG4gICAgICBleHByZXNzaW9uOiBleHByZXNzaW9uLmVycm9yLFxuICAgIH0pXG4gIH1cblxuICB0cmFuc2Zvcm1fcGVyaW9kKHBlcmlvZDogT3BlbmZpc2NhQXN0UGVyaW9kKToge1xuICAgIGlucHV0OiBPcGVuZmlzY2FBc3ROb2RlXG4gICAgb3V0cHV0OiB1bmtub3duXG4gICAgZXJyb3I/OiB1bmtub3duXG4gIH0ge1xuICAgIHJldHVybiB7IGlucHV0OiBwZXJpb2QsIG91dHB1dDogdGhpcy5wZXJpb2QgfVxuICB9XG5cbiAgdHJhbnNmb3JtX1VuYXJ5T3AodW5hcnlPcDogUHl0aG9uQXN0VW5hcnlPcCk6IHtcbiAgICBpbnB1dDogT3BlbmZpc2NhQXN0Tm9kZVxuICAgIG91dHB1dDogdW5rbm93blxuICAgIGVycm9yPzogdW5rbm93blxuICB9IHtcbiAgICBjb25zdCBvcGVyYW5kID0gdGhpcy50cmFuc2Zvcm0odW5hcnlPcC5vcGVyYW5kKVxuICAgIGlmIChvcGVyYW5kLmVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHN3aXRjaCAodW5hcnlPcC5vcC5hc3RfY2xhc3MpIHtcbiAgICAgICAgY2FzZSBcIkludmVydFwiOlxuICAgICAgICBjYXNlIFwiTm90XCI6XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSBcIlVBZGRcIjpcbiAgICAgICAgICByZXR1cm4geyBpbnB1dDogdW5hcnlPcCwgb3V0cHV0OiBvcGVyYW5kLm91dHB1dCB9XG4gICAgICAgIGNhc2UgXCJVU3ViXCI6XG4gICAgICAgICAgcmV0dXJuIHsgaW5wdXQ6IHVuYXJ5T3AsIG91dHB1dDogLShvcGVyYW5kLm91dHB1dCBhcyBudW1iZXIpIH1cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBhc3NlcnROZXZlcihcInVuYXJ5IG9wZXJhdG9yXCIsIHVuYXJ5T3Aub3ApXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gdGhpcy5yZWR1Y2VFcnJvckJ5S2V5KFxuICAgICAgdW5hcnlPcCxcbiAgICAgIHtcbiAgICAgICAgLi4udW5hcnlPcCxcbiAgICAgICAgb3BlcmFuZDogb3BlcmFuZC5vdXRwdXQsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBvcGVyYW5kOiBvcGVyYW5kLmVycm9yLFxuICAgICAgfSxcbiAgICApXG4gICAgcmV0dXJuIHJlc3VsdC5lcnJvciA9PT0gdW5kZWZpbmVkXG4gICAgICA/IHtcbiAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgZXJyb3I6IFwiVW5oYW5kbGVkIFVuYXJ5T3AgaW4gZXZhbHVhdGlvbiBvZiBpbnN0YW50IG9yIHBlcmlvZFwiLFxuICAgICAgICB9XG4gICAgICA6IHJlc3VsdFxuICB9XG5cbiAgdHJhbnNmb3JtR2VuZXJpY091dHB1dEJ5S2V5KFxuICAgIGlucHV0OiBPcGVuZmlzY2FBc3ROb2RlLFxuICAgIF9vdXRwdXRCeUtleToge1xuICAgICAgW2tleTogc3RyaW5nXTogdW5rbm93blxuICAgIH0sXG4gICAgX2Vycm9yQnlLZXk6IHtcbiAgICAgIFtrZXk6IHN0cmluZ106IHVua25vd25cbiAgICB9LFxuICApOiB7XG4gICAgaW5wdXQ6IE9wZW5maXNjYUFzdE5vZGVcbiAgICBvdXRwdXQ6IHVua25vd25cbiAgICBlcnJvcj86IHVua25vd25cbiAgfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlucHV0LFxuICAgICAgb3V0cHV0OiBuZXcgSW5zdGFudCg5OTk5LCAxMiwgMzEpLFxuICAgICAgZXJyb3I6IGBNaXNzaW5nIGluc3RhbnQgb3IgcGVyaW9kIHRyYW5zZm9ybWVyIGZvciAke2lucHV0LmFzdF9jbGFzc31gLFxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBhc3NlcnROZXZlcih0eXBlOiBzdHJpbmcsIHZhbHVlOiBuZXZlcik6IG5ldmVyIHtcbiAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkICR7dHlwZX06ICR7SlNPTi5zdHJpbmdpZnkodmFsdWUpfWApXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBldmFsdWF0ZU9wZW5maXNjYUFzdEluc3RhbnRPclBlcmlvZChcbiAgaW5zdGFudE9yUGVyaW9kOiBPcGVuZmlzY2FBc3ROb2RlLFxuICBwZXJpb2Q6IFBlcmlvZCxcbik6IHtcbiAgaW5wdXQ6IE9wZW5maXNjYUFzdE5vZGVcbiAgb3V0cHV0OiBJbnN0YW50IHwgUGVyaW9kIHwgbnVtYmVyXG4gIGVycm9yPzogdW5rbm93blxufSB7XG4gIGNvbnN0IGluc3RhbnRPclBlcmlvZEV2YWx1YXRvciA9IG5ldyBJbnN0YW50T3JQZXJpb2RFdmFsdWF0b3IocGVyaW9kKVxuICBjb25zdCBpbnN0YW50T3JQZXJpb2RSZXN1bHQgPVxuICAgIGluc3RhbnRPclBlcmlvZEV2YWx1YXRvci50cmFuc2Zvcm0oaW5zdGFudE9yUGVyaW9kKVxuICBpZiAoaW5zdGFudE9yUGVyaW9kUmVzdWx0Lm91dHB1dCBpbnN0YW5jZW9mIEluc3RhbnRPclBlcmlvZE1ldGhvZCkge1xuICAgIC8vIEVycm9yOiBSZXN1bHQgb3V0cHV0IGlzIGEgbWV0aG9kIGluc3RlYWQgb2YgYSBpbnN0YW50IG9yIGEgcGVyaW9kLlxuICAgIHJldHVybiB7XG4gICAgICBpbnB1dDogaW5zdGFudE9yUGVyaW9kUmVzdWx0LmlucHV0LFxuICAgICAgb3V0cHV0OiBpbnN0YW50T3JQZXJpb2RSZXN1bHQub3V0cHV0Lmluc3RhbnRPclBlcmlvZCxcbiAgICAgIGVycm9yOlxuICAgICAgICBpbnN0YW50T3JQZXJpb2RSZXN1bHQuZXJyb3IgPz9cbiAgICAgICAgXCJFdmFsdWF0aW9uIG9mIGluc3RhbnQgb3IgcGVyaW9kIGV4cHJlc3Npb24gaXMgYSBtZXRob2QgaW5zdGVhZCBvZiBhIHZhbHVlXCIsXG4gICAgfVxuICB9XG4gIGlmIChcbiAgICAhKGluc3RhbnRPclBlcmlvZFJlc3VsdC5vdXRwdXQgaW5zdGFuY2VvZiBJbnN0YW50KSAmJlxuICAgICEoaW5zdGFudE9yUGVyaW9kUmVzdWx0Lm91dHB1dCBpbnN0YW5jZW9mIFBlcmlvZCkgJiZcbiAgICAhTnVtYmVyLmlzSW50ZWdlcihpbnN0YW50T3JQZXJpb2RSZXN1bHQub3V0cHV0KVxuICApIHtcbiAgICAvLyBFcnJvcjogVW5leHBlY3RlZCByZXN1bHQgb3V0cHV0LlxuICAgIHJldHVybiB7XG4gICAgICBpbnB1dDogaW5zdGFudE9yUGVyaW9kUmVzdWx0LmlucHV0LFxuICAgICAgb3V0cHV0OiBuZXcgSW5zdGFudCg5OTk5LCAxMiwgMzEpLFxuICAgICAgZXJyb3I6XG4gICAgICAgIGluc3RhbnRPclBlcmlvZFJlc3VsdC5lcnJvciA/P1xuICAgICAgICBcIlVuZXhwZWN0ZWQgcmVzdWx0IGZvciBldmFsdWF0aW9uIG9mIGluc3RhbnQgb3IgcGVyaW9kXCIsXG4gICAgfVxuICB9XG4gIHJldHVybiBpbnN0YW50T3JQZXJpb2RSZXN1bHQgYXMge1xuICAgIGlucHV0OiBPcGVuZmlzY2FBc3ROb2RlXG4gICAgb3V0cHV0OiBJbnN0YW50IHwgUGVyaW9kXG4gICAgZXJyb3I/OiB1bmtub3duXG4gIH1c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