json-as 0.9.28 → 1.0.0-alpha.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/.github/workflows/nodejs.yml +0 -3
- package/.prettierrc.json +4 -1
- package/CHANGELOG +13 -0
- package/LICENSE +1 -1
- package/README.md +22 -7
- package/as-test.config.json +1 -1
- package/asconfig.json +2 -2
- package/assembly/__benches__/misc.bench.ts +17 -31
- package/assembly/__tests__/bool.spec.ts +1 -1
- package/assembly/__tests__/simd/string.spec.ts +32 -0
- package/assembly/__tests__/types.ts +17 -0
- package/assembly/custom/chars.ts +2 -2
- package/assembly/custom/memory.ts +25 -0
- package/assembly/custom/types.ts +1 -0
- package/assembly/custom/util.ts +59 -140
- package/assembly/deserialize/simd/string.ts +103 -0
- package/assembly/deserialize/simple/arbitrary.ts +17 -0
- package/assembly/deserialize/simple/array/arbitrary.ts +113 -0
- package/assembly/deserialize/simple/array/array.ts +18 -0
- package/assembly/deserialize/simple/array/bool.ts +17 -0
- package/assembly/deserialize/simple/array/float.ts +28 -0
- package/assembly/deserialize/simple/array/integer.ts +27 -0
- package/assembly/deserialize/simple/array/map.ts +18 -0
- package/assembly/deserialize/simple/array/object.ts +18 -0
- package/assembly/deserialize/simple/array/string.ts +22 -0
- package/assembly/deserialize/simple/array.ts +48 -0
- package/assembly/deserialize/simple/bool.ts +9 -0
- package/assembly/deserialize/simple/date.ts +11 -0
- package/assembly/deserialize/simple/float.ts +10 -0
- package/assembly/deserialize/simple/integer.ts +5 -0
- package/assembly/deserialize/simple/map.ts +154 -0
- package/assembly/deserialize/simple/object.ts +159 -0
- package/assembly/deserialize/simple/string.ts +48 -0
- package/assembly/globals/tables.ts +417 -0
- package/assembly/index.d.ts +9 -13
- package/assembly/index.ts +282 -158
- package/assembly/serialize/simd/string.ts +176 -0
- package/assembly/serialize/simple/arbitrary.ts +36 -0
- package/assembly/serialize/simple/array.ts +32 -0
- package/assembly/serialize/simple/bool.ts +19 -0
- package/assembly/serialize/simple/date.ts +13 -0
- package/assembly/serialize/simple/float.ts +7 -0
- package/assembly/serialize/simple/integer.ts +7 -0
- package/assembly/serialize/simple/map.ts +43 -0
- package/assembly/serialize/simple/object.ts +7 -0
- package/assembly/serialize/simple/string.ts +48 -0
- package/assembly/test.ts +43 -28
- package/assembly/tsconfig.json +2 -91
- package/assembly/types.ts +0 -0
- package/assembly/util/atoi.ts +35 -0
- package/assembly/util/bytes.ts +12 -0
- package/assembly/util/concat.ts +9 -0
- package/assembly/util/getArrayDepth.ts +17 -0
- package/assembly/util/index.ts +5 -0
- package/assembly/util/isSpace.ts +4 -0
- package/assembly/util/nextPowerOf2.ts +4 -0
- package/assembly/util/ptrToStr.ts +7 -0
- package/assembly/util/snp.ts +69 -0
- package/bench.js +5 -5
- package/modules/bs/index.ts +167 -0
- package/modules/tsconfig.json +8 -0
- package/package.json +42 -47
- package/transform/lib/builder.js +1353 -0
- package/transform/lib/builder.js.map +1 -0
- package/transform/lib/index.js +497 -395
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/index.old.js +404 -0
- package/transform/lib/index.old.js.map +1 -0
- package/transform/lib/linker.js +18 -0
- package/transform/lib/linker.js.map +1 -0
- package/transform/lib/types.js +25 -0
- package/transform/lib/types.js.map +1 -0
- package/transform/lib/util.js +47 -0
- package/transform/lib/util.js.map +1 -0
- package/transform/lib/visitor.js +529 -446
- package/transform/lib/visitor.js.map +1 -0
- package/transform/package.json +1 -34
- package/transform/src/builder.ts +1371 -0
- package/transform/src/index.ts +571 -481
- package/transform/src/linker.ts +21 -0
- package/transform/src/types.ts +27 -0
- package/transform/src/util.ts +56 -0
- package/transform/src/visitor.ts +531 -0
- package/transform/tsconfig.json +3 -1
- package/assembly/__benches__/as-tral.d.ts +0 -1
- package/assembly/custom/bs.ts +0 -211
- package/assembly/deserialize/array/array.ts +0 -31
- package/assembly/deserialize/array/bool.ts +0 -19
- package/assembly/deserialize/array/float.ts +0 -24
- package/assembly/deserialize/array/integer.ts +0 -24
- package/assembly/deserialize/array/map.ts +0 -27
- package/assembly/deserialize/array/object.ts +0 -27
- package/assembly/deserialize/array/string.ts +0 -29
- package/assembly/deserialize/array.ts +0 -46
- package/assembly/deserialize/bool.ts +0 -34
- package/assembly/deserialize/date.ts +0 -19
- package/assembly/deserialize/float.ts +0 -21
- package/assembly/deserialize/integer.ts +0 -16
- package/assembly/deserialize/map.ts +0 -189
- package/assembly/deserialize/object.ts +0 -271
- package/assembly/deserialize/string.ts +0 -164
- package/assembly/serialize/array.ts +0 -51
- package/assembly/serialize/bool.ts +0 -10
- package/assembly/serialize/date.ts +0 -4
- package/assembly/serialize/float.ts +0 -4
- package/assembly/serialize/integer.ts +0 -5
- package/assembly/serialize/map.ts +0 -24
- package/assembly/serialize/object.ts +0 -13
- package/assembly/serialize/string.ts +0 -287
- package/logs/test.log.json +0 -1049
package/transform/src/index.ts
CHANGED
|
@@ -1,424 +1,473 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ClassDeclaration,
|
|
3
|
-
FieldDeclaration,
|
|
4
|
-
IdentifierExpression,
|
|
5
|
-
Parser,
|
|
6
|
-
Source,
|
|
7
|
-
NodeKind,
|
|
8
|
-
Expression,
|
|
9
|
-
CommonFlags,
|
|
10
|
-
StringLiteralExpression,
|
|
11
|
-
IntegerLiteralExpression,
|
|
12
|
-
FloatLiteralExpression,
|
|
13
|
-
NullExpression,
|
|
14
|
-
TrueExpression,
|
|
15
|
-
FalseExpression,
|
|
16
|
-
} from "assemblyscript/dist/assemblyscript.js";
|
|
17
|
-
|
|
18
|
-
import { toString, isStdlib } from "visitor-as/dist/utils.js";
|
|
19
|
-
import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
|
|
1
|
+
import { ClassDeclaration, FieldDeclaration, IdentifierExpression, Parser, Source, NodeKind, Expression, CommonFlags, StringLiteralExpression, IntegerLiteralExpression, FloatLiteralExpression, NullExpression, TrueExpression, FalseExpression, CallExpression, ImportStatement, NamespaceDeclaration, Node, Statement, Tokenizer, SourceKind, PropertyAccessExpression, Token, CommentHandler, ExpressionStatement, BinaryExpression, NamedTypeNode, Range, FEATURE_SIMD, FunctionExpression } from "assemblyscript/dist/assemblyscript.js";
|
|
20
2
|
import { Transform } from "assemblyscript/dist/transform.js";
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
3
|
+
import { Visitor } from "./visitor.js";
|
|
4
|
+
import { SimpleParser, toString } from "./util.js";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import { Property, PropertyFlags, Schema } from "./types.js";
|
|
8
|
+
import { getClasses, getImportedClass } from "./linker.js";
|
|
9
|
+
|
|
10
|
+
let indent = " ";
|
|
11
|
+
|
|
12
|
+
class JSONTransform extends Visitor {
|
|
13
|
+
public parser!: Parser;
|
|
14
|
+
public schemas: Schema[] = [];
|
|
15
|
+
public schema!: Schema;
|
|
25
16
|
public sources = new Set<Source>();
|
|
17
|
+
public imports: ImportStatement[] = [];
|
|
18
|
+
|
|
19
|
+
public jsonImport: string | null = null;
|
|
20
|
+
public bsImport: string | null = null;
|
|
21
|
+
public newStmts: {
|
|
22
|
+
simd: string[];
|
|
23
|
+
} = { simd: [] };
|
|
26
24
|
|
|
27
|
-
visitMethodDeclaration(): void { }
|
|
28
25
|
visitClassDeclaration(node: ClassDeclaration): void {
|
|
29
26
|
if (!node.decorators?.length) return;
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
if (!found) return;
|
|
28
|
+
if (
|
|
29
|
+
!node.decorators.some((decorator) => {
|
|
30
|
+
const name = (<IdentifierExpression>decorator.name).text;
|
|
31
|
+
return name === "json" || name === "serializable";
|
|
32
|
+
})
|
|
33
|
+
)
|
|
34
|
+
return;
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
schema.node = node;
|
|
43
|
-
schema.name = node.name.text;
|
|
36
|
+
this.schema = new Schema();
|
|
37
|
+
this.schema.node = node;
|
|
38
|
+
this.schema.name = node.name.text;
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
this.schemas.push(this.schema);
|
|
41
|
+
if (process.env["JSON_DEBUG"]) console.log("Created schema: " + this.schema.name);
|
|
42
|
+
|
|
43
|
+
const members: FieldDeclaration[] = [...(node.members.filter((v) => v.kind === NodeKind.FieldDeclaration && v.flags !== CommonFlags.Static && v.flags !== CommonFlags.Private && v.flags !== CommonFlags.Protected && !v.decorators?.some((decorator) => (<IdentifierExpression>decorator.name).text === "omit")) as FieldDeclaration[])];
|
|
48
44
|
|
|
49
45
|
if (node.extendsType) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
const extendsName = node.extendsType?.name.identifier.text;
|
|
47
|
+
this.schema.parent = this.schemas.find((v) => v.name == extendsName) as Schema | null;
|
|
48
|
+
if (!this.schema.parent) {
|
|
49
|
+
const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
|
|
50
|
+
if (internalSearch) {
|
|
51
|
+
if (process.env["JSON_DEBUG"]) console.log("Found " + extendsName + " internally");
|
|
52
|
+
this.visitClassDeclaration(internalSearch);
|
|
53
|
+
this.visitClassDeclaration(node);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
|
|
58
|
+
if (externalSearch) {
|
|
59
|
+
if (process.env["JSON_DEBUG"]) console.log("Found " + extendsName + " externally");
|
|
60
|
+
this.visitClassDeclaration(externalSearch);
|
|
61
|
+
this.visitClassDeclaration(node);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (this.schema.parent?.members) {
|
|
66
|
+
for (let i = this.schema.parent.members.length - 1; i >= 0; i--) {
|
|
67
|
+
const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name);
|
|
59
68
|
if (!replace) {
|
|
60
|
-
members.unshift(schema.parent?.members[i]!.node);
|
|
69
|
+
members.unshift(this.schema.parent?.members[i]!.node);
|
|
61
70
|
}
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
if (!members.length) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
|
|
71
|
-
|
|
72
|
-
let DESERIALIZE_EMPTY =
|
|
73
|
-
"__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
|
|
74
|
-
|
|
75
|
-
if (process.env["JSON_DEBUG"]) {
|
|
76
|
-
console.log(SERIALIZE_RAW_EMPTY);
|
|
77
|
-
//console.log(SERIALIZE_PRETTY_EMPTY);
|
|
78
|
-
console.log(INITIALIZE_EMPTY);
|
|
79
|
-
console.log(DESERIALIZE_EMPTY);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
83
|
-
SERIALIZE_RAW_EMPTY,
|
|
84
|
-
node,
|
|
85
|
-
);
|
|
86
|
-
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
87
|
-
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
88
|
-
INITIALIZE_EMPTY,
|
|
89
|
-
node,
|
|
90
|
-
);
|
|
91
|
-
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
92
|
-
DESERIALIZE_EMPTY,
|
|
93
|
-
node,
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
97
|
-
node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
98
|
-
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
99
|
-
node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
100
|
-
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
101
|
-
node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
102
|
-
|
|
103
|
-
this.schemasList.push(schema);
|
|
76
|
+
this.generateEmptyMethods(node);
|
|
77
|
+
return;
|
|
104
78
|
}
|
|
105
79
|
|
|
80
|
+
this.addRequiredImports(node);
|
|
81
|
+
|
|
106
82
|
for (const member of members) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (!member.type) {
|
|
110
|
-
throw new Error(
|
|
111
|
-
"Fields must be strongly typed! Found " +
|
|
112
|
-
toString(member) +
|
|
113
|
-
" at " +
|
|
114
|
-
node.range.source.normalizedPath,
|
|
115
|
-
);
|
|
116
|
-
}
|
|
83
|
+
if (!member.type) throwError("Fields must be strongly typed", node.range);
|
|
84
|
+
|
|
117
85
|
const type = toString(member.type!);
|
|
118
|
-
|
|
86
|
+
const name = member.name;
|
|
119
87
|
const value = member.initializer ? toString(member.initializer!) : null;
|
|
120
88
|
|
|
121
|
-
if (
|
|
122
|
-
if (member.flags === CommonFlags.Private) continue;
|
|
123
|
-
if (member.flags === CommonFlags.Protected) continue;
|
|
89
|
+
if (type.startsWith("(") && type.includes("=>")) continue;
|
|
124
90
|
|
|
125
91
|
const mem = new Property();
|
|
126
92
|
mem.name = name.text;
|
|
127
93
|
mem.type = type;
|
|
128
94
|
mem.value = value;
|
|
129
95
|
mem.node = member;
|
|
96
|
+
mem.byteSize = sizeof(mem.type);
|
|
130
97
|
|
|
131
|
-
|
|
132
|
-
mem.flags.set(PropertyFlags.JSON_Raw, []);
|
|
133
|
-
}
|
|
98
|
+
this.schema.byteSize += mem.byteSize;
|
|
134
99
|
|
|
135
|
-
if (
|
|
136
|
-
mem.flags.set(PropertyFlags.Null, []);
|
|
137
|
-
}
|
|
100
|
+
if (type.includes("JSON.Raw")) mem.flags.set(PropertyFlags.Raw, null);
|
|
138
101
|
|
|
139
102
|
if (member.decorators) {
|
|
140
103
|
for (const decorator of member.decorators) {
|
|
141
|
-
const decoratorName = (decorator.name as IdentifierExpression).text;
|
|
142
|
-
|
|
143
|
-
const args = getArgs(decorator.args);
|
|
144
|
-
|
|
104
|
+
const decoratorName = (decorator.name as IdentifierExpression).text.toLowerCase().trim();
|
|
145
105
|
switch (decoratorName) {
|
|
146
106
|
case "alias": {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
"Expected 1 argument but got zero at @alias in " +
|
|
150
|
-
node.range.source.normalizedPath,
|
|
151
|
-
);
|
|
107
|
+
const args = getArgs(decorator.args);
|
|
108
|
+
if (!args.length) throwError("@alias must have an argument of type string or number", member.range);
|
|
152
109
|
mem.alias = args[0]!;
|
|
153
|
-
mem.flags.set(PropertyFlags.Alias, args);
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
case "omit": {
|
|
157
|
-
mem.flags.set(PropertyFlags.Omit, args);
|
|
158
110
|
break;
|
|
159
111
|
}
|
|
160
112
|
case "omitif": {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
);
|
|
166
|
-
mem.flags.set(PropertyFlags.OmitIf, args);
|
|
113
|
+
let arg = decorator.args[0];
|
|
114
|
+
if (!decorator.args?.length) throwError("@omitif must have an argument or callback that resolves to type bool", member.range);
|
|
115
|
+
mem.flags.set(PropertyFlags.OmitIf, arg);
|
|
116
|
+
this.schema.static = false;
|
|
167
117
|
break;
|
|
168
118
|
}
|
|
169
119
|
case "omitnull": {
|
|
170
|
-
|
|
120
|
+
if (isPrimitive(type)) {
|
|
121
|
+
throwError("@omitnull cannot be used on primitive types!", member.range);
|
|
122
|
+
} else if (!member.type.isNullable) {
|
|
123
|
+
throwError("@omitnull cannot be used on non-nullable types!", member.range);
|
|
124
|
+
}
|
|
125
|
+
mem.flags.set(PropertyFlags.OmitNull, null);
|
|
126
|
+
this.schema.static = false;
|
|
171
127
|
break;
|
|
172
128
|
}
|
|
173
129
|
}
|
|
174
130
|
}
|
|
175
131
|
}
|
|
176
132
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (this.schemasList.find((v) => v.name == type)) {
|
|
180
|
-
mem.initialize =
|
|
181
|
-
"this." +
|
|
182
|
-
name.text +
|
|
183
|
-
" = changetype<nonnull<" +
|
|
184
|
-
mem.type +
|
|
185
|
-
">>(__new(offsetof<nonnull<" +
|
|
186
|
-
mem.type +
|
|
187
|
-
">>(), idof<nonnull<" +
|
|
188
|
-
mem.type +
|
|
189
|
-
">>()));\n changetype<nonnull<" +
|
|
190
|
-
mem.type +
|
|
191
|
-
">>(this." +
|
|
192
|
-
name.text +
|
|
193
|
-
").__INITIALIZE()";
|
|
194
|
-
} else if (mem.value) {
|
|
195
|
-
mem.initialize = "this." + name.text + " = " + mem.value;
|
|
196
|
-
} else if (type === "Map") {
|
|
197
|
-
mem.initialize = "this." + name.text + " = new " + mem.type + "()";
|
|
198
|
-
} else if (type === "string") {
|
|
199
|
-
mem.initialize = "this." + name.text + ' = ""';
|
|
200
|
-
} else if (type === "Array") {
|
|
201
|
-
mem.initialize =
|
|
202
|
-
"this." + name.text + " = instantiate<" + mem.type + ">()";
|
|
203
|
-
} else if (type === "bool" || type === "boolean") {
|
|
204
|
-
mem.initialize = "this." + name.text + " = false";
|
|
205
|
-
} else if (type === "JSON.Raw") {
|
|
206
|
-
mem.initialize = "this." + name.text + ' = ""';
|
|
207
|
-
} else if (
|
|
208
|
-
type === "u8" ||
|
|
209
|
-
type === "u16" ||
|
|
210
|
-
type === "u32" ||
|
|
211
|
-
type === "u64" ||
|
|
212
|
-
type === "i8" ||
|
|
213
|
-
type === "i16" ||
|
|
214
|
-
type === "i32" ||
|
|
215
|
-
type === "i64"
|
|
216
|
-
) {
|
|
217
|
-
mem.initialize = "this." + name.text + " = 0";
|
|
218
|
-
} else if (type === "f32" || type === "f64") {
|
|
219
|
-
mem.initialize = "this." + name.text + " = 0.0";
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
schema.members.push(mem);
|
|
133
|
+
this.schema.members.push(mem);
|
|
223
134
|
}
|
|
224
135
|
|
|
225
|
-
|
|
226
|
-
let SERIALIZE_PRETTY = "__SERIALIZE_PRETTY(): string {\n let out = `{";
|
|
227
|
-
|
|
228
|
-
let INITIALIZE = "__INITIALIZE(): this {\n";
|
|
136
|
+
if (!this.schema.static) this.schema.members = sortMembers(this.schema.members);
|
|
229
137
|
|
|
230
|
-
let
|
|
231
|
-
|
|
232
|
-
let
|
|
138
|
+
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
|
|
139
|
+
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
140
|
+
let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (keyEnd - keyStart) {\n";
|
|
141
|
+
let ALLOCATE = "@inline __ALLOCATE(): void {\n";
|
|
233
142
|
|
|
234
|
-
|
|
143
|
+
indent = " ";
|
|
235
144
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
schema.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
|
|
244
|
-
} else {
|
|
245
|
-
SERIALIZE_RAW += schema.members[0]?.serialize + ",";
|
|
246
|
-
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize + ",\\n";
|
|
247
|
-
found = true;
|
|
145
|
+
if (this.schema.static == false) {
|
|
146
|
+
if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
|
|
147
|
+
SERIALIZE += indent + "let block: usize = 0;\n";
|
|
148
|
+
}
|
|
149
|
+
this.schema.byteSize += 2;
|
|
150
|
+
SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n";
|
|
151
|
+
SERIALIZE += indent + "bs.offset += 2;\n";
|
|
248
152
|
}
|
|
249
153
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
154
|
+
let isPure = this.schema.static;
|
|
155
|
+
let isRegular = isPure;
|
|
156
|
+
let isFirst = true;
|
|
157
|
+
|
|
158
|
+
for (let i = 0; i < this.schema.members.length; i++) {
|
|
159
|
+
const member = this.schema.members[i];
|
|
160
|
+
const aliasName = JSON.stringify(member.alias || member.name);
|
|
161
|
+
const realName = member.name;
|
|
162
|
+
const isLast = i == this.schema.members.length - 1;
|
|
163
|
+
const nonNullType = member.type.replace(" | null", "");
|
|
164
|
+
|
|
165
|
+
if (member.value) {
|
|
166
|
+
INITIALIZE += ` this.${member.name} = ${member.value};\n`;
|
|
167
|
+
} else if (this.schemas.find((v) => nonNullType == v.name)) {
|
|
168
|
+
INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`;
|
|
169
|
+
} else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
|
|
170
|
+
INITIALIZE += ` this.${member.name} = [];\n`;
|
|
171
|
+
} else if (member.type == "string" || member.type == "String" || member.type == "JSON.Raw") {
|
|
172
|
+
INITIALIZE += ` this.${member.name} = "";\n`;
|
|
266
173
|
}
|
|
267
|
-
}
|
|
268
174
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
175
|
+
if (!isRegular && !member.flags.has(PropertyFlags.OmitIf) && !member.flags.has(PropertyFlags.OmitNull)) isRegular = true;
|
|
176
|
+
if (isRegular && isPure) {
|
|
177
|
+
const keyPart = (isFirst ? "{" : ",") + aliasName + ":";
|
|
178
|
+
this.schema.byteSize += keyPart.length << 1;
|
|
179
|
+
SERIALIZE += this.getStores(keyPart)
|
|
180
|
+
.map((v) => indent + v + "\n")
|
|
181
|
+
.join("");
|
|
182
|
+
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
|
|
183
|
+
if (isFirst) isFirst = false;
|
|
184
|
+
} else if (isRegular && !isPure) {
|
|
185
|
+
const keyPart = (isFirst ? "" : ",") + aliasName + ":";
|
|
186
|
+
this.schema.byteSize += keyPart.length << 1;
|
|
187
|
+
SERIALIZE += this.getStores(keyPart)
|
|
188
|
+
.map((v) => indent + v + "\n")
|
|
189
|
+
.join("");
|
|
190
|
+
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
|
|
191
|
+
if (isFirst) isFirst = false;
|
|
192
|
+
} else {
|
|
193
|
+
if (member.flags.has(PropertyFlags.OmitNull)) {
|
|
194
|
+
SERIALIZE += indent + `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`;
|
|
195
|
+
indentInc();
|
|
196
|
+
const keyPart = aliasName + ":";
|
|
197
|
+
this.schema.byteSize += keyPart.length << 1;
|
|
198
|
+
SERIALIZE += this.getStores(keyPart)
|
|
199
|
+
.map((v) => indent + v + "\n")
|
|
200
|
+
.join("");
|
|
201
|
+
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
|
|
202
|
+
|
|
203
|
+
if (!isLast) {
|
|
204
|
+
this.schema.byteSize += 2;
|
|
205
|
+
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
|
|
206
|
+
SERIALIZE += indent + `bs.offset += 2;\n`;
|
|
207
|
+
}
|
|
278
208
|
|
|
279
|
-
|
|
209
|
+
indentDec();
|
|
210
|
+
this.schema.byteSize += 2;
|
|
211
|
+
SERIALIZE += indent + `}\n`;
|
|
212
|
+
} else if (member.flags.has(PropertyFlags.OmitIf)) {
|
|
213
|
+
if (member.flags.get(PropertyFlags.OmitIf).kind == NodeKind.Function) {
|
|
214
|
+
const arg = member.flags.get(PropertyFlags.OmitIf) as FunctionExpression;
|
|
215
|
+
// @ts-ignore: type
|
|
216
|
+
arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range);
|
|
217
|
+
SERIALIZE += indent + `if ((${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`;
|
|
218
|
+
} else {
|
|
219
|
+
SERIALIZE += indent + `if (${toString(member.flags.get(PropertyFlags.OmitIf))}) {\n`;
|
|
220
|
+
}
|
|
221
|
+
indentInc();
|
|
222
|
+
SERIALIZE += this.getStores(aliasName + ":")
|
|
223
|
+
.map((v) => indent + v + "\n")
|
|
224
|
+
.join("");
|
|
225
|
+
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
|
|
226
|
+
|
|
227
|
+
if (!isLast) {
|
|
228
|
+
this.schema.byteSize += 2;
|
|
229
|
+
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
|
|
230
|
+
SERIALIZE += indent + `bs.offset += 2;\n`;
|
|
231
|
+
}
|
|
280
232
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
);
|
|
285
|
-
let len = -1;
|
|
286
|
-
let offset = -1;
|
|
287
|
-
for (let i = 0; i < _sorted.length; i++) {
|
|
288
|
-
const member = _sorted[i]!;
|
|
289
|
-
const _name = member.alias || member.name;
|
|
290
|
-
if (_name.length === len) {
|
|
291
|
-
sortedMembers[offset]?.push(member);
|
|
292
|
-
} else {
|
|
293
|
-
sortedMembers.push([member]);
|
|
294
|
-
len = _name.length;
|
|
295
|
-
offset++;
|
|
233
|
+
indentDec();
|
|
234
|
+
SERIALIZE += indent + `}\n`;
|
|
235
|
+
}
|
|
296
236
|
}
|
|
297
237
|
}
|
|
298
238
|
|
|
299
|
-
let
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
DESERIALIZE +=
|
|
310
|
-
"else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
311
|
-
}
|
|
312
|
-
} else if (_name.length === 2) {
|
|
313
|
-
if (first) {
|
|
314
|
-
DESERIALIZE +=
|
|
315
|
-
" if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
316
|
-
first = false;
|
|
317
|
-
} else {
|
|
318
|
-
DESERIALIZE +=
|
|
319
|
-
"else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
320
|
-
}
|
|
321
|
-
} else if (_name.length === 4) {
|
|
322
|
-
if (first) {
|
|
323
|
-
DESERIALIZE +=
|
|
324
|
-
" if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
325
|
-
first = false;
|
|
239
|
+
let sortedMembers: Property[][] = [];
|
|
240
|
+
|
|
241
|
+
let len = -1;
|
|
242
|
+
this.schema.members
|
|
243
|
+
.slice()
|
|
244
|
+
.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
|
|
245
|
+
.forEach((member) => {
|
|
246
|
+
const _nameLength = member.alias?.length || member.name.length;
|
|
247
|
+
if (_nameLength === len) {
|
|
248
|
+
sortedMembers[sortedMembers.length - 1].push(member);
|
|
326
249
|
} else {
|
|
327
|
-
|
|
328
|
-
|
|
250
|
+
sortedMembers.push([member]);
|
|
251
|
+
len = _nameLength;
|
|
329
252
|
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
sortedMembers = sortedMembers.sort((a, b) => b.length - a.length);
|
|
256
|
+
|
|
257
|
+
indentInc();
|
|
258
|
+
for (const memberGroup of sortedMembers) {
|
|
259
|
+
const memberLen = (memberGroup[0].alias || memberGroup[0].name).length << 1;
|
|
260
|
+
DESERIALIZE += `${indent}case ${memberLen}: {\n`;
|
|
261
|
+
indentInc();
|
|
262
|
+
if (memberLen == 2) DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`;
|
|
263
|
+
else if (memberLen == 4) DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`;
|
|
264
|
+
else if (memberLen == 6) DESERIALIZE += `${indent}let code = (<u64>load<u32>(keyStart) << 16) | <u64>load<u16>(keyStart, 4);\n`;
|
|
265
|
+
else DESERIALIZE += toMemCDecl(memberLen, indent);
|
|
266
|
+
for (let i = 0; i < memberGroup.length; i++) {
|
|
267
|
+
const member = memberGroup[i];
|
|
268
|
+
const memberName = member.alias || member.name;
|
|
269
|
+
if (memberLen == 2) {
|
|
270
|
+
DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`;
|
|
271
|
+
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
272
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
273
|
+
DESERIALIZE += `${indent} }\n`;
|
|
274
|
+
} else if (memberLen == 4) {
|
|
275
|
+
DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`;
|
|
276
|
+
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
277
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
278
|
+
DESERIALIZE += `${indent} }\n`;
|
|
279
|
+
} else if (memberLen == 6) {
|
|
280
|
+
DESERIALIZE += i == 0 ? indent : "";
|
|
281
|
+
DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`;
|
|
282
|
+
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
283
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
284
|
+
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
|
|
334
285
|
} else {
|
|
335
|
-
DESERIALIZE +=
|
|
286
|
+
DESERIALIZE += i == 0 ? indent : "";
|
|
287
|
+
DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`;
|
|
288
|
+
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
289
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
290
|
+
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
|
|
336
291
|
}
|
|
337
292
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const member = memberSet[i]!;
|
|
341
|
-
if (!member.deserialize) continue;
|
|
342
|
-
const _name = encodeKey(member.alias || member.name);
|
|
343
|
-
if (_name.length === 1) {
|
|
344
|
-
DESERIALIZE += ` case ${_name.charCodeAt(0)}: { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
345
|
-
} else if (_name.length === 2) {
|
|
346
|
-
DESERIALIZE += ` case ${charCodeAt32(_name, 0)}: { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
347
|
-
} else if (_name.length === 4) {
|
|
348
|
-
if (f) {
|
|
349
|
-
f = false;
|
|
350
|
-
DESERIALIZE += ` if (${charCodeAt64(_name, 0)} === code) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
351
|
-
} else {
|
|
352
|
-
DESERIALIZE =
|
|
353
|
-
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
354
|
-
`else if (${charCodeAt64(_name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
355
|
-
}
|
|
356
|
-
} else {
|
|
357
|
-
if (f) {
|
|
358
|
-
f = false;
|
|
359
|
-
DESERIALIZE += ` if (0 === memory.compare(changetype<usize>("${escapeQuote(escapeSlash(_name))}"), changetype<usize>(data) + (key_start << 1), ${_name.length << 1})) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
360
|
-
} else {
|
|
361
|
-
DESERIALIZE =
|
|
362
|
-
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
363
|
-
` else if (0 === memory.compare(changetype<usize>("${escapeQuote(escapeSlash(_name))}"), changetype<usize>(data) + (key_start << 1), ${_name.length << 1})) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
293
|
+
if (memberLen < 6) {
|
|
294
|
+
DESERIALIZE += `${indent}}\n`; // Close switch
|
|
366
295
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
DESERIALIZE =
|
|
371
|
-
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
372
|
-
` else {\n return false;\n }\n`;
|
|
373
|
-
} else {
|
|
374
|
-
DESERIALIZE =
|
|
375
|
-
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
376
|
-
` else {\n return false;\n }\n`;
|
|
377
|
-
}
|
|
378
|
-
DESERIALIZE += " } ";
|
|
296
|
+
indentDec();
|
|
297
|
+
DESERIALIZE += `${indent} return;\n`; // Break switch
|
|
298
|
+
DESERIALIZE += `${indent}}\n`; // Close length switch
|
|
379
299
|
}
|
|
380
300
|
|
|
381
|
-
|
|
301
|
+
indentDec();
|
|
302
|
+
DESERIALIZE += `${indent}}\n`; // Close length switch
|
|
303
|
+
indentDec();
|
|
304
|
+
DESERIALIZE += `${indent}}\n`; // Close function
|
|
305
|
+
|
|
306
|
+
indent = " ";
|
|
307
|
+
|
|
308
|
+
this.schema.byteSize += 2;
|
|
309
|
+
SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
|
|
310
|
+
SERIALIZE += indent + "bs.offset += 2;\n";
|
|
311
|
+
SERIALIZE += "}";
|
|
382
312
|
|
|
383
|
-
|
|
313
|
+
ALLOCATE += indent + "bs.ensureSize(" + this.schema.byteSize + ");\n";
|
|
314
|
+
ALLOCATE += "}";
|
|
315
|
+
|
|
316
|
+
INITIALIZE += " return this;\n";
|
|
317
|
+
INITIALIZE += "}";
|
|
384
318
|
|
|
385
319
|
if (process.env["JSON_DEBUG"]) {
|
|
386
|
-
console.log(
|
|
387
|
-
//console.log(SERIALIZE_PRETTY);
|
|
320
|
+
console.log(SERIALIZE);
|
|
388
321
|
console.log(INITIALIZE);
|
|
389
322
|
console.log(DESERIALIZE);
|
|
323
|
+
console.log(ALLOCATE);
|
|
390
324
|
}
|
|
391
325
|
|
|
392
|
-
const
|
|
393
|
-
SERIALIZE_RAW,
|
|
394
|
-
node,
|
|
395
|
-
);
|
|
396
|
-
|
|
397
|
-
const DESERIALIZE_SAFE = DESERIALIZE.replaceAll("__DESERIALIZE", "__DESERIALIZE_SAFE")
|
|
398
|
-
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
326
|
+
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
|
|
399
327
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
400
328
|
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
404
|
-
|
|
405
|
-
if (!node.members.find((v) => v.name.text == "
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
329
|
+
const ALLOCATE_METHOD = SimpleParser.parseClassMember(ALLOCATE, node);
|
|
330
|
+
|
|
331
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_METHOD);
|
|
332
|
+
if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD);
|
|
333
|
+
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD);
|
|
334
|
+
if (!node.members.find((v) => v.name.text == "__ALLOCATE")) node.members.push(ALLOCATE_METHOD);
|
|
335
|
+
super.visitClassDeclaration(node);
|
|
336
|
+
}
|
|
337
|
+
generateEmptyMethods(node: ClassDeclaration): void {
|
|
338
|
+
let SERIALIZE_RAW_EMPTY = '@inline __SERIALIZE(ptr: usize = changetype<usize>(this)): string {\n return "{}";\n}';
|
|
339
|
+
let SERIALIZE_BS_EMPTY = "@inline __SERIALIZE(ptr: usize: bool): void {\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
|
|
340
|
+
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
|
|
341
|
+
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n return false;\n}";
|
|
342
|
+
let ALLOCATE_EMPTY = "@inline __ALLOCATE(): void {\n bs.ensureSize(4);\n}";
|
|
343
|
+
|
|
344
|
+
if (process.env["JSON_DEBUG"]) {
|
|
345
|
+
console.log(SERIALIZE_RAW_EMPTY);
|
|
346
|
+
console.log(SERIALIZE_BS_EMPTY);
|
|
347
|
+
console.log(INITIALIZE_EMPTY);
|
|
348
|
+
console.log(DESERIALIZE_EMPTY);
|
|
349
|
+
console.log(ALLOCATE_EMPTY);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node);
|
|
353
|
+
const SERIALIZE_BS_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_BS_EMPTY, node);
|
|
354
|
+
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
|
|
355
|
+
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
|
|
356
|
+
const ALLOCATE_METHOD_EMPTY = SimpleParser.parseClassMember(ALLOCATE_EMPTY, node);
|
|
357
|
+
|
|
358
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
359
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_BS_METHOD_EMPTY);
|
|
360
|
+
if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
361
|
+
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
362
|
+
if (!node.members.find((v) => v.name.text == "__ALLOCATE")) node.members.push(ALLOCATE_METHOD_EMPTY);
|
|
363
|
+
}
|
|
364
|
+
// visitCallExpression(node: CallExpression, ref: Node): void {
|
|
365
|
+
// super.visitCallExpression(node, ref);
|
|
366
|
+
// if (!(node.expression.kind == NodeKind.PropertyAccess && (node.expression as PropertyAccessExpression).property.text == "stringifyTo") && !(node.expression.kind == NodeKind.Identifier && (node.expression as IdentifierExpression).text == "stringifyTo")) return;
|
|
367
|
+
|
|
368
|
+
// const source = node.range.source;
|
|
369
|
+
|
|
370
|
+
// if (ref.kind == NodeKind.Call) {
|
|
371
|
+
// const newNode = Node.createBinaryExpression(Token.Equals, node.args[1], node, node.range);
|
|
372
|
+
|
|
373
|
+
// (<CallExpression>ref).args[(<CallExpression>ref).args.indexOf(node)] = newNode;
|
|
374
|
+
// } else {
|
|
375
|
+
// const newNode = Node.createExpressionStatement(Node.createBinaryExpression(Token.Equals, node.args[1], node, node.range));
|
|
376
|
+
|
|
377
|
+
// const nodeIndex = source.statements.findIndex((n: Node) => {
|
|
378
|
+
// if (n == node) return true;
|
|
379
|
+
// if (n.kind == NodeKind.Expression && (<ExpressionStatement>n).expression == node) return true;
|
|
380
|
+
// return false;
|
|
381
|
+
// });
|
|
382
|
+
|
|
383
|
+
// if (nodeIndex > 0) source.statements[nodeIndex] = newNode;
|
|
384
|
+
// }
|
|
385
|
+
// }
|
|
386
|
+
// visitBinaryExpression(node: BinaryExpression, ref?: Node | null): void {
|
|
387
|
+
// // if (node.right.kind == NodeKind.Call && (<CallExpression>node).)
|
|
388
|
+
// }
|
|
389
|
+
visitImportStatement(node: ImportStatement): void {
|
|
390
|
+
super.visitImportStatement(node);
|
|
391
|
+
const source = this.parser.sources.find((src) => src.internalPath == node.internalPath);
|
|
392
|
+
if (!source) return;
|
|
393
|
+
|
|
394
|
+
if (source.statements.some((stmt) => stmt.kind === NodeKind.NamespaceDeclaration && (stmt as NamespaceDeclaration).name.text === "JSON")) this.imports.push(node);
|
|
413
395
|
}
|
|
414
396
|
visitSource(node: Source): void {
|
|
397
|
+
this.imports = [];
|
|
415
398
|
super.visitSource(node);
|
|
399
|
+
}
|
|
400
|
+
addRequiredImports(node: ClassDeclaration): void {
|
|
401
|
+
// if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "bs"))) {
|
|
402
|
+
// if (!this.bsImport) {
|
|
403
|
+
// this.bsImport = 'import { bs } from "as-bs"';
|
|
404
|
+
// if (process.env["JSON_DEBUG"]) console.log("Added as-bs import: " + this.bsImport + "\n");
|
|
405
|
+
// }
|
|
406
|
+
// }
|
|
407
|
+
if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "bs"))) {
|
|
408
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
409
|
+
const __dirname = path.dirname(__filename);
|
|
410
|
+
|
|
411
|
+
let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../modules/bs/index.ts"));
|
|
412
|
+
|
|
413
|
+
if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) relativePath = "./" + relativePath;
|
|
414
|
+
// if (!existsSync(relativePath)) {
|
|
415
|
+
// throw new Error("Could not find a valid json-as library to import from! Please add import { JSON } from \"path-to-json-as\"; in " + node.range.source.normalizedPath + "!");
|
|
416
|
+
// }
|
|
417
|
+
|
|
418
|
+
const txt = `import { bs } from "${relativePath}";`;
|
|
419
|
+
if (!this.jsonImport) {
|
|
420
|
+
this.jsonImport = txt;
|
|
421
|
+
if (process.env["JSON_DEBUG"]) console.log("Added bs import: " + txt + "\n");
|
|
422
|
+
}
|
|
423
|
+
}
|
|
416
424
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
425
|
+
if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "JSON"))) {
|
|
426
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
427
|
+
const __dirname = path.dirname(__filename);
|
|
428
|
+
|
|
429
|
+
let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../assembly/index.ts"));
|
|
430
|
+
|
|
431
|
+
if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) relativePath = "./" + relativePath;
|
|
432
|
+
// if (!existsSync(relativePath)) {
|
|
433
|
+
// throw new Error("Could not find a valid json-as library to import from! Please add import { JSON } from \"path-to-json-as\"; in " + node.range.source.normalizedPath + "!");
|
|
434
|
+
// }
|
|
435
|
+
|
|
436
|
+
const txt = `import { JSON } from "${relativePath}";`;
|
|
437
|
+
if (!this.jsonImport) {
|
|
438
|
+
this.jsonImport = txt;
|
|
439
|
+
if (process.env["JSON_DEBUG"]) console.log("Added json-as import: " + txt + "\n");
|
|
440
|
+
}
|
|
420
441
|
}
|
|
421
442
|
}
|
|
443
|
+
|
|
444
|
+
getStores(data: string, simd: boolean = true): string[] {
|
|
445
|
+
const out: string[] = [];
|
|
446
|
+
const sizes = strToNum(data, simd);
|
|
447
|
+
let offset = 0;
|
|
448
|
+
for (const [size, num] of sizes) {
|
|
449
|
+
if (size == "v128") {
|
|
450
|
+
// This could be put in its own file
|
|
451
|
+
let index = this.newStmts.simd.findIndex((v) => v.includes(num));
|
|
452
|
+
let name = "SIMD_" + (index == -1 ? this.newStmts.simd.length : index);
|
|
453
|
+
if (index && !this.newStmts.simd.includes(`const ${name} = ${num};`)) this.newStmts.simd.push(`const ${name} = ${num};`);
|
|
454
|
+
out.push("store<v128>(bs.offset, " + name + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 8));
|
|
455
|
+
offset += 16;
|
|
456
|
+
}
|
|
457
|
+
if (size == "u64") {
|
|
458
|
+
out.push("store<u64>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 4));
|
|
459
|
+
offset += 8;
|
|
460
|
+
} else if (size == "u32") {
|
|
461
|
+
out.push("store<u32>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 2));
|
|
462
|
+
offset += 4;
|
|
463
|
+
} else if (size == "u16") {
|
|
464
|
+
out.push("store<u16>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 1));
|
|
465
|
+
offset += 2;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
out.push("bs.offset += " + offset + ";");
|
|
469
|
+
return out;
|
|
470
|
+
}
|
|
422
471
|
}
|
|
423
472
|
|
|
424
473
|
export default class Transformer extends Transform {
|
|
@@ -428,169 +477,74 @@ export default class Transformer extends Transform {
|
|
|
428
477
|
const transformer = new JSONTransform();
|
|
429
478
|
|
|
430
479
|
// Sort the sources so that user scripts are visited last
|
|
431
|
-
const sources = parser.sources
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
});
|
|
480
|
+
const sources = parser.sources.sort((_a, _b) => {
|
|
481
|
+
const a = _a.internalPath;
|
|
482
|
+
const b = _b.internalPath;
|
|
483
|
+
if (a[0] == "~" && b[0] !== "~") {
|
|
484
|
+
return -1;
|
|
485
|
+
} else if (a[0] !== "~" && b[0] == "~") {
|
|
486
|
+
return 1;
|
|
487
|
+
} else {
|
|
488
|
+
return 0;
|
|
489
|
+
}
|
|
490
|
+
});
|
|
444
491
|
|
|
492
|
+
transformer.parser = parser;
|
|
445
493
|
// Loop over every source
|
|
446
494
|
for (const source of sources) {
|
|
495
|
+
transformer.imports = [];
|
|
496
|
+
transformer.currentSource = source;
|
|
447
497
|
// Ignore all lib and std. Visit everything else.
|
|
448
|
-
|
|
449
|
-
|
|
498
|
+
transformer.visit(source);
|
|
499
|
+
|
|
500
|
+
if (transformer.newStmts.simd) {
|
|
501
|
+
const tokenizer = new Tokenizer(new Source(SourceKind.User, source.normalizedPath, transformer.newStmts.simd.join("\n")));
|
|
502
|
+
parser.currentSource = tokenizer.source;
|
|
503
|
+
for (let i = 0; i < transformer.newStmts.simd.length; i++) source.statements.unshift(parser.parseTopLevelStatement(tokenizer)!);
|
|
504
|
+
parser.currentSource = source;
|
|
505
|
+
transformer.newStmts.simd = [];
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (transformer.jsonImport) {
|
|
509
|
+
const tokenizer = new Tokenizer(new Source(SourceKind.User, source.normalizedPath, transformer.jsonImport));
|
|
510
|
+
parser.currentSource = tokenizer.source;
|
|
511
|
+
source.statements.unshift(parser.parseTopLevelStatement(tokenizer)!);
|
|
512
|
+
parser.currentSource = source;
|
|
513
|
+
transformer.jsonImport = null;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (transformer.bsImport) {
|
|
517
|
+
const tokenizer = new Tokenizer(new Source(SourceKind.User, source.normalizedPath, transformer.bsImport));
|
|
518
|
+
parser.currentSource = tokenizer.source;
|
|
519
|
+
source.statements.unshift(parser.parseTopLevelStatement(tokenizer)!);
|
|
520
|
+
parser.currentSource = source;
|
|
521
|
+
transformer.bsImport = null;
|
|
450
522
|
}
|
|
451
523
|
}
|
|
452
524
|
// Check that every parent and child class is hooked up correctly
|
|
453
|
-
const schemas = transformer.
|
|
525
|
+
const schemas = transformer.schemas;
|
|
454
526
|
for (const schema of schemas) {
|
|
455
527
|
if (schema.parent) {
|
|
456
|
-
const parent = schemas.find((v) => v.name
|
|
457
|
-
if (!parent)
|
|
458
|
-
throw new Error(
|
|
459
|
-
`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator! Add the decorator and rebuild.`,
|
|
460
|
-
);
|
|
528
|
+
const parent = schemas.find((v) => v.name == schema.parent?.name);
|
|
529
|
+
if (!parent) throwError(`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator!`, schema.parent.node.range);
|
|
461
530
|
}
|
|
462
531
|
}
|
|
463
532
|
}
|
|
464
533
|
}
|
|
465
534
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
OmitIf,
|
|
471
|
-
Alias,
|
|
472
|
-
JSON_Raw,
|
|
473
|
-
}
|
|
535
|
+
function sortMembers(members: Property[]): Property[] {
|
|
536
|
+
return members.sort((a, b) => {
|
|
537
|
+
const aMove = a.flags.has(PropertyFlags.OmitIf) || a.flags.has(PropertyFlags.OmitNull);
|
|
538
|
+
const bMove = b.flags.has(PropertyFlags.OmitIf) || b.flags.has(PropertyFlags.OmitNull);
|
|
474
539
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
public value: string | null = null;
|
|
480
|
-
public flags: Map<PropertyFlags, string[]> = new Map<
|
|
481
|
-
PropertyFlags,
|
|
482
|
-
string[]
|
|
483
|
-
>();
|
|
484
|
-
|
|
485
|
-
public serialize: string | null = null;
|
|
486
|
-
public deserialize: string | null = null;
|
|
487
|
-
public initialize: string | null = null;
|
|
488
|
-
|
|
489
|
-
public node!: FieldDeclaration;
|
|
490
|
-
|
|
491
|
-
private right_s: string = "";
|
|
492
|
-
private right_d: string = "";
|
|
493
|
-
|
|
494
|
-
public generate(safe: boolean): void {
|
|
495
|
-
const name = this.name;
|
|
496
|
-
const escapedName = escapeString(JSON.stringify(this.alias || this.name));
|
|
497
|
-
const type = this.type;
|
|
498
|
-
if (this.flags.has(PropertyFlags.Omit)) return;
|
|
499
|
-
|
|
500
|
-
if (this.flags.has(PropertyFlags.JSON_Raw)) {
|
|
501
|
-
if (this.flags.has(PropertyFlags.Null)) {
|
|
502
|
-
this.right_s = "(this." + name + " || \"null\")";
|
|
503
|
-
this.right_d = "value_start === value_end - 4 && 30399761348886638 === load<u64>(changetype<usize>(data) + (value_start << 1)) ? null : data.substring(value_start, value_end)";
|
|
504
|
-
} else {
|
|
505
|
-
this.right_s = "this." + name;
|
|
506
|
-
this.right_d = "data.substring(value_start, value_end);";
|
|
507
|
-
}
|
|
540
|
+
if (aMove && !bMove) {
|
|
541
|
+
return -1;
|
|
542
|
+
} else if (!aMove && bMove) {
|
|
543
|
+
return 1;
|
|
508
544
|
} else {
|
|
509
|
-
|
|
510
|
-
this.right_d =
|
|
511
|
-
(safe ? "__DESERIALIZE_SAFE" : "__DESERIALIZE") + "<" + type + ">(data.substring(value_start, value_end))";
|
|
545
|
+
return 0;
|
|
512
546
|
}
|
|
513
|
-
|
|
514
|
-
if (this.flags.has(PropertyFlags.OmitIf)) {
|
|
515
|
-
const condition = this.flags.get(PropertyFlags.OmitIf)![0];
|
|
516
|
-
if (!condition)
|
|
517
|
-
throw new Error(
|
|
518
|
-
"Could not find condition when using decorator @omitif! Provide at least one condition",
|
|
519
|
-
);
|
|
520
|
-
this.serialize =
|
|
521
|
-
"${" +
|
|
522
|
-
condition +
|
|
523
|
-
' ? "" : \'' +
|
|
524
|
-
escapedName +
|
|
525
|
-
":' + " +
|
|
526
|
-
this.right_s +
|
|
527
|
-
' + ","}';
|
|
528
|
-
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
529
|
-
} else if (this.flags.has(PropertyFlags.OmitNull)) {
|
|
530
|
-
this.serialize =
|
|
531
|
-
"${changetype<usize>(this." +
|
|
532
|
-
name +
|
|
533
|
-
") == <usize>0" +
|
|
534
|
-
' ? "" : \'' +
|
|
535
|
-
escapedName +
|
|
536
|
-
":' + " +
|
|
537
|
-
this.right_s +
|
|
538
|
-
' + ","}';
|
|
539
|
-
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
540
|
-
} else {
|
|
541
|
-
this.serialize = escapedName + ":${" + this.right_s + "}";
|
|
542
|
-
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
class SchemaData {
|
|
548
|
-
public name: string = "";
|
|
549
|
-
public members: Property[] = [];
|
|
550
|
-
public parent: SchemaData | null = null;
|
|
551
|
-
public node!: ClassDeclaration;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
function charCodeAt32(data: string, offset: number): number {
|
|
555
|
-
return (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
function charCodeAt64(data: string, offset: number): bigint {
|
|
559
|
-
if (offset + 3 >= data.length) {
|
|
560
|
-
throw new Error(
|
|
561
|
-
"The string must have at least 4 characters from the specified offset.",
|
|
562
|
-
);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
const firstCharCode = BigInt(data.charCodeAt(offset));
|
|
566
|
-
const secondCharCode = BigInt(data.charCodeAt(offset + 1));
|
|
567
|
-
const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
|
|
568
|
-
const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
|
|
569
|
-
|
|
570
|
-
const u64Value =
|
|
571
|
-
(fourthCharCode << 48n) |
|
|
572
|
-
(thirdCharCode << 32n) |
|
|
573
|
-
(secondCharCode << 16n) |
|
|
574
|
-
firstCharCode;
|
|
575
|
-
|
|
576
|
-
return u64Value;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
function encodeKey(key: string): string {
|
|
580
|
-
const data = JSON.stringify(key);
|
|
581
|
-
return data.slice(1, data.length - 1);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
function escapeString(data: string): string {
|
|
585
|
-
return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
function escapeSlash(data: string): string {
|
|
589
|
-
return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
function escapeQuote(data: string): string {
|
|
593
|
-
return data.replace(/\"/g, '\\"');
|
|
547
|
+
});
|
|
594
548
|
}
|
|
595
549
|
|
|
596
550
|
function getArgs(args: Expression[] | null): string[] {
|
|
@@ -615,3 +569,139 @@ function getArgs(args: Expression[] | null): string[] {
|
|
|
615
569
|
}
|
|
616
570
|
return out;
|
|
617
571
|
}
|
|
572
|
+
|
|
573
|
+
function toU16(data: string, offset: number = 0): string {
|
|
574
|
+
return data.charCodeAt(offset + 0).toString();
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function toU32(data: string, offset: number = 0): string {
|
|
578
|
+
return ((data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0)).toString();
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function toU48(data: string, offset: number = 0): string {
|
|
582
|
+
return ((BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function toU64(data: string, offset: number = 0): string {
|
|
586
|
+
return ((BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function toMemCDecl(n: number, indent: string): string {
|
|
590
|
+
let out = "";
|
|
591
|
+
let offset = 0;
|
|
592
|
+
let index = 0;
|
|
593
|
+
while (n >= 8) {
|
|
594
|
+
out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`;
|
|
595
|
+
offset += 8;
|
|
596
|
+
n -= 8;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
while (n >= 4) {
|
|
600
|
+
out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`;
|
|
601
|
+
offset += 4;
|
|
602
|
+
n -= 4;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
if (n == 1) out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`;
|
|
606
|
+
|
|
607
|
+
return out;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function toMemCCheck(data: string): string {
|
|
611
|
+
let n = data.length << 1;
|
|
612
|
+
let out = "";
|
|
613
|
+
let offset = 0;
|
|
614
|
+
let index = 0;
|
|
615
|
+
while (n >= 8) {
|
|
616
|
+
out += ` && code${index++} == ${toU64(data, offset >> 1)}`;
|
|
617
|
+
offset += 8;
|
|
618
|
+
n -= 8;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
while (n >= 4) {
|
|
622
|
+
out += ` && code${index++} == ${toU32(data, offset >> 1)}`;
|
|
623
|
+
offset += 4;
|
|
624
|
+
n -= 4;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (n == 1) out += ` && code${index++} == ${toU16(data, offset >> 1)}`;
|
|
628
|
+
|
|
629
|
+
return out.slice(4);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function strToNum(data: string, simd: boolean = false, offset: number = 0): string[][] {
|
|
633
|
+
const out: string[][] = [];
|
|
634
|
+
let n = data.length;
|
|
635
|
+
|
|
636
|
+
while (n >= 8 && simd) {
|
|
637
|
+
out.push(["v128", "i16x8(" + data.charCodeAt(offset + 0) + ", " + data.charCodeAt(offset + 1) + ", " + data.charCodeAt(offset + 2) + ", " + data.charCodeAt(offset + 3) + ", " + data.charCodeAt(offset + 4) + ", " + data.charCodeAt(offset + 5) + ", " + data.charCodeAt(offset + 6) + ", " + data.charCodeAt(offset + 7) + ")"]);
|
|
638
|
+
|
|
639
|
+
offset += 8;
|
|
640
|
+
n -= 8;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
while (n >= 4) {
|
|
644
|
+
const value = (BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0));
|
|
645
|
+
out.push(["u64", value.toString()]);
|
|
646
|
+
offset += 4;
|
|
647
|
+
n -= 4;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
while (n >= 2) {
|
|
651
|
+
const value = (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0);
|
|
652
|
+
out.push(["u32", value.toString()]);
|
|
653
|
+
offset += 2;
|
|
654
|
+
n -= 2;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
if (n === 1) {
|
|
658
|
+
const value = data.charCodeAt(offset + 0);
|
|
659
|
+
out.push(["u16", value.toString()]);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
return out;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function isPrimitive(type: string): boolean {
|
|
666
|
+
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
|
|
667
|
+
return primitiveTypes.some((v) => type.includes(v));
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function throwError(message: string, range: Range): never {
|
|
671
|
+
const err = new Error();
|
|
672
|
+
err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
|
|
673
|
+
throw err;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function indentInc(): void {
|
|
677
|
+
indent += " ";
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function indentDec(): void {
|
|
681
|
+
indent = indent.slice(0, Math.max(0, indent.length - 2));
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function sizeof(type: string): number {
|
|
685
|
+
if (type == "u8")
|
|
686
|
+
return 6; // -127
|
|
687
|
+
else if (type == "i8")
|
|
688
|
+
return 8; // 255
|
|
689
|
+
else if (type == "u16")
|
|
690
|
+
return 10; // 65536
|
|
691
|
+
else if (type == "i16")
|
|
692
|
+
return 12; // -32767
|
|
693
|
+
else if (type == "u32")
|
|
694
|
+
return 20; // 4294967295
|
|
695
|
+
else if (type == "i32")
|
|
696
|
+
return 22; // -2147483647
|
|
697
|
+
else if (type == "u64")
|
|
698
|
+
return 40; // 18446744073709551615
|
|
699
|
+
else if (type == "i64")
|
|
700
|
+
return 40; // -9223372036854775807
|
|
701
|
+
else if (type == "bool" || type == "boolean") return 10;
|
|
702
|
+
else return 0;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
function allPrimitive(schema: Schema): boolean {
|
|
706
|
+
return !schema.members.some((p) => p.byteSize == 0);
|
|
707
|
+
}
|