@colyseus/schema 3.0.0-alpha.4 → 3.0.0-alpha.41
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 +2201 -1507
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +2198 -1506
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +2208 -1514
- 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 -32
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +4 -4
- package/lib/Schema.js +44 -50
- 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/bench_encode.d.ts +1 -0
- package/lib/bench_encode.js +130 -0
- package/lib/bench_encode.js.map +1 -0
- 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 +2 -46
- package/lib/codegen/languages/csharp.js.map +1 -1
- package/lib/codegen/languages/haxe.js +1 -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 +1 -2
- 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/debug.d.ts +1 -0
- package/lib/debug.js +51 -0
- package/lib/debug.js.map +1 -0
- package/lib/decoder/DecodeOperation.d.ts +3 -4
- package/lib/decoder/DecodeOperation.js +37 -19
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +6 -7
- package/lib/decoder/Decoder.js +14 -14
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +3 -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 +75 -65
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +27 -21
- package/lib/encoder/ChangeTree.js +246 -186
- 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 +9 -8
- package/lib/encoder/Encoder.js +168 -91
- 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 +70 -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 +35 -20
- package/lib/encoding/decode.js +43 -87
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +36 -17
- package/lib/encoding/encode.js +82 -68
- 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 +23 -0
- package/lib/types/TypeContext.js +111 -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.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +3 -1
- package/lib/types/custom/MapSchema.js +12 -4
- package/lib/types/custom/MapSchema.js.map +1 -1
- 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 +7 -6
- package/src/Metadata.ts +190 -42
- package/src/Reflection.ts +77 -39
- package/src/Schema.ts +59 -64
- package/src/annotations.ts +156 -202
- package/src/bench_encode.ts +108 -0
- package/src/codegen/languages/csharp.ts +1 -47
- package/src/codegen/parser.ts +107 -0
- package/src/codegen/types.ts +1 -0
- package/src/debug.ts +55 -0
- package/src/decoder/DecodeOperation.ts +46 -18
- package/src/decoder/Decoder.ts +17 -15
- package/src/decoder/ReferenceTracker.ts +3 -2
- package/src/decoder/strategy/StateCallbacks.ts +153 -82
- package/src/encoder/ChangeTree.ts +286 -202
- package/src/encoder/EncodeOperation.ts +78 -78
- package/src/encoder/Encoder.ts +202 -97
- package/src/encoder/Root.ts +93 -0
- package/src/encoder/StateView.ts +76 -88
- package/src/encoding/assert.ts +17 -8
- package/src/encoding/decode.ts +62 -97
- package/src/encoding/encode.ts +99 -65
- 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 +133 -0
- package/src/types/custom/ArraySchema.ts +49 -19
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +18 -5
- 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/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,89 @@ 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.isFiltered || changeTree.isPartiallyFiltered)
|
|
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];
|
|
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
|
-
this.
|
|
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 (metadata && metadata[index].tag !== tag) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.add(change.ref, tag, false);
|
|
112
|
+
});
|
|
119
113
|
|
|
120
114
|
return this;
|
|
121
115
|
}
|
|
122
116
|
|
|
123
|
-
protected addParent(changeTree: ChangeTree, tag: number) {
|
|
124
|
-
|
|
125
|
-
|
|
117
|
+
protected addParent(changeTree: ChangeTree, parentIndex: number, tag: number) {
|
|
118
|
+
// view must have all "changeTree" parent tree
|
|
119
|
+
this.items.add(changeTree);
|
|
126
120
|
|
|
127
|
-
|
|
128
|
-
const
|
|
121
|
+
// add parent's parent
|
|
122
|
+
const parentChangeTree = changeTree.parent?.[$changes];
|
|
123
|
+
if (parentChangeTree && (parentChangeTree.isFiltered || parentChangeTree.isPartiallyFiltered)) {
|
|
124
|
+
this.addParent(parentChangeTree, changeTree.parentIndex, tag);
|
|
125
|
+
}
|
|
129
126
|
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
// parent is already available, no need to add it!
|
|
128
|
+
if (!this.invisible.has(changeTree)) {
|
|
132
129
|
return;
|
|
133
130
|
}
|
|
134
131
|
|
|
135
|
-
this.addParent(parentChangeTree, tag);
|
|
136
|
-
|
|
137
132
|
// add parent's tag properties
|
|
138
|
-
if (
|
|
133
|
+
if (changeTree.getChange(parentIndex) !== OPERATION.DELETE) {
|
|
139
134
|
|
|
140
|
-
let
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
this.changes.
|
|
135
|
+
let changes = this.changes[changeTree.refId];
|
|
136
|
+
if (changes === undefined) {
|
|
137
|
+
changes = {};
|
|
138
|
+
this.changes[changeTree.refId] = changes;
|
|
144
139
|
}
|
|
145
140
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// parentChange: (
|
|
150
|
-
// parentChangeTree.getChange(parentIndex) &&
|
|
151
|
-
// OPERATION[parentChangeTree.getChange(parentIndex)]
|
|
152
|
-
// ),
|
|
153
|
-
// })
|
|
141
|
+
if (!this.tags) {
|
|
142
|
+
this.tags = new WeakMap<ChangeTree, Set<number>>();
|
|
143
|
+
}
|
|
154
144
|
|
|
155
|
-
if (!this.tags) { this.tags = new WeakMap<ChangeTree, Set<number>>(); }
|
|
156
145
|
let tags: Set<number>;
|
|
157
|
-
if (!this.tags.has(
|
|
146
|
+
if (!this.tags.has(changeTree)) {
|
|
158
147
|
tags = new Set<number>();
|
|
159
|
-
this.tags.set(
|
|
148
|
+
this.tags.set(changeTree, tags);
|
|
160
149
|
} else {
|
|
161
|
-
tags = this.tags.get(
|
|
150
|
+
tags = this.tags.get(changeTree);
|
|
162
151
|
}
|
|
163
152
|
tags.add(tag);
|
|
164
153
|
|
|
165
|
-
|
|
154
|
+
changes[parentIndex] = OPERATION.ADD;
|
|
166
155
|
}
|
|
167
|
-
|
|
168
156
|
}
|
|
169
157
|
|
|
170
158
|
remove(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {
|
|
@@ -179,10 +167,10 @@ export class StateView {
|
|
|
179
167
|
const ref = changeTree.ref;
|
|
180
168
|
const metadata: Metadata = ref.constructor[Symbol.metadata];
|
|
181
169
|
|
|
182
|
-
let changes = this.changes.
|
|
170
|
+
let changes = this.changes[changeTree.refId];
|
|
183
171
|
if (changes === undefined) {
|
|
184
|
-
changes =
|
|
185
|
-
this.changes.
|
|
172
|
+
changes = {};
|
|
173
|
+
this.changes[changeTree.refId] = changes;
|
|
186
174
|
}
|
|
187
175
|
|
|
188
176
|
if (tag === DEFAULT_VIEW_TAG) {
|
|
@@ -190,25 +178,25 @@ export class StateView {
|
|
|
190
178
|
const parent = changeTree.parent;
|
|
191
179
|
if (!Metadata.isValidInstance(parent)) {
|
|
192
180
|
const parentChangeTree = parent[$changes];
|
|
193
|
-
let changes = this.changes.
|
|
181
|
+
let changes = this.changes[parentChangeTree.refId];
|
|
194
182
|
if (changes === undefined) {
|
|
195
|
-
changes =
|
|
196
|
-
this.changes.
|
|
183
|
+
changes = {};
|
|
184
|
+
this.changes[parentChangeTree.refId] = changes;
|
|
197
185
|
}
|
|
198
186
|
// DELETE / DELETE BY REF ID
|
|
199
|
-
changes
|
|
187
|
+
changes[changeTree.parentIndex] = OPERATION.DELETE;
|
|
200
188
|
|
|
201
189
|
} else {
|
|
202
190
|
// delete all "tagged" properties.
|
|
203
|
-
metadata[
|
|
204
|
-
changes
|
|
191
|
+
metadata[$viewFieldIndexes].forEach((index) =>
|
|
192
|
+
changes[index] = OPERATION.DELETE);
|
|
205
193
|
}
|
|
206
194
|
|
|
207
195
|
|
|
208
196
|
} else {
|
|
209
197
|
// delete only tagged properties
|
|
210
|
-
metadata[
|
|
211
|
-
changes
|
|
198
|
+
metadata[$fieldIndexesByViewTag][tag].forEach((index) =>
|
|
199
|
+
changes[index] = OPERATION.DELETE);
|
|
212
200
|
}
|
|
213
201
|
|
|
214
202
|
// 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,21 @@ export function number (bytes: BufferLike, it: Iterator) {
|
|
|
229
222
|
}
|
|
230
223
|
};
|
|
231
224
|
|
|
232
|
-
export
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export function arrayCheck (bytes: BufferLike, it: Iterator) {
|
|
252
|
-
return bytes[it.offset] < 0xa0;
|
|
253
|
-
|
|
254
|
-
// const prefix = bytes[it.offset] ;
|
|
255
|
-
|
|
256
|
-
// if (prefix < 0xa0) {
|
|
257
|
-
// return prefix;
|
|
258
|
-
|
|
259
|
-
// // array
|
|
260
|
-
// } else if (prefix === 0xdc) {
|
|
261
|
-
// it.offset += 2;
|
|
262
|
-
|
|
263
|
-
// } else if (0xdd) {
|
|
264
|
-
// it.offset += 4;
|
|
265
|
-
// }
|
|
266
|
-
|
|
267
|
-
// return prefix;
|
|
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
|
-
);
|
|
225
|
+
export const decode = {
|
|
226
|
+
utf8Read,
|
|
227
|
+
int8,
|
|
228
|
+
uint8,
|
|
229
|
+
int16,
|
|
230
|
+
uint16,
|
|
231
|
+
int32,
|
|
232
|
+
uint32,
|
|
233
|
+
float32,
|
|
234
|
+
float64,
|
|
235
|
+
int64,
|
|
236
|
+
uint64,
|
|
237
|
+
bigint64,
|
|
238
|
+
biguint64,
|
|
239
|
+
boolean,
|
|
240
|
+
string,
|
|
241
|
+
number,
|
|
277
242
|
}
|