source: trip-planner-front/node_modules/webpack/lib/serialization/BinaryMiddleware.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 25.6 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3*/
4
5"use strict";
6
7const memoize = require("../util/memoize");
8const SerializerMiddleware = require("./SerializerMiddleware");
9
10/** @typedef {import("./types").BufferSerializableType} BufferSerializableType */
11/** @typedef {import("./types").PrimitiveSerializableType} PrimitiveSerializableType */
12
13/*
14Format:
15
16File -> Section*
17
18Section -> NullsSection |
19 BooleansSection |
20 F64NumbersSection |
21 I32NumbersSection |
22 I8NumbersSection |
23 ShortStringSection |
24 StringSection |
25 BufferSection |
26 NopSection
27
28
29
30NullsSection ->
31 NullHeaderByte | Null2HeaderByte | Null3HeaderByte |
32 Nulls8HeaderByte 0xnn (n:count - 4) |
33 Nulls32HeaderByte n:ui32 (n:count - 260) |
34BooleansSection -> TrueHeaderByte | FalseHeaderByte | BooleansSectionHeaderByte BooleansCountAndBitsByte
35F64NumbersSection -> F64NumbersSectionHeaderByte f64*
36I32NumbersSection -> I32NumbersSectionHeaderByte i32*
37I8NumbersSection -> I8NumbersSectionHeaderByte i8*
38ShortStringSection -> ShortStringSectionHeaderByte ascii-byte*
39StringSection -> StringSectionHeaderByte i32:length utf8-byte*
40BufferSection -> BufferSectionHeaderByte i32:length byte*
41NopSection --> NopSectionHeaderByte
42
43ShortStringSectionHeaderByte -> 0b1nnn_nnnn (n:length)
44
45F64NumbersSectionHeaderByte -> 0b001n_nnnn (n:count - 1)
46I32NumbersSectionHeaderByte -> 0b010n_nnnn (n:count - 1)
47I8NumbersSectionHeaderByte -> 0b011n_nnnn (n:count - 1)
48
49NullsSectionHeaderByte -> 0b0001_nnnn (n:count - 1)
50BooleansCountAndBitsByte ->
51 0b0000_1xxx (count = 3) |
52 0b0001_xxxx (count = 4) |
53 0b001x_xxxx (count = 5) |
54 0b01xx_xxxx (count = 6) |
55 0b1nnn_nnnn (n:count - 7, 7 <= count <= 133)
56 0xff n:ui32 (n:count, 134 <= count < 2^32)
57
58StringSectionHeaderByte -> 0b0000_1110
59BufferSectionHeaderByte -> 0b0000_1111
60NopSectionHeaderByte -> 0b0000_1011
61FalseHeaderByte -> 0b0000_1100
62TrueHeaderByte -> 0b0000_1101
63
64RawNumber -> n (n <= 10)
65
66*/
67
68const LAZY_HEADER = 0x0b;
69const TRUE_HEADER = 0x0c;
70const FALSE_HEADER = 0x0d;
71const BOOLEANS_HEADER = 0x0e;
72const NULL_HEADER = 0x10;
73const NULL2_HEADER = 0x11;
74const NULL3_HEADER = 0x12;
75const NULLS8_HEADER = 0x13;
76const NULLS32_HEADER = 0x14;
77const NULL_AND_I8_HEADER = 0x15;
78const NULL_AND_I32_HEADER = 0x16;
79const NULL_AND_TRUE_HEADER = 0x17;
80const NULL_AND_FALSE_HEADER = 0x18;
81const STRING_HEADER = 0x1e;
82const BUFFER_HEADER = 0x1f;
83const I8_HEADER = 0x60;
84const I32_HEADER = 0x40;
85const F64_HEADER = 0x20;
86const SHORT_STRING_HEADER = 0x80;
87
88/** Uplift high-order bits */
89const NUMBERS_HEADER_MASK = 0xe0;
90const NUMBERS_COUNT_MASK = 0x1f; // 0b0001_1111
91const SHORT_STRING_LENGTH_MASK = 0x7f; // 0b0111_1111
92
93const HEADER_SIZE = 1;
94const I8_SIZE = 1;
95const I32_SIZE = 4;
96const F64_SIZE = 8;
97
98const MEASURE_START_OPERATION = Symbol("MEASURE_START_OPERATION");
99const MEASURE_END_OPERATION = Symbol("MEASURE_END_OPERATION");
100
101/** @typedef {typeof MEASURE_START_OPERATION} MEASURE_START_OPERATION_TYPE */
102/** @typedef {typeof MEASURE_END_OPERATION} MEASURE_END_OPERATION_TYPE */
103
104const identifyNumber = n => {
105 if (n === (n | 0)) {
106 if (n <= 127 && n >= -128) return 0;
107 if (n <= 2147483647 && n >= -2147483648) return 1;
108 }
109 return 2;
110};
111
112/**
113 * @typedef {PrimitiveSerializableType[]} DeserializedType
114 * @typedef {BufferSerializableType[]} SerializedType
115 * @extends {SerializerMiddleware<DeserializedType, SerializedType>}
116 */
117class BinaryMiddleware extends SerializerMiddleware {
118 /**
119 * @param {DeserializedType} data data
120 * @param {Object} context context object
121 * @returns {SerializedType|Promise<SerializedType>} serialized data
122 */
123 serialize(data, context) {
124 return this._serialize(data, context);
125 }
126
127 _serializeLazy(fn, context) {
128 return SerializerMiddleware.serializeLazy(fn, data =>
129 this._serialize(data, context)
130 );
131 }
132
133 /**
134 * @param {DeserializedType} data data
135 * @param {Object} context context object
136 * @param {{ leftOverBuffer: Buffer | null, allocationSize: number, increaseCounter: number }} allocationScope allocation scope
137 * @returns {SerializedType} serialized data
138 */
139 _serialize(
140 data,
141 context,
142 allocationScope = {
143 allocationSize: 1024,
144 increaseCounter: 0,
145 leftOverBuffer: null
146 }
147 ) {
148 /** @type {Buffer} */
149 let leftOverBuffer = null;
150 /** @type {BufferSerializableType[]} */
151 let buffers = [];
152 /** @type {Buffer} */
153 let currentBuffer = allocationScope ? allocationScope.leftOverBuffer : null;
154 allocationScope.leftOverBuffer = null;
155 let currentPosition = 0;
156 if (currentBuffer === null) {
157 currentBuffer = Buffer.allocUnsafe(allocationScope.allocationSize);
158 }
159 const allocate = bytesNeeded => {
160 if (currentBuffer !== null) {
161 if (currentBuffer.length - currentPosition >= bytesNeeded) return;
162 flush();
163 }
164 if (leftOverBuffer && leftOverBuffer.length >= bytesNeeded) {
165 currentBuffer = leftOverBuffer;
166 leftOverBuffer = null;
167 } else {
168 currentBuffer = Buffer.allocUnsafe(
169 Math.max(bytesNeeded, allocationScope.allocationSize)
170 );
171 if (
172 !(allocationScope.increaseCounter =
173 (allocationScope.increaseCounter + 1) % 4) &&
174 allocationScope.allocationSize < 16777216
175 ) {
176 allocationScope.allocationSize = allocationScope.allocationSize << 1;
177 }
178 }
179 };
180 const flush = () => {
181 if (currentBuffer !== null) {
182 if (currentPosition > 0) {
183 buffers.push(
184 Buffer.from(
185 currentBuffer.buffer,
186 currentBuffer.byteOffset,
187 currentPosition
188 )
189 );
190 }
191 if (
192 !leftOverBuffer ||
193 leftOverBuffer.length < currentBuffer.length - currentPosition
194 ) {
195 leftOverBuffer = Buffer.from(
196 currentBuffer.buffer,
197 currentBuffer.byteOffset + currentPosition,
198 currentBuffer.byteLength - currentPosition
199 );
200 }
201
202 currentBuffer = null;
203 currentPosition = 0;
204 }
205 };
206 const writeU8 = byte => {
207 currentBuffer.writeUInt8(byte, currentPosition++);
208 };
209 const writeU32 = ui32 => {
210 currentBuffer.writeUInt32LE(ui32, currentPosition);
211 currentPosition += 4;
212 };
213 const measureStack = [];
214 const measureStart = () => {
215 measureStack.push(buffers.length, currentPosition);
216 };
217 const measureEnd = () => {
218 const oldPos = measureStack.pop();
219 const buffersIndex = measureStack.pop();
220 let size = currentPosition - oldPos;
221 for (let i = buffersIndex; i < buffers.length; i++) {
222 size += buffers[i].length;
223 }
224 return size;
225 };
226 for (let i = 0; i < data.length; i++) {
227 const thing = data[i];
228 switch (typeof thing) {
229 case "function": {
230 if (!SerializerMiddleware.isLazy(thing))
231 throw new Error("Unexpected function " + thing);
232 /** @type {SerializedType | (() => SerializedType)} */
233 let serializedData =
234 SerializerMiddleware.getLazySerializedValue(thing);
235 if (serializedData === undefined) {
236 if (SerializerMiddleware.isLazy(thing, this)) {
237 flush();
238 allocationScope.leftOverBuffer = leftOverBuffer;
239 const result =
240 /** @type {(Exclude<PrimitiveSerializableType, Promise<PrimitiveSerializableType>>)[]} */ (
241 thing()
242 );
243 const data = this._serialize(result, context, allocationScope);
244 leftOverBuffer = allocationScope.leftOverBuffer;
245 allocationScope.leftOverBuffer = null;
246 SerializerMiddleware.setLazySerializedValue(thing, data);
247 serializedData = data;
248 } else {
249 serializedData = this._serializeLazy(thing, context);
250 flush();
251 buffers.push(serializedData);
252 break;
253 }
254 } else {
255 if (typeof serializedData === "function") {
256 flush();
257 buffers.push(serializedData);
258 break;
259 }
260 }
261 const lengths = [];
262 for (const item of serializedData) {
263 let last;
264 if (typeof item === "function") {
265 lengths.push(0);
266 } else if (item.length === 0) {
267 // ignore
268 } else if (
269 lengths.length > 0 &&
270 (last = lengths[lengths.length - 1]) !== 0
271 ) {
272 const remaining = 0xffffffff - last;
273 if (remaining >= item.length) {
274 lengths[lengths.length - 1] += item.length;
275 } else {
276 lengths.push(item.length - remaining);
277 lengths[lengths.length - 2] = 0xffffffff;
278 }
279 } else {
280 lengths.push(item.length);
281 }
282 }
283 allocate(5 + lengths.length * 4);
284 writeU8(LAZY_HEADER);
285 writeU32(lengths.length);
286 for (const l of lengths) {
287 writeU32(l);
288 }
289 flush();
290 for (const item of serializedData) {
291 buffers.push(item);
292 }
293 break;
294 }
295 case "string": {
296 const len = Buffer.byteLength(thing);
297 if (len >= 128 || len !== thing.length) {
298 allocate(len + HEADER_SIZE + I32_SIZE);
299 writeU8(STRING_HEADER);
300 writeU32(len);
301 currentBuffer.write(thing, currentPosition);
302 } else {
303 allocate(len + HEADER_SIZE);
304 writeU8(SHORT_STRING_HEADER | len);
305 currentBuffer.write(thing, currentPosition, "latin1");
306 }
307 currentPosition += len;
308 break;
309 }
310 case "number": {
311 const type = identifyNumber(thing);
312 if (type === 0 && thing >= 0 && thing <= 10) {
313 // shortcut for very small numbers
314 allocate(I8_SIZE);
315 writeU8(thing);
316 break;
317 }
318 /**
319 * amount of numbers to write
320 * @type {number}
321 */
322 let n = 1;
323 for (; n < 32 && i + n < data.length; n++) {
324 const item = data[i + n];
325 if (typeof item !== "number") break;
326 if (identifyNumber(item) !== type) break;
327 }
328 switch (type) {
329 case 0:
330 allocate(HEADER_SIZE + I8_SIZE * n);
331 writeU8(I8_HEADER | (n - 1));
332 while (n > 0) {
333 currentBuffer.writeInt8(
334 /** @type {number} */ (data[i]),
335 currentPosition
336 );
337 currentPosition += I8_SIZE;
338 n--;
339 i++;
340 }
341 break;
342 case 1:
343 allocate(HEADER_SIZE + I32_SIZE * n);
344 writeU8(I32_HEADER | (n - 1));
345 while (n > 0) {
346 currentBuffer.writeInt32LE(
347 /** @type {number} */ (data[i]),
348 currentPosition
349 );
350 currentPosition += I32_SIZE;
351 n--;
352 i++;
353 }
354 break;
355 case 2:
356 allocate(HEADER_SIZE + F64_SIZE * n);
357 writeU8(F64_HEADER | (n - 1));
358 while (n > 0) {
359 currentBuffer.writeDoubleLE(
360 /** @type {number} */ (data[i]),
361 currentPosition
362 );
363 currentPosition += F64_SIZE;
364 n--;
365 i++;
366 }
367 break;
368 }
369
370 i--;
371 break;
372 }
373 case "boolean": {
374 let lastByte = thing === true ? 1 : 0;
375 const bytes = [];
376 let count = 1;
377 let n;
378 for (n = 1; n < 0xffffffff && i + n < data.length; n++) {
379 const item = data[i + n];
380 if (typeof item !== "boolean") break;
381 const pos = count & 0x7;
382 if (pos === 0) {
383 bytes.push(lastByte);
384 lastByte = item === true ? 1 : 0;
385 } else if (item === true) {
386 lastByte |= 1 << pos;
387 }
388 count++;
389 }
390 i += count - 1;
391 if (count === 1) {
392 allocate(HEADER_SIZE);
393 writeU8(lastByte === 1 ? TRUE_HEADER : FALSE_HEADER);
394 } else if (count === 2) {
395 allocate(HEADER_SIZE * 2);
396 writeU8(lastByte & 1 ? TRUE_HEADER : FALSE_HEADER);
397 writeU8(lastByte & 2 ? TRUE_HEADER : FALSE_HEADER);
398 } else if (count <= 6) {
399 allocate(HEADER_SIZE + I8_SIZE);
400 writeU8(BOOLEANS_HEADER);
401 writeU8((1 << count) | lastByte);
402 } else if (count <= 133) {
403 allocate(HEADER_SIZE + I8_SIZE + I8_SIZE * bytes.length + I8_SIZE);
404 writeU8(BOOLEANS_HEADER);
405 writeU8(0x80 | (count - 7));
406 for (const byte of bytes) writeU8(byte);
407 writeU8(lastByte);
408 } else {
409 allocate(
410 HEADER_SIZE +
411 I8_SIZE +
412 I32_SIZE +
413 I8_SIZE * bytes.length +
414 I8_SIZE
415 );
416 writeU8(BOOLEANS_HEADER);
417 writeU8(0xff);
418 writeU32(count);
419 for (const byte of bytes) writeU8(byte);
420 writeU8(lastByte);
421 }
422 break;
423 }
424 case "object": {
425 if (thing === null) {
426 let n;
427 for (n = 1; n < 0x100000104 && i + n < data.length; n++) {
428 const item = data[i + n];
429 if (item !== null) break;
430 }
431 i += n - 1;
432 if (n === 1) {
433 if (i + 1 < data.length) {
434 const next = data[i + 1];
435 if (next === true) {
436 allocate(HEADER_SIZE);
437 writeU8(NULL_AND_TRUE_HEADER);
438 i++;
439 } else if (next === false) {
440 allocate(HEADER_SIZE);
441 writeU8(NULL_AND_FALSE_HEADER);
442 i++;
443 } else if (typeof next === "number") {
444 const type = identifyNumber(next);
445 if (type === 0) {
446 allocate(HEADER_SIZE + I8_SIZE);
447 writeU8(NULL_AND_I8_HEADER);
448 currentBuffer.writeInt8(next, currentPosition);
449 currentPosition += I8_SIZE;
450 i++;
451 } else if (type === 1) {
452 allocate(HEADER_SIZE + I32_SIZE);
453 writeU8(NULL_AND_I32_HEADER);
454 currentBuffer.writeInt32LE(next, currentPosition);
455 currentPosition += I32_SIZE;
456 i++;
457 } else {
458 allocate(HEADER_SIZE);
459 writeU8(NULL_HEADER);
460 }
461 } else {
462 allocate(HEADER_SIZE);
463 writeU8(NULL_HEADER);
464 }
465 } else {
466 allocate(HEADER_SIZE);
467 writeU8(NULL_HEADER);
468 }
469 } else if (n === 2) {
470 allocate(HEADER_SIZE);
471 writeU8(NULL2_HEADER);
472 } else if (n === 3) {
473 allocate(HEADER_SIZE);
474 writeU8(NULL3_HEADER);
475 } else if (n < 260) {
476 allocate(HEADER_SIZE + I8_SIZE);
477 writeU8(NULLS8_HEADER);
478 writeU8(n - 4);
479 } else {
480 allocate(HEADER_SIZE + I32_SIZE);
481 writeU8(NULLS32_HEADER);
482 writeU32(n - 260);
483 }
484 } else if (Buffer.isBuffer(thing)) {
485 if (thing.length < 8192) {
486 allocate(HEADER_SIZE + I32_SIZE + thing.length);
487 writeU8(BUFFER_HEADER);
488 writeU32(thing.length);
489 thing.copy(currentBuffer, currentPosition);
490 currentPosition += thing.length;
491 } else {
492 allocate(HEADER_SIZE + I32_SIZE);
493 writeU8(BUFFER_HEADER);
494 writeU32(thing.length);
495 flush();
496 buffers.push(thing);
497 }
498 }
499 break;
500 }
501 case "symbol": {
502 if (thing === MEASURE_START_OPERATION) {
503 measureStart();
504 } else if (thing === MEASURE_END_OPERATION) {
505 const size = measureEnd();
506 allocate(HEADER_SIZE + I32_SIZE);
507 writeU8(I32_HEADER);
508 currentBuffer.writeInt32LE(size, currentPosition);
509 currentPosition += I32_SIZE;
510 }
511 break;
512 }
513 }
514 }
515 flush();
516
517 allocationScope.leftOverBuffer = leftOverBuffer;
518
519 // avoid leaking memory
520 currentBuffer = null;
521 leftOverBuffer = null;
522 allocationScope = undefined;
523 const _buffers = buffers;
524 buffers = undefined;
525 return _buffers;
526 }
527
528 /**
529 * @param {SerializedType} data data
530 * @param {Object} context context object
531 * @returns {DeserializedType|Promise<DeserializedType>} deserialized data
532 */
533 deserialize(data, context) {
534 return this._deserialize(data, context);
535 }
536
537 _createLazyDeserialized(content, context) {
538 return SerializerMiddleware.createLazy(
539 memoize(() => this._deserialize(content, context)),
540 this,
541 undefined,
542 content
543 );
544 }
545
546 _deserializeLazy(fn, context) {
547 return SerializerMiddleware.deserializeLazy(fn, data =>
548 this._deserialize(data, context)
549 );
550 }
551
552 /**
553 * @param {SerializedType} data data
554 * @param {Object} context context object
555 * @returns {DeserializedType} deserialized data
556 */
557 _deserialize(data, context) {
558 let currentDataItem = 0;
559 let currentBuffer = data[0];
560 let currentIsBuffer = Buffer.isBuffer(currentBuffer);
561 let currentPosition = 0;
562
563 const retainedBuffer = context.retainedBuffer || (x => x);
564
565 const checkOverflow = () => {
566 if (currentPosition >= currentBuffer.length) {
567 currentPosition = 0;
568 currentDataItem++;
569 currentBuffer =
570 currentDataItem < data.length ? data[currentDataItem] : null;
571 currentIsBuffer = Buffer.isBuffer(currentBuffer);
572 }
573 };
574 const isInCurrentBuffer = n => {
575 return currentIsBuffer && n + currentPosition <= currentBuffer.length;
576 };
577 const ensureBuffer = () => {
578 if (!currentIsBuffer) {
579 throw new Error(
580 currentBuffer === null
581 ? "Unexpected end of stream"
582 : "Unexpected lazy element in stream"
583 );
584 }
585 };
586 /**
587 * Reads n bytes
588 * @param {number} n amount of bytes to read
589 * @returns {Buffer} buffer with bytes
590 */
591 const read = n => {
592 ensureBuffer();
593 const rem = currentBuffer.length - currentPosition;
594 if (rem < n) {
595 const buffers = [read(rem)];
596 n -= rem;
597 ensureBuffer();
598 while (currentBuffer.length < n) {
599 const b = /** @type {Buffer} */ (currentBuffer);
600 buffers.push(b);
601 n -= b.length;
602 currentDataItem++;
603 currentBuffer =
604 currentDataItem < data.length ? data[currentDataItem] : null;
605 currentIsBuffer = Buffer.isBuffer(currentBuffer);
606 ensureBuffer();
607 }
608 buffers.push(read(n));
609 return Buffer.concat(buffers);
610 }
611 const b = /** @type {Buffer} */ (currentBuffer);
612 const res = Buffer.from(b.buffer, b.byteOffset + currentPosition, n);
613 currentPosition += n;
614 checkOverflow();
615 return res;
616 };
617 /**
618 * Reads up to n bytes
619 * @param {number} n amount of bytes to read
620 * @returns {Buffer} buffer with bytes
621 */
622 const readUpTo = n => {
623 ensureBuffer();
624 const rem = currentBuffer.length - currentPosition;
625 if (rem < n) {
626 n = rem;
627 }
628 const b = /** @type {Buffer} */ (currentBuffer);
629 const res = Buffer.from(b.buffer, b.byteOffset + currentPosition, n);
630 currentPosition += n;
631 checkOverflow();
632 return res;
633 };
634 const readU8 = () => {
635 ensureBuffer();
636 /**
637 * There is no need to check remaining buffer size here
638 * since {@link checkOverflow} guarantees at least one byte remaining
639 */
640 const byte = /** @type {Buffer} */ (currentBuffer).readUInt8(
641 currentPosition
642 );
643 currentPosition += I8_SIZE;
644 checkOverflow();
645 return byte;
646 };
647 const readU32 = () => {
648 return read(I32_SIZE).readUInt32LE(0);
649 };
650 const readBits = (data, n) => {
651 let mask = 1;
652 while (n !== 0) {
653 result.push((data & mask) !== 0);
654 mask = mask << 1;
655 n--;
656 }
657 };
658 const dispatchTable = Array.from({ length: 256 }).map((_, header) => {
659 switch (header) {
660 case LAZY_HEADER:
661 return () => {
662 const count = readU32();
663 const lengths = Array.from({ length: count }).map(() => readU32());
664 const content = [];
665 for (let l of lengths) {
666 if (l === 0) {
667 if (typeof currentBuffer !== "function") {
668 throw new Error("Unexpected non-lazy element in stream");
669 }
670 content.push(currentBuffer);
671 currentDataItem++;
672 currentBuffer =
673 currentDataItem < data.length ? data[currentDataItem] : null;
674 currentIsBuffer = Buffer.isBuffer(currentBuffer);
675 } else {
676 do {
677 const buf = readUpTo(l);
678 l -= buf.length;
679 content.push(retainedBuffer(buf));
680 } while (l > 0);
681 }
682 }
683 result.push(this._createLazyDeserialized(content, context));
684 };
685 case BUFFER_HEADER:
686 return () => {
687 const len = readU32();
688 result.push(retainedBuffer(read(len)));
689 };
690 case TRUE_HEADER:
691 return () => result.push(true);
692 case FALSE_HEADER:
693 return () => result.push(false);
694 case NULL3_HEADER:
695 return () => result.push(null, null, null);
696 case NULL2_HEADER:
697 return () => result.push(null, null);
698 case NULL_HEADER:
699 return () => result.push(null);
700 case NULL_AND_TRUE_HEADER:
701 return () => result.push(null, true);
702 case NULL_AND_FALSE_HEADER:
703 return () => result.push(null, false);
704 case NULL_AND_I8_HEADER:
705 return () => {
706 if (currentIsBuffer) {
707 result.push(
708 null,
709 /** @type {Buffer} */ (currentBuffer).readInt8(currentPosition)
710 );
711 currentPosition += I8_SIZE;
712 checkOverflow();
713 } else {
714 result.push(null, read(I8_SIZE).readInt8(0));
715 }
716 };
717 case NULL_AND_I32_HEADER:
718 return () => {
719 result.push(null);
720 if (isInCurrentBuffer(I32_SIZE)) {
721 result.push(
722 /** @type {Buffer} */ (currentBuffer).readInt32LE(
723 currentPosition
724 )
725 );
726 currentPosition += I32_SIZE;
727 checkOverflow();
728 } else {
729 result.push(read(I32_SIZE).readInt32LE(0));
730 }
731 };
732 case NULLS8_HEADER:
733 return () => {
734 const len = readU8() + 4;
735 for (let i = 0; i < len; i++) {
736 result.push(null);
737 }
738 };
739 case NULLS32_HEADER:
740 return () => {
741 const len = readU32() + 260;
742 for (let i = 0; i < len; i++) {
743 result.push(null);
744 }
745 };
746 case BOOLEANS_HEADER:
747 return () => {
748 const innerHeader = readU8();
749 if ((innerHeader & 0xf0) === 0) {
750 readBits(innerHeader, 3);
751 } else if ((innerHeader & 0xe0) === 0) {
752 readBits(innerHeader, 4);
753 } else if ((innerHeader & 0xc0) === 0) {
754 readBits(innerHeader, 5);
755 } else if ((innerHeader & 0x80) === 0) {
756 readBits(innerHeader, 6);
757 } else if (innerHeader !== 0xff) {
758 let count = (innerHeader & 0x7f) + 7;
759 while (count > 8) {
760 readBits(readU8(), 8);
761 count -= 8;
762 }
763 readBits(readU8(), count);
764 } else {
765 let count = readU32();
766 while (count > 8) {
767 readBits(readU8(), 8);
768 count -= 8;
769 }
770 readBits(readU8(), count);
771 }
772 };
773 case STRING_HEADER:
774 return () => {
775 const len = readU32();
776 if (isInCurrentBuffer(len) && currentPosition + len < 0x7fffffff) {
777 result.push(
778 currentBuffer.toString(
779 undefined,
780 currentPosition,
781 currentPosition + len
782 )
783 );
784 currentPosition += len;
785 checkOverflow();
786 } else {
787 result.push(read(len).toString());
788 }
789 };
790 case SHORT_STRING_HEADER:
791 return () => result.push("");
792 case SHORT_STRING_HEADER | 1:
793 return () => {
794 if (currentIsBuffer && currentPosition < 0x7ffffffe) {
795 result.push(
796 currentBuffer.toString(
797 "latin1",
798 currentPosition,
799 currentPosition + 1
800 )
801 );
802 currentPosition++;
803 checkOverflow();
804 } else {
805 result.push(read(1).toString("latin1"));
806 }
807 };
808 case I8_HEADER:
809 return () => {
810 if (currentIsBuffer) {
811 result.push(
812 /** @type {Buffer} */ (currentBuffer).readInt8(currentPosition)
813 );
814 currentPosition++;
815 checkOverflow();
816 } else {
817 result.push(read(1).readInt8(0));
818 }
819 };
820 default:
821 if (header <= 10) {
822 return () => result.push(header);
823 } else if ((header & SHORT_STRING_HEADER) === SHORT_STRING_HEADER) {
824 const len = header & SHORT_STRING_LENGTH_MASK;
825 return () => {
826 if (
827 isInCurrentBuffer(len) &&
828 currentPosition + len < 0x7fffffff
829 ) {
830 result.push(
831 currentBuffer.toString(
832 "latin1",
833 currentPosition,
834 currentPosition + len
835 )
836 );
837 currentPosition += len;
838 checkOverflow();
839 } else {
840 result.push(read(len).toString("latin1"));
841 }
842 };
843 } else if ((header & NUMBERS_HEADER_MASK) === F64_HEADER) {
844 const len = (header & NUMBERS_COUNT_MASK) + 1;
845 return () => {
846 const need = F64_SIZE * len;
847 if (isInCurrentBuffer(need)) {
848 for (let i = 0; i < len; i++) {
849 result.push(
850 /** @type {Buffer} */ (currentBuffer).readDoubleLE(
851 currentPosition
852 )
853 );
854 currentPosition += F64_SIZE;
855 }
856 checkOverflow();
857 } else {
858 const buf = read(need);
859 for (let i = 0; i < len; i++) {
860 result.push(buf.readDoubleLE(i * F64_SIZE));
861 }
862 }
863 };
864 } else if ((header & NUMBERS_HEADER_MASK) === I32_HEADER) {
865 const len = (header & NUMBERS_COUNT_MASK) + 1;
866 return () => {
867 const need = I32_SIZE * len;
868 if (isInCurrentBuffer(need)) {
869 for (let i = 0; i < len; i++) {
870 result.push(
871 /** @type {Buffer} */ (currentBuffer).readInt32LE(
872 currentPosition
873 )
874 );
875 currentPosition += I32_SIZE;
876 }
877 checkOverflow();
878 } else {
879 const buf = read(need);
880 for (let i = 0; i < len; i++) {
881 result.push(buf.readInt32LE(i * I32_SIZE));
882 }
883 }
884 };
885 } else if ((header & NUMBERS_HEADER_MASK) === I8_HEADER) {
886 const len = (header & NUMBERS_COUNT_MASK) + 1;
887 return () => {
888 const need = I8_SIZE * len;
889 if (isInCurrentBuffer(need)) {
890 for (let i = 0; i < len; i++) {
891 result.push(
892 /** @type {Buffer} */ (currentBuffer).readInt8(
893 currentPosition
894 )
895 );
896 currentPosition += I8_SIZE;
897 }
898 checkOverflow();
899 } else {
900 const buf = read(need);
901 for (let i = 0; i < len; i++) {
902 result.push(buf.readInt8(i * I8_SIZE));
903 }
904 }
905 };
906 } else {
907 return () => {
908 throw new Error(
909 `Unexpected header byte 0x${header.toString(16)}`
910 );
911 };
912 }
913 }
914 });
915
916 /** @type {DeserializedType} */
917 let result = [];
918 while (currentBuffer !== null) {
919 if (typeof currentBuffer === "function") {
920 result.push(this._deserializeLazy(currentBuffer, context));
921 currentDataItem++;
922 currentBuffer =
923 currentDataItem < data.length ? data[currentDataItem] : null;
924 currentIsBuffer = Buffer.isBuffer(currentBuffer);
925 } else {
926 const header = readU8();
927 dispatchTable[header]();
928 }
929 }
930
931 // avoid leaking memory in context
932 let _result = result;
933 result = undefined;
934 return _result;
935 }
936}
937
938module.exports = BinaryMiddleware;
939
940module.exports.MEASURE_START_OPERATION = MEASURE_START_OPERATION;
941module.exports.MEASURE_END_OPERATION = MEASURE_END_OPERATION;
Note: See TracBrowser for help on using the repository browser.