"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AsnSchemaStorage = void 0; const asn1js = require("asn1js"); const enums_1 = require("./enums"); const helper_1 = require("./helper"); class AsnSchemaStorage { constructor() { this.items = new WeakMap(); } has(target) { return this.items.has(target); } get(target, checkSchema = false) { const schema = this.items.get(target); if (!schema) { throw new Error(`Cannot get schema for '${target.prototype.constructor.name}' target`); } if (checkSchema && !schema.schema) { throw new Error(`Schema '${target.prototype.constructor.name}' doesn't contain ASN.1 schema. Call 'AsnSchemaStorage.cache'.`); } return schema; } cache(target) { const schema = this.get(target); if (!schema.schema) { schema.schema = this.create(target, true); } } createDefault(target) { const schema = { type: enums_1.AsnTypeTypes.Sequence, items: {} }; const parentSchema = this.findParentSchema(target); if (parentSchema) { Object.assign(schema, parentSchema); schema.items = Object.assign({}, schema.items, parentSchema.items); } return schema; } create(target, useNames) { const schema = this.items.get(target) || this.createDefault(target); const asn1Value = []; for (const key in schema.items) { const item = schema.items[key]; const name = useNames ? key : ""; let asn1Item; if (typeof item.type === "number") { const Asn1TypeName = enums_1.AsnPropTypes[item.type]; const Asn1Type = asn1js[Asn1TypeName]; if (!Asn1Type) { throw new Error(`Cannot get ASN1 class by name '${Asn1TypeName}'`); } asn1Item = new Asn1Type({ name }); } else if ((0, helper_1.isConvertible)(item.type)) { const instance = new item.type(); asn1Item = instance.toSchema(name); } else if (item.optional) { const itemSchema = this.get(item.type); if (itemSchema.type === enums_1.AsnTypeTypes.Choice) { asn1Item = new asn1js.Any({ name }); } else { asn1Item = this.create(item.type, false); asn1Item.name = name; } } else { asn1Item = new asn1js.Any({ name }); } const optional = !!item.optional || item.defaultValue !== undefined; if (item.repeated) { asn1Item.name = ""; const Container = item.repeated === "set" ? asn1js.Set : asn1js.Sequence; asn1Item = new Container({ name: "", value: [new asn1js.Repeated({ name, value: asn1Item })], }); } if (item.context !== null && item.context !== undefined) { if (item.implicit) { if (typeof item.type === "number" || (0, helper_1.isConvertible)(item.type)) { const Container = item.repeated ? asn1js.Constructed : asn1js.Primitive; asn1Value.push(new Container({ name, optional, idBlock: { tagClass: 3, tagNumber: item.context } })); } else { this.cache(item.type); const isRepeated = !!item.repeated; let value = !isRepeated ? this.get(item.type, true).schema : asn1Item; value = "valueBlock" in value ? value.valueBlock.value : value.value; asn1Value.push(new asn1js.Constructed({ name: !isRepeated ? name : "", optional, idBlock: { tagClass: 3, tagNumber: item.context }, value: value, })); } } else { asn1Value.push(new asn1js.Constructed({ optional, idBlock: { tagClass: 3, tagNumber: item.context }, value: [asn1Item], })); } } else { asn1Item.optional = optional; asn1Value.push(asn1Item); } } switch (schema.type) { case enums_1.AsnTypeTypes.Sequence: return new asn1js.Sequence({ value: asn1Value, name: "" }); case enums_1.AsnTypeTypes.Set: return new asn1js.Set({ value: asn1Value, name: "" }); case enums_1.AsnTypeTypes.Choice: return new asn1js.Choice({ value: asn1Value, name: "" }); default: throw new Error(`Unsupported ASN1 type in use`); } } set(target, schema) { this.items.set(target, schema); return this; } findParentSchema(target) { const parent = Object.getPrototypeOf(target); if (parent) { const schema = this.items.get(parent); return schema || this.findParentSchema(parent); } return null; } } exports.AsnSchemaStorage = AsnSchemaStorage;