IonDecoderBase.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.IonDecoderBase = void 0;
  4. const tslib_1 = require("tslib");
  5. const Reader_1 = require("@jsonjoy.com/buffers/lib/Reader");
  6. const sharedCachedUtf8Decoder_1 = tslib_1.__importDefault(require("@jsonjoy.com/buffers/lib/utf8/sharedCachedUtf8Decoder"));
  7. const Import_1 = require("./Import");
  8. class IonDecoderBase {
  9. constructor(reader) {
  10. this.reader = (reader ?? new Reader_1.Reader());
  11. this.utf8Decoder = sharedCachedUtf8Decoder_1.default;
  12. }
  13. val() {
  14. const typedesc = this.reader.u8();
  15. const type = (typedesc >> 4) & 0xf;
  16. const length = typedesc & 0xf;
  17. switch (type) {
  18. case 0:
  19. return this.readNull(length);
  20. case 1:
  21. return this.readBool(length);
  22. case 2:
  23. return this.readUint(length);
  24. case 3:
  25. return this.readNint(length);
  26. case 4:
  27. return this.readFloat(length);
  28. case 8:
  29. return this.readString(length);
  30. case 10:
  31. return this.readBinary(length);
  32. case 11:
  33. return this.readList(length);
  34. case 13:
  35. return this.readStruct(length);
  36. case 14:
  37. return this.readAnnotation(length);
  38. default:
  39. throw new Error(`Unknown Ion type: 0x${type.toString(16)}`);
  40. }
  41. }
  42. readNull(length) {
  43. if (length === 15)
  44. return null;
  45. if (length === 0) {
  46. this.val();
  47. return null;
  48. }
  49. if (length === 14) {
  50. const padLength = this.readVUint();
  51. this.reader.x += padLength;
  52. this.val();
  53. return null;
  54. }
  55. this.reader.x += length;
  56. this.val();
  57. return null;
  58. }
  59. readBool(length) {
  60. if (length === 15)
  61. return null;
  62. if (length === 0)
  63. return false;
  64. if (length === 1)
  65. return true;
  66. throw new Error(`Invalid bool length: ${length}`);
  67. }
  68. readUint(length) {
  69. if (length === 15)
  70. return null;
  71. if (length === 0)
  72. return 0;
  73. let value = 0;
  74. for (let i = 0; i < length; i++) {
  75. value = value * 256 + this.reader.u8();
  76. }
  77. return value;
  78. }
  79. readNint(length) {
  80. if (length === 15)
  81. return null;
  82. if (length === 0)
  83. throw new Error('Negative zero is illegal');
  84. let value = 0;
  85. for (let i = 0; i < length; i++) {
  86. value = value * 256 + this.reader.u8();
  87. }
  88. return -value;
  89. }
  90. readFloat(length) {
  91. if (length === 15)
  92. return null;
  93. if (length === 0)
  94. return 0.0;
  95. if (length === 4)
  96. return this.reader.f32();
  97. if (length === 8)
  98. return this.reader.f64();
  99. throw new Error(`Unsupported float length: ${length}`);
  100. }
  101. readString(length) {
  102. if (length === 15)
  103. return null;
  104. let actualLength = length;
  105. if (length === 14) {
  106. actualLength = this.readVUint();
  107. }
  108. if (actualLength === 0)
  109. return '';
  110. return this.reader.utf8(actualLength);
  111. }
  112. readBinary(length) {
  113. if (length === 15)
  114. return null;
  115. let actualLength = length;
  116. if (length === 14) {
  117. actualLength = this.readVUint();
  118. }
  119. if (actualLength === 0)
  120. return new Uint8Array(0);
  121. return this.reader.buf(actualLength);
  122. }
  123. readList(length) {
  124. if (length === 15)
  125. return null;
  126. let actualLength = length;
  127. if (length === 14) {
  128. actualLength = this.readVUint();
  129. }
  130. if (actualLength === 0)
  131. return [];
  132. const endPos = this.reader.x + actualLength;
  133. const list = [];
  134. while (this.reader.x < endPos) {
  135. list.push(this.val());
  136. }
  137. if (this.reader.x !== endPos) {
  138. throw new Error('List parsing error: incorrect length');
  139. }
  140. return list;
  141. }
  142. readStruct(length) {
  143. if (length === 15)
  144. return null;
  145. let actualLength = length;
  146. if (length === 14) {
  147. actualLength = this.readVUint();
  148. }
  149. if (actualLength === 0)
  150. return {};
  151. const endPos = this.reader.x + actualLength;
  152. const struct = {};
  153. while (this.reader.x < endPos) {
  154. const fieldNameId = this.readVUint();
  155. const fieldName = this.getSymbolText(fieldNameId);
  156. const fieldValue = this.val();
  157. struct[fieldName] = fieldValue;
  158. }
  159. if (this.reader.x !== endPos) {
  160. throw new Error('Struct parsing error: incorrect length');
  161. }
  162. return struct;
  163. }
  164. readAnnotation(length) {
  165. if (length < 3) {
  166. throw new Error('Annotation wrapper must have at least 3 bytes');
  167. }
  168. let actualLength = length;
  169. if (length === 14) {
  170. actualLength = this.readVUint();
  171. }
  172. const annotLength = this.readVUint();
  173. const endAnnotPos = this.reader.x + annotLength;
  174. while (this.reader.x < endAnnotPos) {
  175. this.readVUint();
  176. }
  177. if (this.reader.x !== endAnnotPos) {
  178. throw new Error('Annotation parsing error: incorrect annotation length');
  179. }
  180. return this.val();
  181. }
  182. readVUint() {
  183. let value = 0;
  184. let byte;
  185. do {
  186. byte = this.reader.u8();
  187. value = (value << 7) | (byte & 0x7f);
  188. } while ((byte & 0x80) === 0);
  189. return value;
  190. }
  191. readVInt() {
  192. const firstByte = this.reader.u8();
  193. if (firstByte & 0x80) {
  194. const sign = firstByte & 0x40 ? -1 : 1;
  195. const magnitude = firstByte & 0x3f;
  196. return sign * magnitude;
  197. }
  198. const sign = firstByte & 0x40 ? -1 : 1;
  199. let magnitude = firstByte & 0x3f;
  200. let byte;
  201. do {
  202. byte = this.reader.u8();
  203. magnitude = (magnitude << 7) | (byte & 0x7f);
  204. } while ((byte & 0x80) === 0);
  205. return sign * magnitude;
  206. }
  207. getSymbolText(symbolId) {
  208. if (!this.symbols) {
  209. throw new Error('No symbol table available');
  210. }
  211. const symbol = this.symbols.getText(symbolId);
  212. if (symbol === undefined) {
  213. throw new Error(`Unknown symbol ID: ${symbolId}`);
  214. }
  215. return symbol;
  216. }
  217. validateBVM() {
  218. const bvm = this.reader.u32();
  219. if (bvm !== 0xe00100ea) {
  220. throw new Error(`Invalid Ion Binary Version Marker: 0x${bvm.toString(16)}`);
  221. }
  222. }
  223. readSymbolTable() {
  224. if (this.reader.x < this.reader.uint8.length) {
  225. const nextByte = this.reader.peak();
  226. const type = (nextByte >> 4) & 0xf;
  227. if (type === 14) {
  228. const annotValue = this.val();
  229. if (annotValue && typeof annotValue === 'object' && !Array.isArray(annotValue)) {
  230. const symbolsKey = 'symbols';
  231. const obj = annotValue;
  232. if (symbolsKey in obj && Array.isArray(obj[symbolsKey])) {
  233. const newSymbols = obj[symbolsKey];
  234. this.symbols = new Import_1.Import(this.symbols || null, newSymbols);
  235. }
  236. }
  237. }
  238. }
  239. }
  240. }
  241. exports.IonDecoderBase = IonDecoderBase;
  242. //# sourceMappingURL=IonDecoderBase.js.map