StreamingReader.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.StreamingReader = void 0;
  4. const Writer_1 = require("./Writer");
  5. const decodeUtf8_1 = require("./utf8/decodeUtf8");
  6. const Reader_1 = require("./Reader");
  7. class StreamingReader {
  8. constructor(allocSize = 16 * 1024) {
  9. /**
  10. * Offset from the start of the buffer (x0 in Writer).
  11. */
  12. this.dx = 0;
  13. this.writer = new Writer_1.Writer(allocSize);
  14. }
  15. /**
  16. * Returns the number of bytes remaining in the buffer.
  17. */
  18. size() {
  19. return this.writer.x - this.x;
  20. }
  21. /**
  22. * Assert that there is enough data in the buffer to read `size` bytes.
  23. *
  24. * @param size Number of bytes to read.
  25. */
  26. assertSize(size) {
  27. if (size > this.size())
  28. throw new RangeError('OUT_OF_BOUNDS');
  29. }
  30. /**
  31. * Add a chunk of data to be decoded. The chunk is copied into the
  32. * internal buffer, so you can reuse the chunk after calling this method; or
  33. * this chunk can be neutered by the caller.
  34. *
  35. * @param uint8 `Uint8Array` chunk of data to be decoded.
  36. */
  37. push(uint8) {
  38. this.writer.buf(uint8, uint8.length);
  39. }
  40. /**
  41. * Mark the current position as consumed. This will free up memory
  42. * for reuse.
  43. */
  44. consume() {
  45. this.writer.x0 += this.dx;
  46. this.dx = 0;
  47. }
  48. // ------------------------------------------------------------------ IReader
  49. get uint8() {
  50. return this.writer.uint8;
  51. }
  52. get view() {
  53. return this.writer.view;
  54. }
  55. get x() {
  56. return this.writer.x0 + this.dx;
  57. }
  58. set x(x) {
  59. this.dx = x - this.writer.x0;
  60. }
  61. peek() {
  62. this.assertSize(1);
  63. return this.view.getUint8(this.x);
  64. }
  65. /**
  66. * Get current byte value without advancing the cursor.
  67. * @deprecated Use peek() instead.
  68. */
  69. peak() {
  70. return this.peek();
  71. }
  72. skip(length) {
  73. this.assertSize(length);
  74. this.x += length;
  75. }
  76. buf(size = this.size()) {
  77. this.assertSize(size);
  78. const end = this.x + size;
  79. const bin = this.uint8.subarray(this.x, end);
  80. this.x = end;
  81. return bin;
  82. }
  83. subarray(start = 0, end) {
  84. const x = this.x;
  85. const actualStart = x + start;
  86. const actualEnd = typeof end === 'number' ? x + end : this.size() + x - start;
  87. return this.uint8.subarray(actualStart, actualEnd);
  88. }
  89. /**
  90. * Creates a new {@link Reader} that references the same underlying memory
  91. * buffer. But with independent cursor and end.
  92. *
  93. * @param start Start offset relative to the current cursor position.
  94. * @param end End offset relative to the current cursor position.
  95. * @returns A new {@link Reader} instance.
  96. */
  97. slice(start = 0, end) {
  98. const x = this.x;
  99. const actualStart = x + start;
  100. const actualEnd = typeof end === 'number' ? x + end : this.size() + x - start;
  101. return new Reader_1.Reader(this.uint8, this.view, actualStart, actualEnd);
  102. }
  103. /**
  104. * Similar to {@link slice} but also advances the cursor. Returns a new
  105. * {@link Reader} that references the same underlying memory buffer, starting
  106. * from the current cursor position.
  107. *
  108. * @param size Number of bytes to cut from the current position.
  109. * @returns A new {@link Reader} instance.
  110. */
  111. cut(size = this.size()) {
  112. const slice = this.slice(0, size);
  113. this.skip(size);
  114. return slice;
  115. }
  116. u8() {
  117. this.assertSize(1);
  118. return this.view.getUint8(this.x++);
  119. }
  120. i8() {
  121. this.assertSize(1);
  122. return this.view.getInt8(this.x++);
  123. }
  124. u16() {
  125. this.assertSize(2);
  126. const num = this.view.getUint16(this.x);
  127. this.x += 2;
  128. return num;
  129. }
  130. i16() {
  131. this.assertSize(2);
  132. const num = this.view.getInt16(this.x);
  133. this.x += 2;
  134. return num;
  135. }
  136. u32() {
  137. this.assertSize(4);
  138. const num = this.view.getUint32(this.x);
  139. this.x += 4;
  140. return num;
  141. }
  142. i32() {
  143. this.assertSize(4);
  144. const num = this.view.getInt32(this.x);
  145. this.x += 4;
  146. return num;
  147. }
  148. u64() {
  149. this.assertSize(8);
  150. const num = this.view.getBigUint64(this.x);
  151. this.x += 8;
  152. return num;
  153. }
  154. i64() {
  155. this.assertSize(8);
  156. const num = this.view.getBigInt64(this.x);
  157. this.x += 8;
  158. return num;
  159. }
  160. f32() {
  161. this.assertSize(4);
  162. const pos = this.x;
  163. this.x += 4;
  164. return this.view.getFloat32(pos);
  165. }
  166. f64() {
  167. this.assertSize(8);
  168. const pos = this.x;
  169. this.x += 8;
  170. return this.view.getFloat64(pos);
  171. }
  172. utf8(size) {
  173. this.assertSize(size);
  174. const start = this.x;
  175. this.x += size;
  176. return (0, decodeUtf8_1.decodeUtf8)(this.uint8, start, size);
  177. }
  178. ascii(length) {
  179. this.assertSize(length);
  180. const uint8 = this.uint8;
  181. let str = '';
  182. const end = this.x + length;
  183. for (let i = this.x; i < end; i++)
  184. str += String.fromCharCode(uint8[i]);
  185. this.x = end;
  186. return str;
  187. }
  188. // -------------------------------------------------------- IReaderResettable
  189. reset(uint8) {
  190. this.dx = 0;
  191. this.writer.reset();
  192. this.push(uint8);
  193. }
  194. }
  195. exports.StreamingReader = StreamingReader;
  196. //# sourceMappingURL=StreamingReader.js.map