binary-packet 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,9 +33,10 @@ Currently, these kinds of `fields` are supported:
33
33
  | `BinaryPacket` | BinaryPacket "subpacket" | BinaryPacket | size(BinaryPacket) |
34
34
  | `FieldArray` | Dynamically-sized array of one of the types above | Up to 256 elements | 1 + length \* size(Element) |
35
35
  | `FieldFixedArray` | Statically-sized array of one of the types above | Any pre-defined numbers of elements | length \* size(Element) |
36
+ | `FieldBitFlags` | Boolean flags packed into a single 8 bits integer | Up to 8 boolean flags | 1 |
36
37
 
37
- As you can see from the table above, both arrays and nested objects ("subpackets") are supported. \
38
- Note that `FieldFixedArray`s are much more memory efficient and performant than `FieldArray`s, but require a pre-defined length.
38
+ As shown, both arrays and nested objects ("subpackets") are supported. \
39
+ Note: `FieldFixedArray` is much more memory efficient and performant than `FieldArray`, but require a pre-defined length.
39
40
 
40
41
  ## Usage Examples
41
42
 
@@ -110,14 +111,14 @@ So, take these "performance" comparisons with a grain of salt; or, even better,
110
111
 
111
112
  This library has been benchmarked against the following alternatives:
112
113
 
113
- - [msgpackr](https://www.npmjs.com/package/msgpackr) - A very popular, fast and battle-tested library. Currently offers **many** more features than binary-packet, but it appears to be 2x-4x slower in writes and 3x-10x slower in reads (depends on the packet structure) - is also less type-safe.
114
+ - [msgpackr](https://www.npmjs.com/package/msgpackr) - A very popular, fast and battle-tested library. Currently offers more features than binary-packet, but it appears to be 2x-4x slower in writes and 3x-10x slower in reads (depends on the packet structure) - is also less type-safe.
114
115
  - [restructure](https://www.npmjs.com/package/restructure) - An older, popular schema-based library, has some extra features like LazyArrays, but it is **much slower** than both binary-packet and msgpackr. And, sadly, easily crashes with complex structures.
115
116
 
116
117
  The benchmarks are executed on three different kinds of packets:
117
118
 
118
119
  - EmptyPacket: basically an empty javascript object.
119
120
  - SimplePacket: objects with just primitive fields and statically-sized arrays.
120
- - ComplexPacket: objects with primitives, statically-sized arrays, dynamically-sized arrays and other nested objects/arrays.
121
+ - ComplexPacket: objects with primitives, statically-sized arrays, dynamically-sized arrays, bitflags and other nested objects/arrays.
121
122
 
122
123
  You can see and run the benchmarks yourself if you clone the repository and launch `npm run benchmark`.
123
124
 
package/dist/index.d.mts CHANGED
@@ -55,6 +55,19 @@ declare function FieldArray<T extends Field | BinaryPacket<Definition>>(item: T)
55
55
  * NOTE: If an array will not always have the same length, use the `FieldArray` type.
56
56
  */
57
57
  declare function FieldFixedArray<T extends Field | BinaryPacket<Definition>, Length extends number>(item: T, length: Length): [itemType: T, length: Length];
58
+ type BitFlags = (string[] | ReadonlyArray<string>) & {
59
+ length: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
60
+ };
61
+ /**
62
+ * Defines a sequence of up to 8 "flags" (basically single bits/booleans) that can be packed together into a single 8 bits value. \
63
+ * This is useful for minimizing bytes usage when there are lots of boolean fields/flags, instead of saving each flag separately as its own 8 bits value.
64
+ *
65
+ * The input should be an array of strings (with at most 8 elements) where each string defines the name of a flag. \
66
+ * This is just for definition purposes, then when actually writing or reading packets it'll just be a record-object with those names as keys and boolean values.
67
+ */
68
+ declare function FieldBitFlags<const FlagsArray extends BitFlags>(flags: FlagsArray): {
69
+ flags: FlagsArray;
70
+ };
58
71
  declare class BinaryPacket<T extends Definition> {
59
72
  private readonly packetId;
60
73
  /**
@@ -205,7 +218,9 @@ declare class BinaryPacket<T extends Definition> {
205
218
  * // ...
206
219
  */
207
220
  type Definition = {
208
- [fieldName: string]: MaybeArray<Field> | MaybeArray<BinaryPacket<Definition>>;
221
+ [fieldName: string]: MaybeArray<Field> | MaybeArray<BinaryPacket<Definition>> | {
222
+ flags: BitFlags;
223
+ };
209
224
  };
210
225
  type MaybeArray<T> = T | [itemType: T] | [itemType: T, length: number];
211
226
  /**
@@ -216,7 +231,12 @@ type ToJson<T extends Definition> = {
216
231
  length: Length;
217
232
  } : number[] & {
218
233
  length: Length;
219
- } : T[K] extends BinaryPacket<infer BPDef> ? ToJson<BPDef> : number;
234
+ } : T[K] extends BinaryPacket<infer BPDef> ? ToJson<BPDef> : T[K] extends {
235
+ flags: infer FlagsArray extends BitFlags;
236
+ } ? BitFlagsToJson<FlagsArray> : number;
237
+ };
238
+ type BitFlagsToJson<FlagsArray extends BitFlags> = {
239
+ [key in FlagsArray[number]]: boolean;
220
240
  };
221
241
 
222
- export { BinaryPacket, type Definition, Field, FieldArray, FieldFixedArray };
242
+ export { BinaryPacket, type Definition, Field, FieldArray, FieldBitFlags, FieldFixedArray };
package/dist/index.d.ts CHANGED
@@ -55,6 +55,19 @@ declare function FieldArray<T extends Field | BinaryPacket<Definition>>(item: T)
55
55
  * NOTE: If an array will not always have the same length, use the `FieldArray` type.
56
56
  */
57
57
  declare function FieldFixedArray<T extends Field | BinaryPacket<Definition>, Length extends number>(item: T, length: Length): [itemType: T, length: Length];
58
+ type BitFlags = (string[] | ReadonlyArray<string>) & {
59
+ length: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
60
+ };
61
+ /**
62
+ * Defines a sequence of up to 8 "flags" (basically single bits/booleans) that can be packed together into a single 8 bits value. \
63
+ * This is useful for minimizing bytes usage when there are lots of boolean fields/flags, instead of saving each flag separately as its own 8 bits value.
64
+ *
65
+ * The input should be an array of strings (with at most 8 elements) where each string defines the name of a flag. \
66
+ * This is just for definition purposes, then when actually writing or reading packets it'll just be a record-object with those names as keys and boolean values.
67
+ */
68
+ declare function FieldBitFlags<const FlagsArray extends BitFlags>(flags: FlagsArray): {
69
+ flags: FlagsArray;
70
+ };
58
71
  declare class BinaryPacket<T extends Definition> {
59
72
  private readonly packetId;
60
73
  /**
@@ -205,7 +218,9 @@ declare class BinaryPacket<T extends Definition> {
205
218
  * // ...
206
219
  */
207
220
  type Definition = {
208
- [fieldName: string]: MaybeArray<Field> | MaybeArray<BinaryPacket<Definition>>;
221
+ [fieldName: string]: MaybeArray<Field> | MaybeArray<BinaryPacket<Definition>> | {
222
+ flags: BitFlags;
223
+ };
209
224
  };
210
225
  type MaybeArray<T> = T | [itemType: T] | [itemType: T, length: number];
211
226
  /**
@@ -216,7 +231,12 @@ type ToJson<T extends Definition> = {
216
231
  length: Length;
217
232
  } : number[] & {
218
233
  length: Length;
219
- } : T[K] extends BinaryPacket<infer BPDef> ? ToJson<BPDef> : number;
234
+ } : T[K] extends BinaryPacket<infer BPDef> ? ToJson<BPDef> : T[K] extends {
235
+ flags: infer FlagsArray extends BitFlags;
236
+ } ? BitFlagsToJson<FlagsArray> : number;
237
+ };
238
+ type BitFlagsToJson<FlagsArray extends BitFlags> = {
239
+ [key in FlagsArray[number]]: boolean;
220
240
  };
221
241
 
222
- export { BinaryPacket, type Definition, Field, FieldArray, FieldFixedArray };
242
+ export { BinaryPacket, type Definition, Field, FieldArray, FieldBitFlags, FieldFixedArray };
package/dist/index.js CHANGED
@@ -1,447 +1,2 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- BinaryPacket: () => BinaryPacket,
24
- Field: () => Field,
25
- FieldArray: () => FieldArray,
26
- FieldFixedArray: () => FieldFixedArray
27
- });
28
- module.exports = __toCommonJS(src_exports);
29
-
30
- // src/buffers.ts
31
- var hasNodeBuffers = typeof Buffer === "function";
32
- function growDataView(dataview, newByteLength) {
33
- const resizedBuffer = new ArrayBuffer(newByteLength);
34
- const amountToCopy = Math.min(dataview.byteLength, resizedBuffer.byteLength);
35
- let length = Math.trunc(amountToCopy / 8);
36
- new Float64Array(resizedBuffer, 0, length).set(new Float64Array(dataview.buffer, 0, length));
37
- const offset = length * 8;
38
- length = amountToCopy - offset;
39
- new Uint8Array(resizedBuffer, offset, length).set(new Uint8Array(dataview.buffer, offset, length));
40
- return new DataView(resizedBuffer);
41
- }
42
- function growNodeBuffer(buffer, newByteLength) {
43
- const newBuffer = Buffer.allocUnsafe(newByteLength);
44
- buffer.copy(newBuffer);
45
- return newBuffer;
46
- }
47
-
48
- // src/index.ts
49
- var Field = /* @__PURE__ */ ((Field2) => {
50
- Field2[Field2["UNSIGNED_INT_8"] = 0] = "UNSIGNED_INT_8";
51
- Field2[Field2["UNSIGNED_INT_16"] = 1] = "UNSIGNED_INT_16";
52
- Field2[Field2["UNSIGNED_INT_32"] = 2] = "UNSIGNED_INT_32";
53
- Field2[Field2["INT_8"] = 3] = "INT_8";
54
- Field2[Field2["INT_16"] = 4] = "INT_16";
55
- Field2[Field2["INT_32"] = 5] = "INT_32";
56
- Field2[Field2["FLOAT_32"] = 6] = "FLOAT_32";
57
- Field2[Field2["FLOAT_64"] = 7] = "FLOAT_64";
58
- return Field2;
59
- })(Field || {});
60
- function FieldArray(item) {
61
- return [item];
62
- }
63
- function FieldFixedArray(item, length) {
64
- if (length < 0 || !Number.isFinite(length)) {
65
- throw new RangeError("Length of a FixedArray must be a positive integer.");
66
- }
67
- return [item, length];
68
- }
69
- var BinaryPacket = class _BinaryPacket {
70
- constructor(packetId, definition) {
71
- this.packetId = packetId;
72
- this.entries = definition ? sortEntries(definition) : [];
73
- const inspection = inspectEntries(this.entries);
74
- this.minimumByteLength = inspection.minimumByteLength;
75
- this.canFastWrite = inspection.canFastWrite;
76
- }
77
- /**
78
- * Defines a new binary packet. \
79
- * Make sure that every `packetId` is unique.
80
- * @throws RangeError If packetId is negative, floating-point, or greater than 255.
81
- */
82
- static define(packetId, definition) {
83
- if (packetId < 0 || !Number.isFinite(packetId)) {
84
- throw new RangeError("Packet IDs must be positive integers.");
85
- }
86
- if (packetId > 255) {
87
- throw new RangeError(
88
- "Packet IDs greater than 255 are not supported. Do you REALLY need more than 255 different kinds of packets?"
89
- );
90
- }
91
- return new _BinaryPacket(packetId, definition);
92
- }
93
- /**
94
- * Reads just the packetId from the given Buffer. \
95
- * This method practically just reads the uint8 at offset `byteOffset` (default: 0). \
96
- * Useful if the receiving side receives multiple types of packets.
97
- */
98
- static readPacketIdNodeBuffer(buffer, byteOffset = 0) {
99
- return buffer.readUint8(byteOffset);
100
- }
101
- /**
102
- * Reads just the packetId from the given DataView. \
103
- * This method practically just reads the uint8 at offset `byteOffset` (default: 0). \
104
- * Useful if the receiving side receives multiple types of packets.
105
- */
106
- static readPacketIdDataView(dataview, byteOffset = 0) {
107
- return dataview.getUint8(byteOffset);
108
- }
109
- /**
110
- * Reads just the packetId from the given ArrayBuffer. \
111
- * This method practically just reads the uint8 at offset `byteOffset`. \
112
- * Useful if the receiving side receives multiple types of packets.
113
- *
114
- * NOTE: Due to security issues, the `byteOffset` argument cannot be defaulted and must be provided by the user. \
115
- * NOTE: For more information read the `readArrayBuffer` method documentation.
116
- */
117
- static readPacketIdArrayBuffer(arraybuffer, byteOffset) {
118
- return new Uint8Array(arraybuffer, byteOffset, 1)[0];
119
- }
120
- /**
121
- * Reads/deserializes from the given Buffer. \
122
- * Method available ONLY on NodeJS and Bun.
123
- *
124
- * If possible, always prefer reading using this method, as it is much faster than the other ones.
125
- *
126
- * NOTE: if you have an ArrayBuffer do not bother wrapping it into a node Buffer yourself. \
127
- * NOTE: if you have an ArrayBuffer use the appropriate `readArrayBuffer`.
128
- */
129
- readNodeBuffer(dataIn, offsetPointer = { offset: 0 }, byteLength = dataIn.byteLength) {
130
- return this.read(dataIn, offsetPointer, byteLength, GET_FUNCTION_BUF);
131
- }
132
- /**
133
- * Reads/deserializes from the given DataView.
134
- *
135
- * NOTE: if you have an ArrayBuffer do not bother wrapping it into a DataView yourself. \
136
- * NOTE: if you have an ArrayBuffer use the appropriate `readArrayBuffer`.
137
- */
138
- readDataView(dataIn, offsetPointer = { offset: 0 }, byteLength = dataIn.byteLength) {
139
- return this.read(dataIn, offsetPointer, byteLength, GET_FUNCTION);
140
- }
141
- /**
142
- * Reads/deserializes from the given ArrayBuffer. \
143
- * WARNING: this method is practically a HACK.
144
- *
145
- * When using this method both the `byteOffset` and `byteLength` are REQUIRED and cannot be defaulted. \
146
- * This is to prevent serious bugs and security issues. \
147
- * That is because often raw ArrayBuffers come from a pre-allocated buffer pool and do not start at byteOffset 0.
148
- *
149
- * NOTE: if you have a node Buffer do not bother wrapping it into an ArrayBuffer yourself. \
150
- * NOTE: if you have a node Buffer use the appropriate `readNodeBuffer` as it is much faster and less error prone.
151
- */
152
- readArrayBuffer(dataIn, byteOffset, byteLength) {
153
- return this.read(
154
- hasNodeBuffers ? Buffer.from(dataIn, byteOffset, byteLength) : new DataView(dataIn, byteOffset, byteLength),
155
- { offset: 0 },
156
- // The underlying buffer has already been offsetted
157
- byteLength,
158
- hasNodeBuffers ? GET_FUNCTION_BUF : GET_FUNCTION
159
- );
160
- }
161
- /**
162
- * Writes/serializes the given object into a Buffer. \
163
- * Method available ONLY on NodeJS and Bun.
164
- *
165
- * If possible, always prefer writing using this method, as it is much faster than the other ones.
166
- */
167
- writeNodeBuffer(dataOut) {
168
- const buffer = Buffer.allocUnsafe(this.minimumByteLength);
169
- return this.write(buffer, dataOut, { offset: 0 }, SET_FUNCTION_BUF, growNodeBuffer);
170
- }
171
- /**
172
- * Writes/serializes the given object into a DataView. \
173
- */
174
- writeDataView(dataOut) {
175
- const dataview = new DataView(new ArrayBuffer(this.minimumByteLength));
176
- return this.write(dataview, dataOut, { offset: 0 }, SET_FUNCTION, growDataView);
177
- }
178
- /**
179
- * Writes/serializes the given object into an ArrayBuffer. \
180
- * This method is just a wrapper around either `writeNodeBuffer` or `writeDataView`. \
181
- *
182
- * This method works with JavaScript standard raw ArrayBuffer(s) and, as such, is very error prone: \
183
- * Make sure you're using the returned byteLength and byteOffset fields in the read counterpart. \
184
- *
185
- * Always consider whether is possible to use directly `writeNodeBuffer` or `writeDataView` instead of `writeArrayBuffer`. \
186
- * For more information read the `readArrayBuffer` documentation.
187
- */
188
- writeArrayBuffer(dataOut) {
189
- const buf = hasNodeBuffers ? this.writeNodeBuffer(dataOut) : this.writeDataView(dataOut);
190
- return { buffer: buf.buffer, byteLength: buf.byteLength, byteOffset: buf.byteOffset };
191
- }
192
- entries;
193
- canFastWrite;
194
- minimumByteLength;
195
- read(dataIn, offsetPointer, byteLength, readFunctions) {
196
- if (byteLength + offsetPointer.offset < this.minimumByteLength) {
197
- throw new Error(
198
- `There is no space available to fit a packet of type ${this.packetId} at offset ${offsetPointer.offset}`
199
- );
200
- }
201
- if (readFunctions[0 /* UNSIGNED_INT_8 */](dataIn, offsetPointer.offset) !== this.packetId) {
202
- throw new Error(
203
- `Data at offset ${offsetPointer.offset} is not a packet of type ${this.packetId}`
204
- );
205
- }
206
- offsetPointer.offset += 1;
207
- const result = {};
208
- for (const [name, def] of this.entries) {
209
- if (Array.isArray(def)) {
210
- const length = (
211
- // def[1] is the length of a statically-sized array, if undefined: must read the length from the buffer as it means it's a dynamically-sized array
212
- def[1] ?? readFunctions[0 /* UNSIGNED_INT_8 */](dataIn, offsetPointer.offset++)
213
- );
214
- const array = Array(length);
215
- const itemType = def[0];
216
- if (typeof itemType === "object") {
217
- for (let i = 0; i < length; ++i) {
218
- array[i] = itemType.read(dataIn, offsetPointer, byteLength, readFunctions);
219
- }
220
- } else {
221
- const itemSize = BYTE_SIZE[itemType];
222
- for (let i = 0; i < length; ++i) {
223
- array[i] = readFunctions[itemType](dataIn, offsetPointer.offset);
224
- offsetPointer.offset += itemSize;
225
- }
226
- }
227
- result[name] = array;
228
- } else if (typeof def === "object") {
229
- result[name] = def.read(dataIn, offsetPointer, byteLength, readFunctions);
230
- } else {
231
- result[name] = readFunctions[def](dataIn, offsetPointer.offset);
232
- offsetPointer.offset += BYTE_SIZE[def];
233
- }
234
- }
235
- return result;
236
- }
237
- write(buffer, dataOut, offsetPointer, writeFunctions, growBufferFunction) {
238
- writeFunctions[0 /* UNSIGNED_INT_8 */](buffer, this.packetId, offsetPointer.offset);
239
- offsetPointer.offset += 1;
240
- if (this.canFastWrite) {
241
- this.fastWrite(buffer, dataOut, offsetPointer, writeFunctions);
242
- return buffer;
243
- } else {
244
- return this.slowWrite(
245
- buffer,
246
- dataOut,
247
- offsetPointer,
248
- this.minimumByteLength,
249
- this.minimumByteLength,
250
- writeFunctions,
251
- growBufferFunction
252
- );
253
- }
254
- }
255
- /**
256
- * Fast write does not support writing dynamically-sized arrays.
257
- */
258
- fastWrite(buffer, dataOut, offsetPointer, writeFunctions) {
259
- for (const [name, def] of this.entries) {
260
- if (Array.isArray(def)) {
261
- const itemType = def[0];
262
- const length = def[1];
263
- const data = dataOut[name];
264
- if (typeof itemType === "object") {
265
- for (let i = 0; i < length; ++i) {
266
- itemType.fastWrite(buffer, data[i], offsetPointer, writeFunctions);
267
- }
268
- } else {
269
- const itemSize = BYTE_SIZE[itemType];
270
- for (let i = 0; i < length; ++i) {
271
- writeFunctions[itemType](buffer, data[i], offsetPointer.offset);
272
- offsetPointer.offset += itemSize;
273
- }
274
- }
275
- } else if (typeof def === "object") {
276
- def.fastWrite(buffer, dataOut[name], offsetPointer, writeFunctions);
277
- } else {
278
- writeFunctions[def](buffer, dataOut[name], offsetPointer.offset);
279
- offsetPointer.offset += BYTE_SIZE[def];
280
- }
281
- }
282
- }
283
- /**
284
- * The slow writing path tries writing data into the buffer as fast as the fast writing path does. \
285
- * But, if a non-empty dynamically-sized array is encountered, the buffer needs to grow, slightly reducing performance.
286
- */
287
- slowWrite(buffer, dataOut, offsetPointer, byteLength, maxByteLength, writeFunctions, growBufferFunction) {
288
- for (const [name, def] of this.entries) {
289
- const data = dataOut[name];
290
- if (Array.isArray(def)) {
291
- const length = data.length;
292
- const isDynamicArray = def[1] === void 0;
293
- if (isDynamicArray) {
294
- writeFunctions[0 /* UNSIGNED_INT_8 */](buffer, length, offsetPointer.offset);
295
- offsetPointer.offset += 1;
296
- }
297
- if (length > 0) {
298
- const itemType = def[0];
299
- if (typeof itemType === "object") {
300
- if (isDynamicArray) {
301
- const neededBytesForElements = length * itemType.minimumByteLength;
302
- byteLength += neededBytesForElements;
303
- maxByteLength += neededBytesForElements;
304
- if (buffer.byteLength < maxByteLength) {
305
- buffer = growBufferFunction(buffer, maxByteLength);
306
- }
307
- }
308
- for (const object of data) {
309
- writeFunctions[0 /* UNSIGNED_INT_8 */](
310
- buffer,
311
- itemType.packetId,
312
- offsetPointer.offset
313
- );
314
- offsetPointer.offset += 1;
315
- buffer = itemType.slowWrite(
316
- buffer,
317
- object,
318
- offsetPointer,
319
- byteLength,
320
- maxByteLength,
321
- writeFunctions,
322
- growBufferFunction
323
- );
324
- byteLength = offsetPointer.offset;
325
- maxByteLength = buffer.byteLength;
326
- }
327
- } else {
328
- const itemSize = BYTE_SIZE[itemType];
329
- if (isDynamicArray) {
330
- const neededBytesForElements = length * itemSize;
331
- byteLength += neededBytesForElements;
332
- maxByteLength += neededBytesForElements;
333
- if (buffer.byteLength < maxByteLength) {
334
- buffer = growBufferFunction(buffer, maxByteLength);
335
- }
336
- }
337
- for (const number of data) {
338
- writeFunctions[itemType](buffer, number, offsetPointer.offset);
339
- offsetPointer.offset += itemSize;
340
- }
341
- }
342
- }
343
- } else if (typeof def === "object") {
344
- writeFunctions[0 /* UNSIGNED_INT_8 */](buffer, def.packetId, offsetPointer.offset);
345
- offsetPointer.offset += 1;
346
- buffer = def.slowWrite(
347
- buffer,
348
- data,
349
- offsetPointer,
350
- byteLength,
351
- maxByteLength,
352
- writeFunctions,
353
- growBufferFunction
354
- );
355
- byteLength = offsetPointer.offset;
356
- maxByteLength = buffer.byteLength;
357
- } else {
358
- writeFunctions[def](buffer, data, offsetPointer.offset);
359
- offsetPointer.offset += BYTE_SIZE[def];
360
- }
361
- }
362
- return buffer;
363
- }
364
- };
365
- function sortEntries(definition) {
366
- return Object.entries(definition).sort(
367
- ([fieldName1], [fieldName2]) => fieldName1.localeCompare(fieldName2)
368
- );
369
- }
370
- function inspectEntries(entries) {
371
- let minimumByteLength = 1;
372
- let canFastWrite = true;
373
- for (const [, type] of entries) {
374
- if (Array.isArray(type)) {
375
- if (type.length === 2) {
376
- const itemSize = typeof type[0] === "object" ? type[0].minimumByteLength : BYTE_SIZE[type[0]];
377
- minimumByteLength += type[1] * itemSize;
378
- } else {
379
- minimumByteLength += 1;
380
- canFastWrite = false;
381
- }
382
- } else if (type instanceof BinaryPacket) {
383
- minimumByteLength += type.minimumByteLength;
384
- canFastWrite &&= type.canFastWrite;
385
- } else {
386
- minimumByteLength += BYTE_SIZE[type];
387
- }
388
- }
389
- return { minimumByteLength, canFastWrite };
390
- }
391
- var BYTE_SIZE = Array(8);
392
- BYTE_SIZE[0 /* UNSIGNED_INT_8 */] = 1;
393
- BYTE_SIZE[3 /* INT_8 */] = 1;
394
- BYTE_SIZE[1 /* UNSIGNED_INT_16 */] = 2;
395
- BYTE_SIZE[4 /* INT_16 */] = 2;
396
- BYTE_SIZE[2 /* UNSIGNED_INT_32 */] = 4;
397
- BYTE_SIZE[5 /* INT_32 */] = 4;
398
- BYTE_SIZE[6 /* FLOAT_32 */] = 4;
399
- BYTE_SIZE[7 /* FLOAT_64 */] = 8;
400
- var GET_FUNCTION = Array(8);
401
- GET_FUNCTION[0 /* UNSIGNED_INT_8 */] = (view, offset) => view.getUint8(offset);
402
- GET_FUNCTION[3 /* INT_8 */] = (view, offset) => view.getInt8(offset);
403
- GET_FUNCTION[1 /* UNSIGNED_INT_16 */] = (view, offset) => view.getUint16(offset);
404
- GET_FUNCTION[4 /* INT_16 */] = (view, offset) => view.getInt16(offset);
405
- GET_FUNCTION[2 /* UNSIGNED_INT_32 */] = (view, offset) => view.getUint32(offset);
406
- GET_FUNCTION[5 /* INT_32 */] = (view, offset) => view.getInt32(offset);
407
- GET_FUNCTION[6 /* FLOAT_32 */] = (view, offset) => view.getFloat32(offset);
408
- GET_FUNCTION[7 /* FLOAT_64 */] = (view, offset) => view.getFloat64(offset);
409
- var SET_FUNCTION = Array(8);
410
- SET_FUNCTION[0 /* UNSIGNED_INT_8 */] = (view, value, offset) => view.setUint8(offset, value);
411
- SET_FUNCTION[3 /* INT_8 */] = (view, value, offset) => view.setInt8(offset, value);
412
- SET_FUNCTION[1 /* UNSIGNED_INT_16 */] = (view, value, offset) => view.setUint16(offset, value);
413
- SET_FUNCTION[4 /* INT_16 */] = (view, value, offset) => view.setInt16(offset, value);
414
- SET_FUNCTION[2 /* UNSIGNED_INT_32 */] = (view, value, offset) => view.setUint32(offset, value);
415
- SET_FUNCTION[5 /* INT_32 */] = (view, value, offset) => view.setInt32(offset, value);
416
- SET_FUNCTION[6 /* FLOAT_32 */] = (view, value, offset) => view.setFloat32(offset, value);
417
- SET_FUNCTION[7 /* FLOAT_64 */] = (view, value, offset) => view.setFloat64(offset, value);
418
- var SET_FUNCTION_BUF = Array(8);
419
- if (hasNodeBuffers) {
420
- SET_FUNCTION_BUF[0 /* UNSIGNED_INT_8 */] = (view, value, offset) => view.writeUint8(value, offset);
421
- SET_FUNCTION_BUF[3 /* INT_8 */] = (view, value, offset) => view.writeInt8(value, offset);
422
- SET_FUNCTION_BUF[1 /* UNSIGNED_INT_16 */] = (view, value, offset) => view.writeUint16LE(value, offset);
423
- SET_FUNCTION_BUF[4 /* INT_16 */] = (view, value, offset) => view.writeInt16LE(value, offset);
424
- SET_FUNCTION_BUF[2 /* UNSIGNED_INT_32 */] = (view, value, offset) => view.writeUint32LE(value, offset);
425
- SET_FUNCTION_BUF[5 /* INT_32 */] = (view, value, offset) => view.writeInt32LE(value, offset);
426
- SET_FUNCTION_BUF[6 /* FLOAT_32 */] = (view, value, offset) => view.writeFloatLE(value, offset);
427
- SET_FUNCTION_BUF[7 /* FLOAT_64 */] = (view, value, offset) => view.writeDoubleLE(value, offset);
428
- }
429
- var GET_FUNCTION_BUF = Array(8);
430
- if (hasNodeBuffers) {
431
- GET_FUNCTION_BUF[0 /* UNSIGNED_INT_8 */] = (view, offset) => view.readUint8(offset);
432
- GET_FUNCTION_BUF[3 /* INT_8 */] = (view, offset) => view.readInt8(offset);
433
- GET_FUNCTION_BUF[1 /* UNSIGNED_INT_16 */] = (view, offset) => view.readUint16LE(offset);
434
- GET_FUNCTION_BUF[4 /* INT_16 */] = (view, offset) => view.readInt16LE(offset);
435
- GET_FUNCTION_BUF[2 /* UNSIGNED_INT_32 */] = (view, offset) => view.readUint32LE(offset);
436
- GET_FUNCTION_BUF[5 /* INT_32 */] = (view, offset) => view.readInt32LE(offset);
437
- GET_FUNCTION_BUF[6 /* FLOAT_32 */] = (view, offset) => view.readFloatLE(offset);
438
- GET_FUNCTION_BUF[7 /* FLOAT_64 */] = (view, offset) => view.readDoubleLE(offset);
439
- }
440
- // Annotate the CommonJS export names for ESM import in node:
441
- 0 && (module.exports = {
442
- BinaryPacket,
443
- Field,
444
- FieldArray,
445
- FieldFixedArray
446
- });
1
+ "use strict";var D=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var S=(n,e)=>{for(var t in e)D(n,t,{get:e[t],enumerable:!0})},L=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of A(e))!b.call(n,i)&&i!==t&&D(n,i,{get:()=>e[i],enumerable:!(r=w(e,i))||r.enumerable});return n};var G=n=>L(D({},"__esModule",{value:!0}),n);var V={};S(V,{BinaryPacket:()=>p,Field:()=>U,FieldArray:()=>O,FieldBitFlags:()=>x,FieldFixedArray:()=>k});module.exports=G(V);var g=typeof Buffer=="function";function E(n,e){let t=new ArrayBuffer(e),r=Math.min(n.byteLength,t.byteLength),i=Math.trunc(r/8);new Float64Array(t,0,i).set(new Float64Array(n.buffer,0,i));let f=i*8;return i=r-f,new Uint8Array(t,f,i).set(new Uint8Array(n.buffer,f,i)),new DataView(t)}function h(n,e){let t=Buffer.allocUnsafe(e);return n.copy(t),t}var U=(s=>(s[s.UNSIGNED_INT_8=0]="UNSIGNED_INT_8",s[s.UNSIGNED_INT_16=1]="UNSIGNED_INT_16",s[s.UNSIGNED_INT_32=2]="UNSIGNED_INT_32",s[s.INT_8=3]="INT_8",s[s.INT_16=4]="INT_16",s[s.INT_32=5]="INT_32",s[s.FLOAT_32=6]="FLOAT_32",s[s.FLOAT_64=7]="FLOAT_64",s))(U||{});function O(n){return[n]}function k(n,e){if(e<0||!Number.isFinite(e))throw new RangeError("Length of a FixedArray must be a positive integer.");return[n,e]}function x(n){if(n.length>8)throw new Error(`Invalid BinaryPacket definition: a BitFlags field can have only up to 8 flags, given: ${n.join(", ")}`);return{flags:n}}var p=class n{constructor(e,t){this.packetId=e;this.entries=t?J(t):[];let r=v(this.entries);this.minimumByteLength=r.minimumByteLength,this.canFastWrite=r.canFastWrite}static define(e,t){if(e<0||!Number.isFinite(e))throw new RangeError("Packet IDs must be positive integers.");if(e>255)throw new RangeError("Packet IDs greater than 255 are not supported. Do you REALLY need more than 255 different kinds of packets?");return new n(e,t)}static readPacketIdNodeBuffer(e,t=0){return e.readUint8(t)}static readPacketIdDataView(e,t=0){return e.getUint8(t)}static readPacketIdArrayBuffer(e,t){return new Uint8Array(e,t,1)[0]}readNodeBuffer(e,t={offset:0},r=e.byteLength){return this.read(e,t,r,u)}readDataView(e,t={offset:0},r=e.byteLength){return this.read(e,t,r,I)}readArrayBuffer(e,t,r){return this.read(g?Buffer.from(e,t,r):new DataView(e,t,r),{offset:0},r,g?u:I)}writeNodeBuffer(e){let t=Buffer.allocUnsafe(this.minimumByteLength);return this.write(t,e,{offset:0},_,h)}writeDataView(e){let t=new DataView(new ArrayBuffer(this.minimumByteLength));return this.write(t,e,{offset:0},m,E)}writeArrayBuffer(e){let t=g?this.writeNodeBuffer(e):this.writeDataView(e);return{buffer:t.buffer,byteLength:t.byteLength,byteOffset:t.byteOffset}}entries;canFastWrite;minimumByteLength;read(e,t,r,i){if(r+t.offset<this.minimumByteLength)throw new Error(`There is no space available to fit a packet of type ${this.packetId} at offset ${t.offset}`);if(i[0](e,t.offset)!==this.packetId)throw new Error(`Data at offset ${t.offset} is not a packet of type ${this.packetId}`);t.offset+=1;let f={};for(let[o,l]of this.entries)if(Array.isArray(l)){let s=l[1]??i[0](e,t.offset++),a=Array(s),T=l[0];if(typeof T=="object")for(let N=0;N<s;++N)a[N]=T.read(e,t,r,i);else{let N=y[T];for(let d=0;d<s;++d)a[d]=i[T](e,t.offset),t.offset+=N}f[o]=a}else if(typeof l=="number")f[o]=i[l](e,t.offset),t.offset+=y[l];else if("flags"in l){let s=i[0](e,t.offset);t.offset+=1,f[o]={};for(let a=0;a<l.flags.length;++a)f[o][l.flags[a]]=!!(s&1<<a)}else f[o]=l.read(e,t,r,i);return f}write(e,t,r,i,f){return i[0](e,this.packetId,r.offset),r.offset+=1,this.canFastWrite?(this.fastWrite(e,t,r,i),e):this.slowWrite(e,t,r,this.minimumByteLength,this.minimumByteLength,i,f)}fastWrite(e,t,r,i){for(let[f,o]of this.entries){let l=t[f];if(Array.isArray(o)){let s=o[0],a=o[1];if(typeof s=="object")for(let T=0;T<a;++T)s.fastWrite(e,l[T],r,i);else{let T=y[s];for(let N=0;N<a;++N)i[s](e,l[N],r.offset),r.offset+=T}}else if(typeof o=="number")i[o](e,l,r.offset),r.offset+=y[o];else if("flags"in o){let s=0;for(let a=0;a<o.flags.length;++a)l[o.flags[a]]&&(s|=1<<a);i[0](e,s,r.offset),r.offset+=1}else o.fastWrite(e,l,r,i)}}slowWrite(e,t,r,i,f,o,l){for(let[s,a]of this.entries){let T=t[s];if(Array.isArray(a)){let N=T.length,d=a[1]===void 0;if(d&&(o[0](e,N,r.offset),r.offset+=1),N>0){let c=a[0];if(typeof c=="object"){if(d){let F=N*c.minimumByteLength;i+=F,f+=F,e.byteLength<f&&(e=l(e,f))}for(let F of T)o[0](e,c.packetId,r.offset),r.offset+=1,e=c.slowWrite(e,F,r,i,f,o,l),i=r.offset,f=e.byteLength}else{let F=y[c];if(d){let B=N*F;i+=B,f+=B,e.byteLength<f&&(e=l(e,f))}for(let B of T)o[c](e,B,r.offset),r.offset+=F}}}else if(typeof a=="number")o[a](e,T,r.offset),r.offset+=y[a];else if("flags"in a){let N=0;for(let d=0;d<a.flags.length;++d)T[a.flags[d]]&&(N|=1<<d);o[0](e,N,r.offset),r.offset+=1}else o[0](e,a.packetId,r.offset),r.offset+=1,e=a.slowWrite(e,T,r,i,f,o,l),i=r.offset,f=e.byteLength}return e}};function J(n){return Object.entries(n).sort(([e],[t])=>e.localeCompare(t))}function v(n){let e=1,t=!0;for(let[,r]of n)if(Array.isArray(r))if(r.length===2){let i=typeof r[0]=="object"?r[0].minimumByteLength:y[r[0]];e+=r[1]*i}else e+=1,t=!1;else r instanceof p?(e+=r.minimumByteLength,t&&=r.canFastWrite):typeof r=="object"?e+=1:e+=y[r];return{minimumByteLength:e,canFastWrite:t}}var y=Array(8);y[0]=1;y[3]=1;y[1]=2;y[4]=2;y[2]=4;y[5]=4;y[6]=4;y[7]=8;var I=Array(8);I[0]=(n,e)=>n.getUint8(e);I[3]=(n,e)=>n.getInt8(e);I[1]=(n,e)=>n.getUint16(e);I[4]=(n,e)=>n.getInt16(e);I[2]=(n,e)=>n.getUint32(e);I[5]=(n,e)=>n.getInt32(e);I[6]=(n,e)=>n.getFloat32(e);I[7]=(n,e)=>n.getFloat64(e);var m=Array(8);m[0]=(n,e,t)=>n.setUint8(t,e);m[3]=(n,e,t)=>n.setInt8(t,e);m[1]=(n,e,t)=>n.setUint16(t,e);m[4]=(n,e,t)=>n.setInt16(t,e);m[2]=(n,e,t)=>n.setUint32(t,e);m[5]=(n,e,t)=>n.setInt32(t,e);m[6]=(n,e,t)=>n.setFloat32(t,e);m[7]=(n,e,t)=>n.setFloat64(t,e);var _=Array(8);g&&(_[0]=(n,e,t)=>n.writeUint8(e,t),_[3]=(n,e,t)=>n.writeInt8(e,t),_[1]=(n,e,t)=>n.writeUint16LE(e,t),_[4]=(n,e,t)=>n.writeInt16LE(e,t),_[2]=(n,e,t)=>n.writeUint32LE(e,t),_[5]=(n,e,t)=>n.writeInt32LE(e,t),_[6]=(n,e,t)=>n.writeFloatLE(e,t),_[7]=(n,e,t)=>n.writeDoubleLE(e,t));var u=Array(8);g&&(u[0]=(n,e)=>n.readUint8(e),u[3]=(n,e)=>n.readInt8(e),u[1]=(n,e)=>n.readUint16LE(e),u[4]=(n,e)=>n.readInt16LE(e),u[2]=(n,e)=>n.readUint32LE(e),u[5]=(n,e)=>n.readInt32LE(e),u[6]=(n,e)=>n.readFloatLE(e),u[7]=(n,e)=>n.readDoubleLE(e));0&&(module.exports={BinaryPacket,Field,FieldArray,FieldBitFlags,FieldFixedArray});
447
2
  //# sourceMappingURL=index.js.map