json-as 1.1.25 → 1.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-12-21 - 1.1.26
4
+
5
+ - chore: remove log
6
+
3
7
  ## 2025-12-21 - 1.1.25
4
8
 
5
9
  - feat: Implement SWAR-based string serialization
@@ -0,0 +1,128 @@
1
+ import { BACK_SLASH } from "../../custom/chars";
2
+ import { DESERIALIZE_ESCAPE_TABLE, ESCAPE_HEX_TABLE } from "../../globals/tables";
3
+
4
+ // @ts-ignore: decorator allowed
5
+ @lazy const LANE_MASK_HIGH = 0xFF00_FF00_FF00_FF00;
6
+ // @ts-ignore: decorator allowed
7
+ @lazy const LANE_MASK_LOW = 0x00FF_00FF_00FF_00FF;
8
+ // @ts-ignore: decorator allowed
9
+ @lazy const UINT64_H8 = 0x8080808080808080;
10
+ // @ts-ignore: decorator allowed
11
+ @lazy const QUOTE_MASK = 0x0022_0022_0022_0022;
12
+ // @ts-ignore: decorator allowed
13
+ @lazy const BACKSLASH_MASK = 0x005C_005C_005C_005C;
14
+ // @ts-ignore: decorator allowed
15
+ @lazy const CONTROL_MASK = 0x0020_0020_0020_0020;
16
+ // @ts-ignore: decorator allowed
17
+ @lazy const U00_MARKER = 13511005048209500;
18
+
19
+ /**
20
+ * Deserializes strings back into into their original form using SIMD operations
21
+ * @param src string to deserialize
22
+ * @param dst buffer to write to
23
+ * @returns number of bytes written
24
+ */
25
+ // todo: optimize and stuff. it works, its not pretty. ideally, i'd like this to be (nearly) branchless
26
+ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize, dst: usize): usize {
27
+ srcStart += 2;
28
+ srcEnd -= 2;
29
+ let dst_ptr = changetype<usize>(dst);
30
+ const src_end_15 = srcEnd - 15;
31
+
32
+ while (srcStart < src_end_15) {
33
+ const block = v128.load(srcStart);
34
+ v128.store(dst_ptr, block);
35
+
36
+ const backslash_indices = i16x8.eq(block, SPLAT_92);
37
+ let mask = i16x8.bitmask(backslash_indices);
38
+
39
+ while (mask != 0) {
40
+ const lane_index = ctz(mask) << 1;
41
+ const dst_offset = dst_ptr + lane_index;
42
+ const src_offset = srcStart + lane_index;
43
+ const code = load<u16>(src_offset, 2);
44
+
45
+ mask &= mask - 1;
46
+ if (code == 117 && load<u32>(src_offset, 4) == 3145776) {
47
+ const block = load<u32>(src_offset, 8);
48
+ const codeA = block & 0xffff;
49
+ const codeB = (block >> 16) & 0xffff;
50
+ const escapedA = load<u8>(ESCAPE_HEX_TABLE + codeA);
51
+ const escapedB = load<u8>(ESCAPE_HEX_TABLE + codeB);
52
+ const escaped = (escapedA << 4) + escapedB;
53
+ // console.log("Escaped:");
54
+ // console.log(" a: " + escapedA.toString())
55
+ // console.log(" b: " + escapedB.toString());
56
+ // console.log(" c: " + escaped.toString());
57
+ // console.log(" o: " + (dst_ptr - dst).toString());
58
+ // console.log(" d: " + (dst_offset - dst).toString())
59
+ // console.log(" l: " + (lane_index).toString())
60
+ store<u16>(dst_offset, escaped);
61
+ v128.store(dst_offset, v128.load(src_offset, 4), 2);
62
+ if (lane_index >= 6) {
63
+ const bytes_left = lane_index - 4;
64
+ srcStart += bytes_left;
65
+ dst_ptr += bytes_left;
66
+ // console.log(" e: " + (bytes_left).toString())
67
+ }
68
+ dst_ptr -= 10;
69
+ } else {
70
+ const escaped = load<u8>(DESERIALIZE_ESCAPE_TABLE + code);
71
+ store<u16>(dst_offset, escaped);
72
+ v128.store(dst_offset, v128.load(src_offset, 4), 2);
73
+ // console.log("Escaped:");
74
+ if (lane_index == 14) {
75
+ srcStart += 2;
76
+ } else {
77
+ dst_ptr -= 2;
78
+ }
79
+ }
80
+ }
81
+
82
+ srcStart += 16;
83
+ dst_ptr += 16;
84
+
85
+ // console.log("src: " + (srcStart - changetype<usize>(src)).toString());
86
+ // console.log("dst: " + (dst_ptr - dst).toString());
87
+ }
88
+ while (srcStart < srcEnd) {
89
+ let code = load<u16>(srcStart);
90
+ if (code == BACK_SLASH) {
91
+ code = load<u16>(DESERIALIZE_ESCAPE_TABLE + load<u8>(srcStart, 2));
92
+ if (code == 117 && load<u32>(srcStart, 4) == 3145776) {
93
+ const block = load<u32>(srcStart, 8);
94
+ const codeA = block & 0xffff;
95
+ const codeB = (block >> 16) & 0xffff;
96
+ const escapedA = load<u8>(ESCAPE_HEX_TABLE + codeA);
97
+ const escapedB = load<u8>(ESCAPE_HEX_TABLE + codeB);
98
+ const escaped = (escapedA << 4) + escapedB;
99
+ store<u16>(dst_ptr, escaped);
100
+ dst_ptr += 2;
101
+ srcStart += 12;
102
+ } else {
103
+ store<u16>(dst_ptr, code);
104
+ dst_ptr += 2;
105
+ srcStart += 4;
106
+ }
107
+ } else {
108
+ store<u16>(dst_ptr, code);
109
+ dst_ptr += 2;
110
+ srcStart += 2;
111
+ }
112
+ }
113
+
114
+ return dst_ptr - dst;
115
+ }
116
+
117
+ // @ts-ignore: decorators allowed
118
+ @inline function v64x4_eq(x: u64, y: u64): u64 {
119
+ const xored = (x ^ LANE_MASK_HIGH) ^ y;
120
+ const mask = (((xored >> 1) | UINT64_H8) - xored) & UINT64_H8;
121
+ return (mask << 1) - (mask >> 7);
122
+ }
123
+
124
+ // @ts-ignore: decorators allowed
125
+ @inline function v64x4_ltu(a: u64, b: u64): u64 {
126
+ // Vigna's algorithm - fastest SWAR unsigned less-than
127
+ return (((a | UINT64_H8) - (b & ~UINT64_H8)) | (a ^ b)) ^ (a | ~b);
128
+ }
@@ -41,7 +41,7 @@ export function serializeString_SWAR(src: string): void {
41
41
 
42
42
  while (mask != 0) {
43
43
  const lane_index = usize(ctz(mask) >> 3);
44
- console.log("lane index " + lane_index.toString());
44
+ // console.log("lane index " + lane_index.toString());
45
45
  const src_offset = srcStart + lane_index;
46
46
  const code = load<u16>(src_offset) << 2;
47
47
  const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + code);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "1.1.25",
3
+ "version": "1.1.26",
4
4
  "author": "Jairus Tanaka",
5
5
  "repository": {
6
6
  "type": "git",