serializer.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.AsnSerializer = void 0;
  4. const tslib_1 = require("tslib");
  5. const asn1js = tslib_1.__importStar(require("asn1js"));
  6. const bytes_1 = require("@peculiar/utils/bytes");
  7. const converters = tslib_1.__importStar(require("./converters"));
  8. const enums_1 = require("./enums");
  9. const helper_1 = require("./helper");
  10. const storage_1 = require("./storage");
  11. class AsnSerializer {
  12. static serialize(obj) {
  13. if (obj instanceof asn1js.BaseBlock) {
  14. return obj.toBER(false);
  15. }
  16. return this.toASN(obj).toBER(false);
  17. }
  18. static toASN(obj) {
  19. if (obj && typeof obj === "object" && (0, helper_1.isConvertible)(obj)) {
  20. return obj.toASN();
  21. }
  22. if (!(obj && typeof obj === "object")) {
  23. throw new TypeError("Parameter 1 should be type of Object.");
  24. }
  25. const target = obj.constructor;
  26. const schema = storage_1.schemaStorage.get(target);
  27. storage_1.schemaStorage.cache(target);
  28. let asn1Value = [];
  29. if (schema.itemType) {
  30. if (!Array.isArray(obj)) {
  31. throw new TypeError("Parameter 1 should be type of Array.");
  32. }
  33. if (typeof schema.itemType === "number") {
  34. const converter = converters.defaultConverter(schema.itemType);
  35. if (!converter) {
  36. throw new Error(`Cannot get default converter for array item of ${target.name} ASN1 schema`);
  37. }
  38. asn1Value = obj.map((o) => converter.toASN(o));
  39. }
  40. else {
  41. asn1Value = obj.map((o) => this.toAsnItem({ type: schema.itemType }, "[]", target, o));
  42. }
  43. }
  44. else {
  45. for (const key in schema.items) {
  46. const schemaItem = schema.items[key];
  47. const objProp = obj[key];
  48. if (objProp === undefined
  49. || schemaItem.defaultValue === objProp
  50. || (typeof schemaItem.defaultValue === "object"
  51. && typeof objProp === "object"
  52. && (0, helper_1.isArrayEqual)(this.serialize(schemaItem.defaultValue), this.serialize(objProp)))) {
  53. continue;
  54. }
  55. const asn1Item = AsnSerializer.toAsnItem(schemaItem, key, target, objProp);
  56. if (typeof schemaItem.context === "number") {
  57. if (schemaItem.implicit) {
  58. if (!schemaItem.repeated
  59. && (typeof schemaItem.type === "number" || (0, helper_1.isConvertible)(schemaItem.type))) {
  60. const value = {};
  61. value.valueHex
  62. = asn1Item instanceof asn1js.Null
  63. ? (0, bytes_1.toArrayBuffer)(asn1Item.valueBeforeDecodeView)
  64. : asn1Item.valueBlock.toBER();
  65. asn1Value.push(new asn1js.Primitive({
  66. optional: schemaItem.optional,
  67. idBlock: {
  68. tagClass: 3,
  69. tagNumber: schemaItem.context,
  70. },
  71. ...value,
  72. }));
  73. }
  74. else {
  75. asn1Value.push(new asn1js.Constructed({
  76. optional: schemaItem.optional,
  77. idBlock: {
  78. tagClass: 3,
  79. tagNumber: schemaItem.context,
  80. },
  81. value: asn1Item.valueBlock.value,
  82. }));
  83. }
  84. }
  85. else {
  86. asn1Value.push(new asn1js.Constructed({
  87. optional: schemaItem.optional,
  88. idBlock: {
  89. tagClass: 3,
  90. tagNumber: schemaItem.context,
  91. },
  92. value: [asn1Item],
  93. }));
  94. }
  95. }
  96. else if (schemaItem.repeated) {
  97. asn1Value = asn1Value.concat(asn1Item);
  98. }
  99. else {
  100. asn1Value.push(asn1Item);
  101. }
  102. }
  103. }
  104. let asnSchema;
  105. switch (schema.type) {
  106. case enums_1.AsnTypeTypes.Sequence:
  107. asnSchema = new asn1js.Sequence({ value: asn1Value });
  108. break;
  109. case enums_1.AsnTypeTypes.Set:
  110. asnSchema = new asn1js.Set({ value: asn1Value });
  111. break;
  112. case enums_1.AsnTypeTypes.Choice:
  113. if (!asn1Value[0]) {
  114. throw new Error(`Schema '${target.name}' has wrong data. Choice cannot be empty.`);
  115. }
  116. asnSchema = asn1Value[0];
  117. break;
  118. }
  119. return asnSchema;
  120. }
  121. static toAsnItem(schemaItem, key, target, objProp) {
  122. let asn1Item;
  123. if (typeof schemaItem.type === "number") {
  124. const converter = schemaItem.converter;
  125. if (!converter) {
  126. throw new Error(`Property '${key}' doesn't have converter for type ${enums_1.AsnPropTypes[schemaItem.type]} in schema '${target.name}'`);
  127. }
  128. if (schemaItem.repeated) {
  129. if (!Array.isArray(objProp)) {
  130. throw new TypeError("Parameter 'objProp' should be type of Array.");
  131. }
  132. const items = Array.from(objProp, (element) => converter.toASN(element));
  133. const Container = schemaItem.repeated === "sequence" ? asn1js.Sequence : asn1js.Set;
  134. asn1Item = new Container({ value: items });
  135. }
  136. else {
  137. asn1Item = converter.toASN(objProp);
  138. }
  139. }
  140. else {
  141. if (schemaItem.repeated) {
  142. if (!Array.isArray(objProp)) {
  143. throw new TypeError("Parameter 'objProp' should be type of Array.");
  144. }
  145. const items = Array.from(objProp, (element) => this.toASN(element));
  146. const Container = schemaItem.repeated === "sequence" ? asn1js.Sequence : asn1js.Set;
  147. asn1Item = new Container({ value: items });
  148. }
  149. else {
  150. asn1Item = this.toASN(objProp);
  151. }
  152. }
  153. return asn1Item;
  154. }
  155. }
  156. exports.AsnSerializer = AsnSerializer;