schema.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.AsnSchemaStorage = void 0;
  4. const asn1js = require("asn1js");
  5. const enums_1 = require("./enums");
  6. const helper_1 = require("./helper");
  7. class AsnSchemaStorage {
  8. constructor() {
  9. this.items = new WeakMap();
  10. }
  11. has(target) {
  12. return this.items.has(target);
  13. }
  14. get(target, checkSchema = false) {
  15. const schema = this.items.get(target);
  16. if (!schema) {
  17. throw new Error(`Cannot get schema for '${target.prototype.constructor.name}' target`);
  18. }
  19. if (checkSchema && !schema.schema) {
  20. throw new Error(`Schema '${target.prototype.constructor.name}' doesn't contain ASN.1 schema. Call 'AsnSchemaStorage.cache'.`);
  21. }
  22. return schema;
  23. }
  24. cache(target) {
  25. const schema = this.get(target);
  26. if (!schema.schema) {
  27. schema.schema = this.create(target, true);
  28. }
  29. }
  30. createDefault(target) {
  31. const schema = { type: enums_1.AsnTypeTypes.Sequence, items: {} };
  32. const parentSchema = this.findParentSchema(target);
  33. if (parentSchema) {
  34. Object.assign(schema, parentSchema);
  35. schema.items = Object.assign({}, schema.items, parentSchema.items);
  36. }
  37. return schema;
  38. }
  39. create(target, useNames) {
  40. const schema = this.items.get(target) || this.createDefault(target);
  41. const asn1Value = [];
  42. for (const key in schema.items) {
  43. const item = schema.items[key];
  44. const name = useNames ? key : "";
  45. let asn1Item;
  46. if (typeof item.type === "number") {
  47. const Asn1TypeName = enums_1.AsnPropTypes[item.type];
  48. const Asn1Type = asn1js[Asn1TypeName];
  49. if (!Asn1Type) {
  50. throw new Error(`Cannot get ASN1 class by name '${Asn1TypeName}'`);
  51. }
  52. asn1Item = new Asn1Type({ name });
  53. }
  54. else if ((0, helper_1.isConvertible)(item.type)) {
  55. const instance = new item.type();
  56. asn1Item = instance.toSchema(name);
  57. }
  58. else if (item.optional) {
  59. const itemSchema = this.get(item.type);
  60. if (itemSchema.type === enums_1.AsnTypeTypes.Choice) {
  61. asn1Item = new asn1js.Any({ name });
  62. }
  63. else {
  64. asn1Item = this.create(item.type, false);
  65. asn1Item.name = name;
  66. }
  67. }
  68. else {
  69. asn1Item = new asn1js.Any({ name });
  70. }
  71. const optional = !!item.optional || item.defaultValue !== undefined;
  72. if (item.repeated) {
  73. asn1Item.name = "";
  74. const Container = item.repeated === "set" ? asn1js.Set : asn1js.Sequence;
  75. asn1Item = new Container({
  76. name: "",
  77. value: [new asn1js.Repeated({ name, value: asn1Item })],
  78. });
  79. }
  80. if (item.context !== null && item.context !== undefined) {
  81. if (item.implicit) {
  82. if (typeof item.type === "number" || (0, helper_1.isConvertible)(item.type)) {
  83. const Container = item.repeated ? asn1js.Constructed : asn1js.Primitive;
  84. asn1Value.push(new Container({ name, optional, idBlock: { tagClass: 3, tagNumber: item.context } }));
  85. }
  86. else {
  87. this.cache(item.type);
  88. const isRepeated = !!item.repeated;
  89. let value = !isRepeated ? this.get(item.type, true).schema : asn1Item;
  90. value =
  91. "valueBlock" in value
  92. ? value.valueBlock.value
  93. :
  94. value.value;
  95. asn1Value.push(new asn1js.Constructed({
  96. name: !isRepeated ? name : "",
  97. optional,
  98. idBlock: { tagClass: 3, tagNumber: item.context },
  99. value: value,
  100. }));
  101. }
  102. }
  103. else {
  104. asn1Value.push(new asn1js.Constructed({
  105. optional,
  106. idBlock: { tagClass: 3, tagNumber: item.context },
  107. value: [asn1Item],
  108. }));
  109. }
  110. }
  111. else {
  112. asn1Item.optional = optional;
  113. asn1Value.push(asn1Item);
  114. }
  115. }
  116. switch (schema.type) {
  117. case enums_1.AsnTypeTypes.Sequence:
  118. return new asn1js.Sequence({ value: asn1Value, name: "" });
  119. case enums_1.AsnTypeTypes.Set:
  120. return new asn1js.Set({ value: asn1Value, name: "" });
  121. case enums_1.AsnTypeTypes.Choice:
  122. return new asn1js.Choice({ value: asn1Value, name: "" });
  123. default:
  124. throw new Error(`Unsupported ASN1 type in use`);
  125. }
  126. }
  127. set(target, schema) {
  128. this.items.set(target, schema);
  129. return this;
  130. }
  131. findParentSchema(target) {
  132. const parent = Object.getPrototypeOf(target);
  133. if (parent) {
  134. const schema = this.items.get(parent);
  135. return schema || this.findParentSchema(parent);
  136. }
  137. return null;
  138. }
  139. }
  140. exports.AsnSchemaStorage = AsnSchemaStorage;