schema.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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,
  32. items: {},
  33. };
  34. const parentSchema = this.findParentSchema(target);
  35. if (parentSchema) {
  36. Object.assign(schema, parentSchema);
  37. schema.items = Object.assign({}, schema.items, parentSchema.items);
  38. }
  39. return schema;
  40. }
  41. create(target, useNames) {
  42. const schema = this.items.get(target) || this.createDefault(target);
  43. const asn1Value = [];
  44. for (const key in schema.items) {
  45. const item = schema.items[key];
  46. const name = useNames ? key : "";
  47. let asn1Item;
  48. if (typeof item.type === "number") {
  49. const Asn1TypeName = enums_1.AsnPropTypes[item.type];
  50. const Asn1Type = asn1js[Asn1TypeName];
  51. if (!Asn1Type) {
  52. throw new Error(`Cannot get ASN1 class by name '${Asn1TypeName}'`);
  53. }
  54. asn1Item = new Asn1Type({ name });
  55. }
  56. else if ((0, helper_1.isConvertible)(item.type)) {
  57. const instance = new item.type();
  58. asn1Item = instance.toSchema(name);
  59. }
  60. else if (item.optional) {
  61. const itemSchema = this.get(item.type);
  62. if (itemSchema.type === enums_1.AsnTypeTypes.Choice) {
  63. asn1Item = new asn1js.Any({ name });
  64. }
  65. else {
  66. asn1Item = this.create(item.type, false);
  67. asn1Item.name = name;
  68. }
  69. }
  70. else {
  71. asn1Item = new asn1js.Any({ name });
  72. }
  73. const optional = !!item.optional || item.defaultValue !== undefined;
  74. if (item.repeated) {
  75. asn1Item.name = "";
  76. const Container = item.repeated === "set" ? asn1js.Set : asn1js.Sequence;
  77. asn1Item = new Container({
  78. name: "",
  79. value: [
  80. new asn1js.Repeated({
  81. name,
  82. value: asn1Item,
  83. }),
  84. ],
  85. });
  86. }
  87. if (item.context !== null && item.context !== undefined) {
  88. if (item.implicit) {
  89. if (typeof item.type === "number" || (0, helper_1.isConvertible)(item.type)) {
  90. const Container = item.repeated ? asn1js.Constructed : asn1js.Primitive;
  91. asn1Value.push(new Container({
  92. name,
  93. optional,
  94. idBlock: {
  95. tagClass: 3,
  96. tagNumber: item.context,
  97. },
  98. }));
  99. }
  100. else {
  101. this.cache(item.type);
  102. const isRepeated = !!item.repeated;
  103. let value = !isRepeated ? this.get(item.type, true).schema : asn1Item;
  104. value = "valueBlock" in value ? value.valueBlock.value : value.value;
  105. asn1Value.push(new asn1js.Constructed({
  106. name: !isRepeated ? name : "",
  107. optional,
  108. idBlock: {
  109. tagClass: 3,
  110. tagNumber: item.context,
  111. },
  112. value: value,
  113. }));
  114. }
  115. }
  116. else {
  117. asn1Value.push(new asn1js.Constructed({
  118. optional,
  119. idBlock: {
  120. tagClass: 3,
  121. tagNumber: item.context,
  122. },
  123. value: [asn1Item],
  124. }));
  125. }
  126. }
  127. else {
  128. asn1Item.optional = optional;
  129. asn1Value.push(asn1Item);
  130. }
  131. }
  132. switch (schema.type) {
  133. case enums_1.AsnTypeTypes.Sequence:
  134. return new asn1js.Sequence({
  135. value: asn1Value,
  136. name: "",
  137. });
  138. case enums_1.AsnTypeTypes.Set:
  139. return new asn1js.Set({
  140. value: asn1Value,
  141. name: "",
  142. });
  143. case enums_1.AsnTypeTypes.Choice:
  144. return new asn1js.Choice({
  145. value: asn1Value,
  146. name: "",
  147. });
  148. default:
  149. throw new Error("Unsupported ASN1 type in use");
  150. }
  151. }
  152. set(target, schema) {
  153. this.items.set(target, schema);
  154. return this;
  155. }
  156. findParentSchema(target) {
  157. const parent = Object.getPrototypeOf(target);
  158. if (parent) {
  159. const schema = this.items.get(parent);
  160. return schema || this.findParentSchema(parent);
  161. }
  162. return null;
  163. }
  164. }
  165. exports.AsnSchemaStorage = AsnSchemaStorage;