Writer.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Writer = void 0;
  4. const Slice_1 = require("./Slice");
  5. const EMPTY_UINT8 = new Uint8Array([]);
  6. const EMPTY_VIEW = new DataView(EMPTY_UINT8.buffer);
  7. const hasBuffer = typeof Buffer === 'function';
  8. const utf8Write = hasBuffer
  9. ? Buffer.prototype.utf8Write
  10. : null;
  11. const from = hasBuffer ? Buffer.from : null;
  12. const textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null;
  13. class Writer {
  14. constructor(allocSize = 64 * 1024) {
  15. this.allocSize = allocSize;
  16. this.view = EMPTY_VIEW;
  17. this.x0 = 0;
  18. this.x = 0;
  19. this.uint8 = new Uint8Array(allocSize);
  20. this.size = allocSize;
  21. this.view = new DataView(this.uint8.buffer);
  22. }
  23. grow(size) {
  24. const x0 = this.x0;
  25. const x = this.x;
  26. const oldUint8 = this.uint8;
  27. const newUint8 = new Uint8Array(size);
  28. const view = new DataView(newUint8.buffer);
  29. const activeSlice = oldUint8.subarray(x0, x);
  30. newUint8.set(activeSlice, 0);
  31. this.x = x - x0;
  32. this.x0 = 0;
  33. this.uint8 = newUint8;
  34. this.size = size;
  35. this.view = view;
  36. }
  37. ensureCapacity(capacity) {
  38. const byteLength = this.size;
  39. const remaining = byteLength - this.x;
  40. if (remaining < capacity) {
  41. const total = byteLength - this.x0;
  42. const required = capacity - remaining;
  43. const totalRequired = total + required;
  44. this.grow(totalRequired <= this.allocSize ? this.allocSize : totalRequired * 2);
  45. }
  46. }
  47. move(capacity) {
  48. this.ensureCapacity(capacity);
  49. this.x += capacity;
  50. }
  51. reset() {
  52. this.x0 = this.x;
  53. }
  54. newBuffer(size) {
  55. const uint8 = (this.uint8 = new Uint8Array(size));
  56. this.size = size;
  57. this.view = new DataView(uint8.buffer);
  58. this.x = this.x0 = 0;
  59. }
  60. flush() {
  61. const result = this.uint8.subarray(this.x0, this.x);
  62. this.x0 = this.x;
  63. return result;
  64. }
  65. flushSlice() {
  66. const slice = new Slice_1.Slice(this.uint8, this.view, this.x0, this.x);
  67. this.x0 = this.x;
  68. return slice;
  69. }
  70. u8(char) {
  71. this.ensureCapacity(1);
  72. this.uint8[this.x++] = char;
  73. }
  74. u16(word) {
  75. this.ensureCapacity(2);
  76. this.view.setUint16(this.x, word);
  77. this.x += 2;
  78. }
  79. u32(dword) {
  80. this.ensureCapacity(4);
  81. this.view.setUint32(this.x, dword);
  82. this.x += 4;
  83. }
  84. i32(dword) {
  85. this.ensureCapacity(4);
  86. this.view.setInt32(this.x, dword);
  87. this.x += 4;
  88. }
  89. u64(qword) {
  90. this.ensureCapacity(8);
  91. this.view.setBigUint64(this.x, BigInt(qword));
  92. this.x += 8;
  93. }
  94. f64(float) {
  95. this.ensureCapacity(8);
  96. this.view.setFloat64(this.x, float);
  97. this.x += 8;
  98. }
  99. u8u16(u8, u16) {
  100. this.ensureCapacity(3);
  101. let x = this.x;
  102. this.uint8[x++] = u8;
  103. this.uint8[x++] = u16 >>> 8;
  104. this.uint8[x++] = u16 & 0xff;
  105. this.x = x;
  106. }
  107. u8u32(u8, u32) {
  108. this.ensureCapacity(5);
  109. let x = this.x;
  110. this.uint8[x++] = u8;
  111. this.view.setUint32(x, u32);
  112. this.x = x + 4;
  113. }
  114. u8u64(u8, u64) {
  115. this.ensureCapacity(9);
  116. let x = this.x;
  117. this.uint8[x++] = u8;
  118. this.view.setBigUint64(x, BigInt(u64));
  119. this.x = x + 8;
  120. }
  121. u8f32(u8, f32) {
  122. this.ensureCapacity(5);
  123. let x = this.x;
  124. this.uint8[x++] = u8;
  125. this.view.setFloat32(x, f32);
  126. this.x = x + 4;
  127. }
  128. u8f64(u8, f64) {
  129. this.ensureCapacity(9);
  130. let x = this.x;
  131. this.uint8[x++] = u8;
  132. this.view.setFloat64(x, f64);
  133. this.x = x + 8;
  134. }
  135. buf(buf, length) {
  136. this.ensureCapacity(length);
  137. const x = this.x;
  138. this.uint8.set(buf, x);
  139. this.x = x + length;
  140. }
  141. utf8(str) {
  142. const maxLength = str.length * 4;
  143. if (maxLength < 168)
  144. return this.utf8Native(str);
  145. if (utf8Write) {
  146. const writeLength = utf8Write.call(this.uint8, str, this.x, maxLength);
  147. this.x += writeLength;
  148. return writeLength;
  149. }
  150. else if (from) {
  151. const uint8 = this.uint8;
  152. const offset = uint8.byteOffset + this.x;
  153. const buf = from(uint8.buffer).subarray(offset, offset + maxLength);
  154. const writeLength = buf.write(str, 0, maxLength, 'utf8');
  155. this.x += writeLength;
  156. return writeLength;
  157. }
  158. else if (maxLength > 1024 && textEncoder) {
  159. const writeLength = textEncoder.encodeInto(str, this.uint8.subarray(this.x, this.x + maxLength)).written;
  160. this.x += writeLength;
  161. return writeLength;
  162. }
  163. return this.utf8Native(str);
  164. }
  165. utf8Native(str) {
  166. const length = str.length;
  167. const uint8 = this.uint8;
  168. let offset = this.x;
  169. let pos = 0;
  170. while (pos < length) {
  171. let value = str.charCodeAt(pos++);
  172. if ((value & 0xffffff80) === 0) {
  173. uint8[offset++] = value;
  174. continue;
  175. }
  176. else if ((value & 0xfffff800) === 0) {
  177. uint8[offset++] = ((value >> 6) & 0x1f) | 0xc0;
  178. }
  179. else {
  180. if (value >= 0xd800 && value <= 0xdbff) {
  181. if (pos < length) {
  182. const extra = str.charCodeAt(pos);
  183. if ((extra & 0xfc00) === 0xdc00) {
  184. pos++;
  185. value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
  186. }
  187. }
  188. }
  189. if ((value & 0xffff0000) === 0) {
  190. uint8[offset++] = ((value >> 12) & 0x0f) | 0xe0;
  191. uint8[offset++] = ((value >> 6) & 0x3f) | 0x80;
  192. }
  193. else {
  194. uint8[offset++] = ((value >> 18) & 0x07) | 0xf0;
  195. uint8[offset++] = ((value >> 12) & 0x3f) | 0x80;
  196. uint8[offset++] = ((value >> 6) & 0x3f) | 0x80;
  197. }
  198. }
  199. uint8[offset++] = (value & 0x3f) | 0x80;
  200. }
  201. const writeLength = offset - this.x;
  202. this.x = offset;
  203. return writeLength;
  204. }
  205. ascii(str) {
  206. const length = str.length;
  207. this.ensureCapacity(length);
  208. const uint8 = this.uint8;
  209. let x = this.x;
  210. let pos = 0;
  211. while (pos < length)
  212. uint8[x++] = str.charCodeAt(pos++);
  213. this.x = x;
  214. }
  215. }
  216. exports.Writer = Writer;
  217. //# sourceMappingURL=Writer.js.map