json-as 1.2.2 → 1.2.4
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/.claude/settings.local.json +9 -0
- package/ARCHITECTURE.md +320 -0
- package/CONTRIBUTING.md +238 -0
- package/LICENSE +2 -2
- package/README.md +35 -1
- package/TODO +1 -0
- package/assembly/custom/chars.ts +9 -0
- package/assembly/deserialize/simd/string.ts +139 -78
- package/assembly/deserialize/simple/arbitrary.ts +1 -2
- package/assembly/deserialize/simple/object.ts +1 -1
- package/assembly/deserialize/simple/set.ts +169 -0
- package/assembly/deserialize/simple/staticarray/array.ts +37 -0
- package/assembly/deserialize/simple/staticarray/bool.ts +39 -0
- package/assembly/deserialize/simple/staticarray/float.ts +44 -0
- package/assembly/deserialize/simple/staticarray/integer.ts +44 -0
- package/assembly/deserialize/simple/staticarray/string.ts +45 -0
- package/assembly/deserialize/simple/staticarray/struct.ts +47 -0
- package/assembly/deserialize/simple/staticarray.ts +28 -0
- package/assembly/deserialize/simple/string.ts +31 -40
- package/assembly/deserialize/swar/string.ts +147 -109
- package/assembly/globals/tables.ts +1 -1
- package/assembly/index.ts +419 -276
- package/assembly/serialize/simd/string.ts +134 -40
- package/assembly/serialize/simple/arbitrary.ts +18 -10
- package/assembly/serialize/simple/set.ts +34 -0
- package/assembly/serialize/simple/staticarray.ts +30 -0
- package/assembly/serialize/simple/string.ts +54 -4
- package/assembly/serialize/swar/string.ts +128 -72
- package/assembly/test.ts +18 -32
- package/assembly/util/masks.ts +47 -0
- package/assembly/util/swar.ts +14 -0
- package/eslint.config.js +77 -0
- package/lib/as-bs.ts +142 -49
- package/package.json +18 -5
- package/transform/lib/builder.d.ts +87 -0
- package/transform/lib/builder.d.ts.map +1 -0
- package/transform/lib/builder.js +169 -169
- package/transform/lib/builder.js.map +1 -1
- package/transform/lib/index.d.ts +32 -0
- package/transform/lib/index.d.ts.map +1 -0
- package/transform/lib/index.js +36 -17
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/linkers/alias.d.ts +12 -0
- package/transform/lib/linkers/alias.d.ts.map +1 -0
- package/transform/lib/linkers/alias.js +1 -1
- package/transform/lib/linkers/alias.js.map +1 -1
- package/transform/lib/linkers/custom.d.ts +10 -0
- package/transform/lib/linkers/custom.d.ts.map +1 -0
- package/transform/lib/linkers/imports.d.ts +3 -0
- package/transform/lib/linkers/imports.d.ts.map +1 -0
- package/transform/lib/linkers/imports.js +1 -1
- package/transform/lib/linkers/imports.js.map +1 -1
- package/transform/lib/types.d.ts +66 -0
- package/transform/lib/types.d.ts.map +1 -0
- package/transform/lib/types.js +6 -5
- package/transform/lib/types.js.map +1 -1
- package/transform/lib/util.d.ts +18 -0
- package/transform/lib/util.d.ts.map +1 -0
- package/transform/lib/util.js +4 -4
- package/transform/lib/util.js.map +1 -1
- package/transform/lib/visitor.d.ts +84 -0
- package/transform/lib/visitor.d.ts.map +1 -0
- package/transform/lib/visitor.js +76 -76
- package/transform/lib/visitor.js.map +1 -1
- package/transform/tsconfig.json +29 -2
- package/assembly/serialize/swar/number.ts +0 -0
- package/transform/lib/linkers/classes.js +0 -36
- package/transform/lib/linkers/classes.js.map +0 -1
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
This document describes the architecture of json-as, a high-performance JSON serialization library for AssemblyScript.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
json-as uses a two-tier architecture:
|
|
8
|
+
|
|
9
|
+
1. **Compile-time Transform**: A TypeScript-based AST transformer that generates optimized serialization/deserialization code
|
|
10
|
+
2. **Runtime Library**: AssemblyScript implementations for JSON processing with multiple optimization levels
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
14
|
+
│ Compile Time │
|
|
15
|
+
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
|
16
|
+
│ │ Source Code │ -> │ Transform │ -> │ Generated Code │ │
|
|
17
|
+
│ │ with @json │ │ (TypeScript) │ │ __SERIALIZE etc │ │
|
|
18
|
+
│ └─────────────┘ └──────────────┘ └──────────────────┘ │
|
|
19
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
20
|
+
│
|
|
21
|
+
V
|
|
22
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
23
|
+
│ Runtime │
|
|
24
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
25
|
+
│ │ JSON Namespace │ │
|
|
26
|
+
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
|
|
27
|
+
│ │ │ stringify │ │ parse │ │ Dynamic Types │ │ │
|
|
28
|
+
│ │ └──────┬──────┘ └──────┬──────┘ │ Value, Obj, │ │ │
|
|
29
|
+
│ │ │ │ │ Box, Raw │ │ │
|
|
30
|
+
│ │ V V └─────────────────┘ │ │
|
|
31
|
+
│ │ ┌───────────────────────────────────────────────────┐ │ │
|
|
32
|
+
│ │ │ Optimization Modes │ │ │
|
|
33
|
+
│ │ │ ┌───────┐ ┌────────┐ ┌────────┐ │ │ │
|
|
34
|
+
│ │ │ │ NAIVE │ │ SWAR │ │ SIMD │ │ │ │
|
|
35
|
+
│ │ │ └───────┘ └────────┘ └────────┘ │ │ │
|
|
36
|
+
│ │ └───────────────────────────────────────────────────┘ │ │
|
|
37
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
38
|
+
│ │ │
|
|
39
|
+
│ V │
|
|
40
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
41
|
+
│ │ Memory Allocator (bs namespace) │ │
|
|
42
|
+
│ │ - Dynamic buffer management │ │
|
|
43
|
+
│ │ - EMA-based adaptive sizing │ │
|
|
44
|
+
│ │ - Optional string caching (sc namespace) │ │
|
|
45
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
46
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Transform System
|
|
50
|
+
|
|
51
|
+
The transform (`transform/src/`) is an AssemblyScript compiler plugin that runs during compilation.
|
|
52
|
+
|
|
53
|
+
### How It Works
|
|
54
|
+
|
|
55
|
+
1. **Discovery**: Scans source files for classes decorated with `@json` or `@serializable`
|
|
56
|
+
2. **Schema Building**: Creates a schema for each decorated class including:
|
|
57
|
+
- Field names and types
|
|
58
|
+
- Decorator metadata (@alias, @omit, @omitnull, @omitif)
|
|
59
|
+
- Inheritance relationships
|
|
60
|
+
- Type dependencies
|
|
61
|
+
3. **Code Generation**: Generates two methods for each class:
|
|
62
|
+
- `__SERIALIZE(ptr: usize): void` - Writes JSON to the buffer
|
|
63
|
+
- `__DESERIALIZE<T>(srcStart, srcEnd, out): T` - Parses JSON into object
|
|
64
|
+
|
|
65
|
+
### Key Files
|
|
66
|
+
|
|
67
|
+
- `transform/src/index.ts` - Main transform entry point (JSONTransform class)
|
|
68
|
+
- `transform/src/visitor.ts` - AST visitor for traversing source code
|
|
69
|
+
- `transform/src/builder.ts` - AST builder for code generation
|
|
70
|
+
- `transform/src/types.ts` - Type definitions (Property, Schema, Src)
|
|
71
|
+
|
|
72
|
+
### Generated Code Example
|
|
73
|
+
|
|
74
|
+
For this class:
|
|
75
|
+
```typescript
|
|
76
|
+
@json
|
|
77
|
+
class Player {
|
|
78
|
+
name: string = "";
|
|
79
|
+
score: i32 = 0;
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The transform generates:
|
|
84
|
+
```typescript
|
|
85
|
+
__SERIALIZE(ptr: usize): void {
|
|
86
|
+
store<u16>(bs.offset, 123); // {
|
|
87
|
+
bs.offset += 2;
|
|
88
|
+
// ... "name": serialize string ...
|
|
89
|
+
// ... "score": serialize integer ...
|
|
90
|
+
store<u16>(bs.offset, 125); // }
|
|
91
|
+
bs.offset += 2;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
__DESERIALIZE<T>(srcStart: usize, srcEnd: usize, out: T): T {
|
|
95
|
+
// Key matching and value parsing logic
|
|
96
|
+
// Uses switch statements on key length for efficiency
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Optimization Modes
|
|
101
|
+
|
|
102
|
+
json-as provides three optimization levels, selected via the `JSON_MODE` environment variable:
|
|
103
|
+
|
|
104
|
+
### NAIVE Mode
|
|
105
|
+
|
|
106
|
+
The baseline implementation with character-by-character processing.
|
|
107
|
+
|
|
108
|
+
- **Best for**: Debugging, compatibility testing
|
|
109
|
+
- **Performance**: Slowest but most readable
|
|
110
|
+
- **String escaping**: Checks each character individually
|
|
111
|
+
|
|
112
|
+
### SWAR Mode (Default)
|
|
113
|
+
|
|
114
|
+
Single Instruction, Multiple Data processing at the word level.
|
|
115
|
+
|
|
116
|
+
- **Best for**: General use, good balance of speed and compatibility
|
|
117
|
+
- **Performance**: Processes 4 characters at once
|
|
118
|
+
- **String escaping**: Uses bit manipulation to detect escape characters in parallel:
|
|
119
|
+
```
|
|
120
|
+
// Check if any byte in a 64-bit word needs escaping
|
|
121
|
+
const hasEscape = (word ^ 0x2222...) - 0x0101... & 0x8080...
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### SIMD Mode
|
|
125
|
+
|
|
126
|
+
Uses WebAssembly SIMD instructions for 128-bit parallel processing.
|
|
127
|
+
|
|
128
|
+
- **Best for**: Maximum performance when SIMD is available
|
|
129
|
+
- **Performance**: Processes 8 characters at once
|
|
130
|
+
- **Requirement**: `--enable simd` flag during compilation
|
|
131
|
+
- **String escaping**: Uses `v128` operations for parallel character checking
|
|
132
|
+
|
|
133
|
+
## Buffer System
|
|
134
|
+
|
|
135
|
+
Located in `lib/as-bs.ts`, the buffer system (`bs` namespace) manages memory for serialization output.
|
|
136
|
+
|
|
137
|
+
### Key Features
|
|
138
|
+
|
|
139
|
+
1. **Dynamic Growth**: Buffer grows as needed during serialization
|
|
140
|
+
2. **Adaptive Sizing**: Uses exponential moving average (EMA) to track typical output sizes
|
|
141
|
+
3. **Automatic Shrinking**: Periodically shrinks if buffer is oversized for typical usage
|
|
142
|
+
|
|
143
|
+
### Memory Layout
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
┌───────────────────────────────────────────┐
|
|
147
|
+
│ ArrayBuffer │
|
|
148
|
+
│ ┌───────────────────┬─────────────────┐ │
|
|
149
|
+
│ │ Written Data │ Free Space │ │
|
|
150
|
+
│ └───────────────────┴─────────────────┘ │
|
|
151
|
+
│ ^ buffer ^ offset │
|
|
152
|
+
└───────────────────────────────────────────┘
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Key Functions
|
|
156
|
+
|
|
157
|
+
- `proposeSize(size)` - Ensure buffer can hold additional bytes
|
|
158
|
+
- `ensureSize(size)` - Grow buffer if necessary
|
|
159
|
+
- `out<T>()` - Copy buffer contents to new string, reset for next use
|
|
160
|
+
- `resize(size)` - Explicitly resize buffer
|
|
161
|
+
|
|
162
|
+
### String Caching (`sc` namespace)
|
|
163
|
+
|
|
164
|
+
Optional feature enabled via `JSON_CACHE=1` for repeated string serialization.
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
┌───────────────────────────────────────────────────────────────┐
|
|
168
|
+
│ Cache Structure │
|
|
169
|
+
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
170
|
+
│ │ Entry Table (4096 slots) │ │
|
|
171
|
+
│ │ ┌────────┬────────┬────────┬────────┐ │ │
|
|
172
|
+
│ │ │ Entry 0│ Entry 1│ ... │Entry N │ │ │
|
|
173
|
+
│ │ │key,ptr,│key,ptr,│ │key,ptr,│ │ │
|
|
174
|
+
│ │ │ len │ len │ │ len │ │ │
|
|
175
|
+
│ │ └────────┴────────┴────────┴────────┘ │ │
|
|
176
|
+
│ └─────────────────────────────────────────────────────────┘ │
|
|
177
|
+
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
178
|
+
│ │ Arena (1MB circular buffer) │ │
|
|
179
|
+
│ │ ┌──────────────────────────────────────────────────┐ │ │
|
|
180
|
+
│ │ │ Cached serialized string data... │ │ │
|
|
181
|
+
│ │ └──────────────────────────────────────────────────┘ │ │
|
|
182
|
+
│ │ ^ │ │
|
|
183
|
+
│ │ arenaPtr │ │
|
|
184
|
+
│ └─────────────────────────────────────────────────────────┘ │
|
|
185
|
+
└───────────────────────────────────────────────────────────────┘
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Type System
|
|
189
|
+
|
|
190
|
+
### Static Types
|
|
191
|
+
|
|
192
|
+
Regular AssemblyScript types handled directly:
|
|
193
|
+
- Primitives: `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`, `f32`, `f64`, `bool`
|
|
194
|
+
- Strings: `string`
|
|
195
|
+
- Collections: `Array<T>`, `StaticArray<T>`, `Map<K, V>`
|
|
196
|
+
- Classes decorated with `@json`
|
|
197
|
+
|
|
198
|
+
### Dynamic Types
|
|
199
|
+
|
|
200
|
+
For runtime type flexibility:
|
|
201
|
+
|
|
202
|
+
- **`JSON.Value`**: Can hold any JSON type
|
|
203
|
+
```typescript
|
|
204
|
+
const v = JSON.Value.from<i32>(42);
|
|
205
|
+
v.set<string>("hello"); // Can change type
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
- **`JSON.Obj`**: Dynamic object with string keys
|
|
209
|
+
```typescript
|
|
210
|
+
const obj = new JSON.Obj();
|
|
211
|
+
obj.set("key", 123);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
- **`JSON.Box<T>`**: Nullable wrapper for primitives
|
|
215
|
+
```typescript
|
|
216
|
+
let maybeInt: JSON.Box<i32> | null = null;
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
- **`JSON.Raw`**: Pre-formatted JSON string (no re-serialization)
|
|
220
|
+
```typescript
|
|
221
|
+
map.set("data", new JSON.Raw('{"already":"json"}'));
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Serialization Flow
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
JSON.stringify<T>(data)
|
|
228
|
+
│
|
|
229
|
+
V
|
|
230
|
+
┌───────────────────┐
|
|
231
|
+
│ Type Dispatch │
|
|
232
|
+
│ (compile-time) │
|
|
233
|
+
└─────────┬─────────┘
|
|
234
|
+
│
|
|
235
|
+
┌─────┴─────┬─────────────┬──────────────┐
|
|
236
|
+
V V V V
|
|
237
|
+
┌───────┐ ┌────────┐ ┌──────────┐ ┌──────────┐
|
|
238
|
+
│Boolean│ │Integer │ │ String │ │ Struct │
|
|
239
|
+
│ Float │ │ │ │ │ │ (@json) │
|
|
240
|
+
└───┬───┘ └────┬───┘ └────┬─────┘ └────┬─────┘
|
|
241
|
+
│ │ │ │
|
|
242
|
+
│ │ │ │
|
|
243
|
+
└───────────┴─────┬──────┴──────────────┘
|
|
244
|
+
V
|
|
245
|
+
┌───────────────┐
|
|
246
|
+
│ Buffer System │
|
|
247
|
+
└───────┬───────┘
|
|
248
|
+
V
|
|
249
|
+
┌───────────────┐
|
|
250
|
+
│ Heap │
|
|
251
|
+
└───────┬───────┘
|
|
252
|
+
V
|
|
253
|
+
String
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Deserialization Flow
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
JSON.parse<T>(jsonString)
|
|
260
|
+
│
|
|
261
|
+
V
|
|
262
|
+
┌───────────────────┐
|
|
263
|
+
│ Type Dispatch │
|
|
264
|
+
│ (compile-time) │
|
|
265
|
+
└─────────┬─────────┘
|
|
266
|
+
│
|
|
267
|
+
┌─────┴─────┬─────────────┬──────────────┐
|
|
268
|
+
V V V V
|
|
269
|
+
┌───────┐ ┌────────┐ ┌──────────┐ ┌──────────┐
|
|
270
|
+
│Boolean│ │Integer │ │ String │ │ Struct │
|
|
271
|
+
└───┬───┘ └────┬───┘ └────┬─────┘ └────┬─────┘
|
|
272
|
+
│ │ │ │
|
|
273
|
+
└───────────┴─────┬──────┴──────────────┘
|
|
274
|
+
│
|
|
275
|
+
V
|
|
276
|
+
T
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Struct Deserialization
|
|
280
|
+
|
|
281
|
+
For `@json` decorated classes, the generated `__DESERIALIZE` method:
|
|
282
|
+
|
|
283
|
+
1. Scans for opening `{`
|
|
284
|
+
2. Iterates through key-value pairs
|
|
285
|
+
3. Uses switch on key length for fast dispatch
|
|
286
|
+
4. Compares key bytes directly (often as `u32` or `u64` for short keys)
|
|
287
|
+
5. Deserializes value to appropriate type
|
|
288
|
+
6. Stores in output object at correct offset
|
|
289
|
+
|
|
290
|
+
## Environment Variables
|
|
291
|
+
|
|
292
|
+
| Variable | Default | Description |
|
|
293
|
+
|----------|---------|-------------|
|
|
294
|
+
| `JSON_MODE` | SWAR | Optimization mode: NAIVE, SWAR, SIMD |
|
|
295
|
+
| `JSON_DEBUG` | 0 | Debug level 0-3 (prints generated code) |
|
|
296
|
+
| `JSON_WRITE` | "" | Comma-separated files to output after transform |
|
|
297
|
+
| `JSON_CACHE` | 0 | Enable string caching (set to 1) |
|
|
298
|
+
| `JSON_STRICT` | false | Enable strict JSON validation |
|
|
299
|
+
|
|
300
|
+
## Performance Considerations
|
|
301
|
+
|
|
302
|
+
### Serialization
|
|
303
|
+
|
|
304
|
+
- Pre-computes static key bytes at compile time
|
|
305
|
+
- Uses direct memory stores for known strings
|
|
306
|
+
- SIMD/SWAR for escape character detection
|
|
307
|
+
- Optional caching for repeated strings
|
|
308
|
+
|
|
309
|
+
### Deserialization
|
|
310
|
+
|
|
311
|
+
- Groups fields by key length for switch optimization
|
|
312
|
+
- Uses direct memory loads for key comparison
|
|
313
|
+
- Avoids string allocation during key matching
|
|
314
|
+
- Tracks depth for nested structures
|
|
315
|
+
|
|
316
|
+
### Memory
|
|
317
|
+
|
|
318
|
+
- Single reusable buffer reduces allocations
|
|
319
|
+
- EMA-based sizing prevents memory waste
|
|
320
|
+
- Circular arena for cache prevents unbounded growth
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Contributing to json-as
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to json-as! This document provides guidelines and instructions for contributing.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Getting Started](#getting-started)
|
|
8
|
+
- [Development Setup](#development-setup)
|
|
9
|
+
- [Project Structure](#project-structure)
|
|
10
|
+
- [Making Changes](#making-changes)
|
|
11
|
+
- [Testing](#testing)
|
|
12
|
+
- [Code Style](#code-style)
|
|
13
|
+
- [Pull Request Process](#pull-request-process)
|
|
14
|
+
- [Reporting Issues](#reporting-issues)
|
|
15
|
+
|
|
16
|
+
## Getting Started
|
|
17
|
+
|
|
18
|
+
1. Fork the repository on GitHub
|
|
19
|
+
2. Clone your fork locally:
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/YOUR_USERNAME/json-as.git
|
|
22
|
+
cd json-as
|
|
23
|
+
```
|
|
24
|
+
3. Add the upstream remote:
|
|
25
|
+
```bash
|
|
26
|
+
git remote add upstream https://github.com/JairusSW/json-as.git
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Development Setup
|
|
30
|
+
|
|
31
|
+
### Prerequisites
|
|
32
|
+
|
|
33
|
+
- Node.js 18+ or Bun
|
|
34
|
+
- Wasmtime (for running tests)
|
|
35
|
+
|
|
36
|
+
### Install Dependencies
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install
|
|
40
|
+
# or
|
|
41
|
+
bun install
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Build the Transform
|
|
45
|
+
|
|
46
|
+
The transform is written in TypeScript and needs to be compiled:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run build:transform
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Running Tests
|
|
53
|
+
|
|
54
|
+
Run the full test suite across all modes (NAIVE, SWAR, SIMD):
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm test
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Run a specific test file:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
./run-tests.sh string # Runs string.spec.ts
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Running Benchmarks
|
|
67
|
+
|
|
68
|
+
AssemblyScript benchmarks:
|
|
69
|
+
```bash
|
|
70
|
+
npm run bench:as
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
JavaScript comparison benchmarks:
|
|
74
|
+
```bash
|
|
75
|
+
npm run bench:js
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Project Structure
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
json-as/
|
|
82
|
+
├── assembly/ # AssemblyScript runtime implementation
|
|
83
|
+
│ ├── index.ts # Main entry point (JSON namespace)
|
|
84
|
+
│ ├── serialize/ # Serialization implementations
|
|
85
|
+
│ │ ├── simple/ # Naive implementation
|
|
86
|
+
│ │ ├── swar/ # SWAR-optimized
|
|
87
|
+
│ │ └── simd/ # SIMD-optimized
|
|
88
|
+
│ ├── deserialize/ # Deserialization implementations
|
|
89
|
+
│ ├── util/ # Utility functions
|
|
90
|
+
│ ├── custom/ # Constants and character codes
|
|
91
|
+
│ └── __tests__/ # Test files
|
|
92
|
+
├── transform/ # TypeScript compiler transform
|
|
93
|
+
│ └── src/ # Transform source code
|
|
94
|
+
├── lib/ # Shared utilities (buffer system)
|
|
95
|
+
├── bench/ # Benchmark suite
|
|
96
|
+
└── .github/ # CI/CD workflows
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Making Changes
|
|
100
|
+
|
|
101
|
+
### Branching Strategy
|
|
102
|
+
|
|
103
|
+
1. Create a feature branch from `main`:
|
|
104
|
+
```bash
|
|
105
|
+
git checkout -b feature/your-feature-name
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
2. Make your changes with clear, atomic commits
|
|
109
|
+
|
|
110
|
+
3. Keep your branch up to date:
|
|
111
|
+
```bash
|
|
112
|
+
git fetch upstream
|
|
113
|
+
git rebase upstream/main
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Commit Messages
|
|
117
|
+
|
|
118
|
+
Use clear, descriptive commit messages:
|
|
119
|
+
|
|
120
|
+
- `feat: add support for BigInt serialization`
|
|
121
|
+
- `fix: handle escaped unicode in strings`
|
|
122
|
+
- `perf: optimize SIMD string escaping`
|
|
123
|
+
- `docs: update README examples`
|
|
124
|
+
- `test: add edge case tests for nested arrays`
|
|
125
|
+
- `chore: update dependencies`
|
|
126
|
+
|
|
127
|
+
## Testing
|
|
128
|
+
|
|
129
|
+
### Writing Tests
|
|
130
|
+
|
|
131
|
+
Tests are located in `assembly/__tests__/`. Each test file follows the pattern `*.spec.ts`.
|
|
132
|
+
|
|
133
|
+
Example test structure:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { JSON } from "..";
|
|
137
|
+
|
|
138
|
+
describe("Feature Name", () => {
|
|
139
|
+
test("should serialize correctly", () => {
|
|
140
|
+
const result = JSON.stringify<string>("hello");
|
|
141
|
+
expect(result).toBe('"hello"');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("should deserialize correctly", () => {
|
|
145
|
+
const result = JSON.parse<string>('"hello"');
|
|
146
|
+
expect(result).toBe("hello");
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Test Coverage
|
|
152
|
+
|
|
153
|
+
Ensure your changes include tests for:
|
|
154
|
+
- Happy path scenarios
|
|
155
|
+
- Edge cases
|
|
156
|
+
- Error conditions
|
|
157
|
+
- All three modes (NAIVE, SWAR, SIMD) if applicable
|
|
158
|
+
|
|
159
|
+
## Code Style
|
|
160
|
+
|
|
161
|
+
### Formatting
|
|
162
|
+
|
|
163
|
+
The project uses Prettier for formatting:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npm run format
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### AssemblyScript Guidelines
|
|
170
|
+
|
|
171
|
+
- Use `@inline` decorator for small, frequently-called functions
|
|
172
|
+
- Prefer `store<T>` and `load<T>` for direct memory operations
|
|
173
|
+
- Use typed arrays and explicit types
|
|
174
|
+
- Add `// @ts-ignore` comments with explanations when necessary
|
|
175
|
+
|
|
176
|
+
### TypeScript Guidelines (Transform)
|
|
177
|
+
|
|
178
|
+
- Use strict TypeScript settings
|
|
179
|
+
- Document complex logic with comments
|
|
180
|
+
- Keep functions focused and small
|
|
181
|
+
|
|
182
|
+
## Pull Request Process
|
|
183
|
+
|
|
184
|
+
1. **Before submitting:**
|
|
185
|
+
- Run the full test suite: `npm test`
|
|
186
|
+
- Run the formatter: `npm run format`
|
|
187
|
+
- Ensure your branch is up to date with `main`
|
|
188
|
+
|
|
189
|
+
2. **PR Description:**
|
|
190
|
+
- Clearly describe the changes
|
|
191
|
+
- Reference any related issues
|
|
192
|
+
- Include before/after benchmarks for performance changes
|
|
193
|
+
|
|
194
|
+
3. **Review Process:**
|
|
195
|
+
- PRs require at least one approval
|
|
196
|
+
- Address review feedback promptly
|
|
197
|
+
- Keep the PR focused on a single concern
|
|
198
|
+
|
|
199
|
+
4. **After Merge:**
|
|
200
|
+
- Delete your feature branch
|
|
201
|
+
- Update any related issues
|
|
202
|
+
|
|
203
|
+
## Reporting Issues
|
|
204
|
+
|
|
205
|
+
### Bug Reports
|
|
206
|
+
|
|
207
|
+
Include:
|
|
208
|
+
- json-as version
|
|
209
|
+
- AssemblyScript version
|
|
210
|
+
- Minimal reproduction case
|
|
211
|
+
- Expected vs actual behavior
|
|
212
|
+
- Error messages (if any)
|
|
213
|
+
|
|
214
|
+
### Feature Requests
|
|
215
|
+
|
|
216
|
+
Include:
|
|
217
|
+
- Use case description
|
|
218
|
+
- Proposed API (if applicable)
|
|
219
|
+
- Alternatives considered
|
|
220
|
+
|
|
221
|
+
## Performance Contributions
|
|
222
|
+
|
|
223
|
+
If your change affects performance:
|
|
224
|
+
|
|
225
|
+
1. Run benchmarks before and after
|
|
226
|
+
2. Include benchmark results in the PR
|
|
227
|
+
3. Test across all three modes (NAIVE, SWAR, SIMD)
|
|
228
|
+
4. Consider memory usage implications
|
|
229
|
+
|
|
230
|
+
## Questions?
|
|
231
|
+
|
|
232
|
+
- Open a GitHub Discussion for general questions
|
|
233
|
+
- Join the [AssemblyScript Discord](https://discord.gg/assemblyscript)
|
|
234
|
+
- Email the maintainer at [me@jairus.dev](mailto:me@jairus.dev)
|
|
235
|
+
|
|
236
|
+
## License
|
|
237
|
+
|
|
238
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 Jairus Tanaka <me@jairus.dev>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
- [Performance Tuning](#performance-tuning)
|
|
20
20
|
- [Running Benchmarks Locally](#running-benchmarks-locally)
|
|
21
21
|
- [Debugging](#debugging)
|
|
22
|
+
- [Architecture](#architecture)
|
|
23
|
+
- [Contributing](#contributing)
|
|
24
|
+
- [Who uses it?](#who-uses-it)
|
|
22
25
|
- [License](#license)
|
|
23
26
|
- [Contact](#contact)
|
|
24
27
|
|
|
@@ -413,6 +416,8 @@ The following charts compare JSON-AS (both SWAR and SIMD variants) against JavaS
|
|
|
413
416
|
|
|
414
417
|
<img src="https://raw.githubusercontent.com/JairusSW/json-as/refs/heads/docs/charts/chart03.png" alt="Performance Chart 3">
|
|
415
418
|
|
|
419
|
+
<img src="https://raw.githubusercontent.com/JairusSW/json-as/refs/heads/docs/charts/chart04.png" alt="Performance Chart 4">
|
|
420
|
+
|
|
416
421
|
> Note: I have focused on extensively optimizing serialization. I used to have deserialization be highly unsafe and extremely fast, but I've since doubled down on safety for deserialization which has negatively affected performance. I will be optimizing soon.
|
|
417
422
|
|
|
418
423
|
### Performance Tuning
|
|
@@ -474,9 +479,38 @@ or
|
|
|
474
479
|
`JSON_DEBUG=2` - The above and prints keys/values as they are deserialized
|
|
475
480
|
`JSON_WRITE=path-to-file.ts` - Writes out generated code to `path-to-file.json.ts` for easy inspection
|
|
476
481
|
|
|
482
|
+
## Architecture
|
|
483
|
+
|
|
484
|
+
For a deep dive into how json-as works internally, including the transform system, optimization modes (NAIVE, SWAR, SIMD), and buffer management, see [ARCHITECTURE.md](./ARCHITECTURE.md).
|
|
485
|
+
|
|
486
|
+
## Contributing
|
|
487
|
+
|
|
488
|
+
We welcome contributions! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on:
|
|
489
|
+
|
|
490
|
+
- Setting up your development environment
|
|
491
|
+
- Running tests and benchmarks
|
|
492
|
+
- Code style and commit conventions
|
|
493
|
+
- The pull request process
|
|
494
|
+
|
|
495
|
+
## Who uses it?
|
|
496
|
+
|
|
497
|
+
A few companies and open-source projects use json-as!
|
|
498
|
+
|
|
499
|
+
| Company/Project | Description |
|
|
500
|
+
|-----------------|-------------|
|
|
501
|
+
| [Impart Security](https://impart.security) | API security platform |
|
|
502
|
+
| [Hypermode](https://hypermode.ai) | AI infrastructure |
|
|
503
|
+
| [Steer Finance](https://steer.finance) | DeFi protocol |
|
|
504
|
+
| [Secretarium](https://secretarium.com) | Confidential computing |
|
|
505
|
+
| [Klave](https://klave.com) | Privacy-first platform |
|
|
506
|
+
| [Bifrost](https://github.com/maximhq/bifrost) | Open source project by Maxim HQ |
|
|
507
|
+
| [Massa Labs](https://github.com/massalabs) | Massa blockchain tooling |
|
|
508
|
+
|
|
477
509
|
## License
|
|
478
510
|
|
|
479
|
-
This project is distributed under an open source license.
|
|
511
|
+
This project is distributed under an open source license. Work on this project is done by passion, but if you want to support it financially, you can do so by making a donation to the project's [GitHub Sponsors](https://github.com/sponsors/JairusSW) page.
|
|
512
|
+
|
|
513
|
+
You can view the full license using the following link: [License](./LICENSE)
|
|
480
514
|
|
|
481
515
|
## Contact
|
|
482
516
|
|
package/TODO
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
get staticarrays working within classes
|
package/assembly/custom/chars.ts
CHANGED
|
@@ -74,3 +74,12 @@
|
|
|
74
74
|
@inline export const FORM_FEED = 12; // \f
|
|
75
75
|
// @ts-ignore: Decorator is valid here
|
|
76
76
|
@inline export const CARRIAGE_RETURN = 13; // \r
|
|
77
|
+
|
|
78
|
+
// Pre-encoded u64 constants for common JSON literals
|
|
79
|
+
// These represent the UTF-16 encoded bytes stored as u64 for fast comparison/storage
|
|
80
|
+
// @ts-ignore: Decorator is valid here
|
|
81
|
+
@inline export const NULL_WORD_U64: u64 = 30399761348886638; // "null" as u64 (n=110, u=117, l=108, l=108)
|
|
82
|
+
// @ts-ignore: Decorator is valid here
|
|
83
|
+
@inline export const TRUE_WORD_U64: u64 = 28429475166421108; // "true" as u64 (t=116, r=114, u=117, e=101)
|
|
84
|
+
// @ts-ignore: Decorator is valid here
|
|
85
|
+
@inline export const FALSE_WORD_U64: u64 = 32370086184550502; // "fals" as u64 (f=102, a=97, l=108, s=115) - first 4 chars of "false"
|