brs-js 2.0.13 → 2.0.14

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.
Files changed (57) hide show
  1. package/package.json +1 -1
  2. package/.babelrc +0 -5
  3. package/.prettierrc +0 -7
  4. package/debug/Conf Spacestation.brs +0 -0
  5. package/debug/Electrks_Feminine_Challenge.brs +0 -0
  6. package/debug/a5bricks.brs +0 -0
  7. package/debug/a5p2.2.brs +0 -0
  8. package/debug/a5p2.brs +0 -0
  9. package/debug/audio.brs +0 -0
  10. package/debug/brick a5.brs +0 -0
  11. package/debug/brick qa.brs +0 -0
  12. package/debug/brickparty.brs +0 -0
  13. package/debug/brsv10.brs +0 -0
  14. package/debug/brsv10brick.brs +0 -0
  15. package/debug/bruteforce.js +0 -254
  16. package/debug/click brick.brs +0 -0
  17. package/debug/clone.html +0 -36
  18. package/debug/clone.js +0 -33
  19. package/debug/ctf_tileset.brs +0 -0
  20. package/debug/ctf_tileset_5.brs +0 -0
  21. package/debug/evil.brs +0 -0
  22. package/debug/evilwrite.js +0 -390
  23. package/debug/foo.txt +0 -3080
  24. package/debug/kenko_big.brs +0 -0
  25. package/debug/light.brs +0 -0
  26. package/debug/out.json +0 -105
  27. package/debug/read.js +0 -30
  28. package/debug/readSpeed.js +0 -32
  29. package/debug/readTest.js +0 -45
  30. package/debug/temp.brs +0 -0
  31. package/debug/unicodeInteract.brs +0 -0
  32. package/debug/western.brs +0 -0
  33. package/examples/ATCFort.brs +0 -0
  34. package/examples/read_example.html +0 -34
  35. package/examples/read_example.js +0 -21
  36. package/examples/write_example.js +0 -25
  37. package/examples/write_planet.html +0 -144
  38. package/examples/write_simplex.html +0 -82
  39. package/examples/write_wedge_sphere.html +0 -173
  40. package/src/constants.ts +0 -6
  41. package/src/index.ts +0 -15
  42. package/src/read.ts +0 -57
  43. package/src/read.v1.ts +0 -99
  44. package/src/read.v10.ts +0 -185
  45. package/src/read.v2.ts +0 -102
  46. package/src/read.v3.ts +0 -111
  47. package/src/read.v4.ts +0 -112
  48. package/src/read.v8.ts +0 -172
  49. package/src/read.v9.ts +0 -181
  50. package/src/types.ts +0 -341
  51. package/src/utils.ts +0 -651
  52. package/src/uuid.ts +0 -78
  53. package/src/write.ts +0 -287
  54. package/test/lib.test.js +0 -51
  55. package/test/utils.test.js +0 -209
  56. package/tsconfig.json +0 -18
  57. package/webpack.config.js +0 -64
package/src/utils.ts DELETED
@@ -1,651 +0,0 @@
1
- import { deflate, inflate } from 'pako';
2
- import { MAX_INT } from './constants';
3
- import {
4
- BRSBytes,
5
- Bytes,
6
- UnrealColor,
7
- UnrealFloat,
8
- UnrealType,
9
- Uuid,
10
- } from './types';
11
- import { uuidParse, uuidStringify } from './uuid';
12
-
13
- /*
14
- Notes:
15
- - Everything is Little Endian by default because
16
- UE4 uses it.
17
- - I'd use Buffer.readUInt16LE if I was making this
18
- nodejs only. I don't want to require('Buffer/')
19
-
20
- */
21
-
22
- // Determine if a string is ascii-only
23
- function isASCII(text: string): boolean {
24
- return /^[\x00-\x7F]*$/.test(text);
25
- }
26
-
27
- // convert BGRA color to RGBA color
28
- export const bgra = ([b, g, r, a]: number[]): [
29
- number,
30
- number,
31
- number,
32
- number
33
- ] => [r, g, b, a];
34
-
35
- // Compare equality of byte arrays
36
- export function isEqual<T>(arrA: Array<T>, arrB: Array<T>): boolean {
37
- return arrA.length === arrB.length && arrA.every((a: T, i) => arrB[i] === a);
38
- }
39
-
40
- function isBRSBytes(data: Bytes): data is BRSBytes {
41
- return (data as BRSBytes).brsOffset !== undefined;
42
- }
43
-
44
- // read `len` bytes and return slice while updating offset
45
- export function subarray(data: Bytes, len: number, isCopy = false): Uint8Array {
46
- if (!(data instanceof Uint8Array)) {
47
- throw new Error(`Invalid data type in bytes reader (${typeof data})`);
48
- }
49
-
50
- let bytes: BRSBytes;
51
- if (!isBRSBytes(data)) {
52
- bytes = data as BRSBytes;
53
- bytes.brsOffset = 0;
54
- } else {
55
- bytes = data;
56
- }
57
-
58
- const chunk = bytes[isCopy ? 'slice' : 'subarray'](
59
- bytes.brsOffset,
60
- bytes.brsOffset + len
61
- );
62
- bytes.brsOffset += len;
63
- return chunk;
64
- }
65
-
66
- // break a byte array into chunks of a specified size
67
- export function chunk(arr: Bytes, size: number): BRSBytes[] {
68
- // relative length based on the offset of the array's data view
69
- const length = arr.length - (isBRSBytes(arr) ? arr.brsOffset : 0);
70
-
71
- // out array of chunks pre-allocated
72
- const out = Array(Math.floor(length / size));
73
-
74
- for (let i = 0; i < length / size; i++) {
75
- out[i] = subarray(arr, size, true);
76
- }
77
-
78
- return out;
79
- }
80
-
81
- // Read a u16 from a byte array
82
- function read_u16(data: Bytes, littleEndian = true): number {
83
- const [a, b] = subarray(data, 2);
84
-
85
- return littleEndian ? (b << 8) | a : (a << 8) | b;
86
- }
87
-
88
- // Write a u16 into byte array
89
- function write_u16(num: number, littleEndian = true): Uint8Array {
90
- const data = [num & 255, (num >> 8) & 255];
91
- return new Uint8Array(!littleEndian ? data.reverse() : data);
92
- }
93
-
94
- // Read an i32 from a byte array
95
- function read_i32(data: Bytes, littleEndian = true): number {
96
- const [a, b, c, d] = subarray(data, 4);
97
- return littleEndian
98
- ? (d << 24) | (c << 16) | (b << 8) | a
99
- : (a << 24) | (b << 16) | (c << 8) | d;
100
- }
101
-
102
- // Write an i32 from a byte array
103
- function write_i32(num: number, littleEndian = true): Uint8Array {
104
- const data = new Uint8Array([
105
- num & 255,
106
- (num >> 8) & 255,
107
- (num >> 16) & 255,
108
- (num >> 24) & 255,
109
- ]);
110
-
111
- return !littleEndian ? data.reverse() : data;
112
- }
113
-
114
- // Decompress a byte array of compressed data
115
- function read_compressed(data: Bytes): Bytes {
116
- const uncompressedSize = read_i32(data);
117
- const compressedSize = read_i32(data);
118
-
119
- // Throw error for weird compression/uncompression sizes
120
- if (
121
- compressedSize < 0 ||
122
- uncompressedSize < 0 ||
123
- compressedSize >= uncompressedSize
124
- ) {
125
- throw new Error(
126
- `Invalid compressed section size (comp: ${compressedSize}, uncomp: ${uncompressedSize})`
127
- );
128
- }
129
-
130
- // No compressed data? Return those bytes
131
- if (compressedSize === 0) {
132
- return subarray(data, uncompressedSize);
133
- } else {
134
- // Decompress the data otherwise
135
- const compressed = subarray(data, compressedSize);
136
- return inflate(compressed);
137
- }
138
- }
139
-
140
- // Compress a byte array into fewer bytes
141
- function write_uncompressed(...args: Uint8Array[]): Uint8Array {
142
- // Concat the args to one massive array
143
- const data = concat(...args);
144
-
145
- // Build the output
146
- return concat(write_i32(data.length), write_i32(0), data);
147
- }
148
-
149
- // Compress a byte array into fewer bytes
150
- function write_compressed(...args: Uint8Array[]): Uint8Array {
151
- // Concat the args to one massive array
152
- const data = concat(...args);
153
-
154
- // Do the compression
155
- const compressed = deflate(data);
156
- const uncompressedSize = data.length;
157
- const compressedSize = compressed.length;
158
-
159
- if (uncompressedSize > MAX_INT) {
160
- throw new Error(`uncompressedSize (${uncompressedSize}) out of range`);
161
- }
162
-
163
- if (compressedSize > MAX_INT) {
164
- throw new Error(`compressedSize (${compressedSize}) out of range`);
165
- }
166
-
167
- // Determine if compression increases size
168
- const badCompress = compressedSize >= uncompressedSize;
169
-
170
- // Build the output
171
- return concat(
172
- write_i32(uncompressedSize),
173
- write_i32(badCompress ? 0 : compressedSize),
174
- badCompress ? data : compressed
175
- );
176
- }
177
-
178
- // Read a string from a byte array
179
- function read_string(data: Bytes): string {
180
- const raw_size = read_i32(data);
181
- const is_ucs2 = raw_size < 0;
182
- const size = is_ucs2 ? -raw_size * 2 : raw_size;
183
-
184
- // Determine if we are using UCS-2
185
- if (is_ucs2) {
186
- if (size % 2 !== 0) {
187
- throw new Error('Invalid UCS-2 data size');
188
- }
189
-
190
- // Create ucs2 encoded string
191
- return String.fromCodePoint(
192
- // Read the data in 2 byte windows
193
- ...chunk(subarray(data, size), 2).map(arr => read_u16(arr)) // Convert the two bytes into u16
194
- );
195
- } else {
196
- // Read the data, remove the \u0000 at the end :)
197
- const strData = subarray(data, size).subarray(0, -1);
198
-
199
- // Convert into ascii
200
- // console.debug('[debug] strdata', strData);
201
- return String.fromCharCode.apply(null, strData);
202
- }
203
- }
204
-
205
- // Write a string to bytes
206
- function write_string(str: string): Uint8Array {
207
- if (isASCII(str)) {
208
- return concat(
209
- write_i32(str.length + 1), // Write string length (+ null term)
210
- new Uint8Array(str.split('').map(s => s.charCodeAt(0))), // Write string as bytes
211
- new Uint8Array([0]) // Null terminator
212
- );
213
- } else {
214
- // ucs2 strings denoted by negative length
215
- const len = -str.length;
216
- return concat(
217
- write_i32(len), // write length
218
- // convert string to little endian ucs2
219
- new Uint8Array(
220
- str
221
- .split('')
222
- .flatMap(s => [s.charCodeAt(0) & 0xff, s.charCodeAt(0) >> 8])
223
- )
224
- // new Uint8Array([0]) // Null terminator
225
- );
226
- }
227
- }
228
-
229
- // Read uuid from 4 LE ints
230
- function read_uuid(data: Bytes): string {
231
- return uuidStringify(
232
- // each chunk is LE
233
- chunk(subarray(data, 16), 4).flatMap(([a, b, c, d]) => [d, c, b, a])
234
- );
235
- }
236
-
237
- // parse a uuid into 4 LE ints
238
- function write_uuid(uuid: Uuid) {
239
- return concat(
240
- ...chunk(uuidParse(uuid), 4).map(
241
- ([a, b, c, d]) => new Uint8Array([d, c, b, a])
242
- )
243
- );
244
- }
245
-
246
- // Read an array of things given a fn
247
- function read_array<T>(data: Bytes, fn: (_: Bytes) => T): T[] {
248
- const length = read_i32(data);
249
- const arr = Array(length);
250
- for (let i = 0; i < length; i++) {
251
- arr[i] = fn(data);
252
- }
253
- return arr;
254
- }
255
-
256
- // iterate an array of things given a fn
257
- function read_each(data: Bytes, fn: (_: Bytes) => void) {
258
- const length = read_i32(data);
259
- for (let i = 0; i < length; i++) {
260
- fn(data);
261
- }
262
- }
263
-
264
- // Write an array of things to bytes
265
- function write_array<T>(arr: T[], fn: (_: T) => Uint8Array) {
266
- return concat(write_i32(arr.length), ...arr.map(o => fn(o)));
267
- }
268
-
269
- // Tool for reading byte arrays 1 bit at a time
270
- export class BitReader {
271
- buffer: Uint8Array;
272
- pos: number = 0;
273
-
274
- constructor(data: Uint8Array) {
275
- this.buffer = data;
276
- }
277
-
278
- empty(): boolean {
279
- return this.pos >= this.buffer.length * 8;
280
- }
281
-
282
- // Read one bit as a boolean
283
- bit(): boolean {
284
- const bit = (this.buffer[this.pos >> 3] & (1 << (this.pos & 0b111))) !== 0;
285
- this.pos++;
286
- return bit;
287
- }
288
-
289
- // Align the pos to the nearest byte
290
- align() {
291
- this.pos = (this.pos + 7) & ~7;
292
- }
293
-
294
- // read an int up to max
295
- int(max: number): number {
296
- let value = 0;
297
- let mask = 1;
298
-
299
- while (value + mask < max && mask !== 0) {
300
- if (this.bit()) {
301
- value |= mask;
302
- }
303
- mask <<= 1;
304
- }
305
-
306
- return value;
307
- }
308
-
309
- // read a packet in from bits
310
- uint_packed(): number {
311
- let value = 0;
312
- for (let i = 0; i < 5; i++) {
313
- const next = this.bit();
314
-
315
- let part = 0;
316
- for (let shift = 0; shift < 7; shift++) {
317
- part |= (this.bit() ? 1 : 0) << shift;
318
- }
319
- value |= part << (7 * i);
320
- if (!next) {
321
- break;
322
- }
323
- }
324
-
325
- return value;
326
- }
327
-
328
- // an item in a read_positive_int_vector array
329
- int_packed(): number {
330
- const value = this.uint_packed();
331
- return (value >> 1) * ((value & 1) !== 0 ? 1 : -1);
332
- }
333
-
334
- // read some bits
335
- bits(num: number): number[] {
336
- const arr: number[] = [];
337
- for (let bit = 0; bit < num; bit++) {
338
- const shift = bit & 7;
339
- arr[bit >> 3] =
340
- (arr[bit >> 3] & ~(1 << shift)) | ((this.bit() ? 1 : 0) << shift);
341
- }
342
- return arr;
343
- }
344
-
345
- // Read some bytes
346
- bytes(num: number): Uint8Array {
347
- return new Uint8Array(this.bytesArr(num));
348
- }
349
-
350
- // read some bytes but not as a Uint8Array
351
- bytesArr(num: number): number[] {
352
- return this.bits(num * 8);
353
- }
354
-
355
- // read an array
356
- array<T>(fn: (_: BitReader) => T): T[] {
357
- const length = read_i32(this.bytes(4));
358
- const arr = Array(length);
359
- for (let i = 0; i < length; i++) {
360
- arr[i] = fn(this);
361
- }
362
- return arr;
363
- }
364
-
365
- // for each
366
- each(fn: (data: BitReader) => void) {
367
- const length = read_i32(this.bytes(4));
368
- for (let i = 0; i < length; i++) {
369
- fn(this);
370
- }
371
- }
372
-
373
- // read a string
374
- string(): string {
375
- const lenBytes = this.bytesArr(4);
376
- let len = read_i32(new Uint8Array(lenBytes));
377
- if (len < 0) len = -len * 2;
378
- return read_string(new Uint8Array(lenBytes.concat(this.bytesArr(len))));
379
- }
380
-
381
- // read a 32-bit float
382
- float(): number {
383
- const view = new DataView(new ArrayBuffer(4));
384
-
385
- // Write the ints to it
386
- view.setUint16(2, read_u16(this.bytes(2)));
387
- view.setUint16(0, read_u16(this.bytes(2)));
388
-
389
- // Read the bits as a float; note that by doing this, we're implicitly
390
- // converting it from a 32-bit float into JavaScript's native 64-bit double
391
- return view.getFloat32(0);
392
- }
393
-
394
- // read unreal types
395
- unreal(type: string): UnrealType {
396
- switch (type) {
397
- case 'String':
398
- case 'Class':
399
- case 'Object':
400
- return this.string();
401
- case 'Boolean':
402
- return !!read_i32(this.bytes(4));
403
- case 'Float':
404
- return this.float();
405
- case 'Color':
406
- return bgra(this.bytesArr(4)) as UnrealColor;
407
- case 'Byte':
408
- return this.bytes(1)[0];
409
- case 'Rotator':
410
- return [this.float(), this.float(), this.float()];
411
- }
412
- throw new Error('Unknown unreal type ' + type);
413
- }
414
- }
415
-
416
- export class BitWriter {
417
- buffer: number[] = [];
418
- cur: number = 0;
419
- bitNum: number = 0;
420
-
421
- // Write a boolean as a bit
422
- bit(val: boolean) {
423
- this.cur |= (val ? 1 : 0) << this.bitNum;
424
- this.bitNum++;
425
- if (this.bitNum >= 8) {
426
- this.align();
427
- }
428
- }
429
-
430
- // Write `len` bits from `src` bytes
431
- bits(src: number[] | Uint8Array, len: number) {
432
- for (let bit = 0; bit < len; bit++) {
433
- this.bit((src[bit >> 3] & (1 << (bit & 7))) !== 0);
434
- }
435
- }
436
-
437
- // Write multiple bytes
438
- bytes(src: number[] | Uint8Array) {
439
- this.bits(src, 8 * src.length);
440
- }
441
-
442
- // Push the current bit into the buffer
443
- align() {
444
- if (this.bitNum > 0) {
445
- this.buffer.push(this.cur);
446
- this.cur = 0;
447
- this.bitNum = 0;
448
- }
449
- }
450
-
451
- // Write an int up to the potential max size
452
- int(value: number, max: number) {
453
- if (max < 2) {
454
- throw new Error(
455
- `Invalid input (BitWriter) -- max (${max}) must be at least 2`
456
- );
457
- }
458
-
459
- if (value >= max) {
460
- throw new Error(
461
- `Invalid input (BitWriter) -- value (${value}) is larger than max (${max})`
462
- );
463
- }
464
-
465
- let new_val = 0;
466
- let mask = 1;
467
-
468
- while (new_val + mask < max && mask !== 0) {
469
- this.bit((value & mask) !== 0);
470
- if ((value & mask) !== 0) {
471
- new_val |= mask;
472
- }
473
-
474
- mask <<= 1;
475
- }
476
- }
477
-
478
- // Write a packed unsigned int
479
- uint_packed(value: number) {
480
- do {
481
- const src = value & 0b1111111;
482
- value >>= 7;
483
- this.bit(value !== 0);
484
- this.bits([src], 7);
485
- } while (value !== 0);
486
- }
487
-
488
- // Write a packed integer
489
- int_packed(value: number) {
490
- this.uint_packed((Math.abs(value) << 1) | (value >= 0 ? 1 : 0));
491
- }
492
-
493
- // Return built buffer
494
- finish(): Uint8Array {
495
- this.align();
496
- return new Uint8Array(this.buffer);
497
- }
498
-
499
- // Return built buffer (and include length)
500
- finishSection() {
501
- this.align();
502
- return concat(write_i32(this.buffer.length), new Uint8Array(this.buffer));
503
- }
504
-
505
- // write a string
506
- string(str: string) {
507
- this.bytes(write_string(str));
508
- }
509
-
510
- float(num: UnrealFloat) {
511
- // create a float array
512
- const floatArr = new Float32Array(1);
513
- // assign the number
514
- floatArr[0] = num;
515
- // convert it into a byte array
516
- const bytes = new Int8Array(floatArr.buffer);
517
- this.bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
518
- }
519
-
520
- // run a function with `this` as a BitReader
521
- self(fn: (this: BitWriter) => void) {
522
- fn.bind(this)();
523
- return this;
524
- }
525
-
526
- // write an array
527
- array<T>(arr: T[], fn: (this: BitWriter, item: T, index: number) => void) {
528
- this.bytes(write_i32(arr.length));
529
- arr.forEach(fn.bind(this));
530
- return this;
531
- }
532
-
533
- // write things from an array
534
- each<T>(arr: T[], fn: (this: BitWriter, item: T, index: number) => void) {
535
- arr.forEach(fn.bind(this));
536
- return this;
537
- }
538
-
539
- // write unreal types
540
- unreal(type: string, value: UnrealType) {
541
- switch (type) {
542
- case 'Class':
543
- if (typeof value !== 'string') {
544
- throw new Error(
545
- `writing unreal type Class, did not receive string (${value})`
546
- );
547
- }
548
- this.string(value);
549
- return;
550
- case 'String':
551
- if (typeof value !== 'string') {
552
- throw new Error(
553
- `writing unreal type String, did not receive string (${value})`
554
- );
555
- }
556
- this.string(value);
557
- return;
558
- case 'Object':
559
- if (typeof value !== 'string') {
560
- throw new Error(
561
- `writing unreal type Object, did not receive string (${value})`
562
- );
563
- }
564
- this.string(value);
565
- return;
566
- case 'Boolean':
567
- if (typeof value !== 'boolean') {
568
- throw new Error(
569
- `writing unreal type Boolean, did not receive boolean (${value})`
570
- );
571
- }
572
- this.bytes(write_i32(value ? 1 : 0));
573
- return;
574
- case 'Float':
575
- if (typeof value !== 'number') {
576
- throw new Error(
577
- `writing unreal type Float, did not receive float (${value})`
578
- );
579
- }
580
- this.float(value);
581
- return;
582
- case 'Byte':
583
- if (typeof value !== 'number') {
584
- throw new Error(
585
- `writing unreal type Byte, did not receive Byte (${value})`
586
- );
587
- }
588
- this.bytes([value & 255]);
589
- return;
590
- case 'Color':
591
- if (!Array.isArray(value) || value.length !== 4) {
592
- throw new Error(
593
- `writing unreal type Array, did not receive Array (${value})`
594
- );
595
- }
596
- this.bytes(bgra(value));
597
- return;
598
- case 'Rotator':
599
- if (!Array.isArray(value) || value.length !== 3) {
600
- throw new Error(
601
- `writing unreal type Array, did not receive Array (${value})`
602
- );
603
- }
604
-
605
- this.float(value[0]);
606
- this.float(value[1]);
607
- this.float(value[2]);
608
- return;
609
- }
610
- throw new Error('Unknown unreal type ' + type);
611
- }
612
- }
613
-
614
- // concat uint8arrays together
615
- export function concat(...arrays: Uint8Array[]): Uint8Array {
616
- const buffLen = arrays.reduce((sum, value) => sum + value.length, 0);
617
- const buff = new Uint8Array(buffLen);
618
-
619
- // for each array - copy it over buff
620
- // next array is copied right after the previous one
621
- let length = 0;
622
- for (const array of arrays) {
623
- buff.set(array, length);
624
- length += array.length;
625
- }
626
-
627
- return buff;
628
- }
629
-
630
- export const read = {
631
- bytes: subarray,
632
- u16: read_u16,
633
- i32: read_i32,
634
- compressed: read_compressed,
635
- string: read_string,
636
- uuid: read_uuid,
637
- array: read_array,
638
- each: read_each,
639
- bits: (data: Bytes) => new BitReader(data),
640
- };
641
-
642
- export const write = {
643
- u16: write_u16,
644
- i32: write_i32,
645
- compressed: write_compressed,
646
- uncompressed: write_uncompressed,
647
- string: write_string,
648
- uuid: write_uuid,
649
- array: write_array,
650
- bits: () => new BitWriter(),
651
- };