@colyseus/schema 3.0.0-alpha.9 → 3.0.1
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 +148 -62
- package/bin/schema-debug +94 -0
- package/build/cjs/index.js +2222 -1513
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +2223 -1516
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +2225 -1516
- package/lib/Metadata.d.ts +21 -9
- package/lib/Metadata.js +169 -32
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.d.ts +19 -4
- package/lib/Reflection.js +66 -31
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +12 -5
- package/lib/Schema.js +57 -56
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +31 -34
- package/lib/annotations.js +110 -160
- package/lib/annotations.js.map +1 -1
- package/lib/codegen/api.js +1 -2
- package/lib/codegen/api.js.map +1 -1
- package/lib/codegen/languages/cpp.js +1 -2
- package/lib/codegen/languages/cpp.js.map +1 -1
- package/lib/codegen/languages/csharp.js +9 -46
- package/lib/codegen/languages/csharp.js.map +1 -1
- package/lib/codegen/languages/haxe.js +4 -2
- package/lib/codegen/languages/haxe.js.map +1 -1
- package/lib/codegen/languages/java.js +1 -2
- package/lib/codegen/languages/java.js.map +1 -1
- package/lib/codegen/languages/js.js +1 -2
- package/lib/codegen/languages/js.js.map +1 -1
- package/lib/codegen/languages/lua.js +23 -25
- package/lib/codegen/languages/lua.js.map +1 -1
- package/lib/codegen/languages/ts.js +1 -2
- package/lib/codegen/languages/ts.js.map +1 -1
- package/lib/codegen/parser.js +85 -3
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +6 -3
- package/lib/codegen/types.js.map +1 -1
- package/lib/decoder/DecodeOperation.d.ts +3 -4
- package/lib/decoder/DecodeOperation.js +35 -17
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +5 -6
- package/lib/decoder/Decoder.js +10 -10
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +4 -2
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/RawChanges.js +1 -2
- package/lib/decoder/strategy/RawChanges.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.d.ts +44 -11
- package/lib/decoder/strategy/StateCallbacks.js +74 -64
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +28 -20
- package/lib/encoder/ChangeTree.js +242 -188
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +3 -6
- package/lib/encoder/EncodeOperation.js +51 -65
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +8 -7
- package/lib/encoder/Encoder.js +128 -79
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +22 -0
- package/lib/encoder/Root.js +81 -0
- package/lib/encoder/Root.js.map +1 -0
- package/lib/encoder/StateView.d.ts +7 -7
- package/lib/encoder/StateView.js +72 -74
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/assert.d.ts +7 -6
- package/lib/encoding/assert.js +13 -5
- package/lib/encoding/assert.js.map +1 -1
- package/lib/encoding/decode.d.ts +36 -19
- package/lib/encoding/decode.js +54 -84
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +36 -18
- package/lib/encoding/encode.js +61 -48
- package/lib/encoding/encode.js.map +1 -1
- package/lib/encoding/spec.d.ts +4 -5
- package/lib/encoding/spec.js +1 -2
- package/lib/encoding/spec.js.map +1 -1
- package/lib/index.d.ts +10 -9
- package/lib/index.js +24 -17
- package/lib/index.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +34 -2
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/TypeContext.d.ts +29 -0
- package/lib/types/TypeContext.js +151 -0
- package/lib/types/TypeContext.js.map +1 -0
- package/lib/types/custom/ArraySchema.d.ts +2 -2
- package/lib/types/custom/ArraySchema.js +33 -22
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.d.ts +2 -2
- package/lib/types/custom/CollectionSchema.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +18 -16
- package/lib/types/custom/MapSchema.js +12 -4
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.d.ts +2 -2
- package/lib/types/custom/SetSchema.js +1 -0
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/registry.d.ts +8 -1
- package/lib/types/registry.js +23 -6
- package/lib/types/registry.js.map +1 -1
- package/lib/types/symbols.d.ts +8 -5
- package/lib/types/symbols.js +9 -6
- package/lib/types/symbols.js.map +1 -1
- package/lib/types/utils.js +1 -2
- package/lib/types/utils.js.map +1 -1
- package/lib/utils.js +9 -7
- package/lib/utils.js.map +1 -1
- package/package.json +19 -18
- package/src/Metadata.ts +190 -42
- package/src/Reflection.ts +76 -38
- package/src/Schema.ts +72 -70
- package/src/annotations.ts +156 -202
- package/src/codegen/languages/csharp.ts +8 -47
- package/src/codegen/languages/haxe.ts +4 -0
- package/src/codegen/languages/lua.ts +19 -27
- package/src/codegen/parser.ts +107 -0
- package/src/codegen/types.ts +1 -0
- package/src/decoder/DecodeOperation.ts +43 -15
- package/src/decoder/Decoder.ts +12 -10
- package/src/decoder/ReferenceTracker.ts +5 -3
- package/src/decoder/strategy/StateCallbacks.ts +152 -81
- package/src/encoder/ChangeTree.ts +282 -209
- package/src/encoder/EncodeOperation.ts +78 -78
- package/src/encoder/Encoder.ts +152 -88
- package/src/encoder/Root.ts +93 -0
- package/src/encoder/StateView.ts +80 -88
- package/src/encoding/assert.ts +17 -8
- package/src/encoding/decode.ts +73 -93
- package/src/encoding/encode.ts +76 -45
- package/src/encoding/spec.ts +3 -5
- package/src/index.ts +12 -20
- package/src/types/HelperTypes.ts +54 -2
- package/src/types/TypeContext.ts +175 -0
- package/src/types/custom/ArraySchema.ts +49 -19
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +30 -17
- package/src/types/custom/SetSchema.ts +1 -0
- package/src/types/registry.ts +22 -3
- package/src/types/symbols.ts +10 -7
- package/src/utils.ts +7 -3
- package/lib/Decoder.d.ts +0 -16
- package/lib/Decoder.js +0 -182
- package/lib/Decoder.js.map +0 -1
- package/lib/Encoder.d.ts +0 -13
- package/lib/Encoder.js +0 -79
- package/lib/Encoder.js.map +0 -1
- package/lib/changes/ChangeSet.d.ts +0 -12
- package/lib/changes/ChangeSet.js +0 -35
- package/lib/changes/ChangeSet.js.map +0 -1
- package/lib/changes/ChangeTree.d.ts +0 -53
- package/lib/changes/ChangeTree.js +0 -202
- package/lib/changes/ChangeTree.js.map +0 -1
- package/lib/changes/DecodeOperation.d.ts +0 -15
- package/lib/changes/DecodeOperation.js +0 -186
- package/lib/changes/DecodeOperation.js.map +0 -1
- package/lib/changes/EncodeOperation.d.ts +0 -18
- package/lib/changes/EncodeOperation.js +0 -130
- package/lib/changes/EncodeOperation.js.map +0 -1
- package/lib/changes/ReferenceTracker.d.ts +0 -14
- package/lib/changes/ReferenceTracker.js +0 -83
- package/lib/changes/ReferenceTracker.js.map +0 -1
- package/lib/changes/consts.d.ts +0 -14
- package/lib/changes/consts.js +0 -18
- package/lib/changes/consts.js.map +0 -1
- package/lib/decoding/decode.d.ts +0 -48
- package/lib/decoding/decode.js +0 -267
- package/lib/decoding/decode.js.map +0 -1
- package/lib/ecs.d.ts +0 -11
- package/lib/ecs.js +0 -160
- package/lib/ecs.js.map +0 -1
- package/lib/filters/index.d.ts +0 -8
- package/lib/filters/index.js +0 -24
- package/lib/filters/index.js.map +0 -1
- package/lib/spec.d.ts +0 -13
- package/lib/spec.js +0 -42
- package/lib/spec.js.map +0 -1
- package/lib/types/ArraySchema.d.ts +0 -238
- package/lib/types/ArraySchema.js +0 -555
- package/lib/types/ArraySchema.js.map +0 -1
- package/lib/types/CollectionSchema.d.ts +0 -35
- package/lib/types/CollectionSchema.js +0 -150
- package/lib/types/CollectionSchema.js.map +0 -1
- package/lib/types/MapSchema.d.ts +0 -38
- package/lib/types/MapSchema.js +0 -215
- package/lib/types/MapSchema.js.map +0 -1
- package/lib/types/SetSchema.d.ts +0 -32
- package/lib/types/SetSchema.js +0 -162
- package/lib/types/SetSchema.js.map +0 -1
- package/lib/types/typeRegistry.d.ts +0 -5
- package/lib/types/typeRegistry.js +0 -13
- package/lib/types/typeRegistry.js.map +0 -1
- package/lib/usage.d.ts +0 -1
- package/lib/usage.js +0 -22
- package/lib/usage.js.map +0 -1
- package/lib/v3.d.ts +0 -1
- package/lib/v3.js +0 -427
- package/lib/v3.js.map +0 -1
- package/lib/v3_experiment.d.ts +0 -1
- package/lib/v3_experiment.js +0 -407
- package/lib/v3_experiment.js.map +0 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { OPERATION } from "../encoding/spec";
|
|
2
|
+
import { TypeContext } from "../types/TypeContext";
|
|
3
|
+
import { spliceOne } from "../types/utils";
|
|
4
|
+
import { ChangeTree, setOperationAtIndex } from "./ChangeTree";
|
|
5
|
+
|
|
6
|
+
export class Root {
|
|
7
|
+
protected nextUniqueId: number = 0;
|
|
8
|
+
|
|
9
|
+
refCount: {[id: number]: number} = {};
|
|
10
|
+
changeTrees: {[refId: number]: ChangeTree} = {};
|
|
11
|
+
|
|
12
|
+
// all changes
|
|
13
|
+
allChanges: ChangeTree[] = [];
|
|
14
|
+
allFilteredChanges: ChangeTree[] = [];// TODO: do not initialize it if filters are not used
|
|
15
|
+
|
|
16
|
+
// pending changes to be encoded
|
|
17
|
+
changes: ChangeTree[] = [];
|
|
18
|
+
filteredChanges: ChangeTree[] = [];// TODO: do not initialize it if filters are not used
|
|
19
|
+
|
|
20
|
+
constructor(public types: TypeContext) { }
|
|
21
|
+
|
|
22
|
+
getNextUniqueId() {
|
|
23
|
+
return this.nextUniqueId++;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
add(changeTree: ChangeTree) {
|
|
27
|
+
// FIXME: move implementation of `ensureRefId` to `Root` class
|
|
28
|
+
changeTree.ensureRefId();
|
|
29
|
+
|
|
30
|
+
const isNewChangeTree = (this.changeTrees[changeTree.refId] === undefined);
|
|
31
|
+
if (isNewChangeTree) { this.changeTrees[changeTree.refId] = changeTree; }
|
|
32
|
+
|
|
33
|
+
const previousRefCount = this.refCount[changeTree.refId];
|
|
34
|
+
if (previousRefCount === 0) {
|
|
35
|
+
//
|
|
36
|
+
// When a ChangeTree is re-added, it means that it was previously removed.
|
|
37
|
+
// We need to re-add all changes to the `changes` map.
|
|
38
|
+
//
|
|
39
|
+
const ops = changeTree.allChanges.operations;
|
|
40
|
+
let len = ops.length;
|
|
41
|
+
while (len--) {
|
|
42
|
+
changeTree.indexedOperations[ops[len]] = OPERATION.ADD;
|
|
43
|
+
setOperationAtIndex(changeTree.changes, len);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.refCount[changeTree.refId] = (previousRefCount || 0) + 1;
|
|
48
|
+
|
|
49
|
+
return isNewChangeTree;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
remove(changeTree: ChangeTree) {
|
|
53
|
+
const refCount = (this.refCount[changeTree.refId]) - 1;
|
|
54
|
+
|
|
55
|
+
if (refCount <= 0) {
|
|
56
|
+
//
|
|
57
|
+
// Only remove "root" reference if it's the last reference
|
|
58
|
+
//
|
|
59
|
+
changeTree.root = undefined;
|
|
60
|
+
delete this.changeTrees[changeTree.refId];
|
|
61
|
+
|
|
62
|
+
this.removeChangeFromChangeSet("allChanges", changeTree);
|
|
63
|
+
this.removeChangeFromChangeSet("changes", changeTree);
|
|
64
|
+
|
|
65
|
+
if (changeTree.filteredChanges) {
|
|
66
|
+
this.removeChangeFromChangeSet("allFilteredChanges", changeTree);
|
|
67
|
+
this.removeChangeFromChangeSet("filteredChanges", changeTree);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.refCount[changeTree.refId] = 0;
|
|
71
|
+
|
|
72
|
+
} else {
|
|
73
|
+
this.refCount[changeTree.refId] = refCount;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
changeTree.forEachChild((child, _) => this.remove(child));
|
|
77
|
+
|
|
78
|
+
return refCount;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
removeChangeFromChangeSet(changeSetName: "allChanges" | "changes" | "filteredChanges" | "allFilteredChanges", changeTree: ChangeTree) {
|
|
82
|
+
const changeSet = this[changeSetName];
|
|
83
|
+
const index = changeSet.indexOf(changeTree);
|
|
84
|
+
if (index !== -1) {
|
|
85
|
+
spliceOne(changeSet, index);
|
|
86
|
+
// changeSet[index] = undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
clear() {
|
|
91
|
+
this.changes.length = 0;
|
|
92
|
+
}
|
|
93
|
+
}
|
package/src/encoder/StateView.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ChangeTree, Ref } from "./ChangeTree";
|
|
2
|
-
import { $changes } from "../types/symbols";
|
|
1
|
+
import { ChangeSet, ChangeTree, IndexedOperations, Ref } from "./ChangeTree";
|
|
2
|
+
import { $changes, $fieldIndexesByViewTag, $viewFieldIndexes } from "../types/symbols";
|
|
3
3
|
import { DEFAULT_VIEW_TAG } from "../annotations";
|
|
4
4
|
import { OPERATION } from "../encoding/spec";
|
|
5
5
|
import { Metadata } from "../Metadata";
|
|
6
|
-
import type { Schema } from "../Schema";
|
|
7
6
|
|
|
8
|
-
export function createView(
|
|
7
|
+
export function createView() {
|
|
8
|
+
return new StateView();
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export class StateView {
|
|
@@ -25,37 +25,35 @@ export class StateView {
|
|
|
25
25
|
* Manual "ADD" operations for changes per ChangeTree, specific to this view.
|
|
26
26
|
* (This is used to force encoding a property, even if it was not changed)
|
|
27
27
|
*/
|
|
28
|
-
changes
|
|
28
|
+
changes: { [refId: number]: IndexedOperations } = {};
|
|
29
29
|
|
|
30
30
|
// TODO: allow to set multiple tags at once
|
|
31
|
-
add(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {
|
|
31
|
+
add(obj: Ref, tag: number = DEFAULT_VIEW_TAG, checkIncludeParent: boolean = true) {
|
|
32
32
|
if (!obj[$changes]) {
|
|
33
33
|
console.warn("StateView#add(), invalid object:", obj);
|
|
34
34
|
return this;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
this.items.add(changeTree);
|
|
39
|
-
|
|
40
|
-
// Add children of this ChangeTree to this view
|
|
41
|
-
changeTree.forEachChild((change, _) =>
|
|
42
|
-
this.add(change.ref, tag));
|
|
43
|
-
|
|
44
|
-
// FIXME: ArraySchema/MapSchema does not have metadata
|
|
37
|
+
// FIXME: ArraySchema/MapSchema do not have metadata
|
|
45
38
|
const metadata: Metadata = obj.constructor[Symbol.metadata];
|
|
39
|
+
const changeTree: ChangeTree = obj[$changes];
|
|
40
|
+
this.items.add(changeTree);
|
|
46
41
|
|
|
47
|
-
// add parent ChangeTree's
|
|
48
|
-
//
|
|
49
|
-
|
|
42
|
+
// add parent ChangeTree's
|
|
43
|
+
// - if it was invisible to this view
|
|
44
|
+
// - if it were previously filtered out
|
|
45
|
+
if (checkIncludeParent && changeTree.parent) {
|
|
46
|
+
this.addParent(changeTree.parent[$changes], changeTree.parentIndex, tag);
|
|
47
|
+
}
|
|
50
48
|
|
|
51
49
|
//
|
|
52
50
|
// TODO: when adding an item of a MapSchema, the changes may not
|
|
53
51
|
// be set (only the parent's changes are set)
|
|
54
52
|
//
|
|
55
|
-
let changes = this.changes.
|
|
53
|
+
let changes = this.changes[changeTree.refId];
|
|
56
54
|
if (changes === undefined) {
|
|
57
|
-
changes =
|
|
58
|
-
this.changes.
|
|
55
|
+
changes = {};
|
|
56
|
+
this.changes[changeTree.refId] = changes;
|
|
59
57
|
}
|
|
60
58
|
|
|
61
59
|
// set tag
|
|
@@ -72,99 +70,93 @@ export class StateView {
|
|
|
72
70
|
}
|
|
73
71
|
tags.add(tag);
|
|
74
72
|
|
|
75
|
-
// console.log("BY TAG:", tag);
|
|
76
|
-
|
|
77
73
|
// Ref: add tagged properties
|
|
78
|
-
metadata?.[
|
|
74
|
+
metadata?.[$fieldIndexesByViewTag]?.[tag]?.forEach((index) => {
|
|
79
75
|
if (changeTree.getChange(index) !== OPERATION.DELETE) {
|
|
80
|
-
changes
|
|
76
|
+
changes[index] = OPERATION.ADD;
|
|
81
77
|
}
|
|
82
78
|
});
|
|
83
79
|
|
|
84
80
|
} else {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// // add default tag properties
|
|
89
|
-
// metadata?.[-3]?.[DEFAULT_VIEW_TAG]?.forEach((index) => {
|
|
90
|
-
// if (changeTree.getChange(index) !== OPERATION.DELETE) {
|
|
91
|
-
// changes.set(index, OPERATION.ADD);
|
|
92
|
-
// }
|
|
93
|
-
// });
|
|
94
|
-
|
|
95
|
-
const allChangesSet = (changeTree.isFiltered || changeTree.isPartiallyFiltered)
|
|
81
|
+
const isInvisible = this.invisible.has(changeTree);
|
|
82
|
+
const changeSet = (changeTree.filteredChanges !== undefined)
|
|
96
83
|
? changeTree.allFilteredChanges
|
|
97
84
|
: changeTree.allChanges;
|
|
98
|
-
const it = allChangesSet.keys();
|
|
99
|
-
const isInvisible = this.invisible.has(changeTree);
|
|
100
85
|
|
|
101
|
-
for (
|
|
86
|
+
for (let i = 0, len = changeSet.operations.length; i < len; i++) {
|
|
87
|
+
const index = changeSet.operations[i];
|
|
88
|
+
if (index === undefined) { continue; } // skip "undefined" indexes
|
|
89
|
+
|
|
90
|
+
const op = changeTree.indexedOperations[index] ?? OPERATION.ADD;
|
|
91
|
+
const tagAtIndex = metadata?.[index].tag;
|
|
102
92
|
if (
|
|
103
|
-
(
|
|
104
|
-
|
|
93
|
+
(
|
|
94
|
+
isInvisible || // if "invisible", include all
|
|
95
|
+
tagAtIndex === undefined || // "all change" with no tag
|
|
96
|
+
tagAtIndex === tag // tagged property
|
|
97
|
+
) &&
|
|
98
|
+
op !== OPERATION.DELETE
|
|
105
99
|
) {
|
|
106
|
-
changes
|
|
100
|
+
changes[index] = op;
|
|
107
101
|
}
|
|
108
102
|
}
|
|
109
103
|
}
|
|
110
104
|
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
105
|
+
// Add children of this ChangeTree to this view
|
|
106
|
+
changeTree.forEachChild((change, index) => {
|
|
107
|
+
// Do not ADD children that don't have the same tag
|
|
108
|
+
if (
|
|
109
|
+
metadata &&
|
|
110
|
+
metadata[index].tag !== undefined &&
|
|
111
|
+
metadata[index].tag !== tag
|
|
112
|
+
) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
this.add(change.ref, tag, false);
|
|
116
|
+
});
|
|
119
117
|
|
|
120
118
|
return this;
|
|
121
119
|
}
|
|
122
120
|
|
|
123
|
-
protected addParent(changeTree: ChangeTree, tag: number) {
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
protected addParent(changeTree: ChangeTree, parentIndex: number, tag: number) {
|
|
122
|
+
// view must have all "changeTree" parent tree
|
|
123
|
+
this.items.add(changeTree);
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
const
|
|
125
|
+
// add parent's parent
|
|
126
|
+
const parentChangeTree: ChangeTree = changeTree.parent?.[$changes];
|
|
127
|
+
if (parentChangeTree && (parentChangeTree.filteredChanges !== undefined)) {
|
|
128
|
+
this.addParent(parentChangeTree, changeTree.parentIndex, tag);
|
|
129
|
+
}
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
// parent is already available, no need to add it!
|
|
132
|
+
if (!this.invisible.has(changeTree)) {
|
|
132
133
|
return;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
this.addParent(parentChangeTree, tag);
|
|
136
|
-
|
|
137
136
|
// add parent's tag properties
|
|
138
|
-
if (
|
|
137
|
+
if (changeTree.getChange(parentIndex) !== OPERATION.DELETE) {
|
|
139
138
|
|
|
140
|
-
let
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
this.changes.
|
|
139
|
+
let changes = this.changes[changeTree.refId];
|
|
140
|
+
if (changes === undefined) {
|
|
141
|
+
changes = {};
|
|
142
|
+
this.changes[changeTree.refId] = changes;
|
|
144
143
|
}
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// parentChange: (
|
|
150
|
-
// parentChangeTree.getChange(parentIndex) &&
|
|
151
|
-
// OPERATION[parentChangeTree.getChange(parentIndex)]
|
|
152
|
-
// ),
|
|
153
|
-
// })
|
|
145
|
+
if (!this.tags) {
|
|
146
|
+
this.tags = new WeakMap<ChangeTree, Set<number>>();
|
|
147
|
+
}
|
|
154
148
|
|
|
155
|
-
if (!this.tags) { this.tags = new WeakMap<ChangeTree, Set<number>>(); }
|
|
156
149
|
let tags: Set<number>;
|
|
157
|
-
if (!this.tags.has(
|
|
150
|
+
if (!this.tags.has(changeTree)) {
|
|
158
151
|
tags = new Set<number>();
|
|
159
|
-
this.tags.set(
|
|
152
|
+
this.tags.set(changeTree, tags);
|
|
160
153
|
} else {
|
|
161
|
-
tags = this.tags.get(
|
|
154
|
+
tags = this.tags.get(changeTree);
|
|
162
155
|
}
|
|
163
156
|
tags.add(tag);
|
|
164
157
|
|
|
165
|
-
|
|
158
|
+
changes[parentIndex] = OPERATION.ADD;
|
|
166
159
|
}
|
|
167
|
-
|
|
168
160
|
}
|
|
169
161
|
|
|
170
162
|
remove(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {
|
|
@@ -179,10 +171,10 @@ export class StateView {
|
|
|
179
171
|
const ref = changeTree.ref;
|
|
180
172
|
const metadata: Metadata = ref.constructor[Symbol.metadata];
|
|
181
173
|
|
|
182
|
-
let changes = this.changes.
|
|
174
|
+
let changes = this.changes[changeTree.refId];
|
|
183
175
|
if (changes === undefined) {
|
|
184
|
-
changes =
|
|
185
|
-
this.changes.
|
|
176
|
+
changes = {};
|
|
177
|
+
this.changes[changeTree.refId] = changes;
|
|
186
178
|
}
|
|
187
179
|
|
|
188
180
|
if (tag === DEFAULT_VIEW_TAG) {
|
|
@@ -190,25 +182,25 @@ export class StateView {
|
|
|
190
182
|
const parent = changeTree.parent;
|
|
191
183
|
if (!Metadata.isValidInstance(parent)) {
|
|
192
184
|
const parentChangeTree = parent[$changes];
|
|
193
|
-
let changes = this.changes.
|
|
185
|
+
let changes = this.changes[parentChangeTree.refId];
|
|
194
186
|
if (changes === undefined) {
|
|
195
|
-
changes =
|
|
196
|
-
this.changes.
|
|
187
|
+
changes = {};
|
|
188
|
+
this.changes[parentChangeTree.refId] = changes;
|
|
197
189
|
}
|
|
198
190
|
// DELETE / DELETE BY REF ID
|
|
199
|
-
changes
|
|
191
|
+
changes[changeTree.parentIndex] = OPERATION.DELETE;
|
|
200
192
|
|
|
201
193
|
} else {
|
|
202
194
|
// delete all "tagged" properties.
|
|
203
|
-
metadata[
|
|
204
|
-
changes
|
|
195
|
+
metadata[$viewFieldIndexes].forEach((index) =>
|
|
196
|
+
changes[index] = OPERATION.DELETE);
|
|
205
197
|
}
|
|
206
198
|
|
|
207
199
|
|
|
208
200
|
} else {
|
|
209
201
|
// delete only tagged properties
|
|
210
|
-
metadata[
|
|
211
|
-
changes
|
|
202
|
+
metadata[$fieldIndexesByViewTag][tag].forEach((index) =>
|
|
203
|
+
changes[index] = OPERATION.DELETE);
|
|
212
204
|
}
|
|
213
205
|
|
|
214
206
|
// remove tag
|
package/src/encoding/assert.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Schema } from "../Schema";
|
|
2
|
-
import { CollectionSchema } from "../types/custom/CollectionSchema";
|
|
3
|
-
import { MapSchema } from "../types/custom/MapSchema";
|
|
4
|
-
import { SetSchema } from "../types/custom/SetSchema";
|
|
5
|
-
import { ArraySchema } from "../types/custom/ArraySchema";
|
|
1
|
+
import type { Schema } from "../Schema";
|
|
2
|
+
import type { CollectionSchema } from "../types/custom/CollectionSchema";
|
|
3
|
+
import type { MapSchema } from "../types/custom/MapSchema";
|
|
4
|
+
import type { SetSchema } from "../types/custom/SetSchema";
|
|
5
|
+
import type { ArraySchema } from "../types/custom/ArraySchema";
|
|
6
|
+
import type { Ref } from "../encoder/ChangeTree";
|
|
6
7
|
|
|
7
8
|
export class EncodeSchemaError extends Error {}
|
|
8
9
|
|
|
@@ -27,6 +28,10 @@ export function assertType(value: any, type: string, klass: Schema, field: strin
|
|
|
27
28
|
console.log(`trying to encode "NaN" in ${klass.constructor.name}#${field}`);
|
|
28
29
|
}
|
|
29
30
|
break;
|
|
31
|
+
case "bigint64":
|
|
32
|
+
case "biguint64":
|
|
33
|
+
typeofTarget = "bigint";
|
|
34
|
+
break;
|
|
30
35
|
case "string":
|
|
31
36
|
typeofTarget = "string";
|
|
32
37
|
allowNull = true;
|
|
@@ -34,6 +39,10 @@ export function assertType(value: any, type: string, klass: Schema, field: strin
|
|
|
34
39
|
case "boolean":
|
|
35
40
|
// boolean is always encoded as true/false based on truthiness
|
|
36
41
|
return;
|
|
42
|
+
default:
|
|
43
|
+
// skip assertion for custom types
|
|
44
|
+
// TODO: allow custom types to define their own assertions
|
|
45
|
+
return;
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
if (typeof (value) !== typeofTarget && (!allowNull || (allowNull && value !== null))) {
|
|
@@ -43,16 +52,16 @@ export function assertType(value: any, type: string, klass: Schema, field: strin
|
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
export function assertInstanceType(
|
|
46
|
-
value:
|
|
55
|
+
value: Ref,
|
|
47
56
|
type: typeof Schema
|
|
48
57
|
| typeof ArraySchema
|
|
49
58
|
| typeof MapSchema
|
|
50
59
|
| typeof CollectionSchema
|
|
51
60
|
| typeof SetSchema,
|
|
52
|
-
|
|
61
|
+
instance: Ref,
|
|
53
62
|
field: string | number,
|
|
54
63
|
) {
|
|
55
64
|
if (!(value instanceof type)) {
|
|
56
|
-
throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && (value as any).constructor.name}' was provided in ${
|
|
65
|
+
throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && (value as any).constructor.name}' was provided in ${instance.constructor.name}#${field}`);
|
|
57
66
|
}
|
|
58
67
|
}
|
package/src/encoding/decode.ts
CHANGED
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
* SOFTWARE
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { SWITCH_TO_STRUCTURE } from "./spec";
|
|
25
24
|
import type { BufferLike } from "./encode";
|
|
26
25
|
|
|
27
26
|
/**
|
|
@@ -31,7 +30,17 @@ import type { BufferLike } from "./encode";
|
|
|
31
30
|
|
|
32
31
|
export interface Iterator { offset: number; }
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
// force little endian to facilitate decoding on multiple implementations
|
|
34
|
+
const _isLittleEndian = true; // new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
|
35
|
+
const _convoBuffer = new ArrayBuffer(8);
|
|
36
|
+
|
|
37
|
+
const _int32 = new Int32Array(_convoBuffer);
|
|
38
|
+
const _float32 = new Float32Array(_convoBuffer);
|
|
39
|
+
const _float64 = new Float64Array(_convoBuffer);
|
|
40
|
+
const _uint64 = new BigUint64Array(_convoBuffer);
|
|
41
|
+
const _int64 = new BigInt64Array(_convoBuffer);
|
|
42
|
+
|
|
43
|
+
function utf8Read(bytes: BufferLike, it: Iterator, length: number) {
|
|
35
44
|
var string = '', chr = 0;
|
|
36
45
|
for (var i = it.offset, end = it.offset + length; i < end; i++) {
|
|
37
46
|
var byte = bytes[i];
|
|
@@ -76,72 +85,70 @@ export function utf8Read(bytes: BufferLike, it: Iterator, length: number) {
|
|
|
76
85
|
return string;
|
|
77
86
|
}
|
|
78
87
|
|
|
79
|
-
|
|
88
|
+
function int8 (bytes: BufferLike, it: Iterator) {
|
|
80
89
|
return uint8(bytes, it) << 24 >> 24;
|
|
81
90
|
};
|
|
82
91
|
|
|
83
|
-
|
|
92
|
+
function uint8 (bytes: BufferLike, it: Iterator) {
|
|
84
93
|
return bytes[it.offset++];
|
|
85
94
|
};
|
|
86
95
|
|
|
87
|
-
|
|
96
|
+
function int16 (bytes: BufferLike, it: Iterator) {
|
|
88
97
|
return uint16(bytes, it) << 16 >> 16;
|
|
89
98
|
};
|
|
90
99
|
|
|
91
|
-
|
|
100
|
+
function uint16 (bytes: BufferLike, it: Iterator) {
|
|
92
101
|
return bytes[it.offset++] | bytes[it.offset++] << 8;
|
|
93
102
|
};
|
|
94
103
|
|
|
95
|
-
|
|
104
|
+
function int32 (bytes: BufferLike, it: Iterator) {
|
|
96
105
|
return bytes[it.offset++] | bytes[it.offset++] << 8 | bytes[it.offset++] << 16 | bytes[it.offset++] << 24;
|
|
97
106
|
};
|
|
98
107
|
|
|
99
|
-
|
|
108
|
+
function uint32 (bytes: BufferLike, it: Iterator) {
|
|
100
109
|
return int32(bytes, it) >>> 0;
|
|
101
110
|
};
|
|
102
111
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
function float32 (bytes: BufferLike, it: Iterator) {
|
|
113
|
+
_int32[0] = int32(bytes, it);
|
|
114
|
+
return _float32[0];
|
|
115
|
+
};
|
|
106
116
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
function float64 (bytes: BufferLike, it: Iterator) {
|
|
118
|
+
_int32[_isLittleEndian ? 0 : 1] = int32(bytes, it);
|
|
119
|
+
_int32[_isLittleEndian ? 1 : 0] = int32(bytes, it);
|
|
120
|
+
return _float64[0];
|
|
121
|
+
};
|
|
110
122
|
|
|
111
|
-
|
|
123
|
+
function int64(bytes: BufferLike, it: Iterator) {
|
|
112
124
|
const low = uint32(bytes, it);
|
|
113
125
|
const high = int32(bytes, it) * Math.pow(2, 32);
|
|
114
126
|
return high + low;
|
|
115
127
|
};
|
|
116
128
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
function uint64(bytes: BufferLike, it: Iterator) {
|
|
130
|
+
const low = uint32(bytes, it);
|
|
131
|
+
const high = uint32(bytes, it) * Math.pow(2, 32);
|
|
132
|
+
return high + low;
|
|
121
133
|
};
|
|
122
134
|
|
|
123
|
-
|
|
124
|
-
const _isLittleEndian = true; // new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
|
125
|
-
const _int32 = new Int32Array(2);
|
|
126
|
-
const _float32 = new Float32Array(_int32.buffer);
|
|
127
|
-
const _float64 = new Float64Array(_int32.buffer);
|
|
128
|
-
|
|
129
|
-
export function readFloat32 (bytes: BufferLike, it: Iterator) {
|
|
135
|
+
function bigint64(bytes: BufferLike, it: Iterator) {
|
|
130
136
|
_int32[0] = int32(bytes, it);
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
_int32[1] = int32(bytes, it);
|
|
138
|
+
return _int64[0];
|
|
139
|
+
}
|
|
133
140
|
|
|
134
|
-
|
|
135
|
-
_int32[
|
|
136
|
-
_int32[
|
|
137
|
-
return
|
|
138
|
-
}
|
|
141
|
+
function biguint64(bytes: BufferLike, it: Iterator) {
|
|
142
|
+
_int32[0] = int32(bytes, it);
|
|
143
|
+
_int32[1] = int32(bytes, it);
|
|
144
|
+
return _uint64[0];
|
|
145
|
+
}
|
|
139
146
|
|
|
140
|
-
|
|
147
|
+
function boolean (bytes: BufferLike, it: Iterator) {
|
|
141
148
|
return uint8(bytes, it) > 0;
|
|
142
149
|
};
|
|
143
150
|
|
|
144
|
-
|
|
151
|
+
function string (bytes: BufferLike, it: Iterator) {
|
|
145
152
|
const prefix = bytes[it.offset++];
|
|
146
153
|
let length: number;
|
|
147
154
|
|
|
@@ -162,21 +169,7 @@ export function string (bytes: BufferLike, it: Iterator) {
|
|
|
162
169
|
return utf8Read(bytes, it, length);
|
|
163
170
|
}
|
|
164
171
|
|
|
165
|
-
|
|
166
|
-
const prefix = bytes[it.offset];
|
|
167
|
-
return (
|
|
168
|
-
// fixstr
|
|
169
|
-
(prefix < 0xc0 && prefix > 0xa0) ||
|
|
170
|
-
// str 8
|
|
171
|
-
prefix === 0xd9 ||
|
|
172
|
-
// str 16
|
|
173
|
-
prefix === 0xda ||
|
|
174
|
-
// str 32
|
|
175
|
-
prefix === 0xdb
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export function number (bytes: BufferLike, it: Iterator) {
|
|
172
|
+
function number (bytes: BufferLike, it: Iterator) {
|
|
180
173
|
const prefix = bytes[it.offset++];
|
|
181
174
|
|
|
182
175
|
if (prefix < 0x80) {
|
|
@@ -185,11 +178,11 @@ export function number (bytes: BufferLike, it: Iterator) {
|
|
|
185
178
|
|
|
186
179
|
} else if (prefix === 0xca) {
|
|
187
180
|
// float 32
|
|
188
|
-
return
|
|
181
|
+
return float32(bytes, it);
|
|
189
182
|
|
|
190
183
|
} else if (prefix === 0xcb) {
|
|
191
184
|
// float 64
|
|
192
|
-
return
|
|
185
|
+
return float64(bytes, it);
|
|
193
186
|
|
|
194
187
|
} else if (prefix === 0xcc) {
|
|
195
188
|
// uint 8
|
|
@@ -229,49 +222,36 @@ export function number (bytes: BufferLike, it: Iterator) {
|
|
|
229
222
|
}
|
|
230
223
|
};
|
|
231
224
|
|
|
232
|
-
export function
|
|
225
|
+
export function stringCheck(bytes: BufferLike, it: Iterator) {
|
|
233
226
|
const prefix = bytes[it.offset];
|
|
234
|
-
// positive fixint - 0x00 - 0x7f
|
|
235
|
-
// float 32 - 0xca
|
|
236
|
-
// float 64 - 0xcb
|
|
237
|
-
// uint 8 - 0xcc
|
|
238
|
-
// uint 16 - 0xcd
|
|
239
|
-
// uint 32 - 0xce
|
|
240
|
-
// uint 64 - 0xcf
|
|
241
|
-
// int 8 - 0xd0
|
|
242
|
-
// int 16 - 0xd1
|
|
243
|
-
// int 32 - 0xd2
|
|
244
|
-
// int 64 - 0xd3
|
|
245
227
|
return (
|
|
246
|
-
|
|
247
|
-
(prefix
|
|
228
|
+
// fixstr
|
|
229
|
+
(prefix < 0xc0 && prefix > 0xa0) ||
|
|
230
|
+
// str 8
|
|
231
|
+
prefix === 0xd9 ||
|
|
232
|
+
// str 16
|
|
233
|
+
prefix === 0xda ||
|
|
234
|
+
// str 32
|
|
235
|
+
prefix === 0xdb
|
|
248
236
|
);
|
|
249
237
|
}
|
|
250
238
|
|
|
251
|
-
export
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
export function switchStructureCheck(bytes: BufferLike, it: Iterator) {
|
|
271
|
-
return (
|
|
272
|
-
// previous byte should be `SWITCH_TO_STRUCTURE`
|
|
273
|
-
bytes[it.offset - 1] === SWITCH_TO_STRUCTURE &&
|
|
274
|
-
// next byte should be a number
|
|
275
|
-
(bytes[it.offset] < 0x80 || (bytes[it.offset] >= 0xca && bytes[it.offset] <= 0xd3))
|
|
276
|
-
);
|
|
277
|
-
}
|
|
239
|
+
export const decode = {
|
|
240
|
+
utf8Read,
|
|
241
|
+
int8,
|
|
242
|
+
uint8,
|
|
243
|
+
int16,
|
|
244
|
+
uint16,
|
|
245
|
+
int32,
|
|
246
|
+
uint32,
|
|
247
|
+
float32,
|
|
248
|
+
float64,
|
|
249
|
+
int64,
|
|
250
|
+
uint64,
|
|
251
|
+
bigint64,
|
|
252
|
+
biguint64,
|
|
253
|
+
boolean,
|
|
254
|
+
string,
|
|
255
|
+
number,
|
|
256
|
+
stringCheck,
|
|
257
|
+
};
|