@colyseus/schema 3.0.0-alpha.0 → 3.0.0-alpha.10
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/build/cjs/index.js +1219 -1427
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +85 -64
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +1219 -1427
- package/lib/Reflection.d.ts +1 -1
- package/lib/Reflection.js +1 -2
- package/lib/Reflection.js.map +1 -1
- package/lib/decoder/DecodeOperation.js +2 -2
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +1 -1
- package/lib/decoder/Decoder.js +4 -4
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.js +1 -1
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +0 -2
- package/lib/encoder/ChangeTree.js +2 -6
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +5 -4
- package/lib/encoder/Encoder.js +46 -43
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/StateView.d.ts +2 -0
- package/lib/encoder/StateView.js +4 -1
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/decode.d.ts +21 -19
- package/lib/encoding/decode.js +6 -6
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +19 -16
- package/lib/encoding/encode.js +24 -22
- package/lib/encoding/encode.js.map +1 -1
- package/package.json +1 -1
- package/src/Reflection.ts +1 -2
- package/src/decoder/DecodeOperation.ts +3 -3
- package/src/decoder/Decoder.ts +5 -5
- package/src/decoder/strategy/StateCallbacks.ts +1 -1
- package/src/encoder/ChangeTree.ts +2 -6
- package/src/encoder/Encoder.ts +51 -47
- package/src/encoder/StateView.ts +4 -0
- package/src/encoding/decode.ts +24 -25
- package/src/encoding/encode.ts +43 -37
package/build/esm/index.mjs
CHANGED
|
@@ -164,7 +164,6 @@ class Root {
|
|
|
164
164
|
// pending changes to be encoded
|
|
165
165
|
this.changes = new Map();
|
|
166
166
|
this.filteredChanges = new Map();
|
|
167
|
-
this.views = [];
|
|
168
167
|
}
|
|
169
168
|
getNextUniqueId() {
|
|
170
169
|
return this.nextUniqueId++;
|
|
@@ -259,14 +258,12 @@ class ChangeTree {
|
|
|
259
258
|
this.checkIsFiltered(parent, parentIndex);
|
|
260
259
|
if (!this.isFiltered) {
|
|
261
260
|
this.root.changes.set(this, this.changes);
|
|
261
|
+
this.root.allChanges.set(this, this.allChanges);
|
|
262
262
|
}
|
|
263
263
|
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
264
264
|
this.root.filteredChanges.set(this, this.filteredChanges);
|
|
265
265
|
this.root.allFilteredChanges.set(this, this.filteredChanges);
|
|
266
266
|
}
|
|
267
|
-
else {
|
|
268
|
-
this.root.allChanges.set(this, this.allChanges);
|
|
269
|
-
}
|
|
270
267
|
this.ensureRefId();
|
|
271
268
|
this.forEachChild((changeTree, atIndex) => {
|
|
272
269
|
changeTree.setParent(this.ref, root, atIndex);
|
|
@@ -358,7 +355,6 @@ class ChangeTree {
|
|
|
358
355
|
}
|
|
359
356
|
_shiftAllChangeIndexes(shiftIndex, startIndex = 0, allChangeSet) {
|
|
360
357
|
Array.from(allChangeSet.entries()).forEach(([index, op]) => {
|
|
361
|
-
// console.log('shiftAllChangeIndexes', index >= startIndex, { index, op, shiftIndex, startIndex })
|
|
362
358
|
if (index >= startIndex) {
|
|
363
359
|
allChangeSet.delete(index);
|
|
364
360
|
allChangeSet.set(index + shiftIndex, op);
|
|
@@ -499,7 +495,7 @@ class ChangeTree {
|
|
|
499
495
|
}
|
|
500
496
|
checkIsFiltered(parent, parentIndex) {
|
|
501
497
|
// Detect if current structure has "filters" declared
|
|
502
|
-
this.isPartiallyFiltered = this.ref['constructor']?.[Symbol.metadata]?.[-2];
|
|
498
|
+
this.isPartiallyFiltered = (this.ref['constructor']?.[Symbol.metadata]?.[-2] !== undefined);
|
|
503
499
|
// TODO: support "partially filtered", where the instance is visible, but only a field is not.
|
|
504
500
|
// Detect if parent has "filters" declared
|
|
505
501
|
while (parent && !this.isFiltered) {
|
|
@@ -560,6 +556,29 @@ try {
|
|
|
560
556
|
textEncoder = new TextEncoder();
|
|
561
557
|
}
|
|
562
558
|
catch (e) { }
|
|
559
|
+
const hasBufferByteLength = (typeof Buffer !== 'undefined' && Buffer.byteLength);
|
|
560
|
+
const utf8Length = (hasBufferByteLength)
|
|
561
|
+
? Buffer.byteLength // node
|
|
562
|
+
: function (str, _) {
|
|
563
|
+
var c = 0, length = 0;
|
|
564
|
+
for (var i = 0, l = str.length; i < l; i++) {
|
|
565
|
+
c = str.charCodeAt(i);
|
|
566
|
+
if (c < 0x80) {
|
|
567
|
+
length += 1;
|
|
568
|
+
}
|
|
569
|
+
else if (c < 0x800) {
|
|
570
|
+
length += 2;
|
|
571
|
+
}
|
|
572
|
+
else if (c < 0xd800 || c >= 0xe000) {
|
|
573
|
+
length += 3;
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
i++;
|
|
577
|
+
length += 4;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return length;
|
|
581
|
+
};
|
|
563
582
|
function utf8Write(view, str, it) {
|
|
564
583
|
var c = 0;
|
|
565
584
|
for (var i = 0, l = str.length; i < l; i++) {
|
|
@@ -654,8 +673,7 @@ function string$1(bytes, value, it) {
|
|
|
654
673
|
if (!value) {
|
|
655
674
|
value = "";
|
|
656
675
|
}
|
|
657
|
-
|
|
658
|
-
let length = Buffer.byteLength(value, "utf8");
|
|
676
|
+
let length = utf8Length(value, "utf8");
|
|
659
677
|
let size = 0;
|
|
660
678
|
// fixstr
|
|
661
679
|
if (length < 0x20) {
|
|
@@ -766,6 +784,7 @@ function number$1(bytes, value, it) {
|
|
|
766
784
|
|
|
767
785
|
var encode = /*#__PURE__*/Object.freeze({
|
|
768
786
|
__proto__: null,
|
|
787
|
+
utf8Length: utf8Length,
|
|
769
788
|
utf8Write: utf8Write,
|
|
770
789
|
int8: int8$1,
|
|
771
790
|
uint8: uint8$1,
|
|
@@ -989,9 +1008,9 @@ const encodeArray = function (encoder, bytes, changeTree, field, operation, it,
|
|
|
989
1008
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
990
1009
|
* SOFTWARE
|
|
991
1010
|
*/
|
|
992
|
-
function utf8Read(bytes,
|
|
1011
|
+
function utf8Read(bytes, it, length) {
|
|
993
1012
|
var string = '', chr = 0;
|
|
994
|
-
for (var i = offset, end = offset + length; i < end; i++) {
|
|
1013
|
+
for (var i = it.offset, end = it.offset + length; i < end; i++) {
|
|
995
1014
|
var byte = bytes[i];
|
|
996
1015
|
if ((byte & 0x80) === 0x00) {
|
|
997
1016
|
string += String.fromCharCode(byte);
|
|
@@ -1026,6 +1045,7 @@ function utf8Read(bytes, offset, length) {
|
|
|
1026
1045
|
// (do not throw error to avoid server/client from crashing due to hack attemps)
|
|
1027
1046
|
// throw new Error('Invalid byte ' + byte.toString(16));
|
|
1028
1047
|
}
|
|
1048
|
+
it.offset += length;
|
|
1029
1049
|
return string;
|
|
1030
1050
|
}
|
|
1031
1051
|
function int8(bytes, it) {
|
|
@@ -1093,9 +1113,7 @@ function string(bytes, it) {
|
|
|
1093
1113
|
else if (prefix === 0xdb) {
|
|
1094
1114
|
length = uint32(bytes, it);
|
|
1095
1115
|
}
|
|
1096
|
-
|
|
1097
|
-
it.offset += length;
|
|
1098
|
-
return value;
|
|
1116
|
+
return utf8Read(bytes, it, length);
|
|
1099
1117
|
}
|
|
1100
1118
|
function stringCheck(bytes, it) {
|
|
1101
1119
|
const prefix = bytes[it.offset];
|
|
@@ -1199,6 +1217,7 @@ function switchStructureCheck(bytes, it) {
|
|
|
1199
1217
|
|
|
1200
1218
|
var decode = /*#__PURE__*/Object.freeze({
|
|
1201
1219
|
__proto__: null,
|
|
1220
|
+
utf8Read: utf8Read,
|
|
1202
1221
|
int8: int8,
|
|
1203
1222
|
uint8: uint8,
|
|
1204
1223
|
int16: int16,
|
|
@@ -1222,7 +1241,7 @@ var decode = /*#__PURE__*/Object.freeze({
|
|
|
1222
1241
|
|
|
1223
1242
|
const DEFINITION_MISMATCH = -1;
|
|
1224
1243
|
function decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges) {
|
|
1225
|
-
const $root = decoder
|
|
1244
|
+
const $root = decoder.root;
|
|
1226
1245
|
const previousValue = ref[$getByIndex](index);
|
|
1227
1246
|
let value;
|
|
1228
1247
|
if ((operation & OPERATION.DELETE) === OPERATION.DELETE) {
|
|
@@ -1422,7 +1441,7 @@ const decodeArray = function (decoder, bytes, it, ref, allChanges) {
|
|
|
1422
1441
|
else if (operation === OPERATION.DELETE_BY_REFID) {
|
|
1423
1442
|
// TODO: refactor here, try to follow same flow as below
|
|
1424
1443
|
const refId = number(bytes, it);
|
|
1425
|
-
const previousValue = decoder
|
|
1444
|
+
const previousValue = decoder.root.refs.get(refId);
|
|
1426
1445
|
const index = ref.findIndex((value) => value === previousValue);
|
|
1427
1446
|
ref[$deleteByIndex](index);
|
|
1428
1447
|
allChanges.push({
|
|
@@ -3358,13 +3377,13 @@ class Encoder {
|
|
|
3358
3377
|
// });
|
|
3359
3378
|
}
|
|
3360
3379
|
setRoot(state) {
|
|
3361
|
-
this
|
|
3380
|
+
this.root = new Root();
|
|
3362
3381
|
this.state = state;
|
|
3363
|
-
state[$changes].setRoot(this
|
|
3382
|
+
state[$changes].setRoot(this.root);
|
|
3364
3383
|
}
|
|
3365
|
-
encode(it = { offset: 0 }, view,
|
|
3384
|
+
encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes) {
|
|
3366
3385
|
const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
|
|
3367
|
-
const isEncodeAll = this
|
|
3386
|
+
const isEncodeAll = this.root.allChanges === changeTrees;
|
|
3368
3387
|
const hasView = (view !== undefined);
|
|
3369
3388
|
const rootChangeTree = this.state[$changes];
|
|
3370
3389
|
const changeTreesIterator = changeTrees.entries();
|
|
@@ -3384,8 +3403,8 @@ class Encoder {
|
|
|
3384
3403
|
}
|
|
3385
3404
|
// skip root `refId` if it's the first change tree
|
|
3386
3405
|
if (it.offset !== initialOffset || changeTree !== rootChangeTree) {
|
|
3387
|
-
|
|
3388
|
-
number$1(
|
|
3406
|
+
buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;
|
|
3407
|
+
number$1(buffer, changeTree.refId, it);
|
|
3389
3408
|
}
|
|
3390
3409
|
const changesIterator = changes.entries();
|
|
3391
3410
|
for (const [fieldIndex, operation] of changesIterator) {
|
|
@@ -3407,17 +3426,21 @@ class Encoder {
|
|
|
3407
3426
|
// fieldIndex,
|
|
3408
3427
|
// operation: OPERATION[operation],
|
|
3409
3428
|
// });
|
|
3410
|
-
encoder(this,
|
|
3429
|
+
encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
|
|
3411
3430
|
}
|
|
3412
3431
|
}
|
|
3413
|
-
if (it.offset >
|
|
3414
|
-
const newSize = getNextPowerOf2(
|
|
3415
|
-
console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " +
|
|
3432
|
+
if (it.offset > buffer.byteLength) {
|
|
3433
|
+
const newSize = getNextPowerOf2(buffer.byteLength * 2);
|
|
3434
|
+
console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " + buffer.byteLength + ", encoding offset: " + it.offset + ", new size: " + newSize);
|
|
3416
3435
|
//
|
|
3417
3436
|
// resize buffer and re-encode (TODO: can we avoid re-encoding here?)
|
|
3418
3437
|
//
|
|
3419
|
-
|
|
3420
|
-
|
|
3438
|
+
buffer = Buffer.allocUnsafeSlow(newSize);
|
|
3439
|
+
// assign resized buffer to local sharedBuffer
|
|
3440
|
+
if (buffer === this.sharedBuffer) {
|
|
3441
|
+
this.sharedBuffer = buffer;
|
|
3442
|
+
}
|
|
3443
|
+
return this.encode({ offset: initialOffset }, view, buffer);
|
|
3421
3444
|
}
|
|
3422
3445
|
else {
|
|
3423
3446
|
//
|
|
@@ -3429,42 +3452,41 @@ class Encoder {
|
|
|
3429
3452
|
//
|
|
3430
3453
|
this.onEndEncode(changeTrees);
|
|
3431
3454
|
}
|
|
3432
|
-
|
|
3433
|
-
return bytes.slice(0, it.offset);
|
|
3455
|
+
return buffer.subarray(0, it.offset);
|
|
3434
3456
|
}
|
|
3435
3457
|
}
|
|
3436
|
-
encodeAll(it = { offset: 0 }) {
|
|
3437
|
-
// console.log(`encodeAll(), this
|
|
3438
|
-
// Array.from(this
|
|
3439
|
-
// console.log("->", item[0].
|
|
3458
|
+
encodeAll(it = { offset: 0 }, buffer = this.sharedBuffer) {
|
|
3459
|
+
// console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);
|
|
3460
|
+
// Array.from(this.root.allChanges.entries()).map((item) => {
|
|
3461
|
+
// console.log("->", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });
|
|
3440
3462
|
// });
|
|
3441
|
-
return this.encode(it, undefined,
|
|
3463
|
+
return this.encode(it, undefined, buffer, this.root.allChanges);
|
|
3442
3464
|
}
|
|
3443
3465
|
encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
3444
3466
|
const viewOffset = it.offset;
|
|
3445
|
-
// console.log(`encodeAllView(), this
|
|
3467
|
+
// console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);
|
|
3446
3468
|
// this.debugAllFilteredChanges();
|
|
3447
3469
|
// try to encode "filtered" changes
|
|
3448
|
-
this.encode(it, view, bytes, this
|
|
3470
|
+
this.encode(it, view, bytes, this.root.allFilteredChanges);
|
|
3449
3471
|
return Buffer.concat([
|
|
3450
|
-
bytes.
|
|
3451
|
-
bytes.
|
|
3472
|
+
bytes.subarray(0, sharedOffset),
|
|
3473
|
+
bytes.subarray(viewOffset, it.offset)
|
|
3452
3474
|
]);
|
|
3453
3475
|
}
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3476
|
+
debugAllFilteredChanges() {
|
|
3477
|
+
Array.from(this.root.allFilteredChanges.entries()).map((item) => {
|
|
3478
|
+
console.log("->", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());
|
|
3479
|
+
if (Array.isArray(item[0].ref.toJSON())) {
|
|
3480
|
+
item[1].forEach((op, key) => {
|
|
3481
|
+
console.log(" ->", { key, op: OPERATION[op] });
|
|
3482
|
+
});
|
|
3483
|
+
}
|
|
3484
|
+
});
|
|
3485
|
+
}
|
|
3464
3486
|
encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
3465
3487
|
const viewOffset = it.offset;
|
|
3466
3488
|
// try to encode "filtered" changes
|
|
3467
|
-
this.encode(it, view, bytes, this
|
|
3489
|
+
this.encode(it, view, bytes, this.root.filteredChanges);
|
|
3468
3490
|
// encode visibility changes (add/remove for this view)
|
|
3469
3491
|
const viewChangesIterator = view.changes.entries();
|
|
3470
3492
|
for (const [changeTree, changes] of viewChangesIterator) {
|
|
@@ -3492,11 +3514,11 @@ class Encoder {
|
|
|
3492
3514
|
// clear "view" changes after encoding
|
|
3493
3515
|
view.changes.clear();
|
|
3494
3516
|
return Buffer.concat([
|
|
3495
|
-
bytes.
|
|
3496
|
-
bytes.
|
|
3517
|
+
bytes.subarray(0, sharedOffset),
|
|
3518
|
+
bytes.subarray(viewOffset, it.offset)
|
|
3497
3519
|
]);
|
|
3498
3520
|
}
|
|
3499
|
-
onEndEncode(changeTrees = this
|
|
3521
|
+
onEndEncode(changeTrees = this.root.changes) {
|
|
3500
3522
|
const changeTreesIterator = changeTrees.entries();
|
|
3501
3523
|
for (const [changeTree, _] of changeTreesIterator) {
|
|
3502
3524
|
changeTree.endEncode();
|
|
@@ -3504,14 +3526,14 @@ class Encoder {
|
|
|
3504
3526
|
}
|
|
3505
3527
|
discardChanges() {
|
|
3506
3528
|
// discard shared changes
|
|
3507
|
-
if (this
|
|
3508
|
-
this.onEndEncode(this
|
|
3509
|
-
this
|
|
3529
|
+
if (this.root.changes.size > 0) {
|
|
3530
|
+
this.onEndEncode(this.root.changes);
|
|
3531
|
+
this.root.changes.clear();
|
|
3510
3532
|
}
|
|
3511
3533
|
// discard filtered changes
|
|
3512
|
-
if (this
|
|
3513
|
-
this.onEndEncode(this
|
|
3514
|
-
this
|
|
3534
|
+
if (this.root.filteredChanges.size > 0) {
|
|
3535
|
+
this.onEndEncode(this.root.filteredChanges);
|
|
3536
|
+
this.root.filteredChanges.clear();
|
|
3515
3537
|
}
|
|
3516
3538
|
}
|
|
3517
3539
|
tryEncodeTypeId(bytes, baseType, targetType, it) {
|
|
@@ -3672,12 +3694,12 @@ class Decoder {
|
|
|
3672
3694
|
}
|
|
3673
3695
|
setRoot(root) {
|
|
3674
3696
|
this.state = root;
|
|
3675
|
-
this
|
|
3676
|
-
this
|
|
3697
|
+
this.root = new ReferenceTracker();
|
|
3698
|
+
this.root.addRef(0, root);
|
|
3677
3699
|
}
|
|
3678
3700
|
decode(bytes, it = { offset: 0 }, ref = this.state) {
|
|
3679
3701
|
const allChanges = [];
|
|
3680
|
-
const $root = this
|
|
3702
|
+
const $root = this.root;
|
|
3681
3703
|
const totalBytes = bytes.byteLength;
|
|
3682
3704
|
let decoder = ref['constructor'][$decoder];
|
|
3683
3705
|
this.currentRefId = 0;
|
|
@@ -3758,7 +3780,7 @@ class Decoder {
|
|
|
3758
3780
|
previousValue: value
|
|
3759
3781
|
});
|
|
3760
3782
|
if (needRemoveRef) {
|
|
3761
|
-
this
|
|
3783
|
+
this.root.removeRef(this.root.refIds.get(value));
|
|
3762
3784
|
}
|
|
3763
3785
|
});
|
|
3764
3786
|
}
|
|
@@ -3798,7 +3820,7 @@ class Reflection extends Schema {
|
|
|
3798
3820
|
super(...arguments);
|
|
3799
3821
|
this.types = new ArraySchema();
|
|
3800
3822
|
}
|
|
3801
|
-
static encode(instance, context) {
|
|
3823
|
+
static encode(instance, context, it = { offset: 0 }) {
|
|
3802
3824
|
if (!context) {
|
|
3803
3825
|
context = new TypeContext(instance.constructor);
|
|
3804
3826
|
}
|
|
@@ -3855,7 +3877,6 @@ class Reflection extends Schema {
|
|
|
3855
3877
|
}
|
|
3856
3878
|
buildType(type, klass[Symbol.metadata]);
|
|
3857
3879
|
}
|
|
3858
|
-
const it = { offset: 0 };
|
|
3859
3880
|
const buf = encoder.encodeAll(it);
|
|
3860
3881
|
return Buffer.from(buf, 0, it.offset);
|
|
3861
3882
|
}
|