@andrew_l/tl-pack 0.0.2 → 0.0.3

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.
@@ -1,16 +1,21 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
+ import { TLExtension } from './extension.js';
3
+ export interface BinaryReaderOptions {
4
+ extensions?: TLExtension[];
5
+ }
2
6
  export declare class BinaryReader {
3
7
  private target;
4
8
  private targetView;
5
9
  private _last?;
6
10
  private _dict;
11
+ private extensions;
7
12
  offset: number;
8
13
  length: number;
9
14
  /**
10
15
  * Small utility class to read binary data.
11
16
  * @param data {Buffer}
12
17
  */
13
- constructor(data: Buffer | Uint8Array);
18
+ constructor(data: Buffer | Uint8Array, options?: BinaryReaderOptions);
14
19
  readByte(): number;
15
20
  readInt32(signed?: boolean): number;
16
21
  readInt16(signed?: boolean): number;
@@ -61,6 +66,7 @@ export declare class BinaryReader {
61
66
  * Reads a object.
62
67
  */
63
68
  readObject(): any;
69
+ private readCore;
64
70
  readDictionary(): string | null;
65
71
  readMap(checkConstructor?: boolean): Record<string, any>;
66
72
  decode(value: Buffer | Uint8Array): any;
@@ -5,19 +5,26 @@ export class BinaryReader {
5
5
  targetView;
6
6
  _last;
7
7
  _dict;
8
+ extensions;
8
9
  offset;
9
10
  length;
10
11
  /**
11
12
  * Small utility class to read binary data.
12
13
  * @param data {Buffer}
13
14
  */
14
- constructor(data) {
15
+ constructor(data, options) {
15
16
  this.target = data;
16
17
  this.targetView = new DataView(data.buffer, 0, data.length);
17
18
  this._last = undefined;
18
19
  this._dict = new Map();
19
20
  this.offset = 0;
20
21
  this.length = data.length;
22
+ this.extensions = new Map();
23
+ if (options && options.extensions) {
24
+ options.extensions.forEach((ext) => {
25
+ this.extensions.set(ext.token, ext);
26
+ });
27
+ }
21
28
  }
22
29
  readByte() {
23
30
  this.assertRead(1);
@@ -41,7 +48,7 @@ export class BinaryReader {
41
48
  this._last = this.targetView.getInt16(this.offset, true);
42
49
  }
43
50
  else {
44
- this._last = this.targetView.getUint16(this.offset);
51
+ this._last = this.targetView.getUint16(this.offset, true);
45
52
  }
46
53
  this.offset += 2;
47
54
  return this._last;
@@ -162,7 +169,20 @@ export class BinaryReader {
162
169
  * Reads a object.
163
170
  */
164
171
  readObject() {
172
+ const offset = this.offset;
165
173
  const constructorId = this.readByte();
174
+ const ext = this.extensions.get(constructorId);
175
+ let value;
176
+ if (ext) {
177
+ value = this.readObject();
178
+ value = ext.decode(value);
179
+ }
180
+ else {
181
+ value = this.readCore(constructorId);
182
+ }
183
+ return value;
184
+ }
185
+ readCore(constructorId) {
166
186
  switch (constructorId) {
167
187
  case CORE_TYPES.None:
168
188
  return this.readObject();
@@ -203,22 +223,27 @@ export class BinaryReader {
203
223
  }
204
224
  readDictionary() {
205
225
  const constructorId = this.readByte();
226
+ let key = null;
206
227
  switch (constructorId) {
207
228
  case CORE_TYPES.DictIndex: {
208
229
  const idx = this.readLength();
209
- return this._dict.get(idx);
230
+ key = this._dict.get(idx);
231
+ break;
210
232
  }
211
233
  case CORE_TYPES.DictValue: {
212
- const key = this.readString();
234
+ key = this.readString();
213
235
  this._dict.set(this._dict.size + 1, key);
214
- return key;
236
+ break;
215
237
  }
216
238
  case CORE_TYPES.None: {
217
- return null;
239
+ key = null;
240
+ break;
241
+ }
242
+ default: {
243
+ this.seek(-1);
218
244
  }
219
245
  }
220
- this.seek(-1);
221
- return null;
246
+ return key;
222
247
  }
223
248
  readMap(checkConstructor = true) {
224
249
  if (checkConstructor && this.readByte() !== CORE_TYPES.Map) {
@@ -1,10 +1,15 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
+ import { TLExtension } from './extension.js';
3
+ export interface BinaryWriterOptions {
4
+ extensions?: TLExtension[];
5
+ }
2
6
  export declare class BinaryWriter {
3
7
  private target;
4
8
  private targetView;
5
9
  private dict;
10
+ private extensions;
6
11
  offset: number;
7
- constructor();
12
+ constructor(options?: BinaryWriterOptions);
8
13
  allocate(size: number): void;
9
14
  makeRoom(end: number): void;
10
15
  get safeEnd(): number;
@@ -25,5 +30,7 @@ export declare class BinaryWriter {
25
30
  writeMap(object: Record<string, any>): void;
26
31
  wireDictionary(value: string): void;
27
32
  encode(value: any): Uint8Array | Buffer;
33
+ private _writeCustom;
28
34
  writeObject(value: any): void;
35
+ private writeCore;
29
36
  }
@@ -21,11 +21,17 @@ export class BinaryWriter {
21
21
  target;
22
22
  targetView;
23
23
  dict;
24
+ extensions;
24
25
  offset;
25
- constructor() {
26
- this.target = Buffer.alloc(0);
26
+ constructor(options) {
27
27
  this.dict = new Map();
28
28
  this.offset = 0;
29
+ this.extensions = new Map();
30
+ if (options && options.extensions) {
31
+ options.extensions.forEach((ext) => {
32
+ this.extensions.set(ext.token, ext);
33
+ });
34
+ }
29
35
  this.target = byteArrayAllocate(8192);
30
36
  this.targetView = new DataView(this.target.buffer, 0, this.target.length);
31
37
  }
@@ -150,8 +156,6 @@ export class BinaryWriter {
150
156
  this.target[start++] = (bytes >> 16) % 256;
151
157
  }
152
158
  this.offset += bytes;
153
- // this.target.set(bytes, this.offset);
154
- // this.offset += bytes.length;
155
159
  }
156
160
  writeBytes(value) {
157
161
  const length = value.length;
@@ -177,11 +181,18 @@ export class BinaryWriter {
177
181
  const length = value.length;
178
182
  this.writeLength(length);
179
183
  for (let i = 0; i < length; i++) {
180
- this.writeObject(value[i]);
184
+ if (value[i] === undefined) {
185
+ this.writeNull();
186
+ }
187
+ else {
188
+ this.writeObject(value[i]);
189
+ }
181
190
  }
182
191
  }
183
192
  writeMap(object) {
184
193
  for (const key in object) {
194
+ if (object[key] === undefined)
195
+ continue;
185
196
  this.wireDictionary(key);
186
197
  this.writeObject(object[key]);
187
198
  }
@@ -190,14 +201,12 @@ export class BinaryWriter {
190
201
  wireDictionary(value) {
191
202
  if (this.dict.has(value)) {
192
203
  const idx = this.dict.get(value);
193
- this.writeByte(CORE_TYPES.DictIndex);
194
- this.writeLength(idx);
204
+ this.writeCore(CORE_TYPES.DictIndex, idx);
195
205
  }
196
206
  else {
197
207
  const newIndex = this.dict.size + 1;
198
208
  this.dict.set(value, newIndex);
199
- this.writeByte(CORE_TYPES.DictValue);
200
- this.writeString(value);
209
+ this.writeCore(CORE_TYPES.DictValue, value);
201
210
  }
202
211
  }
203
212
  encode(value) {
@@ -207,18 +216,54 @@ export class BinaryWriter {
207
216
  this.offset = start;
208
217
  return this.target.subarray(start, end);
209
218
  }
219
+ _writeCustom(value) {
220
+ for (const ext of this.extensions.values()) {
221
+ const result = ext.encode(value);
222
+ if (result !== undefined) {
223
+ const constructorId = coreType(result);
224
+ if (constructorId === CORE_TYPES.None) {
225
+ throw new TypeError(`Invalid encode extension = ${ext.token} type of ${value}`);
226
+ }
227
+ if (ext.token !== -1) {
228
+ this.writeByte(ext.token);
229
+ }
230
+ this.writeCore(constructorId, result);
231
+ return true;
232
+ }
233
+ }
234
+ return false;
235
+ }
210
236
  writeObject(value) {
211
237
  if (value === undefined)
212
238
  return;
213
239
  const constructorId = coreType(value);
240
+ // console.log('write', {
241
+ // offset: this.offset,
242
+ // constructorId: CORE_TYPES[constructorId],
243
+ // value: String(value),
244
+ // });
214
245
  if (constructorId === CORE_TYPES.None) {
215
- throw new TypeError(`Invalid core type of ${typeof value}`);
246
+ if (this._writeCustom(value)) {
247
+ return;
248
+ }
249
+ throw new TypeError(`Invalid core type of ${value}`);
216
250
  }
251
+ this.writeCore(constructorId, value);
252
+ }
253
+ writeCore(constructorId, value) {
217
254
  if (![CORE_TYPES.BoolFalse, CORE_TYPES.BoolTrue, CORE_TYPES.Null].includes(constructorId)) {
218
255
  this.writeByte(constructorId);
219
256
  }
220
257
  switch (constructorId) {
221
- case CORE_TYPES.BoolFalse:
258
+ case CORE_TYPES.DictIndex: {
259
+ return this.writeLength(value);
260
+ }
261
+ case CORE_TYPES.DictValue: {
262
+ return this.writeString(value);
263
+ }
264
+ case CORE_TYPES.BoolFalse: {
265
+ return this.writeBool(value);
266
+ }
222
267
  case CORE_TYPES.BoolTrue: {
223
268
  return this.writeBool(value);
224
269
  }
@@ -0,0 +1,11 @@
1
+ export type EncodeHandler = (value: any) => string | number | undefined;
2
+ export type DecodeHandler = (value: string | number) => any;
3
+ export interface TLExtension {
4
+ token: number;
5
+ encode: EncodeHandler;
6
+ decode: DecodeHandler;
7
+ }
8
+ export declare function createExtension(token: number, { encode, decode }: {
9
+ encode: EncodeHandler;
10
+ decode: DecodeHandler;
11
+ }): TLExtension;
@@ -0,0 +1,10 @@
1
+ export function createExtension(token, { encode, decode }) {
2
+ if (token !== -1 && (token > 254 || token < 0 || token << 0 !== token)) {
3
+ throw new TypeError('Token must be a 8 bit number');
4
+ }
5
+ return {
6
+ token,
7
+ encode,
8
+ decode,
9
+ };
10
+ }
package/dist/helpers.js CHANGED
@@ -95,11 +95,32 @@ export function coreType(value) {
95
95
  if (Array.isArray(value)) {
96
96
  return CORE_TYPES.Vector;
97
97
  }
98
- // @ts-ignore
99
- if (toString.call(value) === '[object Object]') {
98
+ if (isPlainObject(value)) {
100
99
  return CORE_TYPES.Map;
101
100
  }
102
101
  }
103
102
  }
104
103
  return CORE_TYPES.None;
105
104
  }
105
+ /** @ts-ignore */
106
+ const isObject = (val) => toString.call(val) === '[object Object]';
107
+ function isPlainObject(value) {
108
+ let ctor, prot;
109
+ if (!isObject(value))
110
+ return false;
111
+ // If it has modified constructor
112
+ ctor = value.constructor;
113
+ if (ctor === undefined)
114
+ return true;
115
+ // If it has modified prototype
116
+ prot = ctor.prototype;
117
+ if (isObject(prot) === false)
118
+ return false;
119
+ // If constructor does not have an Object-specific method
120
+ // eslint-disable-next-line no-prototype-builtins
121
+ if (prot.hasOwnProperty('isPrototypeOf') === false) {
122
+ return false;
123
+ }
124
+ // Most likely a plain Object
125
+ return true;
126
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- export { BinaryWriter } from './BinaryWriter.js';
2
- export { BinaryReader } from './BinaryReader.js';
1
+ export * from './BinaryWriter.js';
2
+ export * from './BinaryReader.js';
3
3
  export * from './constants.js';
4
+ export * from './extension.js';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
- export { BinaryWriter } from './BinaryWriter.js';
2
- export { BinaryReader } from './BinaryReader.js';
1
+ export * from './BinaryWriter.js';
2
+ export * from './BinaryReader.js';
3
3
  export * from './constants.js';
4
+ export * from './extension.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrew_l/tl-pack",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "scripts": {