@andrew_l/tl-pack 0.1.7 → 0.1.8

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
@@ -120,9 +120,13 @@ const extensions = [
120
120
  this.writeBytes(value.id);
121
121
  }
122
122
  },
123
- // in the browser you possibly need to decode as a plain string
124
123
  decode() {
125
124
  const bytes = this.readBytes();
125
+
126
+ if (IS_BROWSER) {
127
+ return hex(bytes);
128
+ }
129
+
126
130
  return new ObjectId(bytes);
127
131
  },
128
132
  }),
@@ -146,6 +150,24 @@ console.log(reader.readObject());
146
150
  lastName: 'L.'
147
151
  }
148
152
  */
153
+
154
+ const byteToHex: string[] = [];
155
+
156
+ for (let n = 0; n <= 0xff; ++n) {
157
+ const hexOctet = n.toString(16).padStart(2, '0');
158
+ byteToHex.push(hexOctet);
159
+ }
160
+
161
+ function hex(arrayBuffer: Uint8Array) {
162
+ const buff = new Uint8Array(arrayBuffer);
163
+ const hexOctets = new Array(buff.length);
164
+
165
+ for (let i = 0; i < buff.length; ++i) {
166
+ hexOctets[i] = byteToHex[buff[i]];
167
+ }
168
+
169
+ return hexOctets.join('');
170
+ }
149
171
  ```
150
172
 
151
173
  ## Dictionary
@@ -77,7 +77,7 @@ export declare class BinaryReader {
77
77
  readGzip(): Uint8Array;
78
78
  private readCore;
79
79
  getDictionaryValue(index: number): string | undefined;
80
- readDictionary(): string | null;
80
+ readDictionary(): null | string;
81
81
  readMap(checkConstructor?: boolean): Record<string, any>;
82
82
  decode(value: Buffer | Uint8Array): any;
83
83
  /**
@@ -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 { bytesToUtf8, float32, float64, int32 } from './helpers.js';
4
+ import { float32, float64, int32, utf8Read } from './helpers.js';
5
5
  export class BinaryReader {
6
6
  target;
7
7
  _last;
@@ -160,10 +160,8 @@ export class BinaryReader {
160
160
  readString() {
161
161
  const length = this.readLength();
162
162
  this.assertRead(length);
163
- const bytes = this.target.subarray(this.offset, this.offset + length);
164
- this.offset += bytes.length;
165
- // return pako.inflateRaw(bytes, { to: 'string' });
166
- const result = bytesToUtf8(bytes);
163
+ const result = utf8Read(this.target, length, this.offset);
164
+ this.offset += length;
167
165
  this._last = result;
168
166
  return result;
169
167
  }
@@ -267,6 +265,15 @@ export class BinaryReader {
267
265
  return this.readDouble();
268
266
  case CORE_TYPES.Map:
269
267
  return this.readMap(false);
268
+ case CORE_TYPES.DictIndex: {
269
+ const idx = this.readLength();
270
+ return this.getDictionaryValue(idx);
271
+ }
272
+ case CORE_TYPES.DictValue: {
273
+ const value = this.readString();
274
+ this.dictionaryExtended.maybeInsert(value);
275
+ return value;
276
+ }
270
277
  case CORE_TYPES.Repeat: {
271
278
  const size = this.readLength();
272
279
  this._repeat = { pool: size - 1, value: this._lastObject };
@@ -1,25 +1,8 @@
1
1
  import pako from 'pako';
2
- import { CORE_TYPES } from './constants.js';
2
+ import { CORE_TYPES, MAX_BUFFER_SIZE } from './constants.js';
3
3
  import { Dictionary } from './dictionary.js';
4
- import { coreType, float32, float64, int32 } from './helpers.js';
5
- const hasNodeBuffer = typeof Buffer !== 'undefined';
6
- const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
7
- const textEncoder = new TextEncoder();
4
+ import { byteArrayAllocate, coreType, float32, float64, int32, utf8Write, } from './helpers.js';
8
5
  const noop = Symbol();
9
- const writeUtf8 = hasNodeBuffer
10
- ? function (target, value, offset) {
11
- const length = target.utf8Write(value, offset, 0xffffffff);
12
- return length;
13
- }
14
- : function (target, value, offset) {
15
- return textEncoder.encodeInto(value, target.subarray(offset)).written;
16
- };
17
- function byteArrayAllocate(length) {
18
- if (hasNodeBuffer) {
19
- return Buffer.allocUnsafeSlow(length);
20
- }
21
- return new Uint8Array(length);
22
- }
23
6
  const NO_CONSTRUCTOR = new Set([CORE_TYPES.BoolFalse, CORE_TYPES.BoolTrue, CORE_TYPES.Null]);
24
7
  const SUPPORT_COMPRESSION = new Set([CORE_TYPES.String]);
25
8
  export class BinaryWriter {
@@ -77,7 +60,6 @@ export class BinaryWriter {
77
60
  newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12;
78
61
  }
79
62
  const newBuffer = byteArrayAllocate(newSize);
80
- const newView = new DataView(newBuffer.buffer, 0, newSize);
81
63
  end = Math.min(end, target.length);
82
64
  if ('copy' in target) {
83
65
  target.copy(newBuffer, 0, start, end);
@@ -162,8 +144,9 @@ export class BinaryWriter {
162
144
  writeString(value) {
163
145
  // const compressed = pako.deflateRaw(value, { level: 9 });
164
146
  // this.writeBytes(compressed);
147
+ const strLength = value.length;
165
148
  let start = this.offset;
166
- let require = value.length << 2;
149
+ let require = strLength << 2;
167
150
  if (require < 254) {
168
151
  require += 1;
169
152
  this.offset += 1;
@@ -173,7 +156,7 @@ export class BinaryWriter {
173
156
  this.offset += 4;
174
157
  }
175
158
  this.allocate(require);
176
- const bytes = writeUtf8(this.target, value, this.offset);
159
+ const bytes = utf8Write(this.target, value, this.offset);
177
160
  if (require < 254) {
178
161
  this.target[start++] = bytes;
179
162
  }
@@ -375,6 +358,11 @@ export class BinaryWriter {
375
358
  return this.writeNull();
376
359
  }
377
360
  case CORE_TYPES.String: {
361
+ // write short strings into dictionary
362
+ if (value.length <= 0x10) {
363
+ this.offset--;
364
+ return this.wireDictionary(value);
365
+ }
378
366
  return this.writeString(value);
379
367
  }
380
368
  case CORE_TYPES.Vector: {
@@ -22,3 +22,5 @@ export declare enum CORE_TYPES {
22
22
  Repeat = 20,
23
23
  GZIP = 25
24
24
  }
25
+ export declare const HAS_NODE_BUFFER: boolean;
26
+ export declare const MAX_BUFFER_SIZE: number;
package/dist/constants.js CHANGED
@@ -23,3 +23,5 @@ export var CORE_TYPES;
23
23
  CORE_TYPES[CORE_TYPES["Repeat"] = 20] = "Repeat";
24
24
  CORE_TYPES[CORE_TYPES["GZIP"] = 25] = "GZIP";
25
25
  })(CORE_TYPES || (CORE_TYPES = {}));
26
+ export const HAS_NODE_BUFFER = typeof Buffer !== 'undefined';
27
+ export const MAX_BUFFER_SIZE = HAS_NODE_BUFFER ? 0x100000000 : 0x7fd00000;
package/dist/helpers.d.ts CHANGED
@@ -3,6 +3,9 @@ import { CORE_TYPES } from './constants.js';
3
3
  export declare const int32: Int32Array;
4
4
  export declare const float32: Float32Array;
5
5
  export declare const float64: Float64Array;
6
- export declare function bytesToUtf8(bytes: Buffer | Uint8Array): string;
7
- export declare function utf8ToBytes(string: string): Uint8Array;
6
+ export declare function byteArrayAllocate(length: number): Buffer | Uint8Array;
8
7
  export declare function coreType(value: any): CORE_TYPES;
8
+ export declare function utf8Read(target: Buffer | Uint8Array, length: number, offset: number): string;
9
+ export declare function utf8ReadShort(target: Buffer | Uint8Array, length: number, offset: number): string | undefined;
10
+ export declare const utf8Write: (target: any, value: string, offset: number) => number;
11
+ export declare const utf8WriteShort: (target: any, value: string, offset: number) => number;
package/dist/helpers.js CHANGED
@@ -1,16 +1,15 @@
1
- import { CORE_TYPES } from './constants.js';
2
- const textEncoder = new TextEncoder();
3
- const textDecoder = new TextDecoder();
1
+ import { CORE_TYPES, HAS_NODE_BUFFER } from './constants.js';
2
+ const encoder = new TextEncoder();
3
+ const decoder = new TextDecoder();
4
+ const fromCharCode = String.fromCharCode;
4
5
  export const int32 = new Int32Array(2);
5
6
  export const float32 = new Float32Array(int32.buffer);
6
7
  export const float64 = new Float64Array(int32.buffer);
7
- export function bytesToUtf8(bytes) {
8
- return textDecoder.decode(bytes);
9
- }
10
- export function utf8ToBytes(string) {
11
- const buff = new Uint8Array(string.length << 2);
12
- const length = textEncoder.encodeInto(string, buff).written;
13
- return buff.subarray(0, length);
8
+ export function byteArrayAllocate(length) {
9
+ if (HAS_NODE_BUFFER) {
10
+ return Buffer.allocUnsafeSlow(length);
11
+ }
12
+ return new Uint8Array(length);
14
13
  }
15
14
  export function coreType(value) {
16
15
  switch (typeof value) {
@@ -59,6 +58,245 @@ export function coreType(value) {
59
58
  }
60
59
  return CORE_TYPES.None;
61
60
  }
61
+ export function utf8Read(target, length, offset) {
62
+ let result;
63
+ if (length < 16) {
64
+ if ((result = utf8ReadShort(target, length, offset)))
65
+ return result;
66
+ }
67
+ if (length > 64 && decoder)
68
+ return decoder.decode(target.subarray(offset, (offset += length)));
69
+ const end = offset + length;
70
+ const units = [];
71
+ result = '';
72
+ while (offset < end) {
73
+ const byte1 = target[offset++];
74
+ if ((byte1 & 0x80) === 0) {
75
+ // 1 byte
76
+ units.push(byte1);
77
+ }
78
+ else if ((byte1 & 0xe0) === 0xc0) {
79
+ // 2 bytes
80
+ const byte2 = target[offset++] & 0x3f;
81
+ units.push(((byte1 & 0x1f) << 6) | byte2);
82
+ }
83
+ else if ((byte1 & 0xf0) === 0xe0) {
84
+ // 3 bytes
85
+ const byte2 = target[offset++] & 0x3f;
86
+ const byte3 = target[offset++] & 0x3f;
87
+ units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
88
+ }
89
+ else if ((byte1 & 0xf8) === 0xf0) {
90
+ // 4 bytes
91
+ const byte2 = target[offset++] & 0x3f;
92
+ const byte3 = target[offset++] & 0x3f;
93
+ const byte4 = target[offset++] & 0x3f;
94
+ let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
95
+ if (unit > 0xffff) {
96
+ unit -= 0x10000;
97
+ units.push(((unit >>> 10) & 0x3ff) | 0xd800);
98
+ unit = 0xdc00 | (unit & 0x3ff);
99
+ }
100
+ units.push(unit);
101
+ }
102
+ else {
103
+ units.push(byte1);
104
+ }
105
+ if (units.length >= 0x1000) {
106
+ result += fromCharCode.apply(String, units);
107
+ units.length = 0;
108
+ }
109
+ }
110
+ if (units.length > 0) {
111
+ result += fromCharCode.apply(String, units);
112
+ }
113
+ return result;
114
+ }
115
+ export function utf8ReadShort(target, length, offset) {
116
+ if (length < 4) {
117
+ if (length < 2) {
118
+ if (length === 0)
119
+ return '';
120
+ else {
121
+ let a = target[offset++];
122
+ if ((a & 0x80) > 1) {
123
+ offset -= 1;
124
+ return;
125
+ }
126
+ return fromCharCode(a);
127
+ }
128
+ }
129
+ else {
130
+ let a = target[offset++];
131
+ let b = target[offset++];
132
+ if ((a & 0x80) > 0 || (b & 0x80) > 0) {
133
+ offset -= 2;
134
+ return;
135
+ }
136
+ if (length < 3)
137
+ return fromCharCode(a, b);
138
+ let c = target[offset++];
139
+ if ((c & 0x80) > 0) {
140
+ offset -= 3;
141
+ return;
142
+ }
143
+ return fromCharCode(a, b, c);
144
+ }
145
+ }
146
+ else {
147
+ let a = target[offset++];
148
+ let b = target[offset++];
149
+ let c = target[offset++];
150
+ let d = target[offset++];
151
+ if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {
152
+ offset -= 4;
153
+ return;
154
+ }
155
+ if (length < 6) {
156
+ if (length === 4)
157
+ return fromCharCode(a, b, c, d);
158
+ else {
159
+ let e = target[offset++];
160
+ if ((e & 0x80) > 0) {
161
+ offset -= 5;
162
+ return;
163
+ }
164
+ return fromCharCode(a, b, c, d, e);
165
+ }
166
+ }
167
+ else if (length < 8) {
168
+ let e = target[offset++];
169
+ let f = target[offset++];
170
+ if ((e & 0x80) > 0 || (f & 0x80) > 0) {
171
+ offset -= 6;
172
+ return;
173
+ }
174
+ if (length < 7)
175
+ return fromCharCode(a, b, c, d, e, f);
176
+ let g = target[offset++];
177
+ if ((g & 0x80) > 0) {
178
+ offset -= 7;
179
+ return;
180
+ }
181
+ return fromCharCode(a, b, c, d, e, f, g);
182
+ }
183
+ else {
184
+ let e = target[offset++];
185
+ let f = target[offset++];
186
+ let g = target[offset++];
187
+ let h = target[offset++];
188
+ if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
189
+ offset -= 8;
190
+ return;
191
+ }
192
+ if (length < 10) {
193
+ if (length === 8)
194
+ return fromCharCode(a, b, c, d, e, f, g, h);
195
+ else {
196
+ let i = target[offset++];
197
+ if ((i & 0x80) > 0) {
198
+ offset -= 9;
199
+ return;
200
+ }
201
+ return fromCharCode(a, b, c, d, e, f, g, h, i);
202
+ }
203
+ }
204
+ else if (length < 12) {
205
+ let i = target[offset++];
206
+ let j = target[offset++];
207
+ if ((i & 0x80) > 0 || (j & 0x80) > 0) {
208
+ offset -= 10;
209
+ return;
210
+ }
211
+ if (length < 11)
212
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j);
213
+ let k = target[offset++];
214
+ if ((k & 0x80) > 0) {
215
+ offset -= 11;
216
+ return;
217
+ }
218
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k);
219
+ }
220
+ else {
221
+ let i = target[offset++];
222
+ let j = target[offset++];
223
+ let k = target[offset++];
224
+ let l = target[offset++];
225
+ if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
226
+ offset -= 12;
227
+ return;
228
+ }
229
+ if (length < 14) {
230
+ if (length === 12)
231
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l);
232
+ else {
233
+ let m = target[offset++];
234
+ if ((m & 0x80) > 0) {
235
+ offset -= 13;
236
+ return;
237
+ }
238
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m);
239
+ }
240
+ }
241
+ else {
242
+ let m = target[offset++];
243
+ let n = target[offset++];
244
+ if ((m & 0x80) > 0 || (n & 0x80) > 0) {
245
+ offset -= 14;
246
+ return;
247
+ }
248
+ if (length < 15)
249
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
250
+ let o = target[offset++];
251
+ if ((o & 0x80) > 0) {
252
+ offset -= 15;
253
+ return;
254
+ }
255
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }
261
+ export const utf8Write = HAS_NODE_BUFFER
262
+ ? function (target, value, offset) {
263
+ return value.length < 0x40
264
+ ? utf8WriteShort(target, value, offset)
265
+ : target.utf8Write(value, offset, 0xffffffff);
266
+ }
267
+ : function (target, value, offset) {
268
+ return value.length < 0x40
269
+ ? utf8WriteShort(target, value, offset)
270
+ : encoder.encodeInto(value, target.subarray(offset)).written;
271
+ };
272
+ export const utf8WriteShort = (target, value, offset) => {
273
+ let i, c1, c2, strPosition = offset;
274
+ const strLength = value.length;
275
+ for (i = 0; i < strLength; i++) {
276
+ c1 = value.charCodeAt(i);
277
+ if (c1 < 0x80) {
278
+ target[strPosition++] = c1;
279
+ }
280
+ else if (c1 < 0x800) {
281
+ target[strPosition++] = (c1 >> 6) | 0xc0;
282
+ target[strPosition++] = (c1 & 0x3f) | 0x80;
283
+ }
284
+ else if ((c1 & 0xfc00) === 0xd800 && ((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00) {
285
+ c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
286
+ i++;
287
+ target[strPosition++] = (c1 >> 18) | 0xf0;
288
+ target[strPosition++] = ((c1 >> 12) & 0x3f) | 0x80;
289
+ target[strPosition++] = ((c1 >> 6) & 0x3f) | 0x80;
290
+ target[strPosition++] = (c1 & 0x3f) | 0x80;
291
+ }
292
+ else {
293
+ target[strPosition++] = (c1 >> 12) | 0xe0;
294
+ target[strPosition++] = ((c1 >> 6) & 0x3f) | 0x80;
295
+ target[strPosition++] = (c1 & 0x3f) | 0x80;
296
+ }
297
+ }
298
+ return strPosition - offset;
299
+ };
62
300
  /** @ts-ignore */
63
301
  const isObject = (val) => toString.call(val) === '[object Object]';
64
302
  function isPlainObject(value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrew_l/tl-pack",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Binary serialization library",
5
5
  "type": "module",
6
6
  "scripts": {