json-as 1.1.12 → 1.1.14-preview.1

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.
@@ -0,0 +1,388 @@
1
+ import {
2
+ bs
3
+ } from "../lib/as-bs";
4
+ import {
5
+ JSON
6
+ } from ".";
7
+ import {
8
+ Vec3
9
+ } from "./types";
10
+ @json
11
+ class Player {
12
+ @alias("first name")
13
+ firstName!: string;
14
+ lastName!: string;
15
+ lastActive!: Array<i32>;
16
+ @omitif((self: this): boolean => self.age < 18)
17
+ age!: i32;
18
+ @omitnull()
19
+ pos!: Vec3 | null;
20
+ isVerified!: boolean;
21
+ __SERIALIZE(ptr: usize): void {
22
+ bs.proposeSize(160);
23
+ let block: usize = 0;
24
+ store<u16>(bs.offset, 123, 0);
25
+ bs.offset += 2;
26
+ if (!((self: this): boolean => self.age < 18)(this)) {
27
+ store<u64>(bs.offset, 28429415035764770, 0);
28
+ store<u32>(bs.offset, 3801122, 8);
29
+ bs.offset += 12;
30
+ JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("age")));
31
+ store<u16>(bs.offset, 44, 0);
32
+ bs.offset += 2;
33
+ }
34
+ if ((block = load<usize>(ptr, offsetof<this>("pos"))) !== 0) {
35
+ store<u64>(bs.offset, 32370099070435362, 0);
36
+ store<u32>(bs.offset, 3801122, 8);
37
+ bs.offset += 12;
38
+ JSON.__serialize<Vec3 | null>(load<Vec3 | null>(ptr, offsetof<this>("pos")));
39
+ store<u16>(bs.offset, 44, 0);
40
+ bs.offset += 2;
41
+ }
42
+ store<u64>(bs.offset, 32088598323265570, 0);
43
+ store<u64>(bs.offset, 30962384884727923, 8);
44
+ store<u64>(bs.offset, 9570583007002721, 16);
45
+ store<u16>(bs.offset, 58, 24);
46
+ bs.offset += 26;
47
+ JSON.__serialize<string>(load<string>(ptr, offsetof<this>("firstName")));
48
+ store<u64>(bs.offset, 27303536599629868, 0);
49
+ store<u64>(bs.offset, 27303407755985011, 8);
50
+ store<u64>(bs.offset, 16325694684725357, 16);
51
+ bs.offset += 24;
52
+ JSON.__serialize<string>(load<string>(ptr, offsetof<this>("lastName")));
53
+ store<u64>(bs.offset, 27303536599629868, 0);
54
+ store<u64>(bs.offset, 27866301874831475, 8);
55
+ store<u64>(bs.offset, 28429479460798580, 16);
56
+ store<u32>(bs.offset, 3801122, 24);
57
+ bs.offset += 28;
58
+ JSON.__serialize<Array<i32>>(load<Array<i32>>(ptr, offsetof<this>("lastActive")));
59
+ store<u64>(bs.offset, 32370073295519788, 0);
60
+ store<u64>(bs.offset, 29555362187509846, 8);
61
+ store<u64>(bs.offset, 28147931469643878, 16);
62
+ store<u32>(bs.offset, 3801122, 24);
63
+ bs.offset += 28;
64
+ JSON.__serialize<boolean>(load<boolean>(ptr, offsetof<this>("isVerified")));
65
+ store<u16>(bs.offset, 125, 0);
66
+ bs.offset += 2;
67
+ }
68
+ @inline
69
+ __INITIALIZE(): this {
70
+ this.firstName = "";
71
+ this.lastName = "";
72
+ this.lastActive = [];
73
+ return this;
74
+ }
75
+ __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {
76
+ let keyStart: usize = 0;
77
+ let keyEnd: usize = 0;
78
+ let isKey = false;
79
+ let depth: i32 = 0;
80
+ let lastIndex: usize = 0;
81
+ while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;
82
+ while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
83
+ if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");
84
+ ;
85
+ if (load<u16>(srcStart) != 123) throw new Error("Expected '{' at start of object at position " + (srcEnd - srcStart).toString());
86
+ ;
87
+ if (load<u16>(srcEnd - 2) != 125) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
88
+ ;
89
+ srcStart += 2;
90
+ while (srcStart < srcEnd) {
91
+ let code = load<u16>(srcStart);
92
+ while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);
93
+ if (keyStart == 0) {
94
+ if (code == 34 && load<u16>(srcStart - 2) !== 92) {
95
+ if (isKey) {
96
+ keyStart = lastIndex;
97
+ keyEnd = srcStart;
98
+ while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}
99
+ if (code !== 58) throw new Error("Expected ':' after key at position " + (srcEnd - srcStart).toString());
100
+ ;
101
+ isKey = false;
102
+ } else {
103
+ isKey = true;
104
+ lastIndex = srcStart + 2;
105
+ }
106
+ }
107
+ srcStart += 2;
108
+ } else {
109
+ if (code == 34) {
110
+ lastIndex = srcStart;
111
+ srcStart += 2;
112
+ while (srcStart < srcEnd) {
113
+ const code = load<u16>(srcStart);
114
+ if (code == 34 && load<u16>(srcStart - 2) !== 92) {
115
+ switch (<u32>keyEnd - <u32>keyStart) {
116
+ case 20:
117
+ {
118
+ const codeS8 = load<u64>(keyStart, 0);
119
+ const codeS16 = load<u64>(keyStart, 8);
120
+ const codeS20 = load<u32>(keyStart, 16);
121
+ if (codeS8 == 32370111954878566 && codeS16 == 27303545189433460 && codeS20 == 6619245) {
122
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart + 2), offsetof<this>("firstName"));
123
+ srcStart += 4;
124
+ keyStart = 0;
125
+ break;
126
+ } else {
127
+ srcStart += 4;
128
+ keyStart = 0;
129
+ break;
130
+ }
131
+ }
132
+
133
+ case 16:
134
+ {
135
+ const codeS8 = load<u64>(keyStart, 0);
136
+ const codeS16 = load<u64>(keyStart, 8);
137
+ if (codeS8 == 32651591226032236 && codeS16 == 28429440805568590) {
138
+ store<string>(changetype<usize>(out), JSON.__deserialize<string>(lastIndex, srcStart + 2), offsetof<this>("lastName"));
139
+ srcStart += 4;
140
+ keyStart = 0;
141
+ break;
142
+ } else {
143
+ srcStart += 4;
144
+ keyStart = 0;
145
+ break;
146
+ }
147
+ }
148
+
149
+ default:
150
+ {
151
+ srcStart += 4;
152
+ keyStart = 0;
153
+ break;
154
+ }
155
+
156
+ }
157
+ break;
158
+ }
159
+ srcStart += 2;
160
+ }
161
+ } else if (code - 48 <= 9 || code == 45) {
162
+ lastIndex = srcStart;
163
+ srcStart += 2;
164
+ while (srcStart < srcEnd) {
165
+ const code = load<u16>(srcStart);
166
+ if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {
167
+ switch (<u32>keyEnd - <u32>keyStart) {
168
+ case 6:
169
+ {
170
+ const code48 = load<u64>(keyStart) & 281474976710655;
171
+ if (code48 == 433798447201) {
172
+ store<i32>(changetype<usize>(out), JSON.__deserialize<i32>(lastIndex, srcStart), offsetof<this>("age"));
173
+ srcStart += 2;
174
+ keyStart = 0;
175
+ break;
176
+ } else {
177
+ srcStart += 2;
178
+ keyStart = 0;
179
+ break;
180
+ }
181
+ }
182
+
183
+ default:
184
+ {
185
+ srcStart += 2;
186
+ keyStart = 0;
187
+ break;
188
+ }
189
+
190
+ }
191
+ break;
192
+ }
193
+ srcStart += 2;
194
+ }
195
+ } else if (code == 123) {
196
+ lastIndex = srcStart;
197
+ depth++;
198
+ srcStart += 2;
199
+ while (srcStart < srcEnd) {
200
+ const code = load<u16>(srcStart);
201
+ if (code == 34) {
202
+ srcStart += 2;
203
+ while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;
204
+ } else if (code == 125) {
205
+ if (--depth == 0) {
206
+ srcStart += 2;
207
+ switch (<u32>keyEnd - <u32>keyStart) {
208
+ case 6:
209
+ {
210
+ const code48 = load<u64>(keyStart) & 281474976710655;
211
+ if (code48 == 493928513648) {
212
+ store<Vec3 | null>(changetype<usize>(out), JSON.__deserialize<Vec3 | null>(lastIndex, srcStart), offsetof<this>("pos"));
213
+ keyStart = 0;
214
+ break;
215
+ } else {
216
+ keyStart = 0;
217
+ break;
218
+ }
219
+ }
220
+
221
+ default:
222
+ {
223
+ keyStart = 0;
224
+ break;
225
+ }
226
+
227
+ }
228
+ break;
229
+ }
230
+ } else if (code == 123) depth++;
231
+ ;
232
+ srcStart += 2;
233
+ }
234
+ } else if (code == 91) {
235
+ lastIndex = srcStart;
236
+ depth++;
237
+ srcStart += 2;
238
+ while (srcStart < srcEnd) {
239
+ const code = load<u16>(srcStart);
240
+ if (code == 34) {
241
+ srcStart += 2;
242
+ while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;
243
+ } else if (code == 93) {
244
+ if (--depth == 0) {
245
+ srcStart += 2;
246
+ switch (<u32>keyEnd - <u32>keyStart) {
247
+ case 20:
248
+ {
249
+ const codeS8 = load<u64>(keyStart, 0);
250
+ const codeS16 = load<u64>(keyStart, 8);
251
+ const codeS20 = load<u32>(keyStart, 16);
252
+ if (codeS8 == 32651591226032236 && codeS16 == 29555370777313345 && codeS20 == 6619254) {
253
+ store<Array<i32>>(changetype<usize>(out), JSON.__deserialize<Array<i32>>(lastIndex, srcStart), offsetof<this>("lastActive"));
254
+ keyStart = 0;
255
+ break;
256
+ } else {
257
+ keyStart = 0;
258
+ break;
259
+ }
260
+ }
261
+
262
+ default:
263
+ {
264
+ keyStart = 0;
265
+ break;
266
+ }
267
+
268
+ }
269
+ break;
270
+ }
271
+ } else if (code == 91) depth++;
272
+ ;
273
+ srcStart += 2;
274
+ }
275
+ } else if (code == 116) {
276
+ if (load<u64>(srcStart) == 28429475166421108) {
277
+ srcStart += 8;
278
+ switch (<u32>keyEnd - <u32>keyStart) {
279
+ case 20:
280
+ {
281
+ const codeS8 = load<u64>(keyStart, 0);
282
+ const codeS16 = load<u64>(keyStart, 8);
283
+ const codeS20 = load<u32>(keyStart, 16);
284
+ if (codeS8 == 28429342022500457 && codeS16 == 29555310648164466 && codeS20 == 6553701) {
285
+ store<boolean>(changetype<usize>(out), true, offsetof<this>("isVerified"));
286
+ srcStart += 2;
287
+ keyStart = 0;
288
+ break;
289
+ } else {
290
+ srcStart += 2;
291
+ keyStart = 0;
292
+ break;
293
+ }
294
+ }
295
+
296
+ default:
297
+ {
298
+ srcStart += 2;
299
+ keyStart = 0;
300
+ }
301
+
302
+ }
303
+ } else {
304
+ throw new Error("Expected to find 'true' but found '" + JSON.Util.ptrToStr(lastIndex, srcStart) + "' instead at position " + (srcEnd - srcStart).toString());
305
+ }
306
+ } else if (code == 102) {
307
+ if (load<u64>(srcStart, 2) == 28429466576093281) {
308
+ srcStart += 10;
309
+ switch (<u32>keyEnd - <u32>keyStart) {
310
+ case 20:
311
+ {
312
+ const codeS8 = load<u64>(keyStart, 0);
313
+ const codeS16 = load<u64>(keyStart, 8);
314
+ const codeS20 = load<u32>(keyStart, 16);
315
+ if (codeS8 == 28429342022500457 && codeS16 == 29555310648164466 && codeS20 == 6553701) {
316
+ store<boolean>(changetype<usize>(out), false, offsetof<this>("isVerified"));
317
+ srcStart += 2;
318
+ keyStart = 0;
319
+ break;
320
+ } else {
321
+ srcStart += 2;
322
+ keyStart = 0;
323
+ break;
324
+ }
325
+ }
326
+
327
+ default:
328
+ {
329
+ srcStart += 2;
330
+ keyStart = 0;
331
+ }
332
+
333
+ }
334
+ } else {
335
+ throw new Error("Expected to find 'false' but found '" + JSON.Util.ptrToStr(lastIndex, srcStart) + "' instead at position " + (srcEnd - srcStart).toString());
336
+ }
337
+ } else if (code == 110) {
338
+ if (load<u64>(srcStart) == 30399761348886638) {
339
+ srcStart += 8;
340
+ switch (<u32>keyEnd - <u32>keyStart) {
341
+ case 6:
342
+ {
343
+ const code48 = load<u64>(keyStart) & 281474976710655;
344
+ if (code48 == 493928513648) {
345
+ store<usize>(changetype<usize>(out), 0, offsetof<this>("pos"));
346
+ srcStart += 2;
347
+ keyStart = 0;
348
+ break;
349
+ } else {
350
+ srcStart += 2;
351
+ keyStart = 0;
352
+ break;
353
+ }
354
+ }
355
+
356
+ default:
357
+ {
358
+ srcStart += 2;
359
+ keyStart = 0;
360
+ }
361
+
362
+ }
363
+ }
364
+ } else {
365
+ srcStart += 2;
366
+ keyStart = 0;
367
+ }
368
+ }
369
+ }
370
+ return out;
371
+ }
372
+ }
373
+ const player: Player = {
374
+ firstName: "Jairus",
375
+ lastName: "Tanaka",
376
+ lastActive: [3, 9, 2025],
377
+ age: 18,
378
+ pos: {
379
+ x: 3.4,
380
+ y: 1.2,
381
+ z: 8.3
382
+ },
383
+ isVerified: true
384
+ };
385
+ const serialized = JSON.stringify(player);
386
+ console.log("Serialized: " + serialized);
387
+ const deserialized = JSON.parse<Player>(serialized);
388
+ console.log("Deserialized: " + JSON.stringify(deserialized));
package/assembly/test.ts CHANGED
@@ -1,182 +1,33 @@
1
1
  import { JSON } from ".";
2
- import { expect, it } from "./__tests__/lib";
3
-
4
- it("should parse", () => {
5
- const str = `{
6
- "id": "chatcmpl-BbvlnP0ESWa8OForeEjt7AkoIuh3Q",
7
- "object": "chat.completion",
8
- "created": 1748379903,
9
- "model": "gpt-4o-mini-2024-07-18",
10
- "choices": [
11
- {
12
- "index": 0,
13
- "message": {
14
- "role": "assistant",
15
- "content": "Hello! How can I assist you today?",
16
- "refusal": null,
17
- "annotations": []
18
- },
19
- "logprobs": null,
20
- "finish_reason": "stop"
21
- }
22
- ],
23
- "usage": {
24
- "prompt_tokens": 15,
25
- "completion_tokens": 9,
26
- "total_tokens": 24,
27
- "prompt_tokens_details": {
28
- "cached_tokens": 0,
29
- "audio_tokens": 0
30
- },
31
- "completion_tokens_details": {
32
- "reasoning_tokens": 0,
33
- "audio_tokens": 0,
34
- "accepted_prediction_tokens": 0,
35
- "rejected_prediction_tokens": 0
36
- }
37
- },
38
- "service_tier": "default",
39
- "system_fingerprint": "fp_34a54ae93c"
40
- }`;
41
-
42
- const output = JSON.parse<OpenAIChatOutput>(str);
43
- expect(output.id).toBe("chatcmpl-BbvlnP0ESWa8OForeEjt7AkoIuh3Q");
44
- expect(output.object).toBe("chat.completion");
45
- expect(output.created.getTime()).toBe(1748379903000);
46
- expect(output.model).toBe("gpt-4o-mini-2024-07-18");
47
- expect(output.choices.length).toBe(1);
48
-
49
- const choice = output.choices[0];
50
- expect(choice.index).toBe(0);
51
- expect(choice.message.content).toBe("Hello! How can I assist you today?");
52
- // expect(choice.message.refusal).toBe("null");
53
- // expect(choice.logprobs).toBe("null");
54
- // expect(choice.finishReason).toBe("stop");
55
-
56
- // expect(output.usage.promptTokens).toBe(15);
57
- // expect(output.usage.completionTokens).toBe(9);
58
- // expect(output.usage.totalTokens).toBe(24);
59
- // expect(output.serviceTier).toBe("default");
60
- // expect(output.systemFingerprint).toBe("fp_34a54ae93c");
61
- });
62
-
63
- @json
64
- class OpenAIChatOutput {
65
- id!: string;
66
-
67
- object!: string;
68
-
69
- choices: Choice[] = [];
70
-
71
- get created(): Date {
72
- return new Date(this._created * 1000);
73
- }
74
-
75
- @alias("created")
76
- private _created!: i64;
77
-
78
- model!: string;
79
-
80
- @alias("service_tier")
81
- serviceTier: string | null = null;
82
-
83
- @alias("system_fingerprint")
84
- systemFingerprint!: string;
85
-
86
- usage!: Usage;
87
- }
88
-
89
- @json
90
- class ToolCall {
91
- id!: string;
92
-
93
- type: string = "function";
94
-
95
- function!: FunctionCall;
96
- }
97
-
98
- @json
99
- class FunctionCall {
100
- name!: string;
101
-
102
- arguments!: string;
103
- }
104
-
105
- @json
106
- class Usage {
107
- @alias("completion_tokens")
108
- completionTokens!: i32;
109
-
110
- @alias("prompt_tokens")
111
- promptTokens!: i32;
112
-
113
- @alias("total_tokens")
114
- totalTokens!: i32;
115
- }
2
+ import { Vec3 } from "./types";
116
3
 
117
4
  @json
118
- class Choice {
119
- @alias("finish_reason")
120
- finishReason!: string;
121
-
122
- index!: i32;
123
-
124
- message: CompletionMessage = new CompletionMessage();
125
-
126
- logprobs!: Logprobs | null;
127
- }
128
-
129
- @json
130
- class Logprobs {
131
- content: LogprobsContent[] | null = null;
132
- }
133
-
134
- @json
135
- class LogprobsContent {
136
- token!: string;
137
-
138
- logprob!: f64;
139
-
140
- bytes!: u8[] | null;
141
-
142
- @alias("top_logprobs")
143
- topLogprobs!: TopLogprobsContent[];
144
- }
145
-
146
- @json
147
- class TopLogprobsContent {
148
- token!: string;
149
-
150
- logprob!: f64;
151
-
152
- bytes!: u8[] | null;
153
- }
154
-
155
- @json
156
- class CompletionMessage {
157
- content!: string;
158
-
5
+ class Player {
6
+ @alias("first name")
7
+ firstName!: string;
8
+ lastName!: string;
9
+ lastActive!: i32[];
10
+ @omitif((self: Player) => self.age < 18)
11
+ age!: i32;
159
12
  @omitnull()
160
- refusal: string | null = null;
161
-
162
- @alias("tool_calls")
163
- @omitif((self: CompletionMessage) => self.toolCalls.length == 0)
164
- toolCalls: ToolCall[] = [];
165
-
166
- @omitnull()
167
- audio: AudioOutput | null = null;
168
- }
169
-
170
- @json
171
- class AudioOutput {
172
- id!: string;
173
-
174
- get expiresAt(): Date {
175
- return new Date(this._expiresAt * 1000);
176
- }
177
-
178
- @alias("expires_at")
179
- private _expiresAt!: i64;
13
+ pos!: Vec3 | null;
14
+ isVerified!: boolean;
15
+ }
16
+
17
+ const player: Player = {
18
+ firstName: "Jairus",
19
+ lastName: "Tanaka",
20
+ lastActive: [3, 9, 2025],
21
+ age: 18,
22
+ pos: {
23
+ x: 3.4,
24
+ y: 1.2,
25
+ z: 8.3,
26
+ },
27
+ isVerified: true,
28
+ };
180
29
 
181
- transcript!: string;
182
- }
30
+ const serialized = JSON.stringify(player);
31
+ console.log("Serialized: " + serialized);
32
+ const deserialized = JSON.parse<Player>(serialized);
33
+ console.log("Deserialized: " + JSON.stringify(deserialized))
package/assembly/types.ts CHANGED
@@ -65,6 +65,5 @@ export class Vec3 {
65
65
  z: f32 = 0.0;
66
66
  }
67
67
 
68
-
69
68
  @json
70
69
  export class Point { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "1.1.12",
3
+ "version": "1.1.14-preview.1",
4
4
  "author": "Jairus Tanaka",
5
5
  "description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
6
6
  "types": "assembly/index.ts",
@@ -434,10 +434,8 @@ class JSONTransform extends Visitor {
434
434
  sortedMembers.number.push(member);
435
435
  else if (isArray(type))
436
436
  sortedMembers.array.push(member);
437
- else if (isStruct(type, source))
437
+ if (isStruct(type))
438
438
  sortedMembers.object.push(member);
439
- else
440
- throw new Error("Could not determine type " + type + " for member " + member.name + " in class " + this.schema.name);
441
439
  }
442
440
  }
443
441
  indent = "";
@@ -1237,9 +1235,15 @@ function isPrimitive(type) {
1237
1235
  function isBoolean(type) {
1238
1236
  return type == "bool" || type == "boolean";
1239
1237
  }
1240
- function isStruct(type, source) {
1238
+ function isStruct(type) {
1241
1239
  type = stripNull(type);
1242
- return JSONTransform.SN.schemas.get(source.internalPath).some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
1240
+ const schema = JSONTransform.SN.schema;
1241
+ if (schema.name == type)
1242
+ return true;
1243
+ const depSearch = schema.deps.some((v) => v.name == type);
1244
+ if (depSearch)
1245
+ return true;
1246
+ return false;
1243
1247
  }
1244
1248
  function isString(type) {
1245
1249
  return stripNull(type) == "string" || stripNull(type) == "String";