json-as 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_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<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_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,317 @@ 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 + " console.log(\"data: \" + JSON.Util.ptrToStr(srcStart,srcEnd))\n";
304
+ DESERIALIZE += indent + " let keyStart: usize = 0;\n";
305
+ if (shouldGroup || DEBUG)
306
+ DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
307
+ DESERIALIZE += indent + " let isKey = false;\n";
308
+ if (sortedMembers.object.length || sortedMembers.array.length)
309
+ DESERIALIZE += indent + " let depth: i32 = 0;\n";
310
+ DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
311
+ DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
312
+ DESERIALIZE += indent + " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
313
+ DESERIALIZE += indent + ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
314
+ DESERIALIZE += indent + " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
315
+ DESERIALIZE += indent + " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
316
+ DESERIALIZE += indent + " srcStart += 2;\n\n";
317
+ DESERIALIZE += indent + " while (srcStart < srcEnd) {\n";
318
+ DESERIALIZE += indent + " let code = load<u16>(srcStart);\n";
319
+ DESERIALIZE += indent + " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
320
+ DESERIALIZE += indent + " if (keyStart == 0) {\n";
321
+ DESERIALIZE += indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
322
+ DESERIALIZE += indent + " if (isKey) {\n";
323
+ DESERIALIZE += indent + " keyStart = lastIndex;\n";
324
+ if (shouldGroup || DEBUG)
325
+ DESERIALIZE += indent + " keyEnd = srcStart;\n";
326
+ DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
327
+ DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
328
+ DESERIALIZE += indent + " isKey = false;\n";
329
+ DESERIALIZE += indent + " } else {\n";
330
+ DESERIALIZE += indent + " isKey = true;\n";
331
+ DESERIALIZE += indent + " lastIndex = srcStart + 2;\n";
332
+ DESERIALIZE += indent + " }\n";
333
+ DESERIALIZE += indent + " }\n";
334
+ DESERIALIZE += indent + " srcStart += 2;\n";
335
+ DESERIALIZE += indent + " } else {\n";
336
+ const groupMembers = (members) => {
337
+ let sorted = [];
338
+ let len = -1;
339
+ members
340
+ .slice()
341
+ .sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
342
+ .forEach((member) => {
343
+ const _nameLength = member.alias?.length || member.name.length;
344
+ if (_nameLength === len) {
345
+ sorted[sorted.length - 1].push(member);
345
346
  }
346
347
  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"}`;
348
+ sorted.push([member]);
349
+ len = _nameLength;
352
350
  }
353
- }
354
- if (memberLen < 6) {
355
- DESERIALIZE += `${indent}}\n`;
356
- }
357
- indentDec();
358
- DESERIALIZE += `${indent} return;\n`;
359
- DESERIALIZE += `${indent}}\n`;
351
+ });
352
+ sorted = sorted.sort((a, b) => b.length - a.length);
353
+ return sorted;
354
+ };
355
+ const generateComparisions = (members) => {
356
+ if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
357
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
358
+ }
359
+ if (members.some((m) => (m.alias || m.name).length << 1 == 4)) {
360
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
361
+ }
362
+ if (members.some((m) => (m.alias || m.name).length << 1 == 6)) {
363
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
364
+ }
365
+ if (members.some((m) => (m.alias || m.name).length << 1 == 8)) {
366
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
367
+ }
368
+ if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
369
+ DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
370
+ }
371
+ const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
372
+ const firstMemberName = members[0].alias || members[0].name;
373
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
374
+ DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(firstMemberName) + "));\n";
375
+ if (!complex)
376
+ DESERIALIZE += indent + " srcStart += 2;\n";
377
+ DESERIALIZE += indent + " keyStart = 0;\n";
378
+ DESERIALIZE += indent + " break;\n";
379
+ DESERIALIZE += indent + " }";
380
+ for (let i = 1; i < members.length; i++) {
381
+ const member = members[i];
382
+ const memberName = member.alias || member.name;
383
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
384
+ DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(memberName) + "));\n";
385
+ if (isString(members[0].type))
386
+ DESERIALIZE += indent + " srcStart += 4;\n";
387
+ else if (!complex)
388
+ DESERIALIZE += indent + " srcStart += 2;\n";
389
+ DESERIALIZE += indent + " keyStart = 0;\n";
390
+ DESERIALIZE += indent + " break;\n";
391
+ DESERIALIZE += indent + " }";
392
+ }
393
+ DESERIALIZE += " else {\n";
394
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
395
+ DESERIALIZE += indent + " }\n";
396
+ };
397
+ let mbElse = " ";
398
+ if (sortedMembers.string.length) {
399
+ DESERIALIZE += mbElse + "if (code == 34) {\n";
400
+ DESERIALIZE += " lastIndex = srcStart;\n";
401
+ DESERIALIZE += " srcStart += 2;\n";
402
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
403
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
404
+ DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
405
+ DESERIALIZE += " srcStart += 2;\n";
406
+ DESERIALIZE += " console.log(JSON.Util.ptrToStr(keyStart,keyEnd) + \" = \" + load<u16>(keyStart).toString() + \" val \" + JSON.Util.ptrToStr(lastIndex, srcStart));\n";
407
+ generateComparisions(sortedMembers.string);
408
+ DESERIALIZE += " }\n";
409
+ DESERIALIZE += " srcStart += 2;\n";
410
+ DESERIALIZE += " }\n";
411
+ DESERIALIZE += " }\n";
412
+ mbElse = " else ";
413
+ }
414
+ if (sortedMembers.number.length) {
415
+ DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
416
+ DESERIALIZE += " lastIndex = srcStart;\n";
417
+ DESERIALIZE += " srcStart += 2;\n";
418
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
419
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
420
+ DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
421
+ generateComparisions(sortedMembers.number);
422
+ DESERIALIZE += " }\n";
423
+ DESERIALIZE += " srcStart += 2;\n";
424
+ DESERIALIZE += " }\n";
425
+ DESERIALIZE += " }";
426
+ mbElse = " else ";
427
+ }
428
+ if (sortedMembers.object.length) {
429
+ DESERIALIZE += mbElse + "if (code == 123) {\n";
430
+ DESERIALIZE += " lastIndex = srcStart;\n";
431
+ DESERIALIZE += " depth++;\n";
432
+ DESERIALIZE += " srcStart += 2;\n";
433
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
434
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
435
+ DESERIALIZE += " if (code == 34) {\n";
436
+ DESERIALIZE += " srcStart += 2;\n";
437
+ DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
438
+ DESERIALIZE += " } else if (code == 125) {\n";
439
+ DESERIALIZE += " if (--depth == 0) {\n";
440
+ DESERIALIZE += " srcStart += 2;\n";
441
+ indent = " ";
442
+ generateComparisions(sortedMembers.object);
443
+ indent = "";
444
+ DESERIALIZE += " }\n";
445
+ DESERIALIZE += " } else if (code == 123) depth++;\n";
446
+ DESERIALIZE += " srcStart += 2;\n";
447
+ DESERIALIZE += " }\n";
448
+ DESERIALIZE += " }";
449
+ mbElse = " else ";
450
+ }
451
+ if (sortedMembers.array.length) {
452
+ DESERIALIZE += mbElse + "if (code == 91) {\n";
453
+ DESERIALIZE += " lastIndex = srcStart;\n";
454
+ DESERIALIZE += " depth++;\n";
455
+ DESERIALIZE += " srcStart += 2;\n";
456
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
457
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
458
+ DESERIALIZE += " if (code == 34) {\n";
459
+ DESERIALIZE += " srcStart += 2;\n";
460
+ DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
461
+ DESERIALIZE += " } else if (code == 93) {\n";
462
+ DESERIALIZE += " if (--depth == 0) {\n";
463
+ DESERIALIZE += " srcStart += 2;\n";
464
+ indent = " ";
465
+ generateComparisions(sortedMembers.array);
466
+ indent = "";
467
+ DESERIALIZE += " }\n";
468
+ DESERIALIZE += " } else if (code == 91) depth++;\n";
469
+ DESERIALIZE += " srcStart += 2;\n";
470
+ DESERIALIZE += " }\n";
471
+ DESERIALIZE += " }";
472
+ mbElse = " else ";
473
+ }
474
+ if (sortedMembers.boolean.length) {
475
+ DESERIALIZE += mbElse + "if (code == 116) {\n";
476
+ DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
477
+ DESERIALIZE += " srcStart += 8;\n";
478
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 2)) {
479
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
480
+ }
481
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 4)) {
482
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
483
+ }
484
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 6)) {
485
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
486
+ }
487
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 8)) {
488
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
489
+ }
490
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 > 8)) {
491
+ DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.boolean.map((m) => (m.alias || m.name).length << 1)), " ");
492
+ }
493
+ const firstMemberName = sortedMembers.boolean[0].alias || sortedMembers.boolean[0].name;
494
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
495
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
496
+ DESERIALIZE += indent + " srcStart += 2;\n";
497
+ DESERIALIZE += indent + " keyStart = 0;\n";
498
+ DESERIALIZE += indent + " break;\n";
499
+ DESERIALIZE += indent + " }";
500
+ for (let i = 1; i < sortedMembers.boolean.length; i++) {
501
+ const member = sortedMembers.boolean[i];
502
+ const memberName = member.alias || member.name;
503
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
504
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
505
+ DESERIALIZE += indent + " srcStart += 2;\n";
506
+ DESERIALIZE += indent + " keyStart = 0;\n";
507
+ DESERIALIZE += indent + " break;\n";
508
+ DESERIALIZE += indent + " }";
509
+ }
510
+ DESERIALIZE += " else {\n";
511
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
512
+ DESERIALIZE += indent + " }\n";
513
+ DESERIALIZE += " }";
514
+ mbElse = " else ";
515
+ DESERIALIZE += " else if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
516
+ DESERIALIZE += " srcStart += 10;\n";
517
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
518
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
519
+ DESERIALIZE += indent + " srcStart += 2;\n";
520
+ DESERIALIZE += indent + " keyStart = 0;\n";
521
+ DESERIALIZE += indent + " break;\n";
522
+ DESERIALIZE += indent + " }";
523
+ for (let i = 1; i < sortedMembers.boolean.length; i++) {
524
+ const member = sortedMembers.boolean[i];
525
+ const memberName = member.alias || member.name;
526
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
527
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
528
+ DESERIALIZE += indent + " srcStart += 2;\n";
529
+ DESERIALIZE += indent + " keyStart = 0;\n";
530
+ DESERIALIZE += indent + " break;\n";
531
+ DESERIALIZE += indent + " }";
532
+ }
533
+ DESERIALIZE += " else {\n";
534
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
535
+ DESERIALIZE += indent + " }\n";
536
+ DESERIALIZE += " }\n";
537
+ DESERIALIZE += " }";
360
538
  }
539
+ if (sortedMembers.null.length) {
540
+ DESERIALIZE += mbElse + "if (code == 110) {\n";
541
+ DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
542
+ DESERIALIZE += " srcStart += 8;\n";
543
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 2)) {
544
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
545
+ }
546
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 4)) {
547
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
548
+ }
549
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 6)) {
550
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
551
+ }
552
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 8)) {
553
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
554
+ }
555
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 > 8)) {
556
+ DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.null.map((m) => (m.alias || m.name).length << 1)), " ");
557
+ }
558
+ const firstMemberName = sortedMembers.null[0].alias || sortedMembers.null[0].name;
559
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
560
+ DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
561
+ DESERIALIZE += indent + " srcStart += 2;\n";
562
+ DESERIALIZE += indent + " keyStart = 0;\n";
563
+ DESERIALIZE += indent + " break;\n";
564
+ DESERIALIZE += indent + " }";
565
+ for (let i = 1; i < sortedMembers.null.length; i++) {
566
+ const member = sortedMembers.null[i];
567
+ const memberName = member.alias || member.name;
568
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
569
+ DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
570
+ DESERIALIZE += indent + " srcStart += 2;\n";
571
+ DESERIALIZE += indent + " keyStart = 0;\n";
572
+ DESERIALIZE += indent + " break;\n";
573
+ DESERIALIZE += indent + " }";
574
+ }
575
+ DESERIALIZE += " else {\n";
576
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
577
+ DESERIALIZE += indent + " }\n";
578
+ DESERIALIZE += " }";
579
+ DESERIALIZE += "\n }";
580
+ mbElse = " else ";
581
+ }
582
+ DESERIALIZE += " else {\n";
583
+ DESERIALIZE += " srcStart += 2;\n";
584
+ DESERIALIZE += "}\n";
585
+ DESERIALIZE += "\n }\n";
361
586
  indentDec();
362
- DESERIALIZE += `${indent}}\n`;
587
+ DESERIALIZE += ` }\n`;
363
588
  indentDec();
364
- DESERIALIZE += `${indent}}\n`;
589
+ DESERIALIZE += ` return out;\n}\n`;
365
590
  indent = " ";
366
591
  this.schema.byteSize += 2;
367
592
  SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
@@ -370,14 +595,14 @@ class JSONTransform extends Visitor {
370
595
  SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
371
596
  INITIALIZE += " return this;\n";
372
597
  INITIALIZE += "}";
373
- if (process.env["JSON_DEBUG"]) {
374
- console.log(SERIALIZE);
598
+ if (DEBUG) {
599
+ console.log(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE);
375
600
  console.log(INITIALIZE);
376
- console.log(DESERIALIZE);
601
+ console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
377
602
  }
378
- const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
603
+ const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE, node);
379
604
  const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
380
- const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
605
+ const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE_CUSTOM || DESERIALIZE, node);
381
606
  if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
382
607
  node.members.push(SERIALIZE_METHOD);
383
608
  if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
@@ -389,8 +614,8 @@ class JSONTransform extends Visitor {
389
614
  generateEmptyMethods(node) {
390
615
  let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
391
616
  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"]) {
617
+ let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return this;\n}";
618
+ if (DEBUG) {
394
619
  console.log(SERIALIZE_EMPTY);
395
620
  console.log(INITIALIZE_EMPTY);
396
621
  console.log(DESERIALIZE_EMPTY);
@@ -427,7 +652,7 @@ class JSONTransform extends Visitor {
427
652
  }
428
653
  const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
429
654
  this.topStatements.push(replaceNode);
430
- if (process.env["JSON_DEBUG"])
655
+ if (DEBUG)
431
656
  console.log("Added as-bs import: " + toString(replaceNode) + "\n");
432
657
  }
433
658
  if (!jsonImport) {
@@ -436,7 +661,7 @@ class JSONTransform extends Visitor {
436
661
  }
437
662
  const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(jsonPath, node.range), node.range);
438
663
  this.topStatements.push(replaceNode);
439
- if (process.env["JSON_DEBUG"])
664
+ if (DEBUG)
440
665
  console.log("Added json-as import: " + toString(replaceNode) + "\n");
441
666
  }
442
667
  }
@@ -488,7 +713,7 @@ class JSONTransform extends Visitor {
488
713
  }
489
714
  export default class Transformer extends Transform {
490
715
  afterParse(parser) {
491
- const transformer = new JSONTransform();
716
+ const transformer = JSONTransform.SN;
492
717
  const sources = parser.sources
493
718
  .filter((source) => {
494
719
  const p = source.internalPath;
@@ -575,17 +800,17 @@ function toMemCDecl(n, indent) {
575
800
  let offset = 0;
576
801
  let index = 0;
577
802
  while (n >= 8) {
578
- out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`;
803
+ out += `${indent}const codeS${(index += 8)} = load<u64>(keyStart, ${offset});\n`;
579
804
  offset += 8;
580
805
  n -= 8;
581
806
  }
582
807
  while (n >= 4) {
583
- out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`;
808
+ out += `${indent}const codeS${(index += 4)} = load<u32>(keyStart, ${offset});\n`;
584
809
  offset += 4;
585
810
  n -= 4;
586
811
  }
587
812
  if (n == 1)
588
- out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`;
813
+ out += `${indent}const codeS${(index += 1)} = load<u16>(keyStart, ${offset});\n`;
589
814
  return out;
590
815
  }
591
816
  function toMemCCheck(data) {
@@ -594,17 +819,17 @@ function toMemCCheck(data) {
594
819
  let offset = 0;
595
820
  let index = 0;
596
821
  while (n >= 8) {
597
- out += ` && code${index++} == ${toU64(data, offset >> 1)}`;
822
+ out += ` && codeS${(index += 8)} == ${toU64(data, offset >> 1)}`;
598
823
  offset += 8;
599
824
  n -= 8;
600
825
  }
601
826
  while (n >= 4) {
602
- out += ` && code${index++} == ${toU32(data, offset >> 1)}`;
827
+ out += ` && codeS${(index += 4)} == ${toU32(data, offset >> 1)}`;
603
828
  offset += 4;
604
829
  n -= 4;
605
830
  }
606
831
  if (n == 1)
607
- out += ` && code${index++} == ${toU16(data, offset >> 1)}`;
832
+ out += ` && codeS${(index += 1)} == ${toU16(data, offset >> 1)}`;
608
833
  return out.slice(4);
609
834
  }
610
835
  function strToNum(data, simd = false, offset = 0) {
@@ -633,10 +858,6 @@ function strToNum(data, simd = false, offset = 0) {
633
858
  }
634
859
  return out;
635
860
  }
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
861
  function throwError(message, range) {
641
862
  const err = new Error();
642
863
  err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
@@ -670,4 +891,46 @@ function sizeof(type) {
670
891
  else
671
892
  return 0;
672
893
  }
894
+ function isPrimitive(type) {
895
+ const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
896
+ return primitiveTypes.some((v) => type.startsWith(v));
897
+ }
898
+ function isBoolean(type) {
899
+ return type == "bool" || type == "boolean";
900
+ }
901
+ function isStruct(type) {
902
+ type = stripNull(type);
903
+ return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
904
+ }
905
+ function isString(type) {
906
+ return stripNull(type) == "string" || stripNull(type) == "String";
907
+ }
908
+ function isArray(type) {
909
+ return type.startsWith("Array<");
910
+ }
911
+ function stripNull(type) {
912
+ if (type.endsWith(" | null")) {
913
+ return type.slice(0, type.length - 7);
914
+ }
915
+ return type;
916
+ }
917
+ function getComparision(data) {
918
+ switch (data.length << 1) {
919
+ case 2: {
920
+ return "code16 == " + data.charCodeAt(0);
921
+ }
922
+ case 4: {
923
+ return "code32 == " + toU32(data);
924
+ }
925
+ case 6: {
926
+ return "code48 == " + toU48(data);
927
+ }
928
+ case 8: {
929
+ return "code64 == " + toU64(data);
930
+ }
931
+ default: {
932
+ return toMemCCheck(data);
933
+ }
934
+ }
935
+ }
673
936
  //# sourceMappingURL=index.js.map