@colyseus/schema 2.0.32 → 3.0.0-alpha.0
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 +3614 -2634
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +3324 -2445
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +3614 -2634
- package/lib/Decoder.d.ts +16 -0
- package/lib/Decoder.js +182 -0
- package/lib/Decoder.js.map +1 -0
- package/lib/Encoder.d.ts +13 -0
- package/lib/Encoder.js +79 -0
- package/lib/Encoder.js.map +1 -0
- package/lib/Metadata.d.ts +36 -0
- package/lib/Metadata.js +91 -0
- package/lib/Metadata.js.map +1 -0
- package/lib/Reflection.d.ts +7 -5
- package/lib/Reflection.js +62 -58
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +39 -51
- package/lib/Schema.js +189 -731
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +26 -45
- package/lib/annotations.js +363 -194
- package/lib/annotations.js.map +1 -1
- package/lib/changes/ChangeSet.d.ts +12 -0
- package/lib/changes/ChangeSet.js +35 -0
- package/lib/changes/ChangeSet.js.map +1 -0
- package/lib/changes/DecodeOperation.d.ts +15 -0
- package/lib/changes/DecodeOperation.js +186 -0
- package/lib/changes/DecodeOperation.js.map +1 -0
- package/lib/changes/EncodeOperation.d.ts +18 -0
- package/lib/changes/EncodeOperation.js +130 -0
- package/lib/changes/EncodeOperation.js.map +1 -0
- package/lib/changes/consts.d.ts +14 -0
- package/lib/changes/consts.js +18 -0
- package/lib/changes/consts.js.map +1 -0
- package/lib/decoder/DecodeOperation.d.ts +24 -0
- package/lib/decoder/DecodeOperation.js +256 -0
- package/lib/decoder/DecodeOperation.js.map +1 -0
- package/lib/decoder/Decoder.d.ts +21 -0
- package/lib/decoder/Decoder.js +114 -0
- package/lib/decoder/Decoder.js.map +1 -0
- package/lib/decoder/ReferenceTracker.d.ts +26 -0
- package/lib/decoder/ReferenceTracker.js +131 -0
- package/lib/decoder/ReferenceTracker.js.map +1 -0
- package/lib/decoder/strategy/RawChanges.d.ts +3 -0
- package/lib/decoder/strategy/RawChanges.js +8 -0
- package/lib/decoder/strategy/RawChanges.js.map +1 -0
- package/lib/decoder/strategy/StateCallbacks.d.ts +20 -0
- package/lib/decoder/strategy/StateCallbacks.js +240 -0
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -0
- package/lib/decoding/decode.d.ts +48 -0
- package/lib/decoding/decode.js +267 -0
- package/lib/decoding/decode.js.map +1 -0
- package/lib/ecs.d.ts +11 -0
- package/lib/ecs.js +160 -0
- package/lib/ecs.js.map +1 -0
- package/lib/encoder/ChangeTree.d.ts +72 -0
- package/lib/encoder/ChangeTree.js +384 -0
- package/lib/encoder/ChangeTree.js.map +1 -0
- package/lib/encoder/EncodeOperation.d.ts +25 -0
- package/lib/encoder/EncodeOperation.js +156 -0
- package/lib/encoder/EncodeOperation.js.map +1 -0
- package/lib/encoder/Encoder.d.ts +23 -0
- package/lib/encoder/Encoder.js +192 -0
- package/lib/encoder/Encoder.js.map +1 -0
- package/lib/encoder/StateView.d.ts +21 -0
- package/lib/encoder/StateView.js +196 -0
- package/lib/encoder/StateView.js.map +1 -0
- package/lib/encoding/assert.d.ts +9 -0
- package/lib/encoding/assert.js +47 -0
- package/lib/encoding/assert.js.map +1 -0
- package/lib/encoding/decode.js +1 -1
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +17 -16
- package/lib/encoding/encode.js +88 -81
- package/lib/encoding/encode.js.map +1 -1
- package/lib/encoding/spec.d.ts +25 -0
- package/lib/encoding/spec.js +30 -0
- package/lib/encoding/spec.js.map +1 -0
- package/lib/index.d.ts +18 -10
- package/lib/index.js +39 -17
- package/lib/index.js.map +1 -1
- package/lib/symbol.shim.d.ts +6 -0
- package/lib/symbol.shim.js +4 -0
- package/lib/symbol.shim.js.map +1 -0
- package/lib/types/ArraySchema.d.ts +1 -1
- package/lib/types/ArraySchema.js +0 -7
- package/lib/types/ArraySchema.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +10 -2
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/custom/ArraySchema.d.ts +245 -0
- package/lib/types/custom/ArraySchema.js +659 -0
- package/lib/types/custom/ArraySchema.js.map +1 -0
- package/lib/types/custom/CollectionSchema.d.ts +42 -0
- package/lib/types/custom/CollectionSchema.js +165 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -0
- package/lib/types/custom/MapSchema.d.ts +43 -0
- package/lib/types/custom/MapSchema.js +200 -0
- package/lib/types/custom/MapSchema.js.map +1 -0
- package/lib/types/custom/SetSchema.d.ts +39 -0
- package/lib/types/custom/SetSchema.js +177 -0
- package/lib/types/custom/SetSchema.js.map +1 -0
- package/lib/types/registry.d.ts +6 -0
- package/lib/types/registry.js +19 -0
- package/lib/types/registry.js.map +1 -0
- package/lib/types/symbols.d.ts +29 -0
- package/lib/types/symbols.js +33 -0
- package/lib/types/symbols.js.map +1 -0
- package/lib/types/utils.d.ts +0 -8
- package/lib/types/utils.js +1 -33
- package/lib/types/utils.js.map +1 -1
- package/lib/usage.d.ts +1 -0
- package/lib/usage.js +22 -0
- package/lib/usage.js.map +1 -0
- package/lib/utils.d.ts +13 -2
- package/lib/utils.js +36 -15
- package/lib/utils.js.map +1 -1
- package/lib/v3.d.ts +1 -0
- package/lib/v3.js +427 -0
- package/lib/v3.js.map +1 -0
- package/lib/v3_bench.d.ts +1 -0
- package/lib/v3_bench.js +130 -0
- package/lib/v3_bench.js.map +1 -0
- package/lib/v3_experiment.d.ts +1 -0
- package/lib/v3_experiment.js +407 -0
- package/lib/v3_experiment.js.map +1 -0
- package/package.json +5 -5
- package/src/Metadata.ts +135 -0
- package/src/Reflection.ts +75 -66
- package/src/Schema.ts +213 -931
- package/src/annotations.ts +430 -243
- package/src/decoder/DecodeOperation.ts +372 -0
- package/src/decoder/Decoder.ts +155 -0
- package/src/decoder/ReferenceTracker.ts +151 -0
- package/src/decoder/strategy/RawChanges.ts +9 -0
- package/src/decoder/strategy/StateCallbacks.ts +326 -0
- package/src/encoder/ChangeTree.ts +492 -0
- package/src/encoder/EncodeOperation.ts +237 -0
- package/src/encoder/Encoder.ts +246 -0
- package/src/encoder/StateView.ts +229 -0
- package/src/encoding/assert.ts +58 -0
- package/src/encoding/decode.ts +1 -1
- package/src/encoding/encode.ts +88 -82
- package/src/encoding/spec.ts +29 -0
- package/src/index.ts +22 -19
- package/src/symbol.shim.ts +12 -0
- package/src/types/HelperTypes.ts +16 -2
- package/src/types/{ArraySchema.ts → custom/ArraySchema.ts} +342 -248
- package/src/types/{CollectionSchema.ts → custom/CollectionSchema.ts} +56 -46
- package/src/types/{MapSchema.ts → custom/MapSchema.ts} +88 -115
- package/src/types/{SetSchema.ts → custom/SetSchema.ts} +58 -47
- package/src/types/{typeRegistry.ts → registry.ts} +6 -6
- package/src/types/symbols.ts +36 -0
- package/src/types/utils.ts +0 -46
- package/src/utils.ts +50 -21
- package/src/v3_bench.ts +107 -0
- package/src/changes/ChangeTree.ts +0 -295
- package/src/changes/ReferenceTracker.ts +0 -91
- package/src/filters/index.ts +0 -23
- package/src/spec.ts +0 -49
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.ChangeTree = exports.Root = void 0;
|
|
5
|
+
const spec_1 = require("../encoding/spec");
|
|
6
|
+
const symbols_1 = require("../types/symbols");
|
|
7
|
+
const Metadata_1 = require("../Metadata");
|
|
8
|
+
class Root {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.nextUniqueId = 0;
|
|
11
|
+
this.refCount = new WeakMap();
|
|
12
|
+
// all changes
|
|
13
|
+
this.allChanges = new Map();
|
|
14
|
+
this.allFilteredChanges = new Map();
|
|
15
|
+
// pending changes to be encoded
|
|
16
|
+
this.changes = new Map();
|
|
17
|
+
this.filteredChanges = new Map();
|
|
18
|
+
this.views = [];
|
|
19
|
+
}
|
|
20
|
+
getNextUniqueId() {
|
|
21
|
+
return this.nextUniqueId++;
|
|
22
|
+
}
|
|
23
|
+
add(changeTree) {
|
|
24
|
+
const refCount = this.refCount.get(changeTree) || 0;
|
|
25
|
+
this.refCount.set(changeTree, refCount + 1);
|
|
26
|
+
}
|
|
27
|
+
remove(changeTree) {
|
|
28
|
+
const refCount = this.refCount.get(changeTree);
|
|
29
|
+
if (refCount <= 1) {
|
|
30
|
+
this.allChanges.delete(changeTree);
|
|
31
|
+
this.changes.delete(changeTree);
|
|
32
|
+
if (changeTree.isFiltered || changeTree.isPartiallyFiltered) {
|
|
33
|
+
this.allFilteredChanges.delete(changeTree);
|
|
34
|
+
this.filteredChanges.delete(changeTree);
|
|
35
|
+
}
|
|
36
|
+
this.refCount.delete(changeTree);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.refCount.set(changeTree, refCount - 1);
|
|
40
|
+
}
|
|
41
|
+
changeTree.forEachChild((child, _) => this.remove(child));
|
|
42
|
+
}
|
|
43
|
+
clear() {
|
|
44
|
+
this.changes.clear();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.Root = Root;
|
|
48
|
+
class ChangeTree {
|
|
49
|
+
static { _a = symbols_1.$isNew; }
|
|
50
|
+
;
|
|
51
|
+
constructor(ref) {
|
|
52
|
+
this.indexes = {}; // TODO: remove this, only used by MapSchema/SetSchema/CollectionSchema (`encodeKeyValueOperation`)
|
|
53
|
+
this.currentOperationIndex = 0;
|
|
54
|
+
this.allChanges = new Map();
|
|
55
|
+
this.allFilteredChanges = new Map();
|
|
56
|
+
this.changes = new Map();
|
|
57
|
+
this.filteredChanges = new Map();
|
|
58
|
+
this[_a] = true;
|
|
59
|
+
this.ref = ref;
|
|
60
|
+
}
|
|
61
|
+
setRoot(root) {
|
|
62
|
+
this.root = root;
|
|
63
|
+
this.root.add(this);
|
|
64
|
+
//
|
|
65
|
+
// At Schema initialization, the "root" structure might not be available
|
|
66
|
+
// yet, as it only does once the "Encoder" has been set up.
|
|
67
|
+
//
|
|
68
|
+
// So the "parent" may be already set without a "root".
|
|
69
|
+
//
|
|
70
|
+
this.checkIsFiltered(this.parent, this.parentIndex);
|
|
71
|
+
// unique refId for the ChangeTree.
|
|
72
|
+
this.ensureRefId();
|
|
73
|
+
if (!this.isFiltered) {
|
|
74
|
+
this.root.changes.set(this, this.changes);
|
|
75
|
+
}
|
|
76
|
+
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
77
|
+
this.root.allFilteredChanges.set(this, this.allFilteredChanges);
|
|
78
|
+
this.root.filteredChanges.set(this, this.filteredChanges);
|
|
79
|
+
// } else {
|
|
80
|
+
// this.root.allChanges.set(this, this.allChanges);
|
|
81
|
+
}
|
|
82
|
+
if (!this.isFiltered) {
|
|
83
|
+
this.root.allChanges.set(this, this.allChanges);
|
|
84
|
+
}
|
|
85
|
+
this.forEachChild((changeTree, _) => {
|
|
86
|
+
changeTree.setRoot(root);
|
|
87
|
+
});
|
|
88
|
+
// this.allChanges.forEach((_, index) => {
|
|
89
|
+
// const childRef = this.ref[$getByIndex](index);
|
|
90
|
+
// if (childRef && childRef[$changes]) {
|
|
91
|
+
// childRef[$changes].setRoot(root);
|
|
92
|
+
// }
|
|
93
|
+
// });
|
|
94
|
+
}
|
|
95
|
+
setParent(parent, root, parentIndex) {
|
|
96
|
+
this.parent = parent;
|
|
97
|
+
this.parentIndex = parentIndex;
|
|
98
|
+
// avoid setting parents with empty `root`
|
|
99
|
+
if (!root) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
root.add(this);
|
|
103
|
+
// skip if parent is already set
|
|
104
|
+
if (root === this.root) {
|
|
105
|
+
this.forEachChild((changeTree, atIndex) => {
|
|
106
|
+
changeTree.setParent(this.ref, root, atIndex);
|
|
107
|
+
});
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.root = root;
|
|
111
|
+
this.checkIsFiltered(parent, parentIndex);
|
|
112
|
+
if (!this.isFiltered) {
|
|
113
|
+
this.root.changes.set(this, this.changes);
|
|
114
|
+
}
|
|
115
|
+
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
116
|
+
this.root.filteredChanges.set(this, this.filteredChanges);
|
|
117
|
+
this.root.allFilteredChanges.set(this, this.filteredChanges);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.root.allChanges.set(this, this.allChanges);
|
|
121
|
+
}
|
|
122
|
+
this.ensureRefId();
|
|
123
|
+
this.forEachChild((changeTree, atIndex) => {
|
|
124
|
+
changeTree.setParent(this.ref, root, atIndex);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
forEachChild(callback) {
|
|
128
|
+
//
|
|
129
|
+
// assign same parent on child structures
|
|
130
|
+
//
|
|
131
|
+
if (Metadata_1.Metadata.isValidInstance(this.ref)) {
|
|
132
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
133
|
+
// FIXME: need to iterate over parent metadata instead.
|
|
134
|
+
for (const field in metadata) {
|
|
135
|
+
const value = this.ref[field];
|
|
136
|
+
if (value && value[symbols_1.$changes]) {
|
|
137
|
+
callback(value[symbols_1.$changes], metadata[field].index);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else if (typeof (this.ref) === "object") {
|
|
142
|
+
// MapSchema / ArraySchema, etc.
|
|
143
|
+
this.ref.forEach((value, key) => {
|
|
144
|
+
if (Metadata_1.Metadata.isValidInstance(value)) {
|
|
145
|
+
callback(value[symbols_1.$changes], this.ref[symbols_1.$changes].indexes[key]);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
operation(op) {
|
|
151
|
+
this.changes.set(--this.currentOperationIndex, op);
|
|
152
|
+
this.root?.changes.set(this, this.changes);
|
|
153
|
+
}
|
|
154
|
+
change(index, operation = spec_1.OPERATION.ADD) {
|
|
155
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
156
|
+
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
157
|
+
const changeSet = (isFiltered)
|
|
158
|
+
? this.filteredChanges
|
|
159
|
+
: this.changes;
|
|
160
|
+
const previousOperation = changeSet.get(index);
|
|
161
|
+
if (!previousOperation || previousOperation === spec_1.OPERATION.DELETE) {
|
|
162
|
+
const op = (!previousOperation)
|
|
163
|
+
? operation
|
|
164
|
+
: (previousOperation === spec_1.OPERATION.DELETE)
|
|
165
|
+
? spec_1.OPERATION.DELETE_AND_ADD
|
|
166
|
+
: operation;
|
|
167
|
+
changeSet.set(index, op);
|
|
168
|
+
}
|
|
169
|
+
//
|
|
170
|
+
// TODO: are DELETE operations being encoded as ADD here ??
|
|
171
|
+
//
|
|
172
|
+
if (isFiltered) {
|
|
173
|
+
this.allFilteredChanges.set(index, spec_1.OPERATION.ADD);
|
|
174
|
+
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
this.allChanges.set(index, spec_1.OPERATION.ADD);
|
|
178
|
+
this.root?.changes.set(this, this.changes);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
shiftChangeIndexes(shiftIndex) {
|
|
182
|
+
//
|
|
183
|
+
// Used only during:
|
|
184
|
+
//
|
|
185
|
+
// - ArraySchema#unshift()
|
|
186
|
+
//
|
|
187
|
+
const changeSet = (this.isFiltered)
|
|
188
|
+
? this.filteredChanges
|
|
189
|
+
: this.changes;
|
|
190
|
+
const changeSetEntries = Array.from(changeSet.entries());
|
|
191
|
+
changeSet.clear();
|
|
192
|
+
// Re-insert each entry with the shifted index
|
|
193
|
+
for (const [index, op] of changeSetEntries) {
|
|
194
|
+
changeSet.set(index + shiftIndex, op);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
shiftAllChangeIndexes(shiftIndex, startIndex = 0) {
|
|
198
|
+
//
|
|
199
|
+
// Used only during:
|
|
200
|
+
//
|
|
201
|
+
// - ArraySchema#splice()
|
|
202
|
+
//
|
|
203
|
+
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
204
|
+
this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allFilteredChanges);
|
|
205
|
+
this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
_shiftAllChangeIndexes(shiftIndex, startIndex = 0, allChangeSet) {
|
|
212
|
+
Array.from(allChangeSet.entries()).forEach(([index, op]) => {
|
|
213
|
+
// console.log('shiftAllChangeIndexes', index >= startIndex, { index, op, shiftIndex, startIndex })
|
|
214
|
+
if (index >= startIndex) {
|
|
215
|
+
allChangeSet.delete(index);
|
|
216
|
+
allChangeSet.set(index + shiftIndex, op);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
indexedOperation(index, operation, allChangesIndex = index) {
|
|
221
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
222
|
+
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
223
|
+
if (isFiltered) {
|
|
224
|
+
this.allFilteredChanges.set(allChangesIndex, spec_1.OPERATION.ADD);
|
|
225
|
+
this.filteredChanges.set(index, operation);
|
|
226
|
+
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
this.allChanges.set(allChangesIndex, spec_1.OPERATION.ADD);
|
|
230
|
+
this.changes.set(index, operation);
|
|
231
|
+
this.root?.changes.set(this, this.changes);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
getType(index) {
|
|
235
|
+
if (Metadata_1.Metadata.isValidInstance(this.ref)) {
|
|
236
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
237
|
+
return metadata[metadata[index]].type;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
//
|
|
241
|
+
// Get the child type from parent structure.
|
|
242
|
+
// - ["string"] => "string"
|
|
243
|
+
// - { map: "string" } => "string"
|
|
244
|
+
// - { set: "string" } => "string"
|
|
245
|
+
//
|
|
246
|
+
return this.ref[symbols_1.$childType];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
getChange(index) {
|
|
250
|
+
// TODO: optimize this. avoid checking against multiple instances
|
|
251
|
+
return this.changes.get(index) ?? this.filteredChanges.get(index);
|
|
252
|
+
}
|
|
253
|
+
//
|
|
254
|
+
// used during `.encode()`
|
|
255
|
+
//
|
|
256
|
+
getValue(index, isEncodeAll = false) {
|
|
257
|
+
//
|
|
258
|
+
// `isEncodeAll` param is only used by ArraySchema
|
|
259
|
+
//
|
|
260
|
+
return this.ref[symbols_1.$getByIndex](index, isEncodeAll);
|
|
261
|
+
}
|
|
262
|
+
delete(index, operation, allChangesIndex = index) {
|
|
263
|
+
if (index === undefined) {
|
|
264
|
+
try {
|
|
265
|
+
throw new Error(`@colyseus/schema ${this.ref.constructor.name}: trying to delete non-existing index '${index}'`);
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
console.warn(e);
|
|
269
|
+
}
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
273
|
+
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
274
|
+
const changeSet = (isFiltered)
|
|
275
|
+
? this.filteredChanges
|
|
276
|
+
: this.changes;
|
|
277
|
+
const previousValue = this.getValue(index);
|
|
278
|
+
changeSet.set(index, operation ?? spec_1.OPERATION.DELETE);
|
|
279
|
+
// remove `root` reference
|
|
280
|
+
if (previousValue && previousValue[symbols_1.$changes]) {
|
|
281
|
+
previousValue[symbols_1.$changes].root = undefined;
|
|
282
|
+
//
|
|
283
|
+
// FIXME: this.root is "undefined"
|
|
284
|
+
//
|
|
285
|
+
// This method is being called at decoding time when a DELETE operation is found.
|
|
286
|
+
//
|
|
287
|
+
// - This is due to using the concrete Schema class at decoding time.
|
|
288
|
+
// - "Reflected" structures do not have this problem.
|
|
289
|
+
//
|
|
290
|
+
// (the property descriptors should NOT be used at decoding time. only at encoding time.)
|
|
291
|
+
//
|
|
292
|
+
this.root?.remove(previousValue[symbols_1.$changes]);
|
|
293
|
+
}
|
|
294
|
+
//
|
|
295
|
+
// FIXME: this is looking a bit ugly (and repeated from `.change()`)
|
|
296
|
+
//
|
|
297
|
+
if (isFiltered) {
|
|
298
|
+
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
299
|
+
this.allFilteredChanges.delete(allChangesIndex);
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
this.root?.changes.set(this, this.changes);
|
|
303
|
+
this.allChanges.delete(allChangesIndex);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
endEncode() {
|
|
307
|
+
this.changes.clear();
|
|
308
|
+
this.ref[symbols_1.$onEncodeEnd]?.();
|
|
309
|
+
// Not a new instance anymore
|
|
310
|
+
delete this[symbols_1.$isNew];
|
|
311
|
+
}
|
|
312
|
+
discard(discardAll = false) {
|
|
313
|
+
//
|
|
314
|
+
// > MapSchema:
|
|
315
|
+
// Remove cached key to ensure ADD operations is unsed instead of
|
|
316
|
+
// REPLACE in case same key is used on next patches.
|
|
317
|
+
//
|
|
318
|
+
this.ref[symbols_1.$onEncodeEnd]?.();
|
|
319
|
+
this.changes.clear();
|
|
320
|
+
this.filteredChanges.clear();
|
|
321
|
+
// reset operation index
|
|
322
|
+
this.currentOperationIndex = 0;
|
|
323
|
+
if (discardAll) {
|
|
324
|
+
this.allChanges.clear();
|
|
325
|
+
this.allFilteredChanges.clear();
|
|
326
|
+
// remove children references
|
|
327
|
+
this.forEachChild((changeTree, _) => this.root?.remove(changeTree));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Recursively discard all changes from this, and child structures.
|
|
332
|
+
*/
|
|
333
|
+
discardAll() {
|
|
334
|
+
this.changes.forEach((_, fieldIndex) => {
|
|
335
|
+
const value = this.getValue(fieldIndex);
|
|
336
|
+
if (value && value[symbols_1.$changes]) {
|
|
337
|
+
value[symbols_1.$changes].discardAll();
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
this.discard();
|
|
341
|
+
}
|
|
342
|
+
ensureRefId() {
|
|
343
|
+
// skip if refId is already set.
|
|
344
|
+
if (this.refId !== undefined) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
this.refId = this.root.getNextUniqueId();
|
|
348
|
+
}
|
|
349
|
+
get changed() {
|
|
350
|
+
return this.changes.size > 0;
|
|
351
|
+
}
|
|
352
|
+
checkIsFiltered(parent, parentIndex) {
|
|
353
|
+
// Detect if current structure has "filters" declared
|
|
354
|
+
this.isPartiallyFiltered = this.ref['constructor']?.[Symbol.metadata]?.[-2];
|
|
355
|
+
// TODO: support "partially filtered", where the instance is visible, but only a field is not.
|
|
356
|
+
// Detect if parent has "filters" declared
|
|
357
|
+
while (parent && !this.isFiltered) {
|
|
358
|
+
const metadata = parent['constructor'][Symbol.metadata];
|
|
359
|
+
const fieldName = metadata?.[parentIndex];
|
|
360
|
+
const isParentOwned = metadata?.[fieldName]?.tag !== undefined;
|
|
361
|
+
this.isFiltered = isParentOwned || parent[symbols_1.$changes].isFiltered; // metadata?.[-2]
|
|
362
|
+
parent = parent[symbols_1.$changes].parent;
|
|
363
|
+
}
|
|
364
|
+
;
|
|
365
|
+
//
|
|
366
|
+
// TODO: refactor this!
|
|
367
|
+
//
|
|
368
|
+
// swapping `changes` and `filteredChanges` is required here
|
|
369
|
+
// because "isFiltered" may not be imedialely available on `change()`
|
|
370
|
+
//
|
|
371
|
+
if (this.isFiltered && this.changes.size > 0) {
|
|
372
|
+
// swap changes reference
|
|
373
|
+
const changes = this.changes;
|
|
374
|
+
this.changes = this.filteredChanges;
|
|
375
|
+
this.filteredChanges = changes;
|
|
376
|
+
// swap "all changes" reference
|
|
377
|
+
const allFilteredChanges = this.allFilteredChanges;
|
|
378
|
+
this.allFilteredChanges = this.allChanges;
|
|
379
|
+
this.allChanges = allFilteredChanges;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
exports.ChangeTree = ChangeTree;
|
|
384
|
+
//# sourceMappingURL=ChangeTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChangeTree.js","sourceRoot":"","sources":["../../src/encoder/ChangeTree.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { Schema } from \"../Schema\";\nimport { $changes, $childType, $decoder, $onEncodeEnd, $encoder, $getByIndex, $isNew } from \"../types/symbols\";\n\nimport type { MapSchema } from \"../types/custom/MapSchema\";\nimport type { ArraySchema } from \"../types/custom/ArraySchema\";\nimport type { CollectionSchema } from \"../types/custom/CollectionSchema\";\nimport type { SetSchema } from \"../types/custom/SetSchema\";\n\nimport { Metadata } from \"../Metadata\";\nimport type { EncodeOperation } from \"./EncodeOperation\";\nimport type { DecodeOperation } from \"../decoder/DecodeOperation\";\nimport type { StateView } from \"./StateView\";\n\ndeclare global {\n interface Object {\n // FIXME: not a good practice to extend globals here\n [$changes]?: ChangeTree;\n [$encoder]?: EncodeOperation,\n [$decoder]?: DecodeOperation,\n }\n}\n\nexport type Ref = Schema\n | ArraySchema\n | MapSchema\n | CollectionSchema\n | SetSchema;\n\nexport class Root {\n protected nextUniqueId: number = 0;\n refCount = new WeakMap<ChangeTree, number>();\n\n // all changes\n allChanges = new Map<ChangeTree, Map<number, OPERATION>>();\n allFilteredChanges = new Map<ChangeTree, Map<number, OPERATION>>();\n\n // pending changes to be encoded\n changes = new Map<ChangeTree, Map<number, OPERATION>>();\n filteredChanges = new Map<ChangeTree, Map<number, OPERATION>>();\n\n views: StateView[] = [];\n\n getNextUniqueId() {\n return this.nextUniqueId++;\n }\n\n add (changeTree: ChangeTree) {\n const refCount = this.refCount.get(changeTree) || 0;\n this.refCount.set(changeTree, refCount + 1);\n }\n\n remove(changeTree: ChangeTree) {\n const refCount = this.refCount.get(changeTree);\n if (refCount <= 1) {\n this.allChanges.delete(changeTree);\n this.changes.delete(changeTree);\n\n if (changeTree.isFiltered || changeTree.isPartiallyFiltered) {\n this.allFilteredChanges.delete(changeTree);\n this.filteredChanges.delete(changeTree);\n }\n\n this.refCount.delete(changeTree);\n\n } else {\n this.refCount.set(changeTree, refCount - 1);\n }\n\n changeTree.forEachChild((child, _) =>\n this.remove(child));\n }\n\n clear() {\n this.changes.clear();\n }\n}\n\nexport class ChangeTree<T extends Ref=any> {\n ref: T;\n refId: number;\n\n root?: Root;\n\n isFiltered?: boolean;\n isPartiallyFiltered?: boolean;\n\n parent?: Ref;\n parentIndex?: number;\n\n indexes: {[index: string]: any} = {}; // TODO: remove this, only used by MapSchema/SetSchema/CollectionSchema (`encodeKeyValueOperation`)\n currentOperationIndex: number = 0;\n\n allChanges = new Map<number, OPERATION>();\n allFilteredChanges = new Map<number, OPERATION>();\n\n changes = new Map<number, OPERATION>();\n filteredChanges = new Map<number, OPERATION>();;\n\n [$isNew] = true;\n\n constructor(ref: T) {\n this.ref = ref;\n }\n\n setRoot(root: Root) {\n this.root = root;\n this.root.add(this);\n\n //\n // At Schema initialization, the \"root\" structure might not be available\n // yet, as it only does once the \"Encoder\" has been set up.\n //\n // So the \"parent\" may be already set without a \"root\".\n //\n this.checkIsFiltered(this.parent, this.parentIndex);\n\n // unique refId for the ChangeTree.\n this.ensureRefId();\n\n if (!this.isFiltered) {\n this.root.changes.set(this, this.changes);\n }\n\n if (this.isFiltered || this.isPartiallyFiltered) {\n this.root.allFilteredChanges.set(this, this.allFilteredChanges);\n this.root.filteredChanges.set(this, this.filteredChanges);\n\n // } else {\n // this.root.allChanges.set(this, this.allChanges);\n }\n\n if (!this.isFiltered) {\n this.root.allChanges.set(this, this.allChanges);\n }\n\n this.forEachChild((changeTree, _) => {\n changeTree.setRoot(root);\n });\n\n // this.allChanges.forEach((_, index) => {\n // const childRef = this.ref[$getByIndex](index);\n // if (childRef && childRef[$changes]) {\n // childRef[$changes].setRoot(root);\n // }\n // });\n }\n\n setParent(\n parent: Ref,\n root?: Root,\n parentIndex?: number,\n ) {\n this.parent = parent;\n this.parentIndex = parentIndex;\n\n // avoid setting parents with empty `root`\n if (!root) { return; }\n\n root.add(this);\n\n // skip if parent is already set\n if (root === this.root) {\n this.forEachChild((changeTree, atIndex) => {\n changeTree.setParent(this.ref, root, atIndex);\n });\n return;\n }\n\n this.root = root;\n this.checkIsFiltered(parent, parentIndex);\n\n if (!this.isFiltered) {\n this.root.changes.set(this, this.changes);\n }\n\n if (this.isFiltered || this.isPartiallyFiltered) {\n this.root.filteredChanges.set(this, this.filteredChanges);\n this.root.allFilteredChanges.set(this, this.filteredChanges);\n } else {\n this.root.allChanges.set(this, this.allChanges);\n }\n\n this.ensureRefId();\n\n this.forEachChild((changeTree, atIndex) => {\n changeTree.setParent(this.ref, root, atIndex);\n });\n }\n\n forEachChild(callback: (change: ChangeTree, atIndex: number) => void) {\n //\n // assign same parent on child structures\n //\n if (Metadata.isValidInstance(this.ref)) {\n const metadata: Metadata = this.ref['constructor'][Symbol.metadata];\n\n // FIXME: need to iterate over parent metadata instead.\n for (const field in metadata) {\n const value = this.ref[field];\n\n if (value && value[$changes]) {\n callback(value[$changes], metadata[field].index);\n }\n }\n\n } else if (typeof (this.ref) === \"object\") {\n // MapSchema / ArraySchema, etc.\n (this.ref as MapSchema).forEach((value, key) => {\n if (Metadata.isValidInstance(value)) {\n callback(value[$changes], this.ref[$changes].indexes[key]);\n }\n });\n }\n }\n\n operation(op: OPERATION) {\n this.changes.set(--this.currentOperationIndex, op);\n this.root?.changes.set(this, this.changes);\n }\n\n change(index: number, operation: OPERATION = OPERATION.ADD) {\n const metadata = this.ref['constructor'][Symbol.metadata] as Metadata;\n\n const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);\n const changeSet = (isFiltered)\n ? this.filteredChanges\n : this.changes;\n\n const previousOperation = changeSet.get(index);\n if (!previousOperation || previousOperation === OPERATION.DELETE) {\n const op = (!previousOperation)\n ? operation\n : (previousOperation === OPERATION.DELETE)\n ? OPERATION.DELETE_AND_ADD\n : operation\n changeSet.set(index, op);\n }\n\n //\n // TODO: are DELETE operations being encoded as ADD here ??\n //\n\n if (isFiltered) {\n this.allFilteredChanges.set(index, OPERATION.ADD);\n this.root?.filteredChanges.set(this, this.filteredChanges);\n\n } else {\n this.allChanges.set(index, OPERATION.ADD);\n this.root?.changes.set(this, this.changes);\n }\n }\n\n shiftChangeIndexes(shiftIndex: number) {\n //\n // Used only during:\n //\n // - ArraySchema#unshift()\n //\n const changeSet = (this.isFiltered)\n ? this.filteredChanges\n : this.changes;\n\n const changeSetEntries = Array.from(changeSet.entries());\n changeSet.clear();\n\n // Re-insert each entry with the shifted index\n for (const [index, op] of changeSetEntries) {\n changeSet.set(index + shiftIndex, op);\n }\n }\n\n shiftAllChangeIndexes(shiftIndex: number, startIndex: number = 0) {\n //\n // Used only during:\n //\n // - ArraySchema#splice()\n //\n if (this.isFiltered || this.isPartiallyFiltered) {\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allFilteredChanges);\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);\n\n } else {\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);\n }\n }\n\n private _shiftAllChangeIndexes(shiftIndex: number, startIndex: number = 0, allChangeSet: Map<number, OPERATION>) {\n Array.from(allChangeSet.entries()).forEach(([index, op]) => {\n // console.log('shiftAllChangeIndexes', index >= startIndex, { index, op, shiftIndex, startIndex })\n if (index >= startIndex) {\n allChangeSet.delete(index);\n allChangeSet.set(index + shiftIndex, op);\n }\n });\n }\n\n indexedOperation(index: number, operation: OPERATION, allChangesIndex = index) {\n const metadata = this.ref['constructor'][Symbol.metadata] as Metadata;\n const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);\n\n if (isFiltered) {\n this.allFilteredChanges.set(allChangesIndex, OPERATION.ADD);\n this.filteredChanges.set(index, operation);\n this.root?.filteredChanges.set(this, this.filteredChanges);\n\n } else {\n this.allChanges.set(allChangesIndex, OPERATION.ADD);\n this.changes.set(index, operation);\n this.root?.changes.set(this, this.changes);\n }\n }\n\n getType(index?: number) {\n if (Metadata.isValidInstance(this.ref)) {\n const metadata = this.ref['constructor'][Symbol.metadata] as Metadata;\n return metadata[metadata[index]].type;\n\n } else {\n //\n // Get the child type from parent structure.\n // - [\"string\"] => \"string\"\n // - { map: \"string\" } => \"string\"\n // - { set: \"string\" } => \"string\"\n //\n return this.ref[$childType];\n }\n }\n\n getChange(index: number) {\n // TODO: optimize this. avoid checking against multiple instances\n return this.changes.get(index) ?? this.filteredChanges.get(index);\n }\n\n //\n // used during `.encode()`\n //\n getValue(index: number, isEncodeAll: boolean = false) {\n //\n // `isEncodeAll` param is only used by ArraySchema\n //\n return this.ref[$getByIndex](index, isEncodeAll);\n }\n\n delete(index: number, operation?: OPERATION, allChangesIndex = index) {\n if (index === undefined) {\n try {\n throw new Error(`@colyseus/schema ${this.ref.constructor.name}: trying to delete non-existing index '${index}'`);\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n const metadata = this.ref['constructor'][Symbol.metadata] as Metadata;\n const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);\n const changeSet = (isFiltered)\n ? this.filteredChanges\n : this.changes;\n\n const previousValue = this.getValue(index);\n\n changeSet.set(index, operation ?? OPERATION.DELETE);\n\n // remove `root` reference\n if (previousValue && previousValue[$changes]) {\n previousValue[$changes].root = undefined;\n\n //\n // FIXME: this.root is \"undefined\"\n //\n // This method is being called at decoding time when a DELETE operation is found.\n //\n // - This is due to using the concrete Schema class at decoding time.\n // - \"Reflected\" structures do not have this problem.\n //\n // (the property descriptors should NOT be used at decoding time. only at encoding time.)\n //\n this.root?.remove(previousValue[$changes]);\n }\n\n //\n // FIXME: this is looking a bit ugly (and repeated from `.change()`)\n //\n if (isFiltered) {\n this.root?.filteredChanges.set(this, this.filteredChanges);\n this.allFilteredChanges.delete(allChangesIndex);\n\n } else {\n this.root?.changes.set(this, this.changes);\n this.allChanges.delete(allChangesIndex);\n }\n }\n\n endEncode() {\n this.changes.clear();\n this.ref[$onEncodeEnd]?.();\n\n // Not a new instance anymore\n delete this[$isNew];\n }\n\n discard(discardAll: boolean = false) {\n //\n // > MapSchema:\n // Remove cached key to ensure ADD operations is unsed instead of\n // REPLACE in case same key is used on next patches.\n //\n this.ref[$onEncodeEnd]?.();\n\n this.changes.clear();\n this.filteredChanges.clear();\n\n // reset operation index\n this.currentOperationIndex = 0;\n\n if (discardAll) {\n this.allChanges.clear();\n this.allFilteredChanges.clear();\n\n // remove children references\n this.forEachChild((changeTree, _) =>\n this.root?.remove(changeTree));\n }\n }\n\n /**\n * Recursively discard all changes from this, and child structures.\n */\n discardAll() {\n this.changes.forEach((_, fieldIndex) => {\n const value = this.getValue(fieldIndex);\n\n if (value && value[$changes]) {\n value[$changes].discardAll();\n }\n });\n\n this.discard();\n }\n\n ensureRefId() {\n // skip if refId is already set.\n if (this.refId !== undefined) {\n return;\n }\n\n this.refId = this.root.getNextUniqueId();\n }\n\n get changed() {\n return this.changes.size > 0;\n }\n\n protected checkIsFiltered(parent: Ref, parentIndex: number) {\n // Detect if current structure has \"filters\" declared\n this.isPartiallyFiltered = this.ref['constructor']?.[Symbol.metadata]?.[-2];\n\n // TODO: support \"partially filtered\", where the instance is visible, but only a field is not.\n\n // Detect if parent has \"filters\" declared\n while (parent && !this.isFiltered) {\n const metadata: Metadata = parent['constructor'][Symbol.metadata];\n\n const fieldName = metadata?.[parentIndex];\n const isParentOwned = metadata?.[fieldName]?.tag !== undefined;\n\n this.isFiltered = isParentOwned || parent[$changes].isFiltered; // metadata?.[-2]\n\n parent = parent[$changes].parent;\n };\n\n //\n // TODO: refactor this!\n //\n // swapping `changes` and `filteredChanges` is required here\n // because \"isFiltered\" may not be imedialely available on `change()`\n //\n if (this.isFiltered && this.changes.size > 0) {\n // swap changes reference\n const changes = this.changes;\n this.changes = this.filteredChanges;\n this.filteredChanges = changes;\n\n // swap \"all changes\" reference\n const allFilteredChanges = this.allFilteredChanges;\n this.allFilteredChanges = this.allChanges;\n this.allChanges = allFilteredChanges;\n }\n }\n\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { OPERATION } from "../encoding/spec";
|
|
3
|
+
import type { ChangeTree, Ref } from "./ChangeTree";
|
|
4
|
+
import type { Encoder } from "./Encoder";
|
|
5
|
+
import type { Schema } from "../Schema";
|
|
6
|
+
import type { PrimitiveType } from "../annotations";
|
|
7
|
+
import type { Iterator } from "../encoding/decode";
|
|
8
|
+
export type EncodeOperation<T extends Ref = any> = (encoder: Encoder, bytes: Buffer, changeTree: ChangeTree<T>, index: number, operation: OPERATION, it: Iterator, isEncodeAll: boolean, hasView: boolean) => void;
|
|
9
|
+
export declare function encodePrimitiveType(type: PrimitiveType, bytes: Buffer, value: any, klass: Schema, field: string | number, it: Iterator): void;
|
|
10
|
+
export declare function encodeValue(encoder: Encoder, bytes: Buffer, ref: Ref, type: any, value: any, field: string | number, operation: OPERATION, it: Iterator): void;
|
|
11
|
+
/**
|
|
12
|
+
* Used for Schema instances.
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
export declare const encodeSchemaOperation: EncodeOperation;
|
|
16
|
+
/**
|
|
17
|
+
* Used for collections (MapSchema, CollectionSchema, SetSchema)
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
export declare const encodeKeyValueOperation: EncodeOperation;
|
|
21
|
+
/**
|
|
22
|
+
* Used for collections (MapSchema, ArraySchema, etc.)
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
export declare const encodeArray: EncodeOperation;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.encodeArray = exports.encodeKeyValueOperation = exports.encodeSchemaOperation = exports.encodeValue = exports.encodePrimitiveType = void 0;
|
|
4
|
+
const spec_1 = require("../encoding/spec");
|
|
5
|
+
const symbols_1 = require("../types/symbols");
|
|
6
|
+
const registry_1 = require("../types/registry");
|
|
7
|
+
const encode = require("../encoding/encode");
|
|
8
|
+
const assert_1 = require("../encoding/assert");
|
|
9
|
+
function encodePrimitiveType(type, bytes, value, klass, field, it) {
|
|
10
|
+
(0, assert_1.assertType)(value, type, klass, field);
|
|
11
|
+
const encodeFunc = encode[type];
|
|
12
|
+
if (encodeFunc) {
|
|
13
|
+
encodeFunc(bytes, value, it);
|
|
14
|
+
// encodeFunc(bytes, value);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
throw new assert_1.EncodeSchemaError(`a '${type}' was expected, but ${value} was provided in ${klass.constructor.name}#${field}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.encodePrimitiveType = encodePrimitiveType;
|
|
21
|
+
;
|
|
22
|
+
function encodeValue(encoder, bytes, ref, type, value, field, operation, it) {
|
|
23
|
+
if (type[Symbol.metadata] !== undefined) {
|
|
24
|
+
// TODO: move this to the `@type()` annotation
|
|
25
|
+
(0, assert_1.assertInstanceType)(value, type, ref, field);
|
|
26
|
+
//
|
|
27
|
+
// Encode refId for this instance.
|
|
28
|
+
// The actual instance is going to be encoded on next `changeTree` iteration.
|
|
29
|
+
//
|
|
30
|
+
encode.number(bytes, value[symbols_1.$changes].refId, it);
|
|
31
|
+
// Try to encode inherited TYPE_ID if it's an ADD operation.
|
|
32
|
+
if ((operation & spec_1.OPERATION.ADD) === spec_1.OPERATION.ADD) {
|
|
33
|
+
encoder.tryEncodeTypeId(bytes, type, value.constructor, it);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else if (typeof (type) === "string") {
|
|
37
|
+
//
|
|
38
|
+
// Primitive values
|
|
39
|
+
//
|
|
40
|
+
encodePrimitiveType(type, bytes, value, ref, field, it);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
//
|
|
44
|
+
// Custom type (MapSchema, ArraySchema, etc)
|
|
45
|
+
//
|
|
46
|
+
const definition = (0, registry_1.getType)(Object.keys(type)[0]);
|
|
47
|
+
//
|
|
48
|
+
// ensure a ArraySchema has been provided
|
|
49
|
+
//
|
|
50
|
+
(0, assert_1.assertInstanceType)(ref[field], definition.constructor, ref, field);
|
|
51
|
+
//
|
|
52
|
+
// Encode refId for this instance.
|
|
53
|
+
// The actual instance is going to be encoded on next `changeTree` iteration.
|
|
54
|
+
//
|
|
55
|
+
encode.number(bytes, value[symbols_1.$changes].refId, it);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.encodeValue = encodeValue;
|
|
59
|
+
/**
|
|
60
|
+
* Used for Schema instances.
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
const encodeSchemaOperation = function (encoder, bytes, changeTree, index, operation, it) {
|
|
64
|
+
const ref = changeTree.ref;
|
|
65
|
+
const metadata = ref['constructor'][Symbol.metadata];
|
|
66
|
+
const field = metadata[index];
|
|
67
|
+
const type = metadata[field].type;
|
|
68
|
+
const value = ref[field];
|
|
69
|
+
// "compress" field index + operation
|
|
70
|
+
bytes[it.offset++] = (index | operation) & 255;
|
|
71
|
+
// Do not encode value for DELETE operations
|
|
72
|
+
if (operation === spec_1.OPERATION.DELETE) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// TODO: inline this function call small performance gain
|
|
76
|
+
encodeValue(encoder, bytes, ref, type, value, field, operation, it);
|
|
77
|
+
};
|
|
78
|
+
exports.encodeSchemaOperation = encodeSchemaOperation;
|
|
79
|
+
/**
|
|
80
|
+
* Used for collections (MapSchema, CollectionSchema, SetSchema)
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
const encodeKeyValueOperation = function (encoder, bytes, changeTree, field, operation, it) {
|
|
84
|
+
const ref = changeTree.ref;
|
|
85
|
+
// encode operation
|
|
86
|
+
bytes[it.offset++] = operation & 255;
|
|
87
|
+
// custom operations
|
|
88
|
+
if (operation === spec_1.OPERATION.CLEAR) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// encode index
|
|
92
|
+
encode.number(bytes, field, it);
|
|
93
|
+
// Do not encode value for DELETE operations
|
|
94
|
+
if (operation === spec_1.OPERATION.DELETE) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
//
|
|
98
|
+
// encode "alias" for dynamic fields (maps)
|
|
99
|
+
//
|
|
100
|
+
if ((operation & spec_1.OPERATION.ADD) == spec_1.OPERATION.ADD) { // ADD or DELETE_AND_ADD
|
|
101
|
+
if (typeof (ref['set']) === "function") {
|
|
102
|
+
//
|
|
103
|
+
// MapSchema dynamic key
|
|
104
|
+
//
|
|
105
|
+
const dynamicIndex = changeTree.ref['$indexes'].get(field);
|
|
106
|
+
encode.string(bytes, dynamicIndex, it);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const type = changeTree.getType(field);
|
|
110
|
+
const value = changeTree.getValue(field);
|
|
111
|
+
// TODO: inline this function call small performance gain
|
|
112
|
+
encodeValue(encoder, bytes, ref, type, value, field, operation, it);
|
|
113
|
+
};
|
|
114
|
+
exports.encodeKeyValueOperation = encodeKeyValueOperation;
|
|
115
|
+
/**
|
|
116
|
+
* Used for collections (MapSchema, ArraySchema, etc.)
|
|
117
|
+
* @private
|
|
118
|
+
*/
|
|
119
|
+
const encodeArray = function (encoder, bytes, changeTree, field, operation, it, isEncodeAll, hasView) {
|
|
120
|
+
const ref = changeTree.ref;
|
|
121
|
+
if (hasView &&
|
|
122
|
+
operation === spec_1.OPERATION.DELETE &&
|
|
123
|
+
typeof (changeTree.getType(field)) !== "string") {
|
|
124
|
+
// encode delete by refId (array of schemas)
|
|
125
|
+
bytes[it.offset++] = spec_1.OPERATION.DELETE_BY_REFID;
|
|
126
|
+
const value = ref['tmpItems'][field];
|
|
127
|
+
const refId = value[symbols_1.$changes].refId;
|
|
128
|
+
encode.number(bytes, refId, it);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// encode operation
|
|
132
|
+
bytes[it.offset++] = operation & 255;
|
|
133
|
+
// custom operations
|
|
134
|
+
if (operation === spec_1.OPERATION.CLEAR) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// encode index
|
|
138
|
+
encode.number(bytes, field, it);
|
|
139
|
+
// Do not encode value for DELETE operations
|
|
140
|
+
if (operation === spec_1.OPERATION.DELETE) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const type = changeTree.getType(field);
|
|
144
|
+
const value = changeTree.getValue(field, isEncodeAll);
|
|
145
|
+
// console.log("encodeArray -> ", {
|
|
146
|
+
// ref: changeTree.ref.constructor.name,
|
|
147
|
+
// field,
|
|
148
|
+
// operation: OPERATION[operation],
|
|
149
|
+
// value: value?.toJSON(),
|
|
150
|
+
// items: ref.toJSON(),
|
|
151
|
+
// });
|
|
152
|
+
// TODO: inline this function call small performance gain
|
|
153
|
+
encodeValue(encoder, bytes, ref, type, value, field, operation, it);
|
|
154
|
+
};
|
|
155
|
+
exports.encodeArray = encodeArray;
|
|
156
|
+
//# sourceMappingURL=EncodeOperation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncodeOperation.js","sourceRoot":"","sources":["../../src/encoder/EncodeOperation.ts"],"names":[],"mappings":";;;AAAA,2CAA6C;AAC7C,8CAA4C;AAC5C,gDAA4C;AAE5C,6CAA6C;AAC7C,+CAAuF;AAqBvF,SAAgB,mBAAmB,CAC/B,IAAmB,EACnB,KAAa,EACb,KAAU,EACV,KAAa,EACb,KAAsB,EACtB,EAAY;IAEZ,IAAA,mBAAU,EAAC,KAAK,EAAE,IAAc,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEhD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAc,CAAC,CAAC;IAE1C,IAAI,UAAU,EAAE,CAAC;QACb,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7B,4BAA4B;IAEhC,CAAC;SAAM,CAAC;QACJ,MAAM,IAAI,0BAAiB,CAAC,MAAM,IAAI,uBAAuB,KAAK,oBAAoB,KAAK,CAAC,WAAW,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;IAC7H,CAAC;AACL,CAAC;AAnBD,kDAmBC;AAAA,CAAC;AAEF,SAAgB,WAAW,CACvB,OAAgB,EAChB,KAAa,EACb,GAAQ,EACR,IAAS,EACT,KAAU,EACV,KAAsB,EACtB,SAAoB,EACpB,EAAY;IAEZ,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;QACtC,8CAA8C;QAC9C,IAAA,2BAAkB,EAAC,KAAK,EAAE,IAAqB,EAAE,GAAa,EAAE,KAAK,CAAC,CAAC;QAEvE,EAAE;QACF,kCAAkC;QAClC,6EAA6E;QAC7E,EAAE;QACF,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,kBAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAEhD,4DAA4D;QAC5D,IAAI,CAAC,SAAS,GAAG,gBAAS,CAAC,GAAG,CAAC,KAAK,gBAAS,CAAC,GAAG,EAAE,CAAC;YAChD,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE,IAAqB,EAAE,KAAK,CAAC,WAA4B,EAAE,EAAE,CAAC,CAAC;QAClG,CAAC;IAEL,CAAC;SAAM,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QACpC,EAAE;QACF,mBAAmB;QACnB,EAAE;QACF,mBAAmB,CAAC,IAAqB,EAAE,KAAK,EAAE,KAAK,EAAE,GAAa,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IAEvF,CAAC;SAAM,CAAC;QACJ,EAAE;QACF,4CAA4C;QAC5C,EAAE;QACF,MAAM,UAAU,GAAG,IAAA,kBAAO,EAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjD,EAAE;QACF,yCAAyC;QACzC,EAAE;QACF,IAAA,2BAAkB,EAAC,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,WAAW,EAAE,GAAa,EAAE,KAAK,CAAC,CAAC;QAE7E,EAAE;QACF,kCAAkC;QAClC,6EAA6E;QAC7E,EAAE;QACF,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,kBAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpD,CAAC;AACL,CAAC;AAhDD,kCAgDC;AAED;;;GAGG;AACI,MAAM,qBAAqB,GAAoB,UAClD,OAAgB,EAChB,KAAa,EACb,UAA8B,EAC9B,KAAa,EACb,SAAoB,EACpB,EAAY;IAEZ,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC;IAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAErD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;IAClC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IAEzB,qCAAqC;IACrC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC;IAE/C,4CAA4C;IAC5C,IAAI,SAAS,KAAK,gBAAS,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO;IACX,CAAC;IAED,yDAAyD;IACzD,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC,CAAA;AAzBY,QAAA,qBAAqB,yBAyBjC;AAED;;;GAGG;AACI,MAAM,uBAAuB,GAAoB,UACpD,OAAgB,EAChB,KAAa,EACb,UAAsB,EACtB,KAAa,EACb,SAAoB,EACpB,EAAY;IAEZ,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC;IAE3B,mBAAmB;IACnB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC;IAErC,oBAAoB;IACpB,IAAI,SAAS,KAAK,gBAAS,CAAC,KAAK,EAAE,CAAC;QAChC,OAAO;IACX,CAAC;IAED,eAAe;IACf,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IAEhC,4CAA4C;IAC5C,IAAI,SAAS,KAAK,gBAAS,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO;IACX,CAAC;IAED,EAAE;IACF,2CAA2C;IAC3C,EAAE;IACF,IAAI,CAAC,SAAS,GAAG,gBAAS,CAAC,GAAG,CAAC,IAAI,gBAAS,CAAC,GAAG,EAAE,CAAC,CAAC,wBAAwB;QACxE,IAAI,OAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;YACpC,EAAE;YACF,wBAAwB;YACxB,EAAE;YACF,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEzC,yDAAyD;IACzD,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC,CAAA;AA5CY,QAAA,uBAAuB,2BA4CnC;AAED;;;GAGG;AACI,MAAM,WAAW,GAAoB,UACxC,OAAgB,EAChB,KAAa,EACb,UAAmC,EACnC,KAAa,EACb,SAAoB,EACpB,EAAY,EACZ,WAAoB,EACpB,OAAgB;IAEhB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC;IAE3B,IACI,OAAO;QACP,SAAS,KAAK,gBAAS,CAAC,MAAM;QAC9B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,QAAQ,EACjD,CAAC;QACC,4CAA4C;QAC5C,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,gBAAS,CAAC,eAAe,CAAC;QAC/C,MAAM,KAAK,GAAI,GAAG,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,kBAAQ,CAAC,CAAC,KAAK,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAChC,OAAO;IACX,CAAC;IAED,mBAAmB;IACnB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC;IAErC,oBAAoB;IACpB,IAAI,SAAS,KAAK,gBAAS,CAAC,KAAK,EAAE,CAAC;QAChC,OAAO;IACX,CAAC;IAED,eAAe;IACf,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IAEhC,4CAA4C;IAC5C,IAAI,SAAS,KAAK,gBAAS,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO;IACX,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAEtD,mCAAmC;IACnC,4CAA4C;IAC5C,aAAa;IACb,uCAAuC;IACvC,8BAA8B;IAC9B,2BAA2B;IAC3B,MAAM;IAEN,yDAAyD;IACzD,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC,CAAA;AAtDY,QAAA,WAAW,eAsDvB","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { $changes } from \"../types/symbols\";\nimport { getType } from \"../types/registry\";\n\nimport * as encode from \"../encoding/encode\";\nimport { EncodeSchemaError, assertInstanceType, assertType } from \"../encoding/assert\";\n\nimport type { ChangeTree, Ref } from \"./ChangeTree\";\nimport type { Encoder } from \"./Encoder\";\nimport type { Schema } from \"../Schema\";\nimport type { PrimitiveType } from \"../annotations\";\n\nimport type { Iterator } from \"../encoding/decode\";\nimport type { ArraySchema } from \"../types/custom/ArraySchema\";\n\nexport type EncodeOperation<T extends Ref = any> = (\n encoder: Encoder,\n bytes: Buffer,\n changeTree: ChangeTree<T>,\n index: number,\n operation: OPERATION,\n it: Iterator,\n isEncodeAll: boolean,\n hasView: boolean,\n) => void;\n\nexport function encodePrimitiveType(\n type: PrimitiveType,\n bytes: Buffer,\n value: any,\n klass: Schema,\n field: string | number,\n it: Iterator,\n) {\n assertType(value, type as string, klass, field);\n\n const encodeFunc = encode[type as string];\n\n if (encodeFunc) {\n encodeFunc(bytes, value, it);\n // encodeFunc(bytes, value);\n\n } else {\n throw new EncodeSchemaError(`a '${type}' was expected, but ${value} was provided in ${klass.constructor.name}#${field}`);\n }\n};\n\nexport function encodeValue(\n encoder: Encoder,\n bytes: Buffer,\n ref: Ref,\n type: any,\n value: any,\n field: string | number,\n operation: OPERATION,\n it: Iterator,\n) {\n if (type[Symbol.metadata] !== undefined) {\n // TODO: move this to the `@type()` annotation\n assertInstanceType(value, type as typeof Schema, ref as Schema, field);\n\n //\n // Encode refId for this instance.\n // The actual instance is going to be encoded on next `changeTree` iteration.\n //\n encode.number(bytes, value[$changes].refId, it);\n\n // Try to encode inherited TYPE_ID if it's an ADD operation.\n if ((operation & OPERATION.ADD) === OPERATION.ADD) {\n encoder.tryEncodeTypeId(bytes, type as typeof Schema, value.constructor as typeof Schema, it);\n }\n\n } else if (typeof (type) === \"string\") {\n //\n // Primitive values\n //\n encodePrimitiveType(type as PrimitiveType, bytes, value, ref as Schema, field, it);\n\n } else {\n //\n // Custom type (MapSchema, ArraySchema, etc)\n //\n const definition = getType(Object.keys(type)[0]);\n\n //\n // ensure a ArraySchema has been provided\n //\n assertInstanceType(ref[field], definition.constructor, ref as Schema, field);\n\n //\n // Encode refId for this instance.\n // The actual instance is going to be encoded on next `changeTree` iteration.\n //\n encode.number(bytes, value[$changes].refId, it);\n }\n}\n\n/**\n * Used for Schema instances.\n * @private\n */\nexport const encodeSchemaOperation: EncodeOperation = function (\n encoder: Encoder,\n bytes: Buffer,\n changeTree: ChangeTree<Schema>,\n index: number,\n operation: OPERATION,\n it: Iterator,\n) {\n const ref = changeTree.ref;\n const metadata = ref['constructor'][Symbol.metadata];\n\n const field = metadata[index];\n const type = metadata[field].type;\n const value = ref[field];\n\n // \"compress\" field index + operation\n bytes[it.offset++] = (index | operation) & 255;\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE) {\n return;\n }\n\n // TODO: inline this function call small performance gain\n encodeValue(encoder, bytes, ref, type, value, field, operation, it);\n}\n\n/**\n * Used for collections (MapSchema, CollectionSchema, SetSchema)\n * @private\n */\nexport const encodeKeyValueOperation: EncodeOperation = function (\n encoder: Encoder,\n bytes: Buffer,\n changeTree: ChangeTree,\n field: number,\n operation: OPERATION,\n it: Iterator,\n) {\n const ref = changeTree.ref;\n\n // encode operation\n bytes[it.offset++] = operation & 255;\n\n // custom operations\n if (operation === OPERATION.CLEAR) {\n return;\n }\n\n // encode index\n encode.number(bytes, field, it);\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE) {\n return;\n }\n\n //\n // encode \"alias\" for dynamic fields (maps)\n //\n if ((operation & OPERATION.ADD) == OPERATION.ADD) { // ADD or DELETE_AND_ADD\n if (typeof(ref['set']) === \"function\") {\n //\n // MapSchema dynamic key\n //\n const dynamicIndex = changeTree.ref['$indexes'].get(field);\n encode.string(bytes, dynamicIndex, it);\n }\n }\n\n const type = changeTree.getType(field);\n const value = changeTree.getValue(field);\n\n // TODO: inline this function call small performance gain\n encodeValue(encoder, bytes, ref, type, value, field, operation, it);\n}\n\n/**\n * Used for collections (MapSchema, ArraySchema, etc.)\n * @private\n */\nexport const encodeArray: EncodeOperation = function (\n encoder: Encoder,\n bytes: Buffer,\n changeTree: ChangeTree<ArraySchema>,\n field: number,\n operation: OPERATION,\n it: Iterator,\n isEncodeAll: boolean,\n hasView: boolean,\n) {\n const ref = changeTree.ref;\n\n if (\n hasView &&\n operation === OPERATION.DELETE &&\n typeof (changeTree.getType(field)) !== \"string\"\n ) {\n // encode delete by refId (array of schemas)\n bytes[it.offset++] = OPERATION.DELETE_BY_REFID;\n const value = ref['tmpItems'][field];\n const refId = value[$changes].refId;\n encode.number(bytes, refId, it);\n return;\n }\n\n // encode operation\n bytes[it.offset++] = operation & 255;\n\n // custom operations\n if (operation === OPERATION.CLEAR) {\n return;\n }\n\n // encode index\n encode.number(bytes, field, it);\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE) {\n return;\n }\n\n const type = changeTree.getType(field);\n const value = changeTree.getValue(field, isEncodeAll);\n\n // console.log(\"encodeArray -> \", {\n // ref: changeTree.ref.constructor.name,\n // field,\n // operation: OPERATION[operation],\n // value: value?.toJSON(),\n // items: ref.toJSON(),\n // });\n\n // TODO: inline this function call small performance gain\n encodeValue(encoder, bytes, ref, type, value, field, operation, it);\n}"]}
|