| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-27 05:32:57 +08:00
										 |  |  | const memoize = require("../util/memoize"); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | const SerializerMiddleware = require("./SerializerMiddleware"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  | /** @typedef {import("./types").BufferSerializableType} BufferSerializableType */ | 
					
						
							|  |  |  | /** @typedef {import("./types").PrimitiveSerializableType} PrimitiveSerializableType */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | Format: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | File -> Section* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Section -> NullsSection | | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 					 BooleansSection | | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 					 F64NumbersSection | | 
					
						
							|  |  |  | 					 I32NumbersSection | | 
					
						
							|  |  |  | 					 I8NumbersSection | | 
					
						
							|  |  |  | 					 ShortStringSection | | 
					
						
							| 
									
										
										
										
											2023-05-31 04:03:07 +08:00
										 |  |  | 					 BigIntSection | | 
					
						
							|  |  |  | 					 I32BigIntSection | | 
					
						
							|  |  |  | 					 I8BigIntSection | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 					 StringSection | | 
					
						
							|  |  |  | 					 BufferSection | | 
					
						
							|  |  |  | 					 NopSection | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | NullsSection -> | 
					
						
							|  |  |  | 	NullHeaderByte | Null2HeaderByte | Null3HeaderByte | | 
					
						
							|  |  |  | 	Nulls8HeaderByte 0xnn (n:count - 4) | | 
					
						
							|  |  |  | 	Nulls32HeaderByte n:ui32 (n:count - 260) | | 
					
						
							|  |  |  | BooleansSection -> TrueHeaderByte | FalseHeaderByte | BooleansSectionHeaderByte BooleansCountAndBitsByte | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | F64NumbersSection -> F64NumbersSectionHeaderByte f64* | 
					
						
							|  |  |  | I32NumbersSection -> I32NumbersSectionHeaderByte i32* | 
					
						
							|  |  |  | I8NumbersSection -> I8NumbersSectionHeaderByte i8* | 
					
						
							| 
									
										
										
										
											2020-12-14 06:20:05 +08:00
										 |  |  | ShortStringSection -> ShortStringSectionHeaderByte ascii-byte* | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | StringSection -> StringSectionHeaderByte i32:length utf8-byte* | 
					
						
							|  |  |  | BufferSection -> BufferSectionHeaderByte i32:length byte* | 
					
						
							|  |  |  | NopSection --> NopSectionHeaderByte | 
					
						
							| 
									
										
										
										
											2023-05-31 04:03:07 +08:00
										 |  |  | BigIntSection -> BigIntSectionHeaderByte i32:length ascii-byte* | 
					
						
							|  |  |  | I32BigIntSection -> I32BigIntSectionHeaderByte i32 | 
					
						
							|  |  |  | I8BigIntSection -> I8BigIntSectionHeaderByte i8 | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ShortStringSectionHeaderByte -> 0b1nnn_nnnn (n:length) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | F64NumbersSectionHeaderByte -> 0b001n_nnnn (n:count - 1) | 
					
						
							|  |  |  | I32NumbersSectionHeaderByte -> 0b010n_nnnn (n:count - 1) | 
					
						
							|  |  |  | I8NumbersSectionHeaderByte -> 0b011n_nnnn (n:count - 1) | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | NullsSectionHeaderByte -> 0b0001_nnnn (n:count - 1) | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | BooleansCountAndBitsByte -> | 
					
						
							|  |  |  | 	0b0000_1xxx (count = 3) | | 
					
						
							|  |  |  | 	0b0001_xxxx (count = 4) | | 
					
						
							|  |  |  | 	0b001x_xxxx (count = 5) | | 
					
						
							|  |  |  | 	0b01xx_xxxx (count = 6) | | 
					
						
							|  |  |  | 	0b1nnn_nnnn (n:count - 7, 7 <= count <= 133) | 
					
						
							|  |  |  | 	0xff n:ui32 (n:count, 134 <= count < 2^32) | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | StringSectionHeaderByte -> 0b0000_1110 | 
					
						
							|  |  |  | BufferSectionHeaderByte -> 0b0000_1111 | 
					
						
							|  |  |  | NopSectionHeaderByte -> 0b0000_1011 | 
					
						
							| 
									
										
										
										
											2023-05-31 04:03:07 +08:00
										 |  |  | BigIntSectionHeaderByte -> 0b0001_1010 | 
					
						
							|  |  |  | I32BigIntSectionHeaderByte -> 0b0001_1100 | 
					
						
							|  |  |  | I8BigIntSectionHeaderByte -> 0b0001_1011 | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | FalseHeaderByte -> 0b0000_1100 | 
					
						
							|  |  |  | TrueHeaderByte -> 0b0000_1101 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RawNumber -> n (n <= 10) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | const LAZY_HEADER = 0x0b; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | const TRUE_HEADER = 0x0c; | 
					
						
							|  |  |  | const FALSE_HEADER = 0x0d; | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | const BOOLEANS_HEADER = 0x0e; | 
					
						
							|  |  |  | const NULL_HEADER = 0x10; | 
					
						
							|  |  |  | const NULL2_HEADER = 0x11; | 
					
						
							|  |  |  | const NULL3_HEADER = 0x12; | 
					
						
							|  |  |  | const NULLS8_HEADER = 0x13; | 
					
						
							|  |  |  | const NULLS32_HEADER = 0x14; | 
					
						
							|  |  |  | const NULL_AND_I8_HEADER = 0x15; | 
					
						
							|  |  |  | const NULL_AND_I32_HEADER = 0x16; | 
					
						
							|  |  |  | const NULL_AND_TRUE_HEADER = 0x17; | 
					
						
							|  |  |  | const NULL_AND_FALSE_HEADER = 0x18; | 
					
						
							| 
									
										
										
										
											2023-05-31 01:09:38 +08:00
										 |  |  | const BIGINT_HEADER = 0x1a; | 
					
						
							|  |  |  | const BIGINT_I8_HEADER = 0x1b; | 
					
						
							|  |  |  | const BIGINT_I32_HEADER = 0x1c; | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | const STRING_HEADER = 0x1e; | 
					
						
							|  |  |  | const BUFFER_HEADER = 0x1f; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | const I8_HEADER = 0x60; | 
					
						
							|  |  |  | const I32_HEADER = 0x40; | 
					
						
							|  |  |  | const F64_HEADER = 0x20; | 
					
						
							|  |  |  | const SHORT_STRING_HEADER = 0x80; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | /** Uplift high-order bits */ | 
					
						
							| 
									
										
										
										
											2023-05-31 01:09:38 +08:00
										 |  |  | const NUMBERS_HEADER_MASK = 0xe0; // 0b1010_0000
 | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | const NUMBERS_COUNT_MASK = 0x1f; // 0b0001_1111
 | 
					
						
							|  |  |  | const SHORT_STRING_LENGTH_MASK = 0x7f; // 0b0111_1111
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const HEADER_SIZE = 1; | 
					
						
							|  |  |  | const I8_SIZE = 1; | 
					
						
							|  |  |  | const I32_SIZE = 4; | 
					
						
							|  |  |  | const F64_SIZE = 8; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-22 01:24:57 +08:00
										 |  |  | const MEASURE_START_OPERATION = Symbol("MEASURE_START_OPERATION"); | 
					
						
							|  |  |  | const MEASURE_END_OPERATION = Symbol("MEASURE_END_OPERATION"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 21:53:23 +08:00
										 |  |  | /** @typedef {typeof MEASURE_START_OPERATION} MEASURE_START_OPERATION_TYPE */ | 
					
						
							|  |  |  | /** @typedef {typeof MEASURE_END_OPERATION} MEASURE_END_OPERATION_TYPE */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-23 02:32:23 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {number} n number | 
					
						
							|  |  |  |  * @returns {0 | 1 | 2} type of number for serialization | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | const identifyNumber = (n) => { | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	if (n === (n | 0)) { | 
					
						
							|  |  |  | 		if (n <= 127 && n >= -128) return 0; | 
					
						
							|  |  |  | 		if (n <= 2147483647 && n >= -2147483648) return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 2; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-30 22:33:47 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {bigint} n bigint | 
					
						
							|  |  |  |  * @returns {0 | 1 | 2} type of bigint for serialization | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | const identifyBigInt = (n) => { | 
					
						
							| 
									
										
										
										
											2023-05-31 01:09:38 +08:00
										 |  |  | 	if (n <= BigInt(127) && n >= BigInt(-128)) return 0; | 
					
						
							|  |  |  | 	if (n <= BigInt(2147483647) && n >= BigInt(-2147483648)) return 1; | 
					
						
							| 
									
										
										
										
											2023-05-30 22:33:47 +08:00
										 |  |  | 	return 2; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | /** @typedef {PrimitiveSerializableType[]} DeserializedType */ | 
					
						
							|  |  |  | /** @typedef {BufferSerializableType[]} SerializedType} */ | 
					
						
							|  |  |  | /** @typedef {{ retainedBuffer?: (x: Buffer) => Buffer }} Context} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  |  * @template LazyInputValue | 
					
						
							|  |  |  |  * @template LazyOutputValue | 
					
						
							|  |  |  |  * @typedef {import("./SerializerMiddleware").LazyFunction<LazyInputValue, LazyOutputValue, BinaryMiddleware, undefined>} LazyFunction | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @extends {SerializerMiddleware<DeserializedType, SerializedType, Context>} | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | class BinaryMiddleware extends SerializerMiddleware { | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  | 	 * @param {DeserializedType} data data | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	 * @param {Context} context context object | 
					
						
							| 
									
										
										
										
											2025-03-11 08:28:01 +08:00
										 |  |  | 	 * @returns {SerializedType | Promise<SerializedType> | null} serialized data | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	serialize(data, context) { | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 		return this._serialize(data, context); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {LazyFunction<DeserializedType, SerializedType>} fn lazy function | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	 * @param {Context} context serialize function | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @returns {LazyFunction<SerializedType, DeserializedType>} new lazy | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2021-04-20 21:17:31 +08:00
										 |  |  | 	_serializeLazy(fn, context) { | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		return SerializerMiddleware.serializeLazy(fn, (data) => | 
					
						
							| 
									
										
										
										
											2021-04-20 21:17:31 +08:00
										 |  |  | 			this._serialize(data, context) | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {DeserializedType} data data | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	 * @param {Context} context context object | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 	 * @param {{ leftOverBuffer: Buffer | null, allocationSize: number, increaseCounter: number }} allocationScope allocation scope | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 	 * @returns {SerializedType} serialized data | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 	_serialize( | 
					
						
							|  |  |  | 		data, | 
					
						
							|  |  |  | 		context, | 
					
						
							|  |  |  | 		allocationScope = { | 
					
						
							|  |  |  | 			allocationSize: 1024, | 
					
						
							|  |  |  | 			increaseCounter: 0, | 
					
						
							|  |  |  | 			leftOverBuffer: null | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	) { | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 		/** @type {Buffer | null} */ | 
					
						
							| 
									
										
										
										
											2020-08-24 20:20:59 +08:00
										 |  |  | 		let leftOverBuffer = null; | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  | 		/** @type {BufferSerializableType[]} */ | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 		let buffers = []; | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 		/** @type {Buffer | null} */ | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 		let currentBuffer = allocationScope ? allocationScope.leftOverBuffer : null; | 
					
						
							|  |  |  | 		allocationScope.leftOverBuffer = null; | 
					
						
							|  |  |  | 		let currentPosition = 0; | 
					
						
							|  |  |  | 		if (currentBuffer === null) { | 
					
						
							|  |  |  | 			currentBuffer = Buffer.allocUnsafe(allocationScope.allocationSize); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @param {number} bytesNeeded bytes needed | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		const allocate = (bytesNeeded) => { | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			if (currentBuffer !== null) { | 
					
						
							|  |  |  | 				if (currentBuffer.length - currentPosition >= bytesNeeded) return; | 
					
						
							|  |  |  | 				flush(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-08-24 20:20:59 +08:00
										 |  |  | 			if (leftOverBuffer && leftOverBuffer.length >= bytesNeeded) { | 
					
						
							|  |  |  | 				currentBuffer = leftOverBuffer; | 
					
						
							|  |  |  | 				leftOverBuffer = null; | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2021-04-19 00:31:56 +08:00
										 |  |  | 				currentBuffer = Buffer.allocUnsafe( | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					Math.max(bytesNeeded, allocationScope.allocationSize) | 
					
						
							| 
									
										
										
										
											2020-08-24 20:20:59 +08:00
										 |  |  | 				); | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 				if ( | 
					
						
							|  |  |  | 					!(allocationScope.increaseCounter = | 
					
						
							|  |  |  | 						(allocationScope.increaseCounter + 1) % 4) && | 
					
						
							|  |  |  | 					allocationScope.allocationSize < 16777216 | 
					
						
							|  |  |  | 				) { | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 					allocationScope.allocationSize <<= 1; | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-08-24 20:20:59 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 		const flush = () => { | 
					
						
							|  |  |  | 			if (currentBuffer !== null) { | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 				if (currentPosition > 0) { | 
					
						
							|  |  |  | 					buffers.push( | 
					
						
							|  |  |  | 						Buffer.from( | 
					
						
							|  |  |  | 							currentBuffer.buffer, | 
					
						
							|  |  |  | 							currentBuffer.byteOffset, | 
					
						
							|  |  |  | 							currentPosition | 
					
						
							|  |  |  | 						) | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-08-24 20:20:59 +08:00
										 |  |  | 				if ( | 
					
						
							|  |  |  | 					!leftOverBuffer || | 
					
						
							|  |  |  | 					leftOverBuffer.length < currentBuffer.length - currentPosition | 
					
						
							| 
									
										
										
										
											2021-06-29 19:02:57 +08:00
										 |  |  | 				) { | 
					
						
							|  |  |  | 					leftOverBuffer = Buffer.from( | 
					
						
							|  |  |  | 						currentBuffer.buffer, | 
					
						
							|  |  |  | 						currentBuffer.byteOffset + currentPosition, | 
					
						
							|  |  |  | 						currentBuffer.byteLength - currentPosition | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 				currentBuffer = null; | 
					
						
							|  |  |  | 				currentPosition = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2023-05-23 02:32:23 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @param {number} byte byte | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		const writeU8 = (byte) => { | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 			/** @type {Buffer} */ | 
					
						
							|  |  |  | 			(currentBuffer).writeUInt8(byte, currentPosition++); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2023-05-23 02:32:23 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @param {number} ui32 ui32 | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		const writeU32 = (ui32) => { | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 			/** @type {Buffer} */ | 
					
						
							|  |  |  | 			(currentBuffer).writeUInt32LE(ui32, currentPosition); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			currentPosition += 4; | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2023-05-23 02:32:23 +08:00
										 |  |  | 		/** @type {number[]} */ | 
					
						
							| 
									
										
										
										
											2019-01-22 01:24:57 +08:00
										 |  |  | 		const measureStack = []; | 
					
						
							|  |  |  | 		const measureStart = () => { | 
					
						
							|  |  |  | 			measureStack.push(buffers.length, currentPosition); | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2023-05-23 02:32:23 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @returns {number} size | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2019-01-22 01:24:57 +08:00
										 |  |  | 		const measureEnd = () => { | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 			const oldPos = /** @type {number} */ (measureStack.pop()); | 
					
						
							|  |  |  | 			const buffersIndex = /** @type {number} */ (measureStack.pop()); | 
					
						
							| 
									
										
										
										
											2019-01-22 01:24:57 +08:00
										 |  |  | 			let size = currentPosition - oldPos; | 
					
						
							|  |  |  | 			for (let i = buffersIndex; i < buffers.length; i++) { | 
					
						
							|  |  |  | 				size += buffers[i].length; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return size; | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 		for (let i = 0; i < data.length; i++) { | 
					
						
							|  |  |  | 			const thing = data[i]; | 
					
						
							|  |  |  | 			switch (typeof thing) { | 
					
						
							|  |  |  | 				case "function": { | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 					if (!SerializerMiddleware.isLazy(thing)) { | 
					
						
							| 
									
										
										
										
											2024-07-31 10:39:30 +08:00
										 |  |  | 						throw new Error(`Unexpected function ${thing}`); | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 					/** @type {SerializedType | LazyFunction<SerializedType, DeserializedType> | undefined} */ | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					let serializedData = | 
					
						
							|  |  |  | 						SerializerMiddleware.getLazySerializedValue(thing); | 
					
						
							|  |  |  | 					if (serializedData === undefined) { | 
					
						
							|  |  |  | 						if (SerializerMiddleware.isLazy(thing, this)) { | 
					
						
							|  |  |  | 							flush(); | 
					
						
							|  |  |  | 							allocationScope.leftOverBuffer = leftOverBuffer; | 
					
						
							|  |  |  | 							const result = | 
					
						
							| 
									
										
										
										
											2025-03-11 08:28:01 +08:00
										 |  |  | 								/** @type {PrimitiveSerializableType[]} */ | 
					
						
							|  |  |  | 								(thing()); | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 							const data = this._serialize(result, context, allocationScope); | 
					
						
							|  |  |  | 							leftOverBuffer = allocationScope.leftOverBuffer; | 
					
						
							|  |  |  | 							allocationScope.leftOverBuffer = null; | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 							SerializerMiddleware.setLazySerializedValue(thing, data); | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 							serializedData = data; | 
					
						
							|  |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 							serializedData = this._serializeLazy(thing, context); | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 							flush(); | 
					
						
							|  |  |  | 							buffers.push(serializedData); | 
					
						
							|  |  |  | 							break; | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:54:55 +08:00
										 |  |  | 					} else if (typeof serializedData === "function") { | 
					
						
							|  |  |  | 						flush(); | 
					
						
							|  |  |  | 						buffers.push(serializedData); | 
					
						
							|  |  |  | 						break; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2023-05-23 02:32:23 +08:00
										 |  |  | 					/** @type {number[]} */ | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					const lengths = []; | 
					
						
							|  |  |  | 					for (const item of serializedData) { | 
					
						
							|  |  |  | 						let last; | 
					
						
							|  |  |  | 						if (typeof item === "function") { | 
					
						
							|  |  |  | 							lengths.push(0); | 
					
						
							|  |  |  | 						} else if (item.length === 0) { | 
					
						
							|  |  |  | 							// ignore
 | 
					
						
							|  |  |  | 						} else if ( | 
					
						
							|  |  |  | 							lengths.length > 0 && | 
					
						
							|  |  |  | 							(last = lengths[lengths.length - 1]) !== 0 | 
					
						
							|  |  |  | 						) { | 
					
						
							|  |  |  | 							const remaining = 0xffffffff - last; | 
					
						
							|  |  |  | 							if (remaining >= item.length) { | 
					
						
							|  |  |  | 								lengths[lengths.length - 1] += item.length; | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								lengths.push(item.length - remaining); | 
					
						
							|  |  |  | 								lengths[lengths.length - 2] = 0xffffffff; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 							lengths.push(item.length); | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					allocate(5 + lengths.length * 4); | 
					
						
							|  |  |  | 					writeU8(LAZY_HEADER); | 
					
						
							|  |  |  | 					writeU32(lengths.length); | 
					
						
							|  |  |  | 					for (const l of lengths) { | 
					
						
							|  |  |  | 						writeU32(l); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					flush(); | 
					
						
							|  |  |  | 					for (const item of serializedData) { | 
					
						
							|  |  |  | 						buffers.push(item); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				case "string": { | 
					
						
							|  |  |  | 					const len = Buffer.byteLength(thing); | 
					
						
							|  |  |  | 					if (len >= 128 || len !== thing.length) { | 
					
						
							|  |  |  | 						allocate(len + HEADER_SIZE + I32_SIZE); | 
					
						
							|  |  |  | 						writeU8(STRING_HEADER); | 
					
						
							|  |  |  | 						writeU32(len); | 
					
						
							|  |  |  | 						currentBuffer.write(thing, currentPosition); | 
					
						
							| 
									
										
										
										
											2021-09-24 20:32:26 +08:00
										 |  |  | 						currentPosition += len; | 
					
						
							|  |  |  | 					} else if (len >= 70) { | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 						allocate(len + HEADER_SIZE); | 
					
						
							|  |  |  | 						writeU8(SHORT_STRING_HEADER | len); | 
					
						
							| 
									
										
										
										
											2021-09-24 20:32:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 						currentBuffer.write(thing, currentPosition, "latin1"); | 
					
						
							| 
									
										
										
										
											2021-09-24 20:32:26 +08:00
										 |  |  | 						currentPosition += len; | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						allocate(len + HEADER_SIZE); | 
					
						
							|  |  |  | 						writeU8(SHORT_STRING_HEADER | len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 							currentBuffer[currentPosition++] = thing.charCodeAt(i); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-05-30 10:18:06 +08:00
										 |  |  | 				case "bigint": { | 
					
						
							| 
									
										
										
										
											2023-05-30 22:33:47 +08:00
										 |  |  | 					const type = identifyBigInt(thing); | 
					
						
							|  |  |  | 					if (type === 0 && thing >= 0 && thing <= BigInt(10)) { | 
					
						
							|  |  |  | 						// shortcut for very small bigints
 | 
					
						
							|  |  |  | 						allocate(HEADER_SIZE + I8_SIZE); | 
					
						
							| 
									
										
										
										
											2023-05-31 01:09:38 +08:00
										 |  |  | 						writeU8(BIGINT_I8_HEADER); | 
					
						
							| 
									
										
										
										
											2023-05-30 22:33:47 +08:00
										 |  |  | 						writeU8(Number(thing)); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-31 01:09:38 +08:00
										 |  |  | 					switch (type) { | 
					
						
							|  |  |  | 						case 0: { | 
					
						
							|  |  |  | 							let n = 1; | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE + I8_SIZE * n); | 
					
						
							|  |  |  | 							writeU8(BIGINT_I8_HEADER | (n - 1)); | 
					
						
							|  |  |  | 							while (n > 0) { | 
					
						
							|  |  |  | 								currentBuffer.writeInt8( | 
					
						
							|  |  |  | 									Number(/** @type {bigint} */ (data[i])), | 
					
						
							|  |  |  | 									currentPosition | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								currentPosition += I8_SIZE; | 
					
						
							|  |  |  | 								n--; | 
					
						
							|  |  |  | 								i++; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							i--; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						case 1: { | 
					
						
							|  |  |  | 							let n = 1; | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE + I32_SIZE * n); | 
					
						
							|  |  |  | 							writeU8(BIGINT_I32_HEADER | (n - 1)); | 
					
						
							|  |  |  | 							while (n > 0) { | 
					
						
							|  |  |  | 								currentBuffer.writeInt32LE( | 
					
						
							|  |  |  | 									Number(/** @type {bigint} */ (data[i])), | 
					
						
							|  |  |  | 									currentPosition | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								currentPosition += I32_SIZE; | 
					
						
							|  |  |  | 								n--; | 
					
						
							|  |  |  | 								i++; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							i--; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						default: { | 
					
						
							|  |  |  | 							const value = thing.toString(); | 
					
						
							|  |  |  | 							const len = Buffer.byteLength(value); | 
					
						
							|  |  |  | 							allocate(len + HEADER_SIZE + I32_SIZE); | 
					
						
							|  |  |  | 							writeU8(BIGINT_HEADER); | 
					
						
							|  |  |  | 							writeU32(len); | 
					
						
							|  |  |  | 							currentBuffer.write(value, currentPosition); | 
					
						
							|  |  |  | 							currentPosition += len; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2023-05-30 10:18:06 +08:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 				case "number": { | 
					
						
							|  |  |  | 					const type = identifyNumber(thing); | 
					
						
							|  |  |  | 					if (type === 0 && thing >= 0 && thing <= 10) { | 
					
						
							|  |  |  | 						// shortcut for very small numbers
 | 
					
						
							|  |  |  | 						allocate(I8_SIZE); | 
					
						
							|  |  |  | 						writeU8(thing); | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 						break; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					/** | 
					
						
							|  |  |  | 					 * amount of numbers to write | 
					
						
							|  |  |  | 					 * @type {number} | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 					let n = 1; | 
					
						
							|  |  |  | 					for (; n < 32 && i + n < data.length; n++) { | 
					
						
							|  |  |  | 						const item = data[i + n]; | 
					
						
							|  |  |  | 						if (typeof item !== "number") break; | 
					
						
							|  |  |  | 						if (identifyNumber(item) !== type) break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					switch (type) { | 
					
						
							|  |  |  | 						case 0: | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE + I8_SIZE * n); | 
					
						
							|  |  |  | 							writeU8(I8_HEADER | (n - 1)); | 
					
						
							|  |  |  | 							while (n > 0) { | 
					
						
							|  |  |  | 								currentBuffer.writeInt8( | 
					
						
							|  |  |  | 									/** @type {number} */ (data[i]), | 
					
						
							|  |  |  | 									currentPosition | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								currentPosition += I8_SIZE; | 
					
						
							|  |  |  | 								n--; | 
					
						
							|  |  |  | 								i++; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 							break; | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 						case 1: | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE + I32_SIZE * n); | 
					
						
							|  |  |  | 							writeU8(I32_HEADER | (n - 1)); | 
					
						
							|  |  |  | 							while (n > 0) { | 
					
						
							|  |  |  | 								currentBuffer.writeInt32LE( | 
					
						
							|  |  |  | 									/** @type {number} */ (data[i]), | 
					
						
							|  |  |  | 									currentPosition | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								currentPosition += I32_SIZE; | 
					
						
							|  |  |  | 								n--; | 
					
						
							|  |  |  | 								i++; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						case 2: | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE + F64_SIZE * n); | 
					
						
							|  |  |  | 							writeU8(F64_HEADER | (n - 1)); | 
					
						
							|  |  |  | 							while (n > 0) { | 
					
						
							|  |  |  | 								currentBuffer.writeDoubleLE( | 
					
						
							|  |  |  | 									/** @type {number} */ (data[i]), | 
					
						
							|  |  |  | 									currentPosition | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								currentPosition += F64_SIZE; | 
					
						
							|  |  |  | 								n--; | 
					
						
							|  |  |  | 								i++; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					i--; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				case "boolean": { | 
					
						
							|  |  |  | 					let lastByte = thing === true ? 1 : 0; | 
					
						
							|  |  |  | 					const bytes = []; | 
					
						
							|  |  |  | 					let count = 1; | 
					
						
							|  |  |  | 					let n; | 
					
						
							|  |  |  | 					for (n = 1; n < 0xffffffff && i + n < data.length; n++) { | 
					
						
							|  |  |  | 						const item = data[i + n]; | 
					
						
							|  |  |  | 						if (typeof item !== "boolean") break; | 
					
						
							|  |  |  | 						const pos = count & 0x7; | 
					
						
							|  |  |  | 						if (pos === 0) { | 
					
						
							|  |  |  | 							bytes.push(lastByte); | 
					
						
							|  |  |  | 							lastByte = item === true ? 1 : 0; | 
					
						
							|  |  |  | 						} else if (item === true) { | 
					
						
							|  |  |  | 							lastByte |= 1 << pos; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						count++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					i += count - 1; | 
					
						
							|  |  |  | 					if (count === 1) { | 
					
						
							|  |  |  | 						allocate(HEADER_SIZE); | 
					
						
							|  |  |  | 						writeU8(lastByte === 1 ? TRUE_HEADER : FALSE_HEADER); | 
					
						
							|  |  |  | 					} else if (count === 2) { | 
					
						
							|  |  |  | 						allocate(HEADER_SIZE * 2); | 
					
						
							|  |  |  | 						writeU8(lastByte & 1 ? TRUE_HEADER : FALSE_HEADER); | 
					
						
							|  |  |  | 						writeU8(lastByte & 2 ? TRUE_HEADER : FALSE_HEADER); | 
					
						
							|  |  |  | 					} else if (count <= 6) { | 
					
						
							|  |  |  | 						allocate(HEADER_SIZE + I8_SIZE); | 
					
						
							|  |  |  | 						writeU8(BOOLEANS_HEADER); | 
					
						
							|  |  |  | 						writeU8((1 << count) | lastByte); | 
					
						
							|  |  |  | 					} else if (count <= 133) { | 
					
						
							|  |  |  | 						allocate(HEADER_SIZE + I8_SIZE + I8_SIZE * bytes.length + I8_SIZE); | 
					
						
							|  |  |  | 						writeU8(BOOLEANS_HEADER); | 
					
						
							|  |  |  | 						writeU8(0x80 | (count - 7)); | 
					
						
							|  |  |  | 						for (const byte of bytes) writeU8(byte); | 
					
						
							|  |  |  | 						writeU8(lastByte); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						allocate( | 
					
						
							|  |  |  | 							HEADER_SIZE + | 
					
						
							|  |  |  | 								I8_SIZE + | 
					
						
							|  |  |  | 								I32_SIZE + | 
					
						
							|  |  |  | 								I8_SIZE * bytes.length + | 
					
						
							|  |  |  | 								I8_SIZE | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 						writeU8(BOOLEANS_HEADER); | 
					
						
							|  |  |  | 						writeU8(0xff); | 
					
						
							|  |  |  | 						writeU32(count); | 
					
						
							|  |  |  | 						for (const byte of bytes) writeU8(byte); | 
					
						
							|  |  |  | 						writeU8(lastByte); | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				case "object": { | 
					
						
							|  |  |  | 					if (thing === null) { | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 						let n; | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 						for (n = 1; n < 0x100000104 && i + n < data.length; n++) { | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 							const item = data[i + n]; | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 							if (item !== null) break; | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 						i += n - 1; | 
					
						
							|  |  |  | 						if (n === 1) { | 
					
						
							|  |  |  | 							if (i + 1 < data.length) { | 
					
						
							|  |  |  | 								const next = data[i + 1]; | 
					
						
							|  |  |  | 								if (next === true) { | 
					
						
							|  |  |  | 									allocate(HEADER_SIZE); | 
					
						
							|  |  |  | 									writeU8(NULL_AND_TRUE_HEADER); | 
					
						
							|  |  |  | 									i++; | 
					
						
							|  |  |  | 								} else if (next === false) { | 
					
						
							|  |  |  | 									allocate(HEADER_SIZE); | 
					
						
							|  |  |  | 									writeU8(NULL_AND_FALSE_HEADER); | 
					
						
							|  |  |  | 									i++; | 
					
						
							|  |  |  | 								} else if (typeof next === "number") { | 
					
						
							|  |  |  | 									const type = identifyNumber(next); | 
					
						
							|  |  |  | 									if (type === 0) { | 
					
						
							|  |  |  | 										allocate(HEADER_SIZE + I8_SIZE); | 
					
						
							|  |  |  | 										writeU8(NULL_AND_I8_HEADER); | 
					
						
							|  |  |  | 										currentBuffer.writeInt8(next, currentPosition); | 
					
						
							|  |  |  | 										currentPosition += I8_SIZE; | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 										i++; | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 									} else if (type === 1) { | 
					
						
							|  |  |  | 										allocate(HEADER_SIZE + I32_SIZE); | 
					
						
							|  |  |  | 										writeU8(NULL_AND_I32_HEADER); | 
					
						
							|  |  |  | 										currentBuffer.writeInt32LE(next, currentPosition); | 
					
						
							|  |  |  | 										currentPosition += I32_SIZE; | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 										i++; | 
					
						
							|  |  |  | 									} else { | 
					
						
							|  |  |  | 										allocate(HEADER_SIZE); | 
					
						
							|  |  |  | 										writeU8(NULL_HEADER); | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} else { | 
					
						
							|  |  |  | 									allocate(HEADER_SIZE); | 
					
						
							|  |  |  | 									writeU8(NULL_HEADER); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} else { | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 								allocate(HEADER_SIZE); | 
					
						
							|  |  |  | 								writeU8(NULL_HEADER); | 
					
						
							| 
									
										
										
										
											2021-04-08 18:39:30 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 						} else if (n === 2) { | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE); | 
					
						
							|  |  |  | 							writeU8(NULL2_HEADER); | 
					
						
							|  |  |  | 						} else if (n === 3) { | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE); | 
					
						
							|  |  |  | 							writeU8(NULL3_HEADER); | 
					
						
							|  |  |  | 						} else if (n < 260) { | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE + I8_SIZE); | 
					
						
							|  |  |  | 							writeU8(NULLS8_HEADER); | 
					
						
							|  |  |  | 							writeU8(n - 4); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE + I32_SIZE); | 
					
						
							|  |  |  | 							writeU8(NULLS32_HEADER); | 
					
						
							|  |  |  | 							writeU32(n - 260); | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					} else if (Buffer.isBuffer(thing)) { | 
					
						
							|  |  |  | 						if (thing.length < 8192) { | 
					
						
							|  |  |  | 							allocate(HEADER_SIZE + I32_SIZE + thing.length); | 
					
						
							|  |  |  | 							writeU8(BUFFER_HEADER); | 
					
						
							|  |  |  | 							writeU32(thing.length); | 
					
						
							|  |  |  | 							thing.copy(currentBuffer, currentPosition); | 
					
						
							|  |  |  | 							currentPosition += thing.length; | 
					
						
							|  |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | 							allocate(HEADER_SIZE + I32_SIZE); | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 							writeU8(BUFFER_HEADER); | 
					
						
							|  |  |  | 							writeU32(thing.length); | 
					
						
							|  |  |  | 							flush(); | 
					
						
							|  |  |  | 							buffers.push(thing); | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2019-01-22 01:24:57 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				case "symbol": { | 
					
						
							|  |  |  | 					if (thing === MEASURE_START_OPERATION) { | 
					
						
							|  |  |  | 						measureStart(); | 
					
						
							|  |  |  | 					} else if (thing === MEASURE_END_OPERATION) { | 
					
						
							|  |  |  | 						const size = measureEnd(); | 
					
						
							|  |  |  | 						allocate(HEADER_SIZE + I32_SIZE); | 
					
						
							|  |  |  | 						writeU8(I32_HEADER); | 
					
						
							|  |  |  | 						currentBuffer.writeInt32LE(size, currentPosition); | 
					
						
							|  |  |  | 						currentPosition += I32_SIZE; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2019-01-22 01:24:57 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2024-07-31 09:37:24 +08:00
										 |  |  | 				default: { | 
					
						
							|  |  |  | 					throw new Error( | 
					
						
							|  |  |  | 						`Unknown typeof "${typeof thing}" in binary middleware` | 
					
						
							|  |  |  | 					); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		flush(); | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 23:30:00 +08:00
										 |  |  | 		allocationScope.leftOverBuffer = leftOverBuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 		// avoid leaking memory
 | 
					
						
							|  |  |  | 		currentBuffer = null; | 
					
						
							|  |  |  | 		leftOverBuffer = null; | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 		allocationScope = /** @type {EXPECTED_ANY} */ (undefined); | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 		const _buffers = buffers; | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 		buffers = /** @type {EXPECTED_ANY} */ (undefined); | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 		return _buffers; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2019-01-24 23:51:05 +08:00
										 |  |  | 	 * @param {SerializedType} data data | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	 * @param {Context} context context object | 
					
						
							|  |  |  | 	 * @returns {DeserializedType | Promise<DeserializedType>} deserialized data | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	deserialize(data, context) { | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 		return this._deserialize(data, context); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @private | 
					
						
							|  |  |  | 	 * @param {SerializedType} content content | 
					
						
							|  |  |  | 	 * @param {Context} context context object | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @returns {LazyFunction<DeserializedType, SerializedType>} lazy function | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2021-04-20 21:17:31 +08:00
										 |  |  | 	_createLazyDeserialized(content, context) { | 
					
						
							|  |  |  | 		return SerializerMiddleware.createLazy( | 
					
						
							|  |  |  | 			memoize(() => this._deserialize(content, context)), | 
					
						
							|  |  |  | 			this, | 
					
						
							|  |  |  | 			undefined, | 
					
						
							|  |  |  | 			content | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @private | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @param {LazyFunction<SerializedType, DeserializedType>} fn lazy function | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	 * @param {Context} context context object | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 	 * @returns {LazyFunction<DeserializedType, SerializedType>} new lazy | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2021-04-20 21:17:31 +08:00
										 |  |  | 	_deserializeLazy(fn, context) { | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		return SerializerMiddleware.deserializeLazy(fn, (data) => | 
					
						
							| 
									
										
										
										
											2021-04-20 21:17:31 +08:00
										 |  |  | 			this._deserialize(data, context) | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {SerializedType} data data | 
					
						
							| 
									
										
										
										
											2025-03-07 21:12:22 +08:00
										 |  |  | 	 * @param {Context} context context object | 
					
						
							| 
									
										
										
										
											2020-01-24 06:51:49 +08:00
										 |  |  | 	 * @returns {DeserializedType} deserialized data | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	_deserialize(data, context) { | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		let currentDataItem = 0; | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 		/** @type {BufferSerializableType | null} */ | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		let currentBuffer = data[0]; | 
					
						
							| 
									
										
										
										
											2019-08-13 22:47:56 +08:00
										 |  |  | 		let currentIsBuffer = Buffer.isBuffer(currentBuffer); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		let currentPosition = 0; | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		const retainedBuffer = context.retainedBuffer || ((x) => x); | 
					
						
							| 
									
										
										
										
											2021-04-20 21:22:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		const checkOverflow = () => { | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 			if (currentPosition >= /** @type {Buffer} */ (currentBuffer).length) { | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 				currentPosition = 0; | 
					
						
							|  |  |  | 				currentDataItem++; | 
					
						
							|  |  |  | 				currentBuffer = | 
					
						
							|  |  |  | 					currentDataItem < data.length ? data[currentDataItem] : null; | 
					
						
							| 
									
										
										
										
											2019-08-13 22:47:56 +08:00
										 |  |  | 				currentIsBuffer = Buffer.isBuffer(currentBuffer); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @param {number} n n | 
					
						
							|  |  |  | 		 * @returns {boolean} true when in current buffer, otherwise false | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		const isInCurrentBuffer = (n) => | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 			currentIsBuffer && | 
					
						
							|  |  |  | 			n + currentPosition <= /** @type {Buffer} */ (currentBuffer).length; | 
					
						
							| 
									
										
										
										
											2021-06-30 06:05:38 +08:00
										 |  |  | 		const ensureBuffer = () => { | 
					
						
							| 
									
										
										
										
											2019-08-13 22:47:56 +08:00
										 |  |  | 			if (!currentIsBuffer) { | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | 				throw new Error( | 
					
						
							|  |  |  | 					currentBuffer === null | 
					
						
							|  |  |  | 						? "Unexpected end of stream" | 
					
						
							|  |  |  | 						: "Unexpected lazy element in stream" | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2019-08-13 22:47:56 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-06-30 06:05:38 +08:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 		/** | 
					
						
							|  |  |  | 		 * Reads n bytes | 
					
						
							|  |  |  | 		 * @param {number} n amount of bytes to read | 
					
						
							|  |  |  | 		 * @returns {Buffer} buffer with bytes | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		const read = (n) => { | 
					
						
							| 
									
										
										
										
											2021-06-30 06:05:38 +08:00
										 |  |  | 			ensureBuffer(); | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 			const rem = | 
					
						
							|  |  |  | 				/** @type {Buffer} */ (currentBuffer).length - currentPosition; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			if (rem < n) { | 
					
						
							| 
									
										
										
										
											2021-06-30 06:05:38 +08:00
										 |  |  | 				const buffers = [read(rem)]; | 
					
						
							|  |  |  | 				n -= rem; | 
					
						
							|  |  |  | 				ensureBuffer(); | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 				while (/** @type {Buffer} */ (currentBuffer).length < n) { | 
					
						
							| 
									
										
										
										
											2021-06-30 06:05:38 +08:00
										 |  |  | 					const b = /** @type {Buffer} */ (currentBuffer); | 
					
						
							|  |  |  | 					buffers.push(b); | 
					
						
							|  |  |  | 					n -= b.length; | 
					
						
							|  |  |  | 					currentDataItem++; | 
					
						
							|  |  |  | 					currentBuffer = | 
					
						
							|  |  |  | 						currentDataItem < data.length ? data[currentDataItem] : null; | 
					
						
							|  |  |  | 					currentIsBuffer = Buffer.isBuffer(currentBuffer); | 
					
						
							|  |  |  | 					ensureBuffer(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				buffers.push(read(n)); | 
					
						
							|  |  |  | 				return Buffer.concat(buffers); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-06-29 19:02:57 +08:00
										 |  |  | 			const b = /** @type {Buffer} */ (currentBuffer); | 
					
						
							|  |  |  | 			const res = Buffer.from(b.buffer, b.byteOffset + currentPosition, n); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			currentPosition += n; | 
					
						
							|  |  |  | 			checkOverflow(); | 
					
						
							|  |  |  | 			return res; | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * Reads up to n bytes | 
					
						
							|  |  |  | 		 * @param {number} n amount of bytes to read | 
					
						
							|  |  |  | 		 * @returns {Buffer} buffer with bytes | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2025-07-17 00:13:14 +08:00
										 |  |  | 		const readUpTo = (n) => { | 
					
						
							| 
									
										
										
										
											2021-06-30 06:05:38 +08:00
										 |  |  | 			ensureBuffer(); | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 			const rem = | 
					
						
							|  |  |  | 				/** @type {Buffer} */ | 
					
						
							|  |  |  | 				(currentBuffer).length - currentPosition; | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 			if (rem < n) { | 
					
						
							|  |  |  | 				n = rem; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-06-29 19:02:57 +08:00
										 |  |  | 			const b = /** @type {Buffer} */ (currentBuffer); | 
					
						
							|  |  |  | 			const res = Buffer.from(b.buffer, b.byteOffset + currentPosition, n); | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 			currentPosition += n; | 
					
						
							|  |  |  | 			checkOverflow(); | 
					
						
							|  |  |  | 			return res; | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2023-05-23 02:32:23 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @returns {number} U8 | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		const readU8 = () => { | 
					
						
							| 
									
										
										
										
											2021-06-30 06:05:38 +08:00
										 |  |  | 			ensureBuffer(); | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | 			/** | 
					
						
							|  |  |  | 			 * There is no need to check remaining buffer size here | 
					
						
							|  |  |  | 			 * since {@link checkOverflow} guarantees at least one byte remaining | 
					
						
							|  |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 			const byte = | 
					
						
							|  |  |  | 				/** @type {Buffer} */ | 
					
						
							|  |  |  | 				(currentBuffer).readUInt8(currentPosition); | 
					
						
							| 
									
										
										
										
											2020-01-31 21:41:53 +08:00
										 |  |  | 			currentPosition += I8_SIZE; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			checkOverflow(); | 
					
						
							|  |  |  | 			return byte; | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2023-05-23 02:32:23 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @returns {number} U32 | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2024-07-31 11:31:11 +08:00
										 |  |  | 		const readU32 = () => read(I32_SIZE).readUInt32LE(0); | 
					
						
							| 
									
										
										
										
											2024-08-09 01:03:17 +08:00
										 |  |  | 		/** | 
					
						
							|  |  |  | 		 * @param {number} data data | 
					
						
							|  |  |  | 		 * @param {number} n n | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 		const readBits = (data, n) => { | 
					
						
							|  |  |  | 			let mask = 1; | 
					
						
							|  |  |  | 			while (n !== 0) { | 
					
						
							|  |  |  | 				result.push((data & mask) !== 0); | 
					
						
							| 
									
										
										
										
											2025-07-02 20:10:54 +08:00
										 |  |  | 				mask <<= 1; | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 				n--; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 		const dispatchTable = Array.from({ length: 256 }).map((_, header) => { | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			switch (header) { | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 				case LAZY_HEADER: | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const count = readU32(); | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 						const lengths = Array.from({ length: count }).map(() => readU32()); | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 						/** @type {(Buffer | LazyFunction<SerializedType, DeserializedType>)[]} */ | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 						const content = []; | 
					
						
							|  |  |  | 						for (let l of lengths) { | 
					
						
							|  |  |  | 							if (l === 0) { | 
					
						
							|  |  |  | 								if (typeof currentBuffer !== "function") { | 
					
						
							|  |  |  | 									throw new Error("Unexpected non-lazy element in stream"); | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 								content.push(currentBuffer); | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 								currentDataItem++; | 
					
						
							|  |  |  | 								currentBuffer = | 
					
						
							|  |  |  | 									currentDataItem < data.length ? data[currentDataItem] : null; | 
					
						
							|  |  |  | 								currentIsBuffer = Buffer.isBuffer(currentBuffer); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								do { | 
					
						
							|  |  |  | 									const buf = readUpTo(l); | 
					
						
							|  |  |  | 									l -= buf.length; | 
					
						
							| 
									
										
										
										
											2021-04-20 21:22:16 +08:00
										 |  |  | 									content.push(retainedBuffer(buf)); | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 								} while (l > 0); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2021-04-20 21:17:31 +08:00
										 |  |  | 						result.push(this._createLazyDeserialized(content, context)); | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 				case BUFFER_HEADER: | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const len = readU32(); | 
					
						
							| 
									
										
										
										
											2021-04-20 21:22:16 +08:00
										 |  |  | 						result.push(retainedBuffer(read(len))); | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					}; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 				case TRUE_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => result.push(true); | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 				case FALSE_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => result.push(false); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 				case NULL3_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => result.push(null, null, null); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 				case NULL2_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => result.push(null, null); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 				case NULL_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => result.push(null); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 				case NULL_AND_TRUE_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => result.push(null, true); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 				case NULL_AND_FALSE_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => result.push(null, false); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 				case NULL_AND_I8_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => { | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 						if (currentIsBuffer) { | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 							result.push( | 
					
						
							|  |  |  | 								null, | 
					
						
							|  |  |  | 								/** @type {Buffer} */ (currentBuffer).readInt8(currentPosition) | 
					
						
							|  |  |  | 							); | 
					
						
							|  |  |  | 							currentPosition += I8_SIZE; | 
					
						
							|  |  |  | 							checkOverflow(); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							result.push(null, read(I8_SIZE).readInt8(0)); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}; | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 				case NULL_AND_I32_HEADER: | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					return () => { | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 						result.push(null); | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 						if (isInCurrentBuffer(I32_SIZE)) { | 
					
						
							|  |  |  | 							result.push( | 
					
						
							|  |  |  | 								/** @type {Buffer} */ (currentBuffer).readInt32LE( | 
					
						
							|  |  |  | 									currentPosition | 
					
						
							|  |  |  | 								) | 
					
						
							|  |  |  | 							); | 
					
						
							|  |  |  | 							currentPosition += I32_SIZE; | 
					
						
							|  |  |  | 							checkOverflow(); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							result.push(read(I32_SIZE).readInt32LE(0)); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 				case NULLS8_HEADER: | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const len = readU8() + 4; | 
					
						
							|  |  |  | 						for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 							result.push(null); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 				case NULLS32_HEADER: | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const len = readU32() + 260; | 
					
						
							|  |  |  | 						for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 							result.push(null); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				case BOOLEANS_HEADER: | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const innerHeader = readU8(); | 
					
						
							|  |  |  | 						if ((innerHeader & 0xf0) === 0) { | 
					
						
							|  |  |  | 							readBits(innerHeader, 3); | 
					
						
							|  |  |  | 						} else if ((innerHeader & 0xe0) === 0) { | 
					
						
							|  |  |  | 							readBits(innerHeader, 4); | 
					
						
							|  |  |  | 						} else if ((innerHeader & 0xc0) === 0) { | 
					
						
							|  |  |  | 							readBits(innerHeader, 5); | 
					
						
							|  |  |  | 						} else if ((innerHeader & 0x80) === 0) { | 
					
						
							|  |  |  | 							readBits(innerHeader, 6); | 
					
						
							|  |  |  | 						} else if (innerHeader !== 0xff) { | 
					
						
							|  |  |  | 							let count = (innerHeader & 0x7f) + 7; | 
					
						
							|  |  |  | 							while (count > 8) { | 
					
						
							|  |  |  | 								readBits(readU8(), 8); | 
					
						
							|  |  |  | 								count -= 8; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							readBits(readU8(), count); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							let count = readU32(); | 
					
						
							|  |  |  | 							while (count > 8) { | 
					
						
							|  |  |  | 								readBits(readU8(), 8); | 
					
						
							|  |  |  | 								count -= 8; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							readBits(readU8(), count); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				case STRING_HEADER: | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const len = readU32(); | 
					
						
							| 
									
										
										
										
											2021-06-29 18:04:14 +08:00
										 |  |  | 						if (isInCurrentBuffer(len) && currentPosition + len < 0x7fffffff) { | 
					
						
							| 
									
										
										
										
											2020-12-14 06:20:05 +08:00
										 |  |  | 							result.push( | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 								/** @type {Buffer} */ | 
					
						
							|  |  |  | 								(currentBuffer).toString( | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 									undefined, | 
					
						
							| 
									
										
										
										
											2020-12-14 06:20:05 +08:00
										 |  |  | 									currentPosition, | 
					
						
							|  |  |  | 									currentPosition + len | 
					
						
							|  |  |  | 								) | 
					
						
							|  |  |  | 							); | 
					
						
							|  |  |  | 							currentPosition += len; | 
					
						
							|  |  |  | 							checkOverflow(); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 							result.push(read(len).toString()); | 
					
						
							| 
									
										
										
										
											2020-12-14 06:16:38 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 				case SHORT_STRING_HEADER: | 
					
						
							|  |  |  | 					return () => result.push(""); | 
					
						
							|  |  |  | 				case SHORT_STRING_HEADER | 1: | 
					
						
							|  |  |  | 					return () => { | 
					
						
							| 
									
										
										
										
											2021-06-29 19:37:34 +08:00
										 |  |  | 						if (currentIsBuffer && currentPosition < 0x7ffffffe) { | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 							result.push( | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 								/** @type {Buffer} */ | 
					
						
							|  |  |  | 								(currentBuffer).toString( | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 									"latin1", | 
					
						
							|  |  |  | 									currentPosition, | 
					
						
							|  |  |  | 									currentPosition + 1 | 
					
						
							|  |  |  | 								) | 
					
						
							|  |  |  | 							); | 
					
						
							|  |  |  | 							currentPosition++; | 
					
						
							| 
									
										
										
										
											2020-02-05 18:19:10 +08:00
										 |  |  | 							checkOverflow(); | 
					
						
							|  |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 							result.push(read(1).toString("latin1")); | 
					
						
							| 
									
										
										
										
											2020-02-05 18:19:10 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					}; | 
					
						
							|  |  |  | 				case I8_HEADER: | 
					
						
							|  |  |  | 					return () => { | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 						if (currentIsBuffer) { | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 							result.push( | 
					
						
							|  |  |  | 								/** @type {Buffer} */ (currentBuffer).readInt8(currentPosition) | 
					
						
							|  |  |  | 							); | 
					
						
							|  |  |  | 							currentPosition++; | 
					
						
							| 
									
										
										
										
											2020-02-05 18:19:10 +08:00
										 |  |  | 							checkOverflow(); | 
					
						
							|  |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 							result.push(read(1).readInt8(0)); | 
					
						
							| 
									
										
										
										
											2020-02-05 18:19:10 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 					}; | 
					
						
							| 
									
										
										
										
											2023-05-31 01:09:38 +08:00
										 |  |  | 				case BIGINT_I8_HEADER: { | 
					
						
							| 
									
										
										
										
											2023-05-30 22:33:47 +08:00
										 |  |  | 					const len = 1; | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const need = I8_SIZE * len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (isInCurrentBuffer(need)) { | 
					
						
							|  |  |  | 							for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 								const value = | 
					
						
							|  |  |  | 									/** @type {Buffer} */ | 
					
						
							|  |  |  | 									(currentBuffer).readInt8(currentPosition); | 
					
						
							|  |  |  | 								result.push(BigInt(value)); | 
					
						
							|  |  |  | 								currentPosition += I8_SIZE; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							checkOverflow(); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							const buf = read(need); | 
					
						
							|  |  |  | 							for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 								const value = buf.readInt8(i * I8_SIZE); | 
					
						
							|  |  |  | 								result.push(BigInt(value)); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-05-31 01:09:38 +08:00
										 |  |  | 				case BIGINT_I32_HEADER: { | 
					
						
							|  |  |  | 					const len = 1; | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const need = I32_SIZE * len; | 
					
						
							|  |  |  | 						if (isInCurrentBuffer(need)) { | 
					
						
							|  |  |  | 							for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 								const value = /** @type {Buffer} */ (currentBuffer).readInt32LE( | 
					
						
							|  |  |  | 									currentPosition | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								result.push(BigInt(value)); | 
					
						
							|  |  |  | 								currentPosition += I32_SIZE; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							checkOverflow(); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							const buf = read(need); | 
					
						
							|  |  |  | 							for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 								const value = buf.readInt32LE(i * I32_SIZE); | 
					
						
							|  |  |  | 								result.push(BigInt(value)); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-05-30 10:18:06 +08:00
										 |  |  | 				case BIGINT_HEADER: { | 
					
						
							|  |  |  | 					return () => { | 
					
						
							|  |  |  | 						const len = readU32(); | 
					
						
							|  |  |  | 						if (isInCurrentBuffer(len) && currentPosition + len < 0x7fffffff) { | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 							const value = | 
					
						
							|  |  |  | 								/** @type {Buffer} */ | 
					
						
							|  |  |  | 								(currentBuffer).toString( | 
					
						
							|  |  |  | 									undefined, | 
					
						
							|  |  |  | 									currentPosition, | 
					
						
							|  |  |  | 									currentPosition + len | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2023-05-30 10:18:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							result.push(BigInt(value)); | 
					
						
							|  |  |  | 							currentPosition += len; | 
					
						
							|  |  |  | 							checkOverflow(); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							const value = read(len).toString(); | 
					
						
							|  |  |  | 							result.push(BigInt(value)); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 				default: | 
					
						
							|  |  |  | 					if (header <= 10) { | 
					
						
							|  |  |  | 						return () => result.push(header); | 
					
						
							|  |  |  | 					} else if ((header & SHORT_STRING_HEADER) === SHORT_STRING_HEADER) { | 
					
						
							|  |  |  | 						const len = header & SHORT_STRING_LENGTH_MASK; | 
					
						
							|  |  |  | 						return () => { | 
					
						
							| 
									
										
										
										
											2021-06-29 18:04:14 +08:00
										 |  |  | 							if ( | 
					
						
							|  |  |  | 								isInCurrentBuffer(len) && | 
					
						
							|  |  |  | 								currentPosition + len < 0x7fffffff | 
					
						
							|  |  |  | 							) { | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 								result.push( | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 									/** @type {Buffer} */ | 
					
						
							|  |  |  | 									(currentBuffer).toString( | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 										"latin1", | 
					
						
							|  |  |  | 										currentPosition, | 
					
						
							|  |  |  | 										currentPosition + len | 
					
						
							|  |  |  | 									) | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								currentPosition += len; | 
					
						
							|  |  |  | 								checkOverflow(); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								result.push(read(len).toString("latin1")); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}; | 
					
						
							|  |  |  | 					} else if ((header & NUMBERS_HEADER_MASK) === F64_HEADER) { | 
					
						
							| 
									
										
										
										
											2020-02-05 18:19:10 +08:00
										 |  |  | 						const len = (header & NUMBERS_COUNT_MASK) + 1; | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 						return () => { | 
					
						
							|  |  |  | 							const need = F64_SIZE * len; | 
					
						
							|  |  |  | 							if (isInCurrentBuffer(need)) { | 
					
						
							|  |  |  | 								for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 									result.push( | 
					
						
							|  |  |  | 										/** @type {Buffer} */ (currentBuffer).readDoubleLE( | 
					
						
							|  |  |  | 											currentPosition | 
					
						
							|  |  |  | 										) | 
					
						
							|  |  |  | 									); | 
					
						
							|  |  |  | 									currentPosition += F64_SIZE; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								checkOverflow(); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								const buf = read(need); | 
					
						
							|  |  |  | 								for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 									result.push(buf.readDoubleLE(i * F64_SIZE)); | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2020-02-05 18:19:10 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 						}; | 
					
						
							|  |  |  | 					} else if ((header & NUMBERS_HEADER_MASK) === I32_HEADER) { | 
					
						
							|  |  |  | 						const len = (header & NUMBERS_COUNT_MASK) + 1; | 
					
						
							|  |  |  | 						return () => { | 
					
						
							|  |  |  | 							const need = I32_SIZE * len; | 
					
						
							|  |  |  | 							if (isInCurrentBuffer(need)) { | 
					
						
							|  |  |  | 								for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 									result.push( | 
					
						
							|  |  |  | 										/** @type {Buffer} */ (currentBuffer).readInt32LE( | 
					
						
							|  |  |  | 											currentPosition | 
					
						
							|  |  |  | 										) | 
					
						
							|  |  |  | 									); | 
					
						
							|  |  |  | 									currentPosition += I32_SIZE; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								checkOverflow(); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								const buf = read(need); | 
					
						
							|  |  |  | 								for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 									result.push(buf.readInt32LE(i * I32_SIZE)); | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2020-02-05 18:19:10 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 						}; | 
					
						
							|  |  |  | 					} else if ((header & NUMBERS_HEADER_MASK) === I8_HEADER) { | 
					
						
							|  |  |  | 						const len = (header & NUMBERS_COUNT_MASK) + 1; | 
					
						
							|  |  |  | 						return () => { | 
					
						
							|  |  |  | 							const need = I8_SIZE * len; | 
					
						
							|  |  |  | 							if (isInCurrentBuffer(need)) { | 
					
						
							|  |  |  | 								for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 									result.push( | 
					
						
							|  |  |  | 										/** @type {Buffer} */ (currentBuffer).readInt8( | 
					
						
							|  |  |  | 											currentPosition | 
					
						
							|  |  |  | 										) | 
					
						
							|  |  |  | 									); | 
					
						
							|  |  |  | 									currentPosition += I8_SIZE; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								checkOverflow(); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								const buf = read(need); | 
					
						
							|  |  |  | 								for (let i = 0; i < len; i++) { | 
					
						
							|  |  |  | 									result.push(buf.readInt8(i * I8_SIZE)); | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2024-07-31 04:21:27 +08:00
										 |  |  | 					return () => { | 
					
						
							|  |  |  | 						throw new Error(`Unexpected header byte 0x${header.toString(16)}`); | 
					
						
							|  |  |  | 					}; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/** @type {DeserializedType} */ | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 		let result = []; | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 		while (currentBuffer !== null) { | 
					
						
							|  |  |  | 			if (typeof currentBuffer === "function") { | 
					
						
							| 
									
										
										
										
											2025-04-16 22:04:11 +08:00
										 |  |  | 				result.push(this._deserializeLazy(currentBuffer, context)); | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 				currentDataItem++; | 
					
						
							|  |  |  | 				currentBuffer = | 
					
						
							|  |  |  | 					currentDataItem < data.length ? data[currentDataItem] : null; | 
					
						
							|  |  |  | 				currentIsBuffer = Buffer.isBuffer(currentBuffer); | 
					
						
							| 
									
										
										
										
											2020-12-14 23:43:29 +08:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				const header = readU8(); | 
					
						
							|  |  |  | 				dispatchTable[header](); | 
					
						
							| 
									
										
										
										
											2020-12-14 07:32:45 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// avoid leaking memory in context
 | 
					
						
							| 
									
										
										
										
											2024-07-31 04:09:42 +08:00
										 |  |  | 		// eslint-disable-next-line prefer-const
 | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 		let _result = result; | 
					
						
							| 
									
										
										
										
											2024-10-24 11:02:20 +08:00
										 |  |  | 		result = /** @type {EXPECTED_ANY} */ (undefined); | 
					
						
							| 
									
										
										
										
											2021-04-20 20:13:04 +08:00
										 |  |  | 		return _result; | 
					
						
							| 
									
										
										
										
											2018-10-09 20:30:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = BinaryMiddleware; | 
					
						
							| 
									
										
										
										
											2019-01-22 01:24:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | module.exports.MEASURE_END_OPERATION = MEASURE_END_OPERATION; | 
					
						
							| 
									
										
										
										
											2025-07-03 17:06:45 +08:00
										 |  |  | module.exports.MEASURE_START_OPERATION = MEASURE_START_OPERATION; |