@andrew_l/tl-pack 0.0.5 → 0.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 ADDED
@@ -0,0 +1,161 @@
1
+ # TLPack for JavaScript/NodeJs
2
+
3
+ ![license](https://img.shields.io/npm/l/%40andrew_l%2Ftl-pack)![npm version](https://img.shields.io/npm/v/%40andrew_l%2Ftl-pack)![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40andrew_l%2Ftl-pack)
4
+
5
+ This library is another implementation of binary serialization like **MessagePack** inspired by TL (Type Language) developed by old VK team.
6
+
7
+ You don't needed in schema for data serialization/deserialization unlike official TL implementation at least in this version.
8
+
9
+ ## Benchmark
10
+
11
+ A bit faster and a bit more compact than **@msgpack/msgpack**
12
+
13
+ ## Synopsis
14
+
15
+ ```javascript
16
+ import { BinaryWriter, BinaryReader } from '@andrew_l/tl-pack';
17
+
18
+ const writer = new BinaryWriter();
19
+
20
+ // use to compress this part of data
21
+ // writer.writeObjectGzip
22
+ writer.writeObject({
23
+ null: null,
24
+ uint8: 255,
25
+ uint16: 256,
26
+ uint32: 65536,
27
+ int8: -128,
28
+ int16: -32768,
29
+ int32: -2147483648,
30
+ double: 3.14,
31
+ string: 'Hello world',
32
+ vector: [1, 2, 3, 4, 5, { text: 'hi' }],
33
+ map: { foo: 'bar' },
34
+ date: new Date(),
35
+ });
36
+
37
+ const reader = new BinaryReader(writer.getBuffer());
38
+
39
+ console.log(reader.readObject());
40
+ /**
41
+ {
42
+ null: null,
43
+ uint8: 255,
44
+ uint16: 256,
45
+ uint32: 65536,
46
+ int8: -128,
47
+ int16: -32768,
48
+ int32: -2147483648,
49
+ double: 3.14,
50
+ string: 'Hello world',
51
+ vector: [ 1, 2, 3, 4, 5, { text: 'hi' } ],
52
+ map: { foo: 'bar' },
53
+ date: 2023-07-03T12:22:26.000Z
54
+ }
55
+ */
56
+ ```
57
+
58
+ ## Supported Types
59
+
60
+ | Constructor ID | Byte Size |
61
+ | -------------- | ------------------ |
62
+ | Binary | 5 + sizeof(object) |
63
+ | BoolFalse | 1 |
64
+ | BoolTrue | 1 |
65
+ | Null | 1 |
66
+ | Date | 4 |
67
+ | Vector | 5 + n \* sizeof(n) |
68
+ | VectorDynamic | 2 + n \* sizeof(n) |
69
+ | Int8 | 1 |
70
+ | Int16 | 2 |
71
+ | Int32 | 4 |
72
+ | UInt8 | 1 |
73
+ | UInt16 | 2 |
74
+ | UInt32 | 4 |
75
+ | Float | 4 |
76
+ | Double | 8 |
77
+ | Map | 2 + sizeof(object) |
78
+ | String | 5 + sizeof(object) |
79
+ | GZIP | 5 + sizeof(object) |
80
+
81
+ ## Stream Example (NodeJs Only)
82
+
83
+ ```javascript
84
+ import { Readable } from 'node:stream';
85
+ import { TLEncode, TLDecode } from '@andrew_l/tl-pack/stream';
86
+
87
+ const values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
88
+
89
+ const dataStream = new Readable({ objectMode: true });
90
+
91
+ dataStream._read = () => {
92
+ const chunk = values.shift();
93
+
94
+ dataStream.push(chunk || null);
95
+ };
96
+
97
+ const encode = new TLEncode();
98
+ const decode = new TLDecode();
99
+
100
+ dataStream.pipe(encode).pipe(decode);
101
+
102
+ decode.on('data', (data) => console.log('stream', data));
103
+ decode.on('error', console.error);
104
+ ```
105
+
106
+ ## Custom Types
107
+
108
+ ```javascript
109
+ import mongoose from 'mongoose';
110
+ import { BinaryWriter, BinaryReader, createExtension } from '@andrew_l/tl-pack';
111
+
112
+ const ObjectId = mongoose.Types.ObjectId;
113
+
114
+ const extensions = [
115
+ // Reserving token - 100 for ObjectId types
116
+ createExtension(100, {
117
+ encode(value) {
118
+ if (value?._bsontype === 'ObjectID') {
119
+ return value.toJSON(); // (string)
120
+ }
121
+ },
122
+ // on client side, you possibly need a decoding as a plain string.
123
+ decode(value) {
124
+ return new ObjectId(value);
125
+ },
126
+ }),
127
+ ];
128
+
129
+ const writer = new BinaryWriter({ extensions });
130
+
131
+ writer.writeObject({
132
+ _id: new Object(),
133
+ firstName: 'Andrew',
134
+ lastName: 'L.',
135
+ });
136
+
137
+ const reader = new BinaryReader(writer.getBuffer(), { extensions });
138
+
139
+ console.log(reader.readObject());
140
+ /**
141
+ {
142
+ _id: 64a2be105e19f67e19a71a1d,
143
+ firstName: 'Andrew',
144
+ lastName: 'L.'
145
+ }
146
+ */
147
+ ```
148
+
149
+ ## Dictionary
150
+
151
+ A dictionary is used to replace strings with numeric indexes, which saves the resulting buffer size. In stream mode, the dictionary is grown while the stream is alive.
152
+
153
+ **Static**
154
+ Dictionary with you initialize a BinaryWriter/BinaryReader.
155
+
156
+ **Dynamic**
157
+ Dictionary which appends while encoding and decoding keys of an object (Map).
158
+
159
+ ## Production
160
+
161
+ No way!
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
+ import { CORE_TYPES } from './constants.js';
2
3
  import { Dictionary } from './dictionary.js';
3
4
  import { TLExtension } from './extension.js';
4
5
  export interface BinaryReaderOptions {
@@ -7,7 +8,6 @@ export interface BinaryReaderOptions {
7
8
  }
8
9
  export declare class BinaryReader {
9
10
  private target;
10
- private targetView;
11
11
  private _last?;
12
12
  private dictionary?;
13
13
  private dictionaryExtended;
@@ -38,18 +38,19 @@ export declare class BinaryReader {
38
38
  * @param length {number}
39
39
  */
40
40
  assertRead(length: number): void;
41
+ assertConstructor(constructorId: CORE_TYPES): void;
41
42
  /**
42
43
  * Gets the byte array representing the current buffer as a whole.
43
44
  * @returns {Buffer}
44
45
  */
45
- getBuffer(): Uint8Array | Buffer;
46
+ getBuffer(): Buffer | Uint8Array;
46
47
  readNull(): null;
47
48
  readLength(): number;
48
49
  readAll(): any[];
49
50
  /**
50
51
  * @returns {Uint8Array | Buffer}
51
52
  */
52
- readBytes(): Uint8Array | Buffer;
53
+ readBytes(): Buffer | Uint8Array;
53
54
  /**
54
55
  * Reads encoded string.
55
56
  * @returns {string}
@@ -82,6 +83,11 @@ export declare class BinaryReader {
82
83
  * @returns {any[]}
83
84
  */
84
85
  readVector(checkConstructor?: boolean): any[];
86
+ /**
87
+ * Reads a vector (a list) of objects.
88
+ * @returns {any[]}
89
+ */
90
+ readVectorDynamic(checkConstructor?: boolean): any[];
85
91
  /**
86
92
  * Tells the current position on the stream.
87
93
  * @returns {number}
@@ -1,10 +1,9 @@
1
1
  import pako from 'pako';
2
2
  import { CORE_TYPES } from './constants.js';
3
3
  import { Dictionary } from './dictionary.js';
4
- import { bytesToUtf8 } from './helpers.js';
4
+ import { bytesToUtf8, float32, float64, int32 } from './helpers.js';
5
5
  export class BinaryReader {
6
6
  target;
7
- targetView;
8
7
  _last;
9
8
  dictionary;
10
9
  dictionaryExtended;
@@ -17,7 +16,6 @@ export class BinaryReader {
17
16
  */
18
17
  constructor(data, options) {
19
18
  this.target = data;
20
- this.targetView = new DataView(data.buffer, 0, data.length);
21
19
  this._last = undefined;
22
20
  this.offset = 0;
23
21
  this.length = data.length;
@@ -48,35 +46,30 @@ export class BinaryReader {
48
46
  }
49
47
  readInt32(signed = true) {
50
48
  this.assertRead(4);
51
- if (signed) {
52
- this._last = this.targetView.getInt32(this.offset, true);
53
- }
54
- else {
55
- this._last = this.targetView.getUint32(this.offset, true);
49
+ this._last =
50
+ this.target[this.offset++] |
51
+ (this.target[this.offset++] << 8) |
52
+ (this.target[this.offset++] << 16) |
53
+ (this.target[this.offset++] << 24);
54
+ if (!signed) {
55
+ this._last = this._last >>> 0;
56
56
  }
57
- this.offset += 4;
58
57
  return this._last;
59
58
  }
60
59
  readInt16(signed = true) {
61
60
  this.assertRead(2);
61
+ this._last = this.target[this.offset++] | (this.target[this.offset++] << 8);
62
62
  if (signed) {
63
- this._last = this.targetView.getInt16(this.offset, true);
63
+ this._last = (this._last << 16) >> 16;
64
64
  }
65
- else {
66
- this._last = this.targetView.getUint16(this.offset, true);
67
- }
68
- this.offset += 2;
69
65
  return this._last;
70
66
  }
71
67
  readInt8(signed = true) {
72
68
  this.assertRead(1);
69
+ this._last = this.target[this.offset++];
73
70
  if (signed) {
74
- this._last = this.targetView.getInt8(this.offset);
75
- }
76
- else {
77
- this._last = this.targetView.getUint8(this.offset);
71
+ this._last = (this._last << 24) >> 24;
78
72
  }
79
- this.offset += 1;
80
73
  return this._last;
81
74
  }
82
75
  /**
@@ -85,8 +78,8 @@ export class BinaryReader {
85
78
  */
86
79
  readFloat() {
87
80
  this.assertRead(4);
88
- this._last = this.targetView.getFloat32(this.offset, true);
89
- this.offset += 4;
81
+ int32[0] = this.readInt32();
82
+ this._last = float32[0];
90
83
  return this._last;
91
84
  }
92
85
  /**
@@ -95,8 +88,9 @@ export class BinaryReader {
95
88
  */
96
89
  readDouble() {
97
90
  this.assertRead(8);
98
- this._last = this.targetView.getFloat64(this.offset, true);
99
- this.offset += 8;
91
+ int32[0] = this.readInt32();
92
+ int32[1] = this.readInt32();
93
+ this._last = float64[0];
100
94
  return this._last;
101
95
  }
102
96
  /**
@@ -113,6 +107,12 @@ export class BinaryReader {
113
107
  throw err;
114
108
  }
115
109
  }
110
+ assertConstructor(constructorId) {
111
+ const byte = this.readByte();
112
+ if (byte !== constructorId) {
113
+ throw new Error(`Invalid constructor code, expected = ${CORE_TYPES[constructorId]}, got = ${CORE_TYPES[byte] || byte}, offset = ${this.offset - 1}`);
114
+ }
115
+ }
116
116
  /**
117
117
  * Gets the byte array representing the current buffer as a whole.
118
118
  * @returns {Buffer}
@@ -227,6 +227,8 @@ export class BinaryReader {
227
227
  return false;
228
228
  case CORE_TYPES.Vector:
229
229
  return this.readVector(false);
230
+ case CORE_TYPES.VectorDynamic:
231
+ return this.readVectorDynamic(false);
230
232
  case CORE_TYPES.Null:
231
233
  return null;
232
234
  case CORE_TYPES.Binary:
@@ -291,8 +293,8 @@ export class BinaryReader {
291
293
  return key;
292
294
  }
293
295
  readMap(checkConstructor = true) {
294
- if (checkConstructor && this.readByte() !== CORE_TYPES.Map) {
295
- throw new Error('Invalid constructor code, map was expected');
296
+ if (checkConstructor) {
297
+ this.assertConstructor(CORE_TYPES.Map);
296
298
  }
297
299
  const temp = {};
298
300
  let key = this.readDictionary();
@@ -304,7 +306,6 @@ export class BinaryReader {
304
306
  }
305
307
  decode(value) {
306
308
  this.target = value;
307
- this.targetView = new DataView(value.buffer, 0, value.length);
308
309
  this._last = undefined;
309
310
  this.offset = 0;
310
311
  this.length = value.length;
@@ -315,8 +316,8 @@ export class BinaryReader {
315
316
  * @returns {any[]}
316
317
  */
317
318
  readVector(checkConstructor = true) {
318
- if (checkConstructor && this.readByte() !== CORE_TYPES.Vector) {
319
- throw new Error('Invalid constructor code, vector was expected');
319
+ if (checkConstructor) {
320
+ this.assertConstructor(CORE_TYPES.Vector);
320
321
  }
321
322
  const count = this.readLength();
322
323
  const temp = [];
@@ -325,6 +326,41 @@ export class BinaryReader {
325
326
  }
326
327
  return temp;
327
328
  }
329
+ /**
330
+ * Reads a vector (a list) of objects.
331
+ * @returns {any[]}
332
+ */
333
+ readVectorDynamic(checkConstructor = true) {
334
+ if (checkConstructor) {
335
+ this.assertConstructor(CORE_TYPES.VectorDynamic);
336
+ }
337
+ const temp = [];
338
+ let complete = false;
339
+ while (this.length > this.offset) {
340
+ const constructorId = this.readByte();
341
+ if (constructorId === CORE_TYPES.None) {
342
+ complete = true;
343
+ break;
344
+ }
345
+ const ext = this.extensions.get(constructorId);
346
+ let value;
347
+ if (ext) {
348
+ value = this.readObject();
349
+ value = ext.decode(value);
350
+ }
351
+ else {
352
+ value = this.readCore(constructorId);
353
+ }
354
+ temp.push(value);
355
+ }
356
+ if (!complete) {
357
+ const err = new Error(`DynamicVector incomplete.`);
358
+ err.incomplete = true;
359
+ Error.captureStackTrace(err, this.readDictionary);
360
+ throw err;
361
+ }
362
+ return temp;
363
+ }
328
364
  /**
329
365
  * Tells the current position on the stream.
330
366
  * @returns {number}
@@ -9,16 +9,15 @@ export interface BinaryWriterOptions {
9
9
  export declare class BinaryWriter {
10
10
  private withGzip;
11
11
  private target;
12
- private targetView;
13
12
  private dictionary?;
14
13
  private dictionaryExtended;
15
14
  private extensions;
16
15
  offset: number;
17
16
  constructor(options?: BinaryWriterOptions);
18
17
  allocate(size: number): void;
19
- makeRoom(end: number): void;
18
+ private makeRoom;
20
19
  get safeEnd(): number;
21
- getBuffer(): Uint8Array | Buffer;
20
+ getBuffer(): Buffer | Uint8Array;
22
21
  writeByte(value: number): void;
23
22
  writeBool(value: boolean): void;
24
23
  writeNull(): void;
@@ -35,7 +34,9 @@ export declare class BinaryWriter {
35
34
  writeMap(object: Record<string, any>): void;
36
35
  wireDictionary(value: string): void;
37
36
  writeGzip(value: any): void;
38
- encode(value: any): Uint8Array | Buffer;
37
+ encode(value: any): Buffer | Uint8Array;
38
+ startDynamicVector(): void;
39
+ endDynamicVector(): void;
39
40
  private _writeCustom;
40
41
  writeObject(value: any): void;
41
42
  writeObjectGzip(value: any): void;
@@ -1,7 +1,7 @@
1
1
  import pako from 'pako';
2
2
  import { CORE_TYPES } from './constants.js';
3
3
  import { Dictionary } from './dictionary.js';
4
- import { coreType } from './helpers.js';
4
+ import { coreType, float32, float64, int32 } from './helpers.js';
5
5
  const hasNodeBuffer = typeof Buffer !== 'undefined';
6
6
  const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
7
7
  const textEncoder = new TextEncoder();
@@ -24,7 +24,6 @@ const SUPPORT_COMPRESSION = new Set([CORE_TYPES.String]);
24
24
  export class BinaryWriter {
25
25
  withGzip;
26
26
  target;
27
- targetView;
28
27
  dictionary;
29
28
  dictionaryExtended;
30
29
  extensions;
@@ -34,7 +33,6 @@ export class BinaryWriter {
34
33
  this.extensions = new Map();
35
34
  this.withGzip = !!options && !!options.gzip;
36
35
  this.target = byteArrayAllocate(8192);
37
- this.targetView = new DataView(this.target.buffer, 0, this.target.length);
38
36
  if (options && options.extensions) {
39
37
  options.extensions.forEach((ext) => {
40
38
  this.extensions.set(ext.token, ext);
@@ -85,7 +83,6 @@ export class BinaryWriter {
85
83
  newBuffer.set(target.slice(start, end));
86
84
  }
87
85
  this.target = newBuffer;
88
- this.targetView = newView;
89
86
  }
90
87
  get safeEnd() {
91
88
  return this.target.length - 10;
@@ -111,41 +108,43 @@ export class BinaryWriter {
111
108
  writeInt32(value, signed = true) {
112
109
  this.allocate(4);
113
110
  if (signed) {
114
- this.targetView.setInt32(this.offset, value, true);
111
+ this.target[this.offset++] = value;
112
+ this.target[this.offset++] = value >> 8;
113
+ this.target[this.offset++] = value >> 16;
114
+ this.target[this.offset++] = value >> 24;
115
115
  }
116
116
  else {
117
- this.targetView.setUint32(this.offset, value, true);
117
+ this.target[this.offset++] = value;
118
+ this.target[this.offset++] = value >> 8;
119
+ this.target[this.offset++] = value >> 16;
120
+ this.target[this.offset++] = value >> 24;
118
121
  }
119
- this.offset += 4;
120
122
  }
121
123
  writeInt16(value, signed = true) {
122
124
  this.allocate(2);
123
125
  if (signed) {
124
- this.targetView.setInt16(this.offset, value, true);
126
+ this.target[this.offset++] = value;
127
+ this.target[this.offset++] = value >> 8;
125
128
  }
126
129
  else {
127
- this.targetView.setUint16(this.offset, value, true);
130
+ this.target[this.offset++] = value;
131
+ this.target[this.offset++] = value >> 8;
128
132
  }
129
- this.offset += 2;
130
133
  }
131
134
  writeInt8(value, signed = true) {
132
135
  this.allocate(1);
133
- if (signed) {
134
- this.target[this.offset++] = value;
135
- }
136
- else {
137
- this.targetView.setUint8(this.offset++, value);
138
- }
136
+ this.target[this.offset++] = value;
139
137
  }
140
138
  writeFloat(value) {
141
139
  this.allocate(4);
142
- this.targetView.setFloat32(this.offset, value, true);
143
- this.offset += 4;
140
+ float32[0] = value;
141
+ this.writeInt32(int32[0]);
144
142
  }
145
143
  writeDouble(value) {
146
144
  this.allocate(8);
147
- this.targetView.setFloat64(this.offset, value, true);
148
- this.offset += 8;
145
+ float64[0] = value;
146
+ this.writeInt32(int32[0], false);
147
+ this.writeInt32(int32[1], false);
149
148
  }
150
149
  writeDate(value) {
151
150
  let timestamp = 0;
@@ -247,10 +246,15 @@ export class BinaryWriter {
247
246
  encode(value) {
248
247
  this.offset = 0;
249
248
  this.target = byteArrayAllocate(256);
250
- this.targetView = new DataView(this.target.buffer, 0, this.target.length);
251
249
  this.writeObject(value);
252
250
  return this.getBuffer();
253
251
  }
252
+ startDynamicVector() {
253
+ this.writeByte(CORE_TYPES.VectorDynamic);
254
+ }
255
+ endDynamicVector() {
256
+ this.writeByte(CORE_TYPES.None);
257
+ }
254
258
  _writeCustom(value) {
255
259
  for (const ext of this.extensions.values()) {
256
260
  const result = ext.encode(value);
@@ -294,7 +298,6 @@ export class BinaryWriter {
294
298
  this.writeCore(CORE_TYPES.GZIP, writer.getBuffer());
295
299
  }
296
300
  writeCore(constructorId, value) {
297
- // console.log('write', { constructorId: CORE_TYPES[constructorId] || constructorId, value });
298
301
  if (this.withGzip && SUPPORT_COMPRESSION.has(constructorId)) {
299
302
  this.writeObjectGzip(value);
300
303
  return;
@@ -6,17 +6,18 @@ export declare enum CORE_TYPES {
6
6
  Null = 4,
7
7
  Date = 5,
8
8
  Vector = 6,
9
- Int32 = 7,
10
- Int16 = 8,
11
- Int8 = 9,
12
- UInt32 = 10,
13
- UInt16 = 11,
14
- UInt8 = 12,
15
- Float = 13,
16
- Double = 14,
17
- Map = 15,
18
- DictValue = 16,
19
- DictIndex = 17,
20
- String = 18,
21
- GZIP = 19
9
+ VectorDynamic = 7,
10
+ Int32 = 8,
11
+ Int16 = 9,
12
+ Int8 = 10,
13
+ UInt32 = 11,
14
+ UInt16 = 12,
15
+ UInt8 = 13,
16
+ Float = 14,
17
+ Double = 15,
18
+ Map = 16,
19
+ DictValue = 17,
20
+ DictIndex = 18,
21
+ String = 19,
22
+ GZIP = 25
22
23
  }
package/dist/constants.js CHANGED
@@ -7,17 +7,18 @@ export var CORE_TYPES;
7
7
  CORE_TYPES[CORE_TYPES["Null"] = 4] = "Null";
8
8
  CORE_TYPES[CORE_TYPES["Date"] = 5] = "Date";
9
9
  CORE_TYPES[CORE_TYPES["Vector"] = 6] = "Vector";
10
- CORE_TYPES[CORE_TYPES["Int32"] = 7] = "Int32";
11
- CORE_TYPES[CORE_TYPES["Int16"] = 8] = "Int16";
12
- CORE_TYPES[CORE_TYPES["Int8"] = 9] = "Int8";
13
- CORE_TYPES[CORE_TYPES["UInt32"] = 10] = "UInt32";
14
- CORE_TYPES[CORE_TYPES["UInt16"] = 11] = "UInt16";
15
- CORE_TYPES[CORE_TYPES["UInt8"] = 12] = "UInt8";
16
- CORE_TYPES[CORE_TYPES["Float"] = 13] = "Float";
17
- CORE_TYPES[CORE_TYPES["Double"] = 14] = "Double";
18
- CORE_TYPES[CORE_TYPES["Map"] = 15] = "Map";
19
- CORE_TYPES[CORE_TYPES["DictValue"] = 16] = "DictValue";
20
- CORE_TYPES[CORE_TYPES["DictIndex"] = 17] = "DictIndex";
21
- CORE_TYPES[CORE_TYPES["String"] = 18] = "String";
22
- CORE_TYPES[CORE_TYPES["GZIP"] = 19] = "GZIP";
10
+ CORE_TYPES[CORE_TYPES["VectorDynamic"] = 7] = "VectorDynamic";
11
+ CORE_TYPES[CORE_TYPES["Int32"] = 8] = "Int32";
12
+ CORE_TYPES[CORE_TYPES["Int16"] = 9] = "Int16";
13
+ CORE_TYPES[CORE_TYPES["Int8"] = 10] = "Int8";
14
+ CORE_TYPES[CORE_TYPES["UInt32"] = 11] = "UInt32";
15
+ CORE_TYPES[CORE_TYPES["UInt16"] = 12] = "UInt16";
16
+ CORE_TYPES[CORE_TYPES["UInt8"] = 13] = "UInt8";
17
+ CORE_TYPES[CORE_TYPES["Float"] = 14] = "Float";
18
+ CORE_TYPES[CORE_TYPES["Double"] = 15] = "Double";
19
+ CORE_TYPES[CORE_TYPES["Map"] = 16] = "Map";
20
+ CORE_TYPES[CORE_TYPES["DictValue"] = 17] = "DictValue";
21
+ CORE_TYPES[CORE_TYPES["DictIndex"] = 18] = "DictIndex";
22
+ CORE_TYPES[CORE_TYPES["String"] = 19] = "String";
23
+ CORE_TYPES[CORE_TYPES["GZIP"] = 25] = "GZIP";
23
24
  })(CORE_TYPES || (CORE_TYPES = {}));
package/dist/extension.js CHANGED
@@ -2,6 +2,9 @@ export function createExtension(token, { encode, decode }) {
2
2
  if (token !== -1 && (token > 254 || token < 0 || token << 0 !== token)) {
3
3
  throw new TypeError('Token must be a 8 bit number');
4
4
  }
5
+ if (token < 35) {
6
+ throw new TypeError('Tokens reserved from 0 to 34');
7
+ }
5
8
  return {
6
9
  token,
7
10
  encode,
package/dist/helpers.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import { CORE_TYPES } from './constants.js';
3
- export declare function concatUint8Arrays(arrays: ArrayLike<number>[]): Uint8Array;
3
+ export declare const int32: Int32Array;
4
+ export declare const float32: Float32Array;
5
+ export declare const float64: Float64Array;
4
6
  export declare function bytesToUtf8(bytes: Buffer | Uint8Array): string;
5
7
  export declare function utf8ToBytes(string: string): Uint8Array;
6
- export declare function serializeBytes(value: Buffer | Uint8Array | string | any): Uint8Array;
7
- export declare function serializeLength(value: number): Buffer;
8
8
  export declare function coreType(value: any): CORE_TYPES;
package/dist/helpers.js CHANGED
@@ -1,19 +1,9 @@
1
1
  import { CORE_TYPES } from './constants.js';
2
2
  const textEncoder = new TextEncoder();
3
3
  const textDecoder = new TextDecoder();
4
- export function concatUint8Arrays(arrays) {
5
- let totalLength = 0;
6
- for (const array of arrays) {
7
- totalLength += array.length;
8
- }
9
- const result = new Uint8Array(totalLength);
10
- let offset = 0;
11
- for (const array of arrays) {
12
- result.set(array, offset);
13
- offset += array.length;
14
- }
15
- return result;
16
- }
4
+ export const int32 = new Int32Array(2);
5
+ export const float32 = new Float32Array(int32.buffer);
6
+ export const float64 = new Float64Array(int32.buffer);
17
7
  export function bytesToUtf8(bytes) {
18
8
  return textDecoder.decode(bytes);
19
9
  }
@@ -22,41 +12,6 @@ export function utf8ToBytes(string) {
22
12
  const length = textEncoder.encodeInto(string, buff).written;
23
13
  return buff.subarray(0, length);
24
14
  }
25
- export function serializeBytes(value) {
26
- let data;
27
- if (typeof value === 'string') {
28
- data = utf8ToBytes(value);
29
- }
30
- else if (value instanceof Buffer) {
31
- data = value;
32
- }
33
- else if (value instanceof Uint8Array) {
34
- data = value;
35
- }
36
- else {
37
- throw Error(`Bytes or str expected, not ${value.constructor.name}`);
38
- }
39
- let length = data.length;
40
- let header;
41
- if (length < 254) {
42
- header = new Uint8Array(1);
43
- header[0] = length;
44
- }
45
- else {
46
- header = new Uint8Array(4);
47
- header[0] = 254;
48
- header[1] = length % 256;
49
- header[2] = (length >> 8) % 256;
50
- header[3] = (length >> 16) % 256;
51
- }
52
- return concatUint8Arrays([header, data]);
53
- }
54
- export function serializeLength(value) {
55
- if (value < 254) {
56
- return Buffer.from([value]);
57
- }
58
- return Buffer.from([254, value % 256, (value >> 8) % 256, (value >> 16) % 256]);
59
- }
60
15
  export function coreType(value) {
61
16
  switch (typeof value) {
62
17
  case 'string': {
@@ -66,23 +21,25 @@ export function coreType(value) {
66
21
  return value ? CORE_TYPES.BoolTrue : CORE_TYPES.BoolFalse;
67
22
  }
68
23
  case 'number': {
69
- if (value >= 0 && value <= 255) {
70
- return CORE_TYPES.UInt8;
71
- }
72
- else if (value >= 0 && value <= 65535) {
73
- return CORE_TYPES.UInt16;
74
- }
75
- else if (value >= 0 && value <= 4294967295) {
76
- return CORE_TYPES.UInt32;
77
- }
78
- else if (value >= -128 && value <= 127) {
79
- return CORE_TYPES.Int8;
80
- }
81
- else if (value >= -32768 && value <= 32767) {
82
- return CORE_TYPES.Int16;
83
- }
84
- else if (value >= -2147483648 && value <= 2147483647) {
85
- return CORE_TYPES.Int32;
24
+ if (value >> 0 === value) {
25
+ if (value >= 0 && value <= 0xff) {
26
+ return CORE_TYPES.UInt8;
27
+ }
28
+ else if (value >= 0 && value <= 0xffff) {
29
+ return CORE_TYPES.UInt16;
30
+ }
31
+ else if (value >= 0 && value <= 0xffffffff) {
32
+ return CORE_TYPES.UInt32;
33
+ }
34
+ else if (value >= -0x80 && value <= 0x7f) {
35
+ return CORE_TYPES.Int8;
36
+ }
37
+ else if (value >= -0x8000 && value <= 0x7fff) {
38
+ return CORE_TYPES.Int16;
39
+ }
40
+ else if (value >= -0x80000000 && value <= 0x7fffffff) {
41
+ return CORE_TYPES.Int32;
42
+ }
86
43
  }
87
44
  return CORE_TYPES.Double;
88
45
  }
package/dist/stream.d.ts CHANGED
@@ -5,7 +5,6 @@ import { BinaryWriter, BinaryWriterOptions } from './BinaryWriter.js';
5
5
  import { BinaryReader } from './BinaryReader.js';
6
6
  export interface TLEncodeOptions extends BinaryWriterOptions {
7
7
  streamOptions?: TransformOptions;
8
- writeVectorWhenEmpty?: boolean;
9
8
  }
10
9
  export declare class TLEncode extends Transform {
11
10
  writer: BinaryWriter;
package/dist/stream.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Transform } from 'stream';
2
2
  import { BinaryWriter } from './BinaryWriter.js';
3
3
  import { BinaryReader } from './BinaryReader.js';
4
+ import { CORE_TYPES } from './constants.js';
4
5
  export class TLEncode extends Transform {
5
6
  writer;
6
7
  count;
@@ -10,10 +11,14 @@ export class TLEncode extends Transform {
10
11
  super(opts.streamOptions);
11
12
  const writer = new BinaryWriter(options);
12
13
  const customFlush = opts.streamOptions.flush;
14
+ const VECTOR_TYPES = new Uint8Array(2);
15
+ VECTOR_TYPES[0] = CORE_TYPES.VectorDynamic;
16
+ VECTOR_TYPES[1] = CORE_TYPES.None;
17
+ // push a byte about dynamic vector starting
18
+ this.push(VECTOR_TYPES.subarray(0, 1));
13
19
  this._flush = (callback) => {
14
- if (this.count === 0 && opts.writeVectorWhenEmpty) {
15
- this.push(writer.encode([]));
16
- }
20
+ // push a byte about dynamic vector ending
21
+ this.push(VECTOR_TYPES.subarray(1, 2));
17
22
  if (customFlush) {
18
23
  customFlush.call(this, callback);
19
24
  }
package/package.json CHANGED
@@ -1,19 +1,34 @@
1
1
  {
2
2
  "name": "@andrew_l/tl-pack",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "nodemon src/playground.ts",
8
8
  "build": "rm -rf dist && npx tsc"
9
9
  },
10
- "keywords": [],
10
+ "keywords": [
11
+ "tl",
12
+ "pack",
13
+ "binary",
14
+ "buffer",
15
+ "serialization",
16
+ "deserialization"
17
+ ],
11
18
  "author": "Andrew L.",
12
19
  "license": "ISC",
13
- "types": "./dist",
14
20
  "files": [
15
21
  "dist/**"
16
22
  ],
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/men232/tl-pack.git"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/men232/tl-pack/issues"
29
+ },
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
17
32
  "exports": {
18
33
  ".": {
19
34
  "import": "./dist/index.js",