json-as 1.3.9 → 1.5.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.
Files changed (122) hide show
  1. package/CHANGELOG.md +60 -19
  2. package/README.md +120 -21
  3. package/assembly/custom/chars.ts +39 -78
  4. package/assembly/deserialize/index/arbitrary.ts +28 -10
  5. package/assembly/deserialize/index/float.ts +2 -4
  6. package/assembly/deserialize/index/integer.ts +2 -4
  7. package/assembly/deserialize/index/object.ts +6 -1
  8. package/assembly/deserialize/index/string.ts +2 -7
  9. package/assembly/deserialize/index/unsigned.ts +2 -4
  10. package/assembly/deserialize/naive/array/arbitrary.ts +3 -136
  11. package/assembly/deserialize/naive/array/array.ts +30 -1
  12. package/assembly/deserialize/naive/array/integer.ts +2 -7
  13. package/assembly/deserialize/naive/array/map.ts +10 -14
  14. package/assembly/deserialize/naive/array/object.ts +10 -14
  15. package/assembly/deserialize/naive/array/struct.ts +19 -1
  16. package/assembly/deserialize/naive/bool.ts +1 -5
  17. package/assembly/deserialize/naive/date.ts +1 -2
  18. package/assembly/deserialize/naive/float.ts +4 -11
  19. package/assembly/deserialize/naive/integer.ts +2 -4
  20. package/assembly/deserialize/naive/map.ts +42 -205
  21. package/assembly/deserialize/naive/object.ts +291 -174
  22. package/assembly/deserialize/naive/raw.ts +1 -5
  23. package/assembly/deserialize/naive/set.ts +3 -6
  24. package/assembly/deserialize/naive/staticarray.ts +2 -4
  25. package/assembly/deserialize/naive/string.ts +68 -24
  26. package/assembly/deserialize/naive/typedarray.ts +1 -2
  27. package/assembly/deserialize/naive/unsigned.ts +2 -4
  28. package/assembly/deserialize/simd/array/integer.ts +5 -13
  29. package/assembly/deserialize/simd/float.ts +5 -12
  30. package/assembly/deserialize/simd/integer.ts +6 -15
  31. package/assembly/deserialize/simd/string.ts +21 -43
  32. package/assembly/deserialize/swar/array/arbitrary.ts +1 -2
  33. package/assembly/deserialize/swar/array/array.ts +2 -4
  34. package/assembly/deserialize/swar/array/bool.ts +2 -4
  35. package/assembly/deserialize/swar/array/box.ts +1 -2
  36. package/assembly/deserialize/swar/array/float.ts +8 -21
  37. package/assembly/deserialize/swar/array/generic.ts +2 -4
  38. package/assembly/deserialize/swar/array/integer.ts +13 -27
  39. package/assembly/deserialize/swar/array/map.ts +1 -2
  40. package/assembly/deserialize/swar/array/object.ts +2 -4
  41. package/assembly/deserialize/swar/array/raw.ts +1 -2
  42. package/assembly/deserialize/swar/array/shared.ts +9 -21
  43. package/assembly/deserialize/swar/array/string.ts +4 -10
  44. package/assembly/deserialize/swar/array/struct.ts +3 -9
  45. package/assembly/deserialize/swar/array.ts +1 -3
  46. package/assembly/deserialize/swar/float.ts +7 -17
  47. package/assembly/deserialize/swar/integer.ts +6 -15
  48. package/assembly/deserialize/swar/string.ts +40 -54
  49. package/assembly/deserialize/swar/typedarray.ts +4 -4
  50. package/assembly/index.d.ts +259 -21
  51. package/assembly/index.ts +1704 -266
  52. package/assembly/serialize/index/arbitrary.ts +70 -4
  53. package/assembly/serialize/index/jsonarray.ts +51 -0
  54. package/assembly/serialize/index/object.ts +39 -14
  55. package/assembly/serialize/index/string.ts +1 -2
  56. package/assembly/serialize/index/typedarray.ts +1 -2
  57. package/assembly/serialize/index.ts +1 -0
  58. package/assembly/serialize/naive/array.ts +23 -34
  59. package/assembly/serialize/naive/bool.ts +0 -1
  60. package/assembly/serialize/naive/float.ts +16 -25
  61. package/assembly/serialize/naive/integer.ts +1 -5
  62. package/assembly/serialize/naive/raw.ts +1 -2
  63. package/assembly/serialize/naive/set.ts +0 -4
  64. package/assembly/serialize/naive/staticarray.ts +0 -5
  65. package/assembly/serialize/naive/string.ts +11 -7
  66. package/assembly/serialize/naive/typedarray.ts +0 -6
  67. package/assembly/serialize/simd/string.ts +1 -3
  68. package/assembly/serialize/swar/string.ts +2 -4
  69. package/assembly/util/atoi-fast.ts +4 -14
  70. package/assembly/util/atoi.ts +1 -2
  71. package/assembly/util/bytes.ts +1 -2
  72. package/assembly/util/idofd.ts +1 -2
  73. package/assembly/util/isSpace.ts +1 -2
  74. package/assembly/util/itoa-fast.ts +9 -15
  75. package/assembly/util/nextPowerOf2.ts +1 -2
  76. package/assembly/util/parsefloat-fast.ts +4 -7
  77. package/assembly/util/ptrToStr.ts +1 -2
  78. package/assembly/util/scanValueEnd.ts +1 -2
  79. package/assembly/util/scanValueEndSimd.ts +198 -0
  80. package/assembly/util/scanValueEndSwar.ts +184 -0
  81. package/assembly/util/scientific.ts +8 -14
  82. package/assembly/util/simd-int.ts +4 -8
  83. package/assembly/util/snp.ts +2 -7
  84. package/assembly/util/stringScan.ts +2 -4
  85. package/assembly/util/swar-int.ts +8 -16
  86. package/assembly/util/swar.ts +2 -4
  87. package/lib/as-bs.ts +57 -42
  88. package/package.json +27 -10
  89. package/transform/lib/builder.d.ts +0 -1
  90. package/transform/lib/builder.js +0 -1
  91. package/transform/lib/index.d.ts +0 -1
  92. package/transform/lib/index.js +617 -326
  93. package/transform/lib/linkers/alias.d.ts +0 -1
  94. package/transform/lib/linkers/alias.js +0 -1
  95. package/transform/lib/linkers/custom.d.ts +0 -1
  96. package/transform/lib/linkers/custom.js +0 -1
  97. package/transform/lib/linkers/imports.d.ts +0 -1
  98. package/transform/lib/linkers/imports.js +0 -1
  99. package/transform/lib/types.d.ts +4 -2
  100. package/transform/lib/types.js +5 -1
  101. package/transform/lib/util.d.ts +0 -1
  102. package/transform/lib/util.js +0 -1
  103. package/transform/lib/visitor.d.ts +0 -1
  104. package/transform/lib/visitor.js +0 -1
  105. package/assembly/util/dragonbox-cache.ts +0 -445
  106. package/assembly/util/dragonbox.ts +0 -660
  107. package/transform/lib/builder.d.ts.map +0 -1
  108. package/transform/lib/builder.js.map +0 -1
  109. package/transform/lib/index.d.ts.map +0 -1
  110. package/transform/lib/index.js.map +0 -1
  111. package/transform/lib/linkers/alias.d.ts.map +0 -1
  112. package/transform/lib/linkers/alias.js.map +0 -1
  113. package/transform/lib/linkers/custom.d.ts.map +0 -1
  114. package/transform/lib/linkers/custom.js.map +0 -1
  115. package/transform/lib/linkers/imports.d.ts.map +0 -1
  116. package/transform/lib/linkers/imports.js.map +0 -1
  117. package/transform/lib/types.d.ts.map +0 -1
  118. package/transform/lib/types.js.map +0 -1
  119. package/transform/lib/util.d.ts.map +0 -1
  120. package/transform/lib/util.js.map +0 -1
  121. package/transform/lib/visitor.d.ts.map +0 -1
  122. package/transform/lib/visitor.js.map +0 -1
@@ -1,22 +1,17 @@
1
1
  import { JSON } from "../..";
2
2
  import {
3
- BACK_SLASH,
4
3
  COMMA,
5
- CHAR_F,
6
4
  BRACE_LEFT,
7
- BRACKET_LEFT,
8
- CHAR_N,
9
5
  QUOTE,
10
6
  BRACE_RIGHT,
11
- BRACKET_RIGHT,
12
- CHAR_T,
13
7
  COLON,
14
8
  } from "../../custom/chars";
15
- import { isSpace, isUnescapedQuote, scanStringEnd } from "../../util";
9
+ import { isSpace, scanStringEnd } from "../../util";
16
10
  import { scanValueEnd } from "../../util/scanValueEnd";
11
+ import { lastValueEnd, parseValue } from "./object";
17
12
 
18
- // @ts-ignore: Decorator is valid here
19
- @inline function deserializeMapKey<T>(start: usize, end: usize): T {
13
+ function deserializeMapKey<T>(start: usize, end: usize): T {
14
+ // @ts-expect-error: exists
20
15
  const keyText = JSON.__deserialize<string>(start - 2, end + 2);
21
16
  if (isString<T>()) return changetype<T>(keyText);
22
17
  return JSON.parse<T>(keyText);
@@ -31,13 +26,7 @@ export function deserializeMap<T extends Map<any, any>>(
31
26
  dst || changetype<usize>(instantiate<T>()),
32
27
  );
33
28
 
34
- let keyStart: usize = 0;
35
- let keyEnd: usize = 0;
36
- let isKey = false;
37
- let depth = 0;
38
- let lastIndex: usize = 0;
39
-
40
- while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2; // would like to optimize this later
29
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
41
30
 
42
31
  if (srcStart - srcEnd == 0)
43
32
  throw new Error("Input string had zero length or was all whitespace");
@@ -52,190 +41,26 @@ export function deserializeMap<T extends Map<any, any>>(
52
41
  (srcEnd - srcStart).toString(),
53
42
  );
54
43
 
55
- srcStart += 2;
56
- while (srcStart < srcEnd) {
57
- let code = load<u16>(srcStart); // while (isSpace(code)) code = load<u16>(srcStart += 2);
58
- if (keyStart == 0) {
59
- if (code == QUOTE && isUnescapedQuote(srcStart)) {
60
- if (isKey) {
61
- keyStart = lastIndex;
62
- keyEnd = srcStart;
63
- // console.log("Key: " + ptrToStr(lastIndex, srcStart));
64
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
65
- while (isSpace((code = load<u16>((srcStart += 2))))) {}
66
- if (code !== COLON)
67
- throw new Error(
68
- "Expected ':' after key at position " +
69
- (srcEnd - srcStart).toString(),
70
- );
71
- isKey = false;
72
- } else {
73
- // console.log("Got key start");
74
- isKey = true; // i don't like this
75
- lastIndex = srcStart + 2;
76
- }
77
- }
78
- // isKey = !isKey;
79
- srcStart += 2;
80
- } else {
81
- if (code == QUOTE) {
82
- lastIndex = srcStart;
83
- srcStart = scanStringEnd(srcStart, srcEnd);
84
- if (srcStart >= srcEnd)
85
- throw new Error("Unterminated string in JSON object");
86
- // @ts-ignore: type
87
- out.set(
88
- deserializeMapKey<indexof<T>>(keyStart, keyEnd),
89
- JSON.__deserialize<valueof<T>>(lastIndex, srcStart + 2),
90
- );
91
- srcStart += 2;
92
- keyStart = 0;
93
- continue;
94
- } else if (code - 48 <= 9 || code == 45) {
95
- lastIndex = srcStart;
96
- srcStart += 2;
97
- while (srcStart < srcEnd) {
98
- const code = load<u16>(srcStart);
99
- if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
100
- // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
101
- // @ts-ignore: type
102
- out.set(
103
- deserializeMapKey<indexof<T>>(keyStart, keyEnd),
104
- JSON.__deserialize<valueof<T>>(lastIndex, srcStart),
105
- );
106
- // while (isSpace(load<u16>((srcStart += 2)))) {
107
- // /* empty */
108
- // }
109
- srcStart += 2;
110
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
111
- keyStart = 0;
112
- break;
113
- }
114
- srcStart += 2;
115
- }
116
- } else if (code == BRACE_LEFT) {
117
- lastIndex = srcStart;
118
- depth++;
119
- srcStart += 2;
120
- while (srcStart < srcEnd) {
121
- const code = load<u16>(srcStart);
122
- if (code == QUOTE) {
123
- srcStart = scanStringEnd(srcStart, srcEnd);
124
- if (srcStart >= srcEnd)
125
- throw new Error("Unterminated string in JSON object");
126
- } else if (code == BRACE_RIGHT) {
127
- if (--depth == 0) {
128
- // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
129
- // @ts-ignore: type
130
- out.set(
131
- deserializeMapKey<indexof<T>>(keyStart, keyEnd),
132
- JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)),
133
- );
134
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
135
- keyStart = 0;
136
- // while (isSpace(load<u16>(srcStart))) {
137
- // /* empty */
138
- // }
139
- break;
140
- }
141
- } else if (code == BRACE_LEFT) depth++;
142
- srcStart += 2;
143
- }
144
- } else if (code == BRACKET_LEFT) {
145
- lastIndex = srcStart;
146
- depth++;
147
- srcStart += 2;
148
- while (srcStart < srcEnd) {
149
- const code = load<u16>(srcStart);
150
- if (code == QUOTE) {
151
- srcStart = scanStringEnd(srcStart, srcEnd);
152
- if (srcStart >= srcEnd)
153
- throw new Error("Unterminated string in JSON object");
154
- } else if (code == BRACKET_RIGHT) {
155
- if (--depth == 0) {
156
- // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
157
- // @ts-ignore: type
158
- out.set(
159
- deserializeMapKey<indexof<T>>(keyStart, keyEnd),
160
- JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)),
161
- );
162
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
163
- keyStart = 0;
164
- // while (isSpace(load<u16>((srcStart += 2)))) {
165
- // /* empty */
166
- // }
167
- break;
168
- }
169
- } else if (code == BRACKET_LEFT) depth++;
170
- srcStart += 2;
171
- }
172
- } else if (code == CHAR_T) {
173
- if (load<u64>(srcStart) == 28429475166421108) {
174
- // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
175
- // @ts-ignore: type
176
- out.set(
177
- deserializeMapKey<indexof<T>>(keyStart, keyEnd),
178
- JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)),
179
- );
180
- // while (isSpace(load<u16>((srcStart += 2)))) {
181
- // /* empty */
182
- // }
183
- srcStart += 2;
184
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)) + " " + (srcStart < srcEnd).toString());
185
- keyStart = 0;
186
- }
187
- } else if (code == CHAR_F) {
188
- if (load<u64>(srcStart, 2) == 28429466576093281) {
189
- // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
190
- // @ts-ignore: type
191
- out.set(
192
- deserializeMapKey<indexof<T>>(keyStart, keyEnd),
193
- JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 10)),
194
- );
195
- // while (isSpace(load<u16>((srcStart += 2)))) {
196
- // /* empty */
197
- // }
198
- srcStart += 2;
199
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
200
- keyStart = 0;
201
- }
202
- } else if (code == CHAR_N) {
203
- if (load<u64>(srcStart) == 30399761348886638) {
204
- // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
205
- // @ts-ignore: type
206
- out.set(
207
- deserializeMapKey<indexof<T>>(keyStart, keyEnd),
208
- JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)),
209
- );
210
- // while (isSpace(load<u16>((srcStart += 2)))) {
211
- /* empty */
212
- // }
213
- srcStart += 2;
214
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
215
- keyStart = 0;
216
- }
217
- } else if (isSpace(code)) {
218
- srcStart += 2;
219
- } else {
220
- throw new Error(
221
- "Unexpected character in JSON object '" +
222
- String.fromCharCode(code) +
223
- "' at position " +
224
- (srcEnd - srcStart).toString(),
225
- );
226
- }
227
- }
228
- }
229
- return out;
44
+ deserializeMapBody<T>(srcStart, srcEnd, changetype<T>(out));
45
+ return changetype<T>(out);
230
46
  }
231
47
 
232
-
233
- @inline function deserializeMapBody<T extends Map<any, any>>(
48
+ /**
49
+ * Shared single-pass map-body parser used by both the top-level and struct-field
50
+ * entry points. Dynamic `JSON.Value` values are parsed in one pass via
51
+ * {@link parseValue}; typed values are bounds-scanned with {@link scanValueEnd}
52
+ * because their generated deserializers take exact `(start, end)` bounds.
53
+ */
54
+ export function deserializeMapBody<T extends Map<any, any>>(
234
55
  srcStart: usize,
235
56
  srcEnd: usize,
236
57
  out: T,
237
58
  ): usize {
238
- changetype<nonnull<T>>(out).clear();
59
+ let arbitraryValue = false;
60
+ if (isManaged<valueof<T>>() || isReference<valueof<T>>()) {
61
+ // @ts-ignore: instanceof on the (reference) value type
62
+ arbitraryValue = changetype<nonnull<valueof<T>>>(0) instanceof JSON.Value;
63
+ }
239
64
 
240
65
  if (srcStart >= srcEnd || load<u16>(srcStart) != BRACE_LEFT)
241
66
  throw new Error("Failed to parse JSON!");
@@ -258,15 +83,24 @@ export function deserializeMap<T extends Map<any, any>>(
258
83
  srcStart += 2;
259
84
  while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
260
85
 
261
- const valueEnd = scanValueEnd(srcStart, srcEnd);
262
- if (!valueEnd || valueEnd <= srcStart) break;
263
-
264
- // @ts-ignore: type
265
- changetype<nonnull<T>>(out).set(
266
- deserializeMapKey<indexof<T>>(keyStart, keyEnd),
267
- JSON.__deserialize<valueof<T>>(srcStart, valueEnd),
268
- );
269
- srcStart = valueEnd;
86
+ if (isReference<valueof<T>>() && arbitraryValue) {
87
+ const val = parseValue(srcStart, srcEnd);
88
+ // @ts-ignore: type - valueof<T> is JSON.Value in this branch
89
+ changetype<nonnull<T>>(out).set(
90
+ deserializeMapKey<indexof<T>>(keyStart, keyEnd),
91
+ changetype<valueof<T>>(changetype<usize>(val)),
92
+ );
93
+ srcStart = lastValueEnd();
94
+ } else {
95
+ const valueEnd = scanValueEnd(srcStart, srcEnd);
96
+ if (!valueEnd || valueEnd <= srcStart) break;
97
+ // @ts-ignore: type
98
+ changetype<nonnull<T>>(out).set(
99
+ deserializeMapKey<indexof<T>>(keyStart, keyEnd),
100
+ JSON.__deserialize<valueof<T>>(srcStart, valueEnd),
101
+ );
102
+ srcStart = valueEnd;
103
+ }
270
104
 
271
105
  while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
272
106
  if (srcStart >= srcEnd) break;
@@ -283,8 +117,7 @@ export function deserializeMap<T extends Map<any, any>>(
283
117
  throw new Error("Failed to parse JSON!");
284
118
  }
285
119
 
286
-
287
- @inline export function deserializeMapField<T extends Map<any, any>>(
120
+ export function deserializeMapField<T extends Map<any, any>>(
288
121
  srcStart: usize,
289
122
  srcEnd: usize,
290
123
  dstObj: usize,
@@ -295,6 +128,10 @@ export function deserializeMap<T extends Map<any, any>>(
295
128
  if (!changetype<usize>(out)) {
296
129
  out = changetype<T>(instantiate<T>());
297
130
  store<T>(fieldPtr, out);
131
+ } else {
132
+ // Reusing an existing field map - clear it before repopulating. Fresh maps
133
+ // (deserializeMap / deserializeMapArray) skip this.
134
+ changetype<nonnull<T>>(out).clear();
298
135
  }
299
136
  return deserializeMapBody<T>(srcStart, srcEnd, out);
300
137
  }