json-as 1.3.6 → 1.3.8

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 (155) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +1 -1
  3. package/assembly/deserialize/helpers/uint.ts +4 -1
  4. package/assembly/deserialize/index/arbitrary.ts +7 -3
  5. package/assembly/deserialize/index/array.ts +42 -17
  6. package/assembly/deserialize/index/bool.ts +1 -1
  7. package/assembly/deserialize/index/date.ts +1 -1
  8. package/assembly/deserialize/index/float.ts +40 -1
  9. package/assembly/deserialize/index/integer.ts +68 -1
  10. package/assembly/deserialize/index/map.ts +1 -1
  11. package/assembly/deserialize/index/object.ts +1 -1
  12. package/assembly/deserialize/index/raw.ts +1 -1
  13. package/assembly/deserialize/index/set.ts +1 -1
  14. package/assembly/deserialize/index/staticarray.ts +4 -1
  15. package/assembly/deserialize/index/string.ts +32 -4
  16. package/assembly/deserialize/index/struct.ts +1 -1
  17. package/assembly/deserialize/index/typedarray.ts +30 -10
  18. package/assembly/deserialize/index/unsigned.ts +78 -1
  19. package/assembly/deserialize/index.ts +1 -0
  20. package/assembly/deserialize/{simple → naive}/array/arbitrary.ts +24 -5
  21. package/assembly/deserialize/{simple → naive}/array/array.ts +8 -2
  22. package/assembly/deserialize/naive/array/bool.ts +68 -0
  23. package/assembly/deserialize/{simple → naive}/array/box.ts +8 -2
  24. package/assembly/deserialize/naive/array/float.ts +63 -0
  25. package/assembly/deserialize/{simple → naive}/array/generic.ts +14 -7
  26. package/assembly/deserialize/naive/array/integer.ts +86 -0
  27. package/assembly/deserialize/naive/array/map.ts +47 -0
  28. package/assembly/deserialize/naive/array/object.ts +47 -0
  29. package/assembly/deserialize/{simple → naive}/array/raw.ts +34 -7
  30. package/assembly/deserialize/naive/array/string.ts +69 -0
  31. package/assembly/deserialize/naive/array/struct.ts +47 -0
  32. package/assembly/deserialize/{simple → naive}/array.ts +15 -10
  33. package/assembly/deserialize/{simple → naive}/bool.ts +6 -2
  34. package/assembly/deserialize/naive/float.ts +135 -0
  35. package/assembly/deserialize/{simple → naive}/integer.ts +10 -2
  36. package/assembly/deserialize/{simple → naive}/map.ts +106 -27
  37. package/assembly/deserialize/{simple → naive}/object.ts +65 -19
  38. package/assembly/deserialize/{simple → naive}/raw.ts +4 -1
  39. package/assembly/deserialize/{simple → naive}/set.ts +49 -19
  40. package/assembly/deserialize/{simple → naive}/staticarray/array.ts +1 -1
  41. package/assembly/deserialize/{simple → naive}/staticarray/bool.ts +1 -1
  42. package/assembly/deserialize/{simple → naive}/staticarray/float.ts +1 -1
  43. package/assembly/deserialize/{simple → naive}/staticarray/integer.ts +1 -1
  44. package/assembly/deserialize/{simple → naive}/staticarray/string.ts +11 -3
  45. package/assembly/deserialize/{simple → naive}/staticarray/struct.ts +1 -2
  46. package/assembly/deserialize/{simple → naive}/staticarray.ts +68 -18
  47. package/assembly/deserialize/naive/string.ts +199 -0
  48. package/assembly/deserialize/{simple → naive}/struct.ts +5 -1
  49. package/assembly/deserialize/{simple → naive}/typedarray.ts +17 -4
  50. package/assembly/deserialize/{simple → naive}/unsigned.ts +10 -15
  51. package/assembly/deserialize/simd/array/integer.ts +339 -62
  52. package/assembly/deserialize/simd/float.ts +303 -0
  53. package/assembly/deserialize/simd/integer.ts +233 -0
  54. package/assembly/deserialize/simd/string.ts +266 -107
  55. package/assembly/deserialize/swar/array/arbitrary.ts +11 -3
  56. package/assembly/deserialize/swar/array/array.ts +40 -9
  57. package/assembly/deserialize/swar/array/bool.ts +28 -5
  58. package/assembly/deserialize/swar/array/box.ts +11 -3
  59. package/assembly/deserialize/swar/array/float.ts +295 -7
  60. package/assembly/deserialize/swar/array/generic.ts +28 -7
  61. package/assembly/deserialize/swar/array/integer.ts +363 -112
  62. package/assembly/deserialize/swar/array/map.ts +11 -3
  63. package/assembly/deserialize/swar/array/object.ts +37 -25
  64. package/assembly/deserialize/swar/array/raw.ts +11 -3
  65. package/assembly/deserialize/swar/array/shared.ts +63 -14
  66. package/assembly/deserialize/swar/array/string.ts +140 -7
  67. package/assembly/deserialize/swar/array/struct.ts +66 -12
  68. package/assembly/deserialize/swar/array.ts +12 -51
  69. package/assembly/deserialize/swar/float.ts +304 -0
  70. package/assembly/deserialize/swar/integer.ts +246 -0
  71. package/assembly/deserialize/swar/string.ts +213 -294
  72. package/assembly/deserialize/swar/typedarray.ts +224 -0
  73. package/assembly/index.d.ts +3 -1
  74. package/assembly/index.ts +402 -261
  75. package/assembly/serialize/index/array.ts +1 -1
  76. package/assembly/serialize/index/bool.ts +1 -1
  77. package/assembly/serialize/index/date.ts +1 -1
  78. package/assembly/serialize/index/float.ts +5 -1
  79. package/assembly/serialize/index/integer.ts +1 -1
  80. package/assembly/serialize/index/map.ts +1 -1
  81. package/assembly/serialize/index/raw.ts +1 -1
  82. package/assembly/serialize/index/set.ts +1 -1
  83. package/assembly/serialize/index/staticarray.ts +1 -1
  84. package/assembly/serialize/index/string.ts +1 -1
  85. package/assembly/serialize/index/struct.ts +1 -1
  86. package/assembly/serialize/index/typedarray.ts +21 -12
  87. package/assembly/serialize/index.ts +1 -0
  88. package/assembly/serialize/naive/array.ts +351 -0
  89. package/assembly/serialize/{simple → naive}/float.ts +4 -1
  90. package/assembly/serialize/naive/integer.ts +19 -0
  91. package/assembly/serialize/{simple → naive}/map.ts +6 -2
  92. package/assembly/serialize/{simple → naive}/raw.ts +5 -1
  93. package/assembly/serialize/{simple → naive}/set.ts +6 -1
  94. package/assembly/serialize/{simple → naive}/staticarray.ts +6 -1
  95. package/assembly/serialize/{simple → naive}/string.ts +1 -2
  96. package/assembly/serialize/{simple → naive}/typedarray.ts +10 -3
  97. package/assembly/serialize/simd/string.ts +6 -2
  98. package/assembly/serialize/swar/string.ts +15 -141
  99. package/assembly/util/atoi-fast.ts +81 -0
  100. package/assembly/util/concat.ts +5 -1
  101. package/assembly/util/dragonbox-cache.ts +443 -2
  102. package/assembly/util/dragonbox.ts +53 -17
  103. package/assembly/util/itoa-fast.ts +241 -0
  104. package/assembly/util/masks.ts +18 -1
  105. package/assembly/util/parsefloat-fast.ts +167 -0
  106. package/assembly/util/scanValueEnd.ts +78 -0
  107. package/assembly/util/scientific.ts +132 -0
  108. package/assembly/util/simd-int.ts +191 -0
  109. package/assembly/util/snp.ts +4 -1
  110. package/assembly/util/swar-int.ts +248 -0
  111. package/assembly/util/swar.ts +13 -3
  112. package/lib/as-bs.ts +27 -6
  113. package/package.json +15 -11
  114. package/transform/lib/builder.d.ts.map +1 -1
  115. package/transform/lib/builder.js +13 -5
  116. package/transform/lib/builder.js.map +1 -1
  117. package/transform/lib/index.d.ts +5 -0
  118. package/transform/lib/index.d.ts.map +1 -1
  119. package/transform/lib/index.js +1046 -340
  120. package/transform/lib/index.js.map +1 -1
  121. package/transform/lib/linkers/alias.d.ts.map +1 -1
  122. package/transform/lib/linkers/alias.js.map +1 -1
  123. package/transform/lib/linkers/custom.d.ts.map +1 -1
  124. package/transform/lib/linkers/custom.js +3 -2
  125. package/transform/lib/linkers/custom.js.map +1 -1
  126. package/transform/lib/linkers/imports.d.ts.map +1 -1
  127. package/transform/lib/linkers/imports.js.map +1 -1
  128. package/transform/lib/types.d.ts.map +1 -1
  129. package/transform/lib/types.js +54 -16
  130. package/transform/lib/types.js.map +1 -1
  131. package/transform/lib/util.d.ts.map +1 -1
  132. package/transform/lib/util.js +1 -1
  133. package/transform/lib/util.js.map +1 -1
  134. package/transform/lib/visitor.d.ts.map +1 -1
  135. package/transform/lib/visitor.js +2 -1
  136. package/transform/lib/visitor.js.map +1 -1
  137. package/assembly/custom/util.ts +0 -310
  138. package/assembly/deserialize/simple/arbitrary.ts +0 -23
  139. package/assembly/deserialize/simple/array/bool.ts +0 -17
  140. package/assembly/deserialize/simple/array/float.ts +0 -28
  141. package/assembly/deserialize/simple/array/integer.ts +0 -27
  142. package/assembly/deserialize/simple/array/map.ts +0 -28
  143. package/assembly/deserialize/simple/array/object.ts +0 -28
  144. package/assembly/deserialize/simple/array/string.ts +0 -23
  145. package/assembly/deserialize/simple/array/struct.ts +0 -28
  146. package/assembly/deserialize/simple/float.ts +0 -201
  147. package/assembly/deserialize/simple/string.ts +0 -132
  148. package/assembly/serialize/simple/arbitrary.ts +0 -79
  149. package/assembly/serialize/simple/array.ts +0 -86
  150. package/assembly/serialize/simple/integer.ts +0 -20
  151. package/assembly/serialize/simple/object.ts +0 -42
  152. /package/assembly/deserialize/{simple → naive}/date.ts +0 -0
  153. /package/assembly/serialize/{simple → naive}/bool.ts +0 -0
  154. /package/assembly/serialize/{simple → naive}/date.ts +0 -0
  155. /package/assembly/serialize/{simple → naive}/struct.ts +0 -0
@@ -1 +1 @@
1
- export { serializeArray } from "../simple/array";
1
+ export { serializeArray } from "../naive/array";
@@ -1 +1 @@
1
- export { serializeBool } from "../simple/bool";
1
+ export { serializeBool } from "../naive/bool";
@@ -1 +1 @@
1
- export { serializeDate } from "../simple/date";
1
+ export { serializeDate } from "../naive/date";
@@ -1 +1,5 @@
1
- export { serializeFloat, serializeFloat32, serializeFloat64 } from "../simple/float";
1
+ export {
2
+ serializeFloat,
3
+ serializeFloat32,
4
+ serializeFloat64,
5
+ } from "../naive/float";
@@ -1 +1 @@
1
- export { serializeInteger } from "../simple/integer";
1
+ export { serializeInteger } from "../naive/integer";
@@ -1 +1 @@
1
- export { serializeMap } from "../simple/map";
1
+ export { serializeMap } from "../naive/map";
@@ -1 +1 @@
1
- export { serializeRaw } from "../simple/raw";
1
+ export { serializeRaw } from "../naive/raw";
@@ -1 +1 @@
1
- export { serializeSet } from "../simple/set";
1
+ export { serializeSet } from "../naive/set";
@@ -1 +1 @@
1
- export { serializeStaticArray } from "../simple/staticarray";
1
+ export { serializeStaticArray } from "../naive/staticarray";
@@ -1,5 +1,5 @@
1
1
  import { JSONMode } from "../..";
2
- import { serializeString as serializeString_NAIVE } from "../simple/string";
2
+ import { serializeString_NAIVE } from "../naive/string";
3
3
  import { serializeString_SIMD } from "../simd/string";
4
4
  import { serializeString_SWAR } from "../swar/string";
5
5
 
@@ -1 +1 @@
1
- export { serializeStruct } from "../simple/struct";
1
+ export { serializeStruct } from "../naive/struct";
@@ -1,12 +1,21 @@
1
1
  import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
2
2
  import { JSON } from "../..";
3
- export { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typedarray";
4
- import { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typedarray";
3
+ export {
4
+ serializeArrayBufferUnsafe,
5
+ serializeTypedArray,
6
+ } from "../naive/typedarray";
7
+ import {
8
+ serializeArrayBufferUnsafe,
9
+ serializeTypedArray,
10
+ } from "../naive/typedarray";
5
11
 
6
12
 
7
13
  @inline export function serializeDynamic(type: u16, data: usize): void {
8
14
  if (type == JSON.Types.ArrayBuffer) {
9
- serializeArrayBufferUnsafe(data, changetype<OBJECT>(data - TOTAL_OVERHEAD).rtSize);
15
+ serializeArrayBufferUnsafe(
16
+ data,
17
+ changetype<OBJECT>(data - TOTAL_OVERHEAD).rtSize,
18
+ );
10
19
  } else if (type == JSON.Types.TypedArray) {
11
20
  const id = changetype<OBJECT>(data - TOTAL_OVERHEAD).rtId;
12
21
  if (id == idof<Int8Array>()) {
@@ -14,7 +23,9 @@ import { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typed
14
23
  } else if (id == idof<Uint8Array>()) {
15
24
  serializeTypedArray<Uint8Array>(changetype<Uint8Array>(data));
16
25
  } else if (id == idof<Uint8ClampedArray>()) {
17
- serializeTypedArray<Uint8ClampedArray>(changetype<Uint8ClampedArray>(data));
26
+ serializeTypedArray<Uint8ClampedArray>(
27
+ changetype<Uint8ClampedArray>(data),
28
+ );
18
29
  } else if (id == idof<Int16Array>()) {
19
30
  serializeTypedArray<Int16Array>(changetype<Int16Array>(data));
20
31
  } else if (id == idof<Uint16Array>()) {
@@ -35,8 +46,12 @@ import { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typed
35
46
  serializeTypedArray<Int8Array>(changetype<Int8Array>(data));
36
47
  } else if (changetype<Uint8Array>(data) instanceof Uint8Array) {
37
48
  serializeTypedArray<Uint8Array>(changetype<Uint8Array>(data));
38
- } else if (changetype<Uint8ClampedArray>(data) instanceof Uint8ClampedArray) {
39
- serializeTypedArray<Uint8ClampedArray>(changetype<Uint8ClampedArray>(data));
49
+ } else if (
50
+ changetype<Uint8ClampedArray>(data) instanceof Uint8ClampedArray
51
+ ) {
52
+ serializeTypedArray<Uint8ClampedArray>(
53
+ changetype<Uint8ClampedArray>(data),
54
+ );
40
55
  } else if (changetype<Int16Array>(data) instanceof Int16Array) {
41
56
  serializeTypedArray<Int16Array>(changetype<Int16Array>(data));
42
57
  } else if (changetype<Uint16Array>(data) instanceof Uint16Array) {
@@ -58,9 +73,3 @@ import { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typed
58
73
  }
59
74
  }
60
75
  }
61
-
62
-
63
- @inline export function serializeArrayBuffer(data: ArrayBuffer): void {
64
- const dataStart = changetype<usize>(data);
65
- serializeArrayBufferUnsafe(dataStart, changetype<OBJECT>(dataStart - TOTAL_OVERHEAD).rtSize);
66
- }
@@ -11,3 +11,4 @@ export * from "./index/set";
11
11
  export * from "./index/staticarray";
12
12
  export * from "./index/string";
13
13
  export * from "./index/struct";
14
+ export * from "./index/typedarray";
@@ -0,0 +1,351 @@
1
+ import { bs } from "../../../lib/as-bs";
2
+ import { COMMA, BRACKET_RIGHT, BRACKET_LEFT } from "../../custom/chars";
3
+ import { JSON } from "../..";
4
+ import { serializeBoolUnsafe } from "./bool";
5
+ import { serializeFloat32Unsafe, serializeFloat64Unsafe } from "./float";
6
+ import { serializeIntegerUnsafe } from "./integer";
7
+ import { serializeString } from "../index/string";
8
+ import {
9
+ dragonbox_f32_buffered,
10
+ dragonbox_f64_buffered,
11
+ } from "../../util/dragonbox";
12
+
13
+
14
+ @inline
15
+ function maxIntegerBytes<T extends number>(): u32 {
16
+ if (sizeof<T>() == 1) return isSigned<T>() ? 8 : 6;
17
+ if (sizeof<T>() == 2) return isSigned<T>() ? 12 : 10;
18
+ if (sizeof<T>() == 4) return isSigned<T>() ? 22 : 20;
19
+ return isSigned<T>() ? 42 : 40;
20
+ }
21
+
22
+
23
+ @inline
24
+ function reservePrimitiveArray<T>(len: i32): void {
25
+ if (len <= 0) return;
26
+ if (isBoolean<T>()) {
27
+ bs.proposeSize(4 + <u32>len * 12);
28
+ } else if (isInteger<T>()) {
29
+ bs.proposeSize(4 + <u32>len * (maxIntegerBytes<T>() + 2));
30
+ } else if (isFloat<T>()) {
31
+ bs.proposeSize(4 + <u32>len * (sizeof<T>() == 4 ? 34 : 66));
32
+ } else {
33
+ bs.proposeSize(4 + <u32>(len - 1) * 2);
34
+ }
35
+ }
36
+
37
+
38
+ @inline
39
+ function serializeArrayElement<T>(value: T): void {
40
+ if (isString<T>()) {
41
+ serializeString(value as string);
42
+ return;
43
+ }
44
+ if (isBoolean<T>()) {
45
+ serializeBoolUnsafe(<bool>value);
46
+ return;
47
+ }
48
+ if (isInteger<T>()) {
49
+ serializeIntegerUnsafe<T>(value);
50
+ return;
51
+ }
52
+ if (isFloat<T>()) {
53
+ if (sizeof<T>() == 4) serializeFloat32Unsafe(<f32>value);
54
+ else serializeFloat64Unsafe(<f64>value);
55
+ return;
56
+ }
57
+ if (isManaged<T>() || isReference<T>()) {
58
+ // Preserve runtime custom serializers for subclass instances stored in
59
+ // parent-typed arrays before falling back to the static dispatcher.
60
+ // @ts-ignore: transform-defined at runtime when present
61
+ if (isDefined(value.__SERIALIZE_CUSTOM)) {
62
+ // @ts-ignore: transform-defined at runtime when present
63
+ value.__SERIALIZE_CUSTOM();
64
+ return;
65
+ }
66
+ }
67
+ JSON.__serialize<T>(value);
68
+ }
69
+
70
+ // ---------------------------------------------------------------------------
71
+ // Specialized fast paths
72
+ // ---------------------------------------------------------------------------
73
+ //
74
+ // `bool[]` and `u8[]` / `i8[]` serializers fold the element write and the
75
+ // trailing comma into a single per-element store. The outer dispatcher
76
+ // emits `[` once, the loop emits `VALUE,` once per element, and the closing
77
+ // `]` overwrites the trailing comma. This eliminates the separate
78
+ // comma-store + advance per element that the generic `serializeArray` does.
79
+
80
+ // `"true,"` packed UTF-16: `t,r,u,e,,` lanes 0..4 = bytes 0..9.
81
+ @inline const TRUE_COMMA_LO: u64 = 0x0065_0075_0072_0074;
82
+
83
+
84
+ @inline const TRUE_COMMA_HI: u16 = 0x002c;
85
+ // `"false,"` packed UTF-16: `f,a,l,s,e,,` lanes 0..5 = bytes 0..11.
86
+ @inline const FALSE_COMMA_LO: u64 = 0x0073_006c_0061_0066;
87
+
88
+
89
+ @inline const FALSE_COMMA_HI: u32 = 0x002c_0065;
90
+
91
+ function serializeBoolArrayFast(src: bool[]): void {
92
+ const len = src.length;
93
+ // Worst case: every element is `"false,"` = 12 bytes; plus 4 for `[]`.
94
+ bs.proposeSize(4 + <u32>len * 12);
95
+ store<u16>(bs.offset, BRACKET_LEFT);
96
+ bs.offset += 2;
97
+ if (len == 0) {
98
+ store<u16>(bs.offset, BRACKET_RIGHT);
99
+ bs.offset += 2;
100
+ return;
101
+ }
102
+
103
+ const dataStart = src.dataStart;
104
+ for (let i: i32 = 0; i < len; i++) {
105
+ if (load<bool>(dataStart + <usize>i)) {
106
+ store<u64>(bs.offset, TRUE_COMMA_LO);
107
+ store<u16>(bs.offset, TRUE_COMMA_HI, 8);
108
+ bs.offset += 10;
109
+ } else {
110
+ store<u64>(bs.offset, FALSE_COMMA_LO);
111
+ store<u32>(bs.offset, FALSE_COMMA_HI, 8);
112
+ bs.offset += 12;
113
+ }
114
+ }
115
+ // Overwrite the final trailing comma with `]`.
116
+ store<u16>(bs.offset - 2, BRACKET_RIGHT);
117
+ }
118
+
119
+ // 256-entry table mapping `u8` value -> UTF-16 chars of `"DDD,"` packed in a
120
+ // u64. Unused lanes hold garbage that the next element's store overwrites.
121
+ const U8_SERIALIZE_LUT: usize = memory.data(2048); // 256 * sizeof<u64>
122
+ // 256-entry table mapping `u8` value -> byte count of the packed encoding.
123
+ const U8_SERIALIZE_LEN_LUT: usize = memory.data(256);
124
+ let _u8LutInited: bool = false;
125
+
126
+ function initU8Lut(): void {
127
+ for (let i: i32 = 0; i < 256; i++) {
128
+ let chars: u64;
129
+ let bytes: u8;
130
+ if (i < 10) {
131
+ chars = u64(0x30 + i) | (u64(0x2c) << 16);
132
+ bytes = 4;
133
+ } else if (i < 100) {
134
+ const d0 = i / 10;
135
+ const d1 = i % 10;
136
+ chars = u64(0x30 + d0) | (u64(0x30 + d1) << 16) | (u64(0x2c) << 32);
137
+ bytes = 6;
138
+ } else {
139
+ const d0 = i / 100;
140
+ const d1 = (i / 10) % 10;
141
+ const d2 = i % 10;
142
+ chars =
143
+ u64(0x30 + d0) |
144
+ (u64(0x30 + d1) << 16) |
145
+ (u64(0x30 + d2) << 32) |
146
+ (u64(0x2c) << 48);
147
+ bytes = 8;
148
+ }
149
+ store<u64>(U8_SERIALIZE_LUT + ((<usize>i) << 3), chars);
150
+ store<u8>(U8_SERIALIZE_LEN_LUT + <usize>i, bytes);
151
+ }
152
+ _u8LutInited = true;
153
+ }
154
+
155
+
156
+ @inline function ensureU8Lut(): void {
157
+ if (!_u8LutInited) initU8Lut();
158
+ }
159
+
160
+ function serializeU8ArrayFast(src: u8[]): void {
161
+ const len = src.length;
162
+ // Worst case: every element is 3 digits + comma = 8 bytes; plus 4 for `[]`.
163
+ bs.proposeSize(4 + <u32>len * 8);
164
+ store<u16>(bs.offset, BRACKET_LEFT);
165
+ bs.offset += 2;
166
+ if (len == 0) {
167
+ store<u16>(bs.offset, BRACKET_RIGHT);
168
+ bs.offset += 2;
169
+ return;
170
+ }
171
+ ensureU8Lut();
172
+
173
+ const dataStart = src.dataStart;
174
+ for (let i: i32 = 0; i < len; i++) {
175
+ const v = <usize>load<u8>(dataStart + <usize>i);
176
+ const chars = load<u64>(U8_SERIALIZE_LUT + (v << 3));
177
+ const byteCount = <usize>load<u8>(U8_SERIALIZE_LEN_LUT + v);
178
+ store<u64>(bs.offset, chars);
179
+ bs.offset += byteCount;
180
+ }
181
+ store<u16>(bs.offset - 2, BRACKET_RIGHT);
182
+ }
183
+
184
+ // Specialized float-array serializer: dragonbox + trailing comma in a
185
+ // uniform per-iteration body, then overwrite the final comma with `]`. The
186
+ // generic dispatcher splits the loop into "N-1 elements with comma, then
187
+ // last element without, then `]`" — the branch on each `i < end` check
188
+ // stalls the loop's tight bs.offset advance pattern. This variant runs the
189
+ // same number of stores per iteration (dragonbox output + COMMA), but the
190
+ // uniform loop body inlines better and the trailing `]` is a single fixed
191
+ // overwrite outside the loop.
192
+ function serializeF64ArrayFast(src: f64[]): void {
193
+ const len = src.length;
194
+ // Worst case per element: ~24 chars for f64 + comma = 50 bytes.
195
+ // Slight over-reserve (66) matches the existing `reservePrimitiveArray`
196
+ // budget and keeps a safety margin for any NaN/Inf spelling.
197
+ bs.proposeSize(4 + <u32>len * 66);
198
+ store<u16>(bs.offset, BRACKET_LEFT);
199
+ bs.offset += 2;
200
+ if (len == 0) {
201
+ store<u16>(bs.offset, BRACKET_RIGHT);
202
+ bs.offset += 2;
203
+ return;
204
+ }
205
+
206
+ // Hoist `bs.offset` into a local so the loop body has a single
207
+ // monotonically-advancing pointer instead of two reads + two writes back
208
+ // to the global per iteration.
209
+ const dataStart = src.dataStart;
210
+ let offset = bs.offset;
211
+ for (let i: i32 = 0; i < len; i++) {
212
+ const v = load<f64>(dataStart + ((<usize>i) << 3));
213
+ const size = dragonbox_f64_buffered(offset, v) << 1;
214
+ store<u16>(offset + size, COMMA);
215
+ offset += size + 2;
216
+ }
217
+ // Overwrite the final trailing comma with `]`.
218
+ store<u16>(offset - 2, BRACKET_RIGHT);
219
+ bs.offset = offset;
220
+ }
221
+
222
+ function serializeF32ArrayFast(src: f32[]): void {
223
+ const len = src.length;
224
+ // Worst case for f32 is ~16 chars + comma = ~34 bytes; mirror the budget
225
+ // used by `reservePrimitiveArray`.
226
+ bs.proposeSize(4 + <u32>len * 34);
227
+ store<u16>(bs.offset, BRACKET_LEFT);
228
+ bs.offset += 2;
229
+ if (len == 0) {
230
+ store<u16>(bs.offset, BRACKET_RIGHT);
231
+ bs.offset += 2;
232
+ return;
233
+ }
234
+
235
+ const dataStart = src.dataStart;
236
+ let offset = bs.offset;
237
+ for (let i: i32 = 0; i < len; i++) {
238
+ const v = load<f32>(dataStart + ((<usize>i) << 2));
239
+ const size = dragonbox_f32_buffered(offset, v) << 1;
240
+ store<u16>(offset + size, COMMA);
241
+ offset += size + 2;
242
+ }
243
+ store<u16>(offset - 2, BRACKET_RIGHT);
244
+ bs.offset = offset;
245
+ }
246
+
247
+ function serializeI8ArrayFast(src: i8[]): void {
248
+ const len = src.length;
249
+ // Worst case: every element is `-DDD,` = 5 chars = 10 bytes; plus 4 for `[]`.
250
+ bs.proposeSize(4 + <u32>len * 10);
251
+ store<u16>(bs.offset, BRACKET_LEFT);
252
+ bs.offset += 2;
253
+ if (len == 0) {
254
+ store<u16>(bs.offset, BRACKET_RIGHT);
255
+ bs.offset += 2;
256
+ return;
257
+ }
258
+ ensureU8Lut();
259
+
260
+ const dataStart = src.dataStart;
261
+ for (let i: i32 = 0; i < len; i++) {
262
+ let signed = load<i8>(dataStart + <usize>i);
263
+ let absVal: u32;
264
+ if (signed < 0) {
265
+ store<u16>(bs.offset, 0x2d); // '-'
266
+ bs.offset += 2;
267
+ absVal = <u32>-(<i32>signed);
268
+ } else {
269
+ absVal = <u32>signed;
270
+ }
271
+ const chars = load<u64>(U8_SERIALIZE_LUT + ((<usize>absVal) << 3));
272
+ const byteCount = <usize>load<u8>(U8_SERIALIZE_LEN_LUT + <usize>absVal);
273
+ store<u64>(bs.offset, chars);
274
+ bs.offset += byteCount;
275
+ }
276
+ store<u16>(bs.offset - 2, BRACKET_RIGHT);
277
+ }
278
+
279
+ export function serializeArray<T extends any[]>(src: T): void {
280
+ // Specialized fast paths fold the per-element comma into the element write,
281
+ // saving one `store<u16>` + advance per iteration. AS folds the type checks
282
+ // at compile time so the non-matching branches don't ship.
283
+ if (isBoolean<valueof<T>>()) {
284
+ // @ts-expect-error: T is bool[]
285
+ serializeBoolArrayFast(changetype<bool[]>(src));
286
+ return;
287
+ }
288
+ if (
289
+ isInteger<valueof<T>>() &&
290
+ !isSigned<valueof<T>>() &&
291
+ sizeof<valueof<T>>() == 1
292
+ ) {
293
+ // @ts-expect-error: T is u8[]
294
+ serializeU8ArrayFast(changetype<u8[]>(src));
295
+ return;
296
+ }
297
+ if (
298
+ isInteger<valueof<T>>() &&
299
+ isSigned<valueof<T>>() &&
300
+ sizeof<valueof<T>>() == 1
301
+ ) {
302
+ // @ts-expect-error: T is i8[]
303
+ serializeI8ArrayFast(changetype<i8[]>(src));
304
+ return;
305
+ }
306
+ if (isFloat<valueof<T>>() && sizeof<valueof<T>>() == 8) {
307
+ // @ts-expect-error: T is f64[]
308
+ serializeF64ArrayFast(changetype<f64[]>(src));
309
+ return;
310
+ }
311
+ if (isFloat<valueof<T>>() && sizeof<valueof<T>>() == 4) {
312
+ // @ts-expect-error: T is f32[]
313
+ serializeF32ArrayFast(changetype<f32[]>(src));
314
+ return;
315
+ }
316
+
317
+ const len = src.length;
318
+ const end = len - 1;
319
+ let i = 0;
320
+ if (end == -1) {
321
+ bs.proposeSize(4);
322
+ store<u32>(bs.offset, 6094939);
323
+ bs.offset += 4;
324
+ return;
325
+ }
326
+ if (
327
+ isBoolean<valueof<T>>() ||
328
+ isInteger<valueof<T>>() ||
329
+ isFloat<valueof<T>>() ||
330
+ isString<valueof<T>>()
331
+ ) {
332
+ reservePrimitiveArray<valueof<T>>(len);
333
+ } else {
334
+ bs.proposeSize(4 + <u32>(len - 1) * 2);
335
+ }
336
+
337
+ store<u16>(bs.offset, BRACKET_LEFT);
338
+ bs.offset += 2;
339
+
340
+ while (i < end) {
341
+ const block = unchecked(src[i++]);
342
+ serializeArrayElement<valueof<T>>(block);
343
+ store<u16>(bs.offset, COMMA);
344
+ bs.offset += 2;
345
+ }
346
+
347
+ const lastBlock = unchecked(src[end]);
348
+ serializeArrayElement<valueof<T>>(lastBlock);
349
+ store<u16>(bs.offset, BRACKET_RIGHT);
350
+ bs.offset += 2;
351
+ }
@@ -1,5 +1,8 @@
1
1
  import { bs } from "../../../lib/as-bs";
2
- import { dragonbox_f32_buffered, dragonbox_f64_buffered } from "../../util/dragonbox";
2
+ import {
3
+ dragonbox_f32_buffered,
4
+ dragonbox_f64_buffered,
5
+ } from "../../util/dragonbox";
3
6
 
4
7
 
5
8
  @inline
@@ -0,0 +1,19 @@
1
+ import { bs } from "../../../lib/as-bs";
2
+ import { ensureItoaPairs, itoaFast } from "../../util/itoa-fast";
3
+
4
+
5
+ @inline
6
+ export function serializeIntegerUnsafe<T extends number>(data: T): void {
7
+ ensureItoaPairs();
8
+ const charsWritten = itoaFast<T>(bs.offset, data);
9
+ bs.offset += (<usize>charsWritten) << 1;
10
+ }
11
+
12
+ // @ts-ignore: inline
13
+ @inline export function serializeInteger<T extends number>(data: T): void {
14
+ ensureItoaPairs();
15
+ bs.ensureSize(sizeof<T>() << 3);
16
+ const charsWritten = itoaFast<T>(bs.offset, data);
17
+ bs.growSize((<u32>charsWritten) << 1);
18
+ bs.offset += (<usize>charsWritten) << 1;
19
+ }
@@ -26,7 +26,9 @@ export function serializeMap<T extends Map<any, any>>(src: T): void {
26
26
  if (keyIsString) {
27
27
  JSON.__serialize(unchecked(keys[i]));
28
28
  } else {
29
- JSON.__serialize<string>(JSON.internal.stringify<indexof<T>>(unchecked(keys[i])));
29
+ JSON.__serialize<string>(
30
+ JSON.internal.stringify<indexof<T>>(unchecked(keys[i])),
31
+ );
30
32
  }
31
33
  store<u16>(bs.offset, COLON);
32
34
  bs.offset += 2;
@@ -38,7 +40,9 @@ export function serializeMap<T extends Map<any, any>>(src: T): void {
38
40
  if (keyIsString) {
39
41
  JSON.__serialize(unchecked(keys[srcEnd]));
40
42
  } else {
41
- JSON.__serialize<string>(JSON.internal.stringify<indexof<T>>(unchecked(keys[srcEnd])));
43
+ JSON.__serialize<string>(
44
+ JSON.internal.stringify<indexof<T>>(unchecked(keys[srcEnd])),
45
+ );
42
46
  }
43
47
  store<u16>(bs.offset, COLON);
44
48
  bs.offset += 2;
@@ -11,6 +11,10 @@ import { bytes } from "../../util";
11
11
  @inline export function serializeRaw(data: JSON.Raw): void {
12
12
  const dataSize = bytes(data.data);
13
13
  bs.proposeSize(dataSize);
14
- memory.copy(changetype<usize>(bs.offset), changetype<usize>(data.data), dataSize);
14
+ memory.copy(
15
+ changetype<usize>(bs.offset),
16
+ changetype<usize>(data.data),
17
+ dataSize,
18
+ );
15
19
  bs.offset += dataSize;
16
20
  }
@@ -38,7 +38,12 @@ export function serializeSet<T extends Set<any>>(src: T): void {
38
38
  bs.offset += 4;
39
39
  return;
40
40
  }
41
- if (isBoolean<indexof<T>>() || isInteger<indexof<T>>() || isFloat<indexof<T>>() || isString<indexof<T>>()) {
41
+ if (
42
+ isBoolean<indexof<T>>() ||
43
+ isInteger<indexof<T>>() ||
44
+ isFloat<indexof<T>>() ||
45
+ isString<indexof<T>>()
46
+ ) {
42
47
  reservePrimitiveSet<indexof<T>>(srcSize);
43
48
  } else {
44
49
  bs.proposeSize(4 + <u32>(srcSize - 1) * 2);
@@ -40,7 +40,12 @@ export function serializeStaticArray<T extends StaticArray<any>>(src: T): void {
40
40
  bs.offset += 4;
41
41
  return;
42
42
  }
43
- if (isBoolean<valueof<T>>() || isInteger<valueof<T>>() || isFloat<valueof<T>>() || isString<valueof<T>>()) {
43
+ if (
44
+ isBoolean<valueof<T>>() ||
45
+ isInteger<valueof<T>>() ||
46
+ isFloat<valueof<T>>() ||
47
+ isString<valueof<T>>()
48
+ ) {
44
49
  reservePrimitiveStaticArray<valueof<T>>(len);
45
50
  } else {
46
51
  bs.proposeSize(4 + <u32>(len - 1) * 2);
@@ -1,5 +1,4 @@
1
1
  import { bs } from "../../../lib/as-bs";
2
- import { _intTo16 } from "../../custom/util";
3
2
  import { bytes } from "../../util/bytes";
4
3
  import { BACK_SLASH, QUOTE } from "../../custom/chars";
5
4
  import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
@@ -17,7 +16,7 @@ import { serializeStruct } from "./struct";
17
16
  * @returns void
18
17
  */
19
18
  // @ts-ignore: inline
20
- @inline export function serializeString(src: string): void {
19
+ @inline export function serializeString_NAIVE(src: string): void {
21
20
  const srcSize = bytes(src);
22
21
  bs.proposeSize(srcSize + 4);
23
22
  let srcPtr = changetype<usize>(src);
@@ -25,9 +25,13 @@ function reserveTypedArray<T extends ArrayLike<number>>(len: i32): void {
25
25
 
26
26
 
27
27
  @inline
28
- function serializeTypedArrayElement<T extends ArrayLike<number>>(src: T, index: i32): void {
28
+ function serializeTypedArrayElement<T extends ArrayLike<number>>(
29
+ src: T,
30
+ index: i32,
31
+ ): void {
29
32
  if (isFloat<valueof<T>>()) {
30
- if (sizeof<valueof<T>>() == 4) serializeFloat32Unsafe(<f32>unchecked(src[index]));
33
+ if (sizeof<valueof<T>>() == 4)
34
+ serializeFloat32Unsafe(<f32>unchecked(src[index]));
31
35
  else serializeFloat64Unsafe(<f64>unchecked(src[index]));
32
36
  } else {
33
37
  serializeIntegerUnsafe<valueof<T>>(unchecked(src[index]));
@@ -59,7 +63,10 @@ export function serializeTypedArray<T extends ArrayLike<number>>(src: T): void {
59
63
  bs.offset += 2;
60
64
  }
61
65
 
62
- export function serializeArrayBufferUnsafe(srcStart: usize, byteLength: i32): void {
66
+ export function serializeArrayBufferUnsafe(
67
+ srcStart: usize,
68
+ byteLength: i32,
69
+ ): void {
63
70
  const end = byteLength - 1;
64
71
 
65
72
  if (end == -1) {
@@ -39,7 +39,9 @@ export function serializeString_SIMD(src: string): void {
39
39
  const lt20 = i16x8.lt_u(block, SPLAT_0020);
40
40
  const gteD8 = i8x16.gt_u(block, SPLAT_FFD8);
41
41
 
42
- const mask = i8x16.bitmask(v128.or(eq22, v128.or(eq5C, v128.or(lt20, gteD8))));
42
+ const mask = i8x16.bitmask(
43
+ v128.or(eq22, v128.or(eq5C, v128.or(lt20, gteD8))),
44
+ );
43
45
  if (mask != 0) break;
44
46
 
45
47
  store<v128>(dst, block);
@@ -83,7 +85,9 @@ export function serializeString_SIMD(src: string): void {
83
85
  // console.log("lt20 : " + mask_to_string_v128(lt20) + " -> " + mask_to_string_v128(SPLAT_0020));
84
86
  // console.log("gteD8 : " + mask_to_string_v128(gteD8) + " -> " + mask_to_string_v128(SPLAT_FFD8));
85
87
 
86
- let mask = i8x16.bitmask(v128.or(eq22, v128.or(eq5C, v128.or(lt20, gteD8))));
88
+ let mask = i8x16.bitmask(
89
+ v128.or(eq22, v128.or(eq5C, v128.or(lt20, gteD8))),
90
+ );
87
91
 
88
92
  if (mask == 0) {
89
93
  store<v128>(bs.offset, block);