json-as 1.0.8 → 1.0.9

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.
@@ -7,7 +7,9 @@ import { fileURLToPath } from "url";
7
7
  import { Property, PropertyFlags, Schema } from "./types.js";
8
8
  import { getClasses, getImportedClass } from "./linker.js";
9
9
  let indent = " ";
10
+ const DEBUG = process.env["JSON_DEBUG"];
10
11
  class JSONTransform extends Visitor {
12
+ static SN = new JSONTransform();
11
13
  program;
12
14
  baseDir;
13
15
  parser;
@@ -29,7 +31,12 @@ class JSONTransform extends Visitor {
29
31
  this.schema.node = node;
30
32
  this.schema.name = node.name.text;
31
33
  this.schemas.push(this.schema);
32
- if (process.env["JSON_DEBUG"])
34
+ let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
35
+ let INITIALIZE = "@inline __INITIALIZE(): this {\n";
36
+ let DESERIALIZE = "__DESERIALIZE<T>(srcStart: usize, srcEnd: usize, out: T): T {\n";
37
+ let DESERIALIZE_CUSTOM = "";
38
+ let SERIALIZE_CUSTOM = "";
39
+ if (DEBUG)
33
40
  console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath);
34
41
  const members = [...node.members.filter((v) => v.kind === 54 && v.flags !== 32 && v.flags !== 512 && v.flags !== 1024 && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
35
42
  const serializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "serializer"))];
@@ -39,6 +46,7 @@ class JSONTransform extends Visitor {
39
46
  if (deserializers.length > 1)
40
47
  throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
41
48
  if (serializers.length) {
49
+ this.schema.custom = true;
42
50
  const serializer = serializers[0];
43
51
  if (serializer.signature.parameters.length > 1)
44
52
  throwError("Found too many parameters in custom serializer for " + this.schema.name + ", but serializers can only accept one parameter of type '" + this.schema.name + "'!", serializer.signature.parameters[1].range);
@@ -49,20 +57,15 @@ class JSONTransform extends Visitor {
49
57
  if (!serializer.decorators.some((v) => v.name.text == "inline")) {
50
58
  serializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", serializer.range), null, serializer.range));
51
59
  }
52
- let SERIALIZER = "";
53
- SERIALIZER += " __SERIALIZE_CUSTOM(): void {\n";
54
- SERIALIZER += " const data = this." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "this" : "") + ");\n";
55
- SERIALIZER += " const dataSize = data.length << 1;\n";
56
- SERIALIZER += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
57
- SERIALIZER += " bs.offset += dataSize;\n";
58
- SERIALIZER += " }\n";
59
- if (process.env["JSON_DEBUG"])
60
- console.log(SERIALIZER);
61
- const SERIALIZER_METHOD = SimpleParser.parseClassMember(SERIALIZER, node);
62
- if (!node.members.find((v) => v.name.text == "__SERIALIZE_CUSTOM"))
63
- node.members.push(SERIALIZER_METHOD);
60
+ SERIALIZE_CUSTOM += " __SERIALIZE(ptr: usize): void {\n";
61
+ SERIALIZE_CUSTOM += " const data = this." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "this" : "") + ");\n";
62
+ SERIALIZE_CUSTOM += " const dataSize = data.length << 1;\n";
63
+ SERIALIZE_CUSTOM += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
64
+ SERIALIZE_CUSTOM += " bs.offset += dataSize;\n";
65
+ SERIALIZE_CUSTOM += " }\n";
64
66
  }
65
67
  if (deserializers.length) {
68
+ this.schema.custom = true;
66
69
  const deserializer = deserializers[0];
67
70
  if (!deserializer.signature.parameters.length)
68
71
  throwError("Could not find any parameters in custom deserializer for " + this.schema.name + ". Deserializers must have one parameter like 'deserializer(data: string): " + this.schema.name + " {}'", deserializer.range);
@@ -75,15 +78,9 @@ class JSONTransform extends Visitor {
75
78
  if (!deserializer.decorators.some((v) => v.name.text == "inline")) {
76
79
  deserializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", deserializer.range), null, deserializer.range));
77
80
  }
78
- let DESERIALIZER = "";
79
- DESERIALIZER += " __DESERIALIZE_CUSTOM(data: string): this {\n";
80
- DESERIALIZER += " return this." + deserializer.name.text + "(data);\n";
81
- DESERIALIZER += " }\n";
82
- if (process.env["JSON_DEBUG"])
83
- console.log(DESERIALIZER);
84
- const DESERIALIZER_METHOD = SimpleParser.parseClassMember(DESERIALIZER, node);
85
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE_CUSTOM"))
86
- node.members.push(DESERIALIZER_METHOD);
81
+ DESERIALIZE_CUSTOM += " __DESERIALIZE<T>(srcStart: usize, srcEnd: usize, out: T): T {\n";
82
+ DESERIALIZE_CUSTOM += " return inline.always(this." + deserializer.name.text + "(changetype<string>(srcStart)));\n";
83
+ DESERIALIZE_CUSTOM += " }\n";
87
84
  }
88
85
  if (node.extendsType) {
89
86
  const extendsName = node.extendsType?.name.identifier.text;
@@ -91,7 +88,7 @@ class JSONTransform extends Visitor {
91
88
  if (!this.schema.parent) {
92
89
  const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
93
90
  if (internalSearch) {
94
- if (process.env["JSON_DEBUG"])
91
+ if (DEBUG)
95
92
  console.log("Found " + extendsName + " internally");
96
93
  this.visitClassDeclaration(internalSearch);
97
94
  this.visitClassDeclaration(node);
@@ -99,7 +96,7 @@ class JSONTransform extends Visitor {
99
96
  }
100
97
  const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
101
98
  if (externalSearch) {
102
- if (process.env["JSON_DEBUG"])
99
+ if (DEBUG)
103
100
  console.log("Found " + extendsName + " externally");
104
101
  this.visitClassDeclaration(externalSearch);
105
102
  this.visitClassDeclaration(node);
@@ -172,9 +169,6 @@ class JSONTransform extends Visitor {
172
169
  }
173
170
  if (!this.schema.static)
174
171
  this.schema.members = sortMembers(this.schema.members);
175
- let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
176
- let INITIALIZE = "@inline __INITIALIZE(): this {\n";
177
- let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n";
178
172
  indent = " ";
179
173
  if (this.schema.static == false) {
180
174
  if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
@@ -282,86 +276,315 @@ class JSONTransform extends Visitor {
282
276
  }
283
277
  }
284
278
  }
285
- let sortedMembers = [];
286
- let len = -1;
287
- this.schema.members
288
- .slice()
289
- .sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
290
- .forEach((member) => {
291
- const _nameLength = member.alias?.length || member.name.length;
292
- if (_nameLength === len) {
293
- sortedMembers[sortedMembers.length - 1].push(member);
294
- }
295
- else {
296
- sortedMembers.push([member]);
297
- len = _nameLength;
298
- }
299
- });
300
- sortedMembers = sortedMembers.sort((a, b) => b.length - a.length);
301
- indentInc();
302
- for (const memberGroup of sortedMembers) {
303
- const memberLen = (memberGroup[0].alias || memberGroup[0].name).length << 1;
304
- DESERIALIZE += `${indent}case ${memberLen}: {\n`;
305
- indentInc();
306
- if (memberLen == 2)
307
- DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`;
308
- else if (memberLen == 4)
309
- DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`;
310
- else if (memberLen == 6)
311
- DESERIALIZE += `${indent}let code = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n`;
312
- else if (memberLen == 8)
313
- DESERIALIZE += `${indent}let code = load<u64>(keyStart);\n`;
279
+ const sortedMembers = {
280
+ string: [],
281
+ number: [],
282
+ boolean: [],
283
+ null: [],
284
+ array: [],
285
+ object: [],
286
+ };
287
+ for (const member of this.schema.members) {
288
+ if (member.type.endsWith(" | null"))
289
+ sortedMembers.null.push(member);
290
+ if (isString(member.type) || member.type == "JSON.Raw")
291
+ sortedMembers.string.push(member);
292
+ else if (isBoolean(member.type) || member.type.startsWith("JSON.Box<bool"))
293
+ sortedMembers.boolean.push(member);
294
+ else if (isPrimitive(member.type) || member.type.startsWith("JSON.Box<"))
295
+ sortedMembers.number.push(member);
296
+ else if (isArray(member.type))
297
+ sortedMembers.array.push(member);
314
298
  else
315
- DESERIALIZE += toMemCDecl(memberLen, indent);
316
- for (let i = 0; i < memberGroup.length; i++) {
317
- const member = memberGroup[i];
318
- const memberName = member.alias || member.name;
319
- const dst = this.schemas.find((v) => v.name == member.type) ? 'load<usize>(ptr + offsetof<this>("' + member.name + '"))' : "0";
320
- if (memberLen == 2) {
321
- DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`;
322
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
323
- DESERIALIZE += `${indent} return;\n`;
324
- DESERIALIZE += `${indent} }\n`;
325
- }
326
- else if (memberLen == 4) {
327
- DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`;
328
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
329
- DESERIALIZE += `${indent} return;\n`;
330
- DESERIALIZE += `${indent} }\n`;
331
- }
332
- else if (memberLen == 6) {
333
- DESERIALIZE += i == 0 ? indent : "";
334
- DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`;
335
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
336
- DESERIALIZE += `${indent} return;\n`;
337
- DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
338
- }
339
- else if (memberLen == 8) {
340
- DESERIALIZE += i == 0 ? indent : "";
341
- DESERIALIZE += `if (code == ${toU64(memberName)}) { // ${memberName}\n`;
342
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
343
- DESERIALIZE += `${indent} return;\n`;
344
- DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
299
+ sortedMembers.object.push(member);
300
+ }
301
+ indent = "";
302
+ let shouldGroup = false;
303
+ DESERIALIZE += indent + " let keyStart: usize = 0;\n";
304
+ if (shouldGroup || DEBUG)
305
+ DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
306
+ DESERIALIZE += indent + " let isKey = false;\n";
307
+ if (sortedMembers.object.length || sortedMembers.array.length)
308
+ DESERIALIZE += indent + " let depth: i32 = 0;\n";
309
+ DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
310
+ DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
311
+ DESERIALIZE += indent + " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
312
+ DESERIALIZE += indent + ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
313
+ DESERIALIZE += indent + " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
314
+ DESERIALIZE += indent + " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
315
+ DESERIALIZE += indent + " srcStart += 2;\n\n";
316
+ DESERIALIZE += indent + " while (srcStart < srcEnd) {\n";
317
+ DESERIALIZE += indent + " let code = load<u16>(srcStart);\n";
318
+ DESERIALIZE += indent + " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
319
+ DESERIALIZE += indent + " if (keyStart == 0) {\n";
320
+ DESERIALIZE += indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
321
+ DESERIALIZE += indent + " if (isKey) {\n";
322
+ DESERIALIZE += indent + " keyStart = lastIndex;\n";
323
+ if (shouldGroup || DEBUG)
324
+ DESERIALIZE += indent + " keyEnd = srcStart;\n";
325
+ DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
326
+ DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
327
+ DESERIALIZE += indent + " isKey = false;\n";
328
+ DESERIALIZE += indent + " } else {\n";
329
+ DESERIALIZE += indent + " isKey = true;\n";
330
+ DESERIALIZE += indent + " lastIndex = srcStart + 2;\n";
331
+ DESERIALIZE += indent + " }\n";
332
+ DESERIALIZE += indent + " }\n";
333
+ DESERIALIZE += indent + " srcStart += 2;\n";
334
+ DESERIALIZE += indent + " } else {\n";
335
+ const groupMembers = (members) => {
336
+ let sorted = [];
337
+ let len = -1;
338
+ members
339
+ .slice()
340
+ .sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
341
+ .forEach((member) => {
342
+ const _nameLength = member.alias?.length || member.name.length;
343
+ if (_nameLength === len) {
344
+ sorted[sorted.length - 1].push(member);
345
345
  }
346
346
  else {
347
- DESERIALIZE += i == 0 ? indent : "";
348
- DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`;
349
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
350
- DESERIALIZE += `${indent} return;\n`;
351
- DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
347
+ sorted.push([member]);
348
+ len = _nameLength;
352
349
  }
353
- }
354
- if (memberLen < 6) {
355
- DESERIALIZE += `${indent}}\n`;
356
- }
357
- indentDec();
358
- DESERIALIZE += `${indent} return;\n`;
359
- DESERIALIZE += `${indent}}\n`;
350
+ });
351
+ sorted = sorted.sort((a, b) => b.length - a.length);
352
+ return sorted;
353
+ };
354
+ const generateComparisions = (members) => {
355
+ if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
356
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
357
+ }
358
+ if (members.some((m) => (m.alias || m.name).length << 1 == 4)) {
359
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
360
+ }
361
+ if (members.some((m) => (m.alias || m.name).length << 1 == 6)) {
362
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
363
+ }
364
+ if (members.some((m) => (m.alias || m.name).length << 1 == 8)) {
365
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
366
+ }
367
+ if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
368
+ DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
369
+ }
370
+ const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
371
+ const firstMemberName = members[0].alias || members[0].name;
372
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
373
+ DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(firstMemberName) + "));\n";
374
+ if (!complex)
375
+ DESERIALIZE += indent + " srcStart += 2;\n";
376
+ DESERIALIZE += indent + " keyStart = 0;\n";
377
+ DESERIALIZE += indent + " break;\n";
378
+ DESERIALIZE += indent + " }";
379
+ for (let i = 1; i < members.length; i++) {
380
+ const member = members[i];
381
+ const memberName = member.alias || member.name;
382
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
383
+ DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(memberName) + "));\n";
384
+ if (isString(members[0].type))
385
+ DESERIALIZE += indent + " srcStart += 4;\n";
386
+ else if (!complex)
387
+ DESERIALIZE += indent + " srcStart += 2;\n";
388
+ DESERIALIZE += indent + " keyStart = 0;\n";
389
+ DESERIALIZE += indent + " break;\n";
390
+ DESERIALIZE += indent + " }";
391
+ }
392
+ DESERIALIZE += " else {\n";
393
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
394
+ DESERIALIZE += indent + " }\n";
395
+ };
396
+ let mbElse = " ";
397
+ if (sortedMembers.string.length) {
398
+ DESERIALIZE += mbElse + "if (code == 34) {\n";
399
+ DESERIALIZE += " lastIndex = srcStart;\n";
400
+ DESERIALIZE += " srcStart += 2;\n";
401
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
402
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
403
+ DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
404
+ DESERIALIZE += " srcStart += 2;\n";
405
+ generateComparisions(sortedMembers.string);
406
+ DESERIALIZE += " }\n";
407
+ DESERIALIZE += " srcStart += 2;\n";
408
+ DESERIALIZE += " }\n";
409
+ DESERIALIZE += " }\n";
410
+ mbElse = " else ";
411
+ }
412
+ if (sortedMembers.number.length) {
413
+ DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
414
+ DESERIALIZE += " lastIndex = srcStart;\n";
415
+ DESERIALIZE += " srcStart += 2;\n";
416
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
417
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
418
+ DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
419
+ generateComparisions(sortedMembers.number);
420
+ DESERIALIZE += " }\n";
421
+ DESERIALIZE += " srcStart += 2;\n";
422
+ DESERIALIZE += " }\n";
423
+ DESERIALIZE += " }";
424
+ mbElse = " else ";
425
+ }
426
+ if (sortedMembers.object.length) {
427
+ DESERIALIZE += mbElse + "if (code == 123) {\n";
428
+ DESERIALIZE += " lastIndex = srcStart;\n";
429
+ DESERIALIZE += " depth++;\n";
430
+ DESERIALIZE += " srcStart += 2;\n";
431
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
432
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
433
+ DESERIALIZE += " if (code == 34) {\n";
434
+ DESERIALIZE += " srcStart += 2;\n";
435
+ DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
436
+ DESERIALIZE += " } else if (code == 125) {\n";
437
+ DESERIALIZE += " if (--depth == 0) {\n";
438
+ DESERIALIZE += " srcStart += 2;\n";
439
+ indent = " ";
440
+ generateComparisions(sortedMembers.object);
441
+ indent = "";
442
+ DESERIALIZE += " }\n";
443
+ DESERIALIZE += " } else if (code == 123) depth++;\n";
444
+ DESERIALIZE += " srcStart += 2;\n";
445
+ DESERIALIZE += " }\n";
446
+ DESERIALIZE += " }";
447
+ mbElse = " else ";
448
+ }
449
+ if (sortedMembers.array.length) {
450
+ DESERIALIZE += mbElse + "if (code == 91) {\n";
451
+ DESERIALIZE += " lastIndex = srcStart;\n";
452
+ DESERIALIZE += " depth++;\n";
453
+ DESERIALIZE += " srcStart += 2;\n";
454
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
455
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
456
+ DESERIALIZE += " if (code == 34) {\n";
457
+ DESERIALIZE += " srcStart += 2;\n";
458
+ DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
459
+ DESERIALIZE += " } else if (code == 93) {\n";
460
+ DESERIALIZE += " if (--depth == 0) {\n";
461
+ DESERIALIZE += " srcStart += 2;\n";
462
+ indent = " ";
463
+ generateComparisions(sortedMembers.array);
464
+ indent = "";
465
+ DESERIALIZE += " }\n";
466
+ DESERIALIZE += " } else if (code == 91) depth++;\n";
467
+ DESERIALIZE += " srcStart += 2;\n";
468
+ DESERIALIZE += " }\n";
469
+ DESERIALIZE += " }";
470
+ mbElse = " else ";
471
+ }
472
+ if (sortedMembers.boolean.length) {
473
+ DESERIALIZE += mbElse + "if (code == 116) {\n";
474
+ DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
475
+ DESERIALIZE += " srcStart += 8;\n";
476
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 2)) {
477
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
478
+ }
479
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 4)) {
480
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
481
+ }
482
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 6)) {
483
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
484
+ }
485
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 8)) {
486
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
487
+ }
488
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 > 8)) {
489
+ DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.boolean.map((m) => (m.alias || m.name).length << 1)), " ");
490
+ }
491
+ const firstMemberName = sortedMembers.boolean[0].alias || sortedMembers.boolean[0].name;
492
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
493
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
494
+ DESERIALIZE += indent + " srcStart += 2;\n";
495
+ DESERIALIZE += indent + " keyStart = 0;\n";
496
+ DESERIALIZE += indent + " break;\n";
497
+ DESERIALIZE += indent + " }";
498
+ for (let i = 1; i < sortedMembers.boolean.length; i++) {
499
+ const member = sortedMembers.boolean[i];
500
+ const memberName = member.alias || member.name;
501
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
502
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
503
+ DESERIALIZE += indent + " srcStart += 2;\n";
504
+ DESERIALIZE += indent + " keyStart = 0;\n";
505
+ DESERIALIZE += indent + " break;\n";
506
+ DESERIALIZE += indent + " }";
507
+ }
508
+ DESERIALIZE += " else {\n";
509
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
510
+ DESERIALIZE += indent + " }\n";
511
+ DESERIALIZE += " }";
512
+ mbElse = " else ";
513
+ DESERIALIZE += " else if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
514
+ DESERIALIZE += " srcStart += 10;\n";
515
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
516
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
517
+ DESERIALIZE += indent + " srcStart += 2;\n";
518
+ DESERIALIZE += indent + " keyStart = 0;\n";
519
+ DESERIALIZE += indent + " break;\n";
520
+ DESERIALIZE += indent + " }";
521
+ for (let i = 1; i < sortedMembers.boolean.length; i++) {
522
+ const member = sortedMembers.boolean[i];
523
+ const memberName = member.alias || member.name;
524
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
525
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
526
+ DESERIALIZE += indent + " srcStart += 2;\n";
527
+ DESERIALIZE += indent + " keyStart = 0;\n";
528
+ DESERIALIZE += indent + " break;\n";
529
+ DESERIALIZE += indent + " }";
530
+ }
531
+ DESERIALIZE += " else {\n";
532
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
533
+ DESERIALIZE += indent + " }\n";
534
+ DESERIALIZE += " }\n";
535
+ DESERIALIZE += " }";
360
536
  }
537
+ if (sortedMembers.null.length) {
538
+ DESERIALIZE += mbElse + "if (code == 110) {\n";
539
+ DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
540
+ DESERIALIZE += " srcStart += 8;\n";
541
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 2)) {
542
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
543
+ }
544
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 4)) {
545
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
546
+ }
547
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 6)) {
548
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
549
+ }
550
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 8)) {
551
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
552
+ }
553
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 > 8)) {
554
+ DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.null.map((m) => (m.alias || m.name).length << 1)), " ");
555
+ }
556
+ const firstMemberName = sortedMembers.null[0].alias || sortedMembers.null[0].name;
557
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
558
+ DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
559
+ DESERIALIZE += indent + " srcStart += 2;\n";
560
+ DESERIALIZE += indent + " keyStart = 0;\n";
561
+ DESERIALIZE += indent + " break;\n";
562
+ DESERIALIZE += indent + " }";
563
+ for (let i = 1; i < sortedMembers.null.length; i++) {
564
+ const member = sortedMembers.null[i];
565
+ const memberName = member.alias || member.name;
566
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
567
+ DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
568
+ DESERIALIZE += indent + " srcStart += 2;\n";
569
+ DESERIALIZE += indent + " keyStart = 0;\n";
570
+ DESERIALIZE += indent + " break;\n";
571
+ DESERIALIZE += indent + " }";
572
+ }
573
+ DESERIALIZE += " else {\n";
574
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
575
+ DESERIALIZE += indent + " }\n";
576
+ DESERIALIZE += " }";
577
+ DESERIALIZE += "\n }";
578
+ mbElse = " else ";
579
+ }
580
+ DESERIALIZE += " else {\n";
581
+ DESERIALIZE += " srcStart += 2;\n";
582
+ DESERIALIZE += "}\n";
583
+ DESERIALIZE += "\n }\n";
361
584
  indentDec();
362
- DESERIALIZE += `${indent}}\n`;
585
+ DESERIALIZE += ` }\n`;
363
586
  indentDec();
364
- DESERIALIZE += `${indent}}\n`;
587
+ DESERIALIZE += ` return out;\n}\n`;
365
588
  indent = " ";
366
589
  this.schema.byteSize += 2;
367
590
  SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
@@ -370,14 +593,14 @@ class JSONTransform extends Visitor {
370
593
  SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
371
594
  INITIALIZE += " return this;\n";
372
595
  INITIALIZE += "}";
373
- if (process.env["JSON_DEBUG"]) {
374
- console.log(SERIALIZE);
596
+ if (DEBUG) {
597
+ console.log(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE);
375
598
  console.log(INITIALIZE);
376
- console.log(DESERIALIZE);
599
+ console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
377
600
  }
378
- const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
601
+ const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE, node);
379
602
  const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
380
- const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
603
+ const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE_CUSTOM || DESERIALIZE, node);
381
604
  if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
382
605
  node.members.push(SERIALIZE_METHOD);
383
606
  if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
@@ -389,8 +612,8 @@ class JSONTransform extends Visitor {
389
612
  generateEmptyMethods(node) {
390
613
  let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
391
614
  let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
392
- let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {}";
393
- if (process.env["JSON_DEBUG"]) {
615
+ let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(srcStart: usize, srcEnd: usize): this {\n return this;\n}";
616
+ if (DEBUG) {
394
617
  console.log(SERIALIZE_EMPTY);
395
618
  console.log(INITIALIZE_EMPTY);
396
619
  console.log(DESERIALIZE_EMPTY);
@@ -427,7 +650,7 @@ class JSONTransform extends Visitor {
427
650
  }
428
651
  const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
429
652
  this.topStatements.push(replaceNode);
430
- if (process.env["JSON_DEBUG"])
653
+ if (DEBUG)
431
654
  console.log("Added as-bs import: " + toString(replaceNode) + "\n");
432
655
  }
433
656
  if (!jsonImport) {
@@ -436,7 +659,7 @@ class JSONTransform extends Visitor {
436
659
  }
437
660
  const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(jsonPath, node.range), node.range);
438
661
  this.topStatements.push(replaceNode);
439
- if (process.env["JSON_DEBUG"])
662
+ if (DEBUG)
440
663
  console.log("Added json-as import: " + toString(replaceNode) + "\n");
441
664
  }
442
665
  }
@@ -488,7 +711,7 @@ class JSONTransform extends Visitor {
488
711
  }
489
712
  export default class Transformer extends Transform {
490
713
  afterParse(parser) {
491
- const transformer = new JSONTransform();
714
+ const transformer = JSONTransform.SN;
492
715
  const sources = parser.sources
493
716
  .filter((source) => {
494
717
  const p = source.internalPath;
@@ -575,17 +798,17 @@ function toMemCDecl(n, indent) {
575
798
  let offset = 0;
576
799
  let index = 0;
577
800
  while (n >= 8) {
578
- out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`;
801
+ out += `${indent}const codeS${(index += 8)} = load<u64>(keyStart, ${offset});\n`;
579
802
  offset += 8;
580
803
  n -= 8;
581
804
  }
582
805
  while (n >= 4) {
583
- out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`;
806
+ out += `${indent}const codeS${(index += 4)} = load<u32>(keyStart, ${offset});\n`;
584
807
  offset += 4;
585
808
  n -= 4;
586
809
  }
587
810
  if (n == 1)
588
- out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`;
811
+ out += `${indent}const codeS${(index += 1)} = load<u16>(keyStart, ${offset});\n`;
589
812
  return out;
590
813
  }
591
814
  function toMemCCheck(data) {
@@ -594,17 +817,17 @@ function toMemCCheck(data) {
594
817
  let offset = 0;
595
818
  let index = 0;
596
819
  while (n >= 8) {
597
- out += ` && code${index++} == ${toU64(data, offset >> 1)}`;
820
+ out += ` && codeS${(index += 8)} == ${toU64(data, offset >> 1)}`;
598
821
  offset += 8;
599
822
  n -= 8;
600
823
  }
601
824
  while (n >= 4) {
602
- out += ` && code${index++} == ${toU32(data, offset >> 1)}`;
825
+ out += ` && codeS${(index += 4)} == ${toU32(data, offset >> 1)}`;
603
826
  offset += 4;
604
827
  n -= 4;
605
828
  }
606
829
  if (n == 1)
607
- out += ` && code${index++} == ${toU16(data, offset >> 1)}`;
830
+ out += ` && codeS${(index += 1)} == ${toU16(data, offset >> 1)}`;
608
831
  return out.slice(4);
609
832
  }
610
833
  function strToNum(data, simd = false, offset = 0) {
@@ -633,10 +856,6 @@ function strToNum(data, simd = false, offset = 0) {
633
856
  }
634
857
  return out;
635
858
  }
636
- function isPrimitive(type) {
637
- const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
638
- return primitiveTypes.some((v) => type.startsWith(v));
639
- }
640
859
  function throwError(message, range) {
641
860
  const err = new Error();
642
861
  err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
@@ -670,4 +889,46 @@ function sizeof(type) {
670
889
  else
671
890
  return 0;
672
891
  }
892
+ function isPrimitive(type) {
893
+ const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
894
+ return primitiveTypes.some((v) => type.startsWith(v));
895
+ }
896
+ function isBoolean(type) {
897
+ return type == "bool" || type == "boolean";
898
+ }
899
+ function isStruct(type) {
900
+ type = stripNull(type);
901
+ return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
902
+ }
903
+ function isString(type) {
904
+ return stripNull(type) == "string" || stripNull(type) == "String";
905
+ }
906
+ function isArray(type) {
907
+ return type.startsWith("Array<");
908
+ }
909
+ function stripNull(type) {
910
+ if (type.endsWith(" | null")) {
911
+ return type.slice(0, type.length - 7);
912
+ }
913
+ return type;
914
+ }
915
+ function getComparision(data) {
916
+ switch (data.length << 1) {
917
+ case 2: {
918
+ return "code16 == " + data.charCodeAt(0);
919
+ }
920
+ case 4: {
921
+ return "code32 == " + toU32(data);
922
+ }
923
+ case 6: {
924
+ return "code48 == " + toU48(data);
925
+ }
926
+ case 8: {
927
+ return "code64 == " + toU64(data);
928
+ }
929
+ default: {
930
+ return toMemCCheck(data);
931
+ }
932
+ }
933
+ }
673
934
  //# sourceMappingURL=index.js.map