Skip to content

Commit cbfe1a9

Browse files
committed
feat: add support for boxed and reboxed JSON.Value
1 parent fc750d1 commit cbfe1a9

4 files changed

Lines changed: 75 additions & 45 deletions

File tree

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,16 @@ obj.data = JSON.Value.from("a string"); // Changing to a string
269269
console.log(JSON.stringify(obj)); // {"id":1,"name":"Example","data":"a string"}
270270
```
271271

272+
**Working with nullable primitives and dynamic data**
273+
274+
```ts
275+
const box = JSON.Box.from<i32>(123);
276+
const value = JSON.Value.from<JSON.Box<i32> | null>(box);
277+
const reboxed = JSON.Box.fromValue<i32>(value); // Box<i32> | null
278+
console.log(reboxed !== null ? reboxed!.toString() : "null");
279+
// 123
280+
```
281+
272282
### Using Raw JSON strings
273283

274284
Sometimes its necessary to simply copy a string instead of serializing it.

assembly/__tests__/arbitrary.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ describe("Should serialize arbitrary types", () => {
2424
o.set("type", "object");
2525

2626
expect(o.toString()).toBe('{"schema":"http://json-schema.org/draft-07/schema#","additionalProperties":false,"properties":{"duration":{"default":10.0,"description":"Duration of the operation in seconds","type":"number"},"steps":{"default":5.0,"description":"Number of steps in the operation","type":"number"}},"type":"object"}');
27+
28+
expect(JSON.stringify(JSON.Value.from<JSON.Box<i32> | null>(null))).toBe("null");
29+
expect(JSON.stringify(JSON.Value.from<JSON.Box<i32> | null>(JSON.Box.from(123)))).toBe("123");
2730
});
2831

2932
describe("Should deserialize arbitrary types", () => {

assembly/index.ts

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -302,57 +302,42 @@ export namespace JSON {
302302
out.set<T>(value);
303303
return out;
304304
}
305+
@inline private setPrimitive<T>(value: T): void {
306+
if (isBoolean(value)) {
307+
this.type = JSON.Types.BoolNull;
308+
store<T>(changetype<usize>(this), value, STORAGE);
309+
} else if (value instanceof u8 || value instanceof i8) {
310+
this.type = JSON.Types.U8Null;
311+
store<T>(changetype<usize>(this), value, STORAGE);
312+
} else if (value instanceof u16 || value instanceof i16) {
313+
this.type = JSON.Types.U16;
314+
store<T>(changetype<usize>(this), value, STORAGE);
315+
} else if (value instanceof u32 || value instanceof i32) {
316+
this.type = JSON.Types.U32Null;
317+
store<T>(changetype<usize>(this), value, STORAGE);
318+
} else if (value instanceof u64 || value instanceof i64) {
319+
this.type = JSON.Types.U64Null;
320+
store<T>(changetype<usize>(this), value, STORAGE);
321+
} else if (value instanceof f32) {
322+
this.type = JSON.Types.F32Null;
323+
store<T>(changetype<usize>(this), value, STORAGE);
324+
} else if (value instanceof f64) {
325+
this.type = JSON.Types.F64Null;
326+
store<T>(changetype<usize>(this), value, STORAGE);
327+
}
328+
}
305329
/**
306330
* Sets the value of the JSON.Value instance.
307331
* @param value - The value to be set.
308332
*/
309333
@inline set<T>(value: T): void {
310334
if (isNullable<T>()) {
311-
335+
this.isNull = changetype<usize>(value) === 0;
312336
if (value instanceof JSON.Box) {
313-
if (isBoolean<T>()) {
314-
this.type = JSON.Types.BoolNull;
315-
store<T>(changetype<usize>(this), value, STORAGE);
316-
} else if (value instanceof u8 || value instanceof i8) {
317-
this.type = JSON.Types.U8Null;
318-
store<T>(changetype<usize>(this), value, STORAGE);
319-
} else if (value instanceof u16 || value instanceof i16) {
320-
this.type = JSON.Types.U16Null;
321-
store<T>(changetype<usize>(this), value, STORAGE);
322-
} else if (value instanceof u32 || value instanceof i32) {
323-
this.type = JSON.Types.U32Null;
324-
store<T>(changetype<usize>(this), value, STORAGE);
325-
} else if (value instanceof u64 || value instanceof i64) {
326-
this.type = JSON.Types.U64Null;
327-
store<T>(changetype<usize>(this), value, STORAGE);
328-
} else if (value instanceof f32) {
329-
this.type = JSON.Types.F32Null;
330-
store<T>(changetype<usize>(this), value, STORAGE);
331-
} else if (value instanceof f64) {
332-
this.type = JSON.Types.F64Null;
333-
store<T>(changetype<usize>(this), value, STORAGE);
334-
}
337+
return this.setPrimitive(value.value);
335338
} else if (isBoolean<T>()) {
336339
this.type = JSON.Types.BoolNull;
337340
store<T>(changetype<usize>(this), value, STORAGE);
338-
} else if (value instanceof u8 || value instanceof i8) {
339-
this.type = JSON.Types.U8Null;
340-
store<T>(changetype<usize>(this), value, STORAGE);
341-
} else if (value instanceof u16 || value instanceof i16) {
342-
this.type = JSON.Types.U16Null;
343-
store<T>(changetype<usize>(this), value, STORAGE);
344-
} else if (value instanceof u32 || value instanceof i32) {
345-
this.type = JSON.Types.U32Null;
346-
store<T>(changetype<usize>(this), value, STORAGE);
347-
} else if (value instanceof u64 || value instanceof i64) {
348-
this.type = JSON.Types.U64Null;
349-
store<T>(changetype<usize>(this), value, STORAGE);
350-
} else if (value instanceof f32) {
351-
this.type = JSON.Types.F32Null;
352-
store<T>(changetype<usize>(this), value, STORAGE);
353-
} else if (value instanceof f64) {
354-
this.type = JSON.Types.F64Null;
355-
store<T>(changetype<usize>(this), value, STORAGE);
356341
} else if (isString<T>()) {
357342
this.type = JSON.Types.StringNull;
358343
store<T>(changetype<usize>(this), value, STORAGE);
@@ -381,7 +366,6 @@ export namespace JSON {
381366
this.type = JSON.Types.ArrayNull;
382367
store<T>(changetype<usize>(this), value, STORAGE);
383368
}
384-
this.isNull = changetype<usize>(value) === 0;
385369
} else {
386370
if (value instanceof JSON.Box) {
387371
return this.set(value.value);
@@ -457,6 +441,16 @@ export namespace JSON {
457441
return load<T>(changetype<usize>(this), STORAGE);
458442
}
459443

444+
/**
445+
* Gets the value of the JSON.Value instance as a Box<T>.
446+
* Alias for .get<T>()
447+
* @returns The encapsulated value.
448+
*/
449+
@inline asBox<T>(): Box<T> | null {
450+
if (this.isNull) return null;
451+
return changetype<Box<T>>(JSON.Box.fromValue<T>(this));
452+
}
453+
460454
/**
461455
* Converts the JSON.Value to a string representation.
462456
* @returns The string representation of the JSON.Value.
@@ -598,6 +592,22 @@ export namespace JSON {
598592
this.value = value;
599593
return this;
600594
}
595+
/**
596+
* Creates a Box<T> | null from a JSON.Value
597+
* This means that it can create a nullable primitive from a JSON.Value
598+
* ```js
599+
* const value = JSON.parse<i32>("null"); // -> Box<i32> | null
600+
* const boxed = JSON.Box.fromValue<i32>(value); // -> Box<i32> | null
601+
* // null
602+
* ```
603+
* @param from T
604+
* @returns Box<T> | null
605+
*/
606+
@inline static fromValue<T>(value: JSON.Value): Box<T> | null {
607+
if (!(value instanceof JSON.Value)) throw new Error("value must be of type JSON.Value");
608+
if (value.isNull) return null;
609+
return new Box(value.get<T>());
610+
}
601611
/**
602612
* Creates a reference to a primitive type
603613
* This means that it can create a nullable primitive

assembly/test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,18 @@ const str: JSON.Value[] = [
2020
JSON.Value.from(true),
2121
JSON.Value.from<JSON.Box<i32> | null>(null),
2222
JSON.Value.from(vec),
23-
JSON.Value.from<Vec3 | null>(null)
23+
JSON.Value.from<Vec3 | null>(null),
24+
JSON.Value.from<JSON.Box<i32> | null>(JSON.Box.from(123)),
25+
JSON.Value.from<JSON.Box<i32> | null>(null),
2426
];
25-
27+
const box = JSON.Box.from<i32>(123);
28+
const value = JSON.Value.from<JSON.Box<i32> | null>(box);
29+
const reboxed = JSON.Box.fromValue<i32>(value); // Box<i32> | null
30+
console.log(reboxed !== null ? reboxed!.toString() : "null");
31+
// console.log(str[9]!.asBox<i32>()?.toString());
32+
// console.log(str.toString())
2633
const serialized = JSON.stringify(str);
2734
console.log("Serialized: " + serialized);
2835

2936
const deserialized = JSON.parse<JSON.Value[]>(serialized);
30-
console.log("Deserialized: " + JSON.stringify(deserialized).toString());
37+
console.log("Deserialized: " + JSON.stringify(deserialized).toString());

0 commit comments

Comments
 (0)