schema.js 5.9 KB

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