json-as
Version:
The only JSON library you'll need for AssemblyScript. SIMD enabled
803 lines (758 loc) • 28.7 kB
text/typescript
/// <reference path="./index.d.ts" />
import { bs } from "../lib/as-bs";
import { serializeString } from "./serialize/simple/string";
import { serializeArray } from "./serialize/simple/array";
import { serializeMap } from "./serialize/simple/map";
import { serializeDate } from "./serialize/simple/date";
import { deserializeBoolean } from "./deserialize/simple/bool";
import { deserializeArray } from "./deserialize/simple/array";
import { deserializeFloat } from "./deserialize/simple/float";
import { deserializeMap } from "./deserialize/simple/map";
import { deserializeDate } from "./deserialize/simple/date";
import { deserializeInteger } from "./deserialize/simple/integer";
import { deserializeString } from "./deserialize/simple/string";
import { serializeArbitrary } from "./serialize/simple/arbitrary";
import { NULL_WORD, QUOTE } from "./custom/chars";
import { dtoa_buffered, itoa_buffered } from "util/number";
import { serializeBool } from "./serialize/simple/bool";
import { serializeInteger } from "./serialize/simple/integer";
import { serializeFloat } from "./serialize/simple/float";
import { serializeStruct } from "./serialize/simple/struct";
import { ptrToStr } from "./util/ptrToStr";
import { atoi, bytes } from "./util";
import { deserializeArbitrary } from "./deserialize/simple/arbitrary";
import { serializeObject } from "./serialize/simple/object";
import { deserializeObject } from "./deserialize/simple/object";
import { serializeRaw } from "./serialize/simple/raw";
import { deserializeRaw } from "./deserialize/simple/raw";
import { serializeString_SIMD } from "./serialize/simd/string";
// import { deserializeString_SIMD } from "./deserialize/simd/string";
/**
* Offset of the 'storage' property in the JSON.Value class.
*/
// @ts-ignore: Decorator valid here
const STORAGE = offsetof<JSON.Value>("storage");
/**
* JSON Encoder/Decoder for AssemblyScript
*/
export namespace JSON {
export namespace Memory {
export function shrink(): void {
bs.resize(64);
}
}
/**
* Serializes valid JSON data
* ```js
* JSON.stringify<T>(data)
* ```
* @param data T
* @returns string
*/
// @ts-ignore: inline
export function stringify<T>(data: T, out: string | null = null): string {
if (isBoolean<T>()) {
if (out) {
if (<bool>data == true) {
out = changetype<string>(__renew(changetype<usize>(out), 8));
store<u64>(changetype<usize>(out), 28429475166421108);
} else {
out = changetype<string>(__renew(changetype<usize>(out), 10));
store<u64>(changetype<usize>(out), 32370086184550502);
store<u16>(changetype<usize>(out), 101, 8);
}
return out;
}
return data ? "true" : "false";
} else if (isInteger<T>() && !isSigned<T>() && nameof<T>() == "usize" && data == 0) {
if (out) {
out = changetype<string>(__renew(changetype<usize>(out), 8));
store<u64>(changetype<usize>(out), 30399761348886638);
return out;
}
return NULL_WORD;
} else if (isInteger<T>(data)) {
if (out) {
out = changetype<string>(__renew(changetype<usize>(out), sizeof<T>() << 3));
// @ts-ignore
const bytes = itoa_buffered(changetype<usize>(out), data) << 1;
return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
}
return data.toString();
} else if (isFloat<T>(data)) {
if (out) {
out = changetype<string>(__renew(changetype<usize>(out), 64));
// @ts-ignore
const bytes = dtoa_buffered(changetype<usize>(out), data) << 1;
return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
}
return data.toString();
// @ts-ignore: Function is generated by transform
} else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
if (out) {
out = changetype<string>(__renew(changetype<usize>(out), 8));
store<u64>(changetype<usize>(out), 30399761348886638);
return out;
}
return NULL_WORD;
// @ts-ignore
} else if (isString<nonnull<T>>()) {
// if (out) {
// out = changetype<string>(__renew(changetype<usize>(out), bytes(data) + 4));
// // const oldSize = bs.byteLength;
// const oldBuf = bs.buffer;
// const newSize = bytes(data) + 4;
// const newBuf = __new(newSize, idof<string>());
// bs.setBuffer(newBuf);
// serializeString(changetype<string>(data));
// bs.setBuffer(oldBuf);
// return changetype<string>(newBuf);
// }
if (ASC_FEATURE_SIMD) {
serializeString_SIMD(data as string);
} else {
serializeString(data as string);
}
return bs.out<string>();
// @ts-ignore: Supplied by transform
} else if (isDefined(data.__SERIALIZE)) {
// @ts-ignore
inline.always(data.__SERIALIZE(changetype<usize>(data)));
return bs.out<string>();
// @ts-ignore: Supplied by transform
} else if (data instanceof Date) {
out = out ? changetype<string>(__renew(changetype<usize>(out), 52)) : changetype<string>(__new(52, idof<string>()));
store<u16>(changetype<usize>(out), QUOTE);
memory.copy(changetype<usize>(out) + 2, changetype<usize>(data.toISOString()), 48);
store<u16>(changetype<usize>(out), QUOTE, 50);
return changetype<string>(out);
} else if (data instanceof Array || data instanceof StaticArray) {
// @ts-ignore
inline.always(serializeArray(changetype<nonnull<T>>(data)));
return bs.out<string>();
} else if (data instanceof Map) {
// @ts-ignore
inline.always(serializeMap(changetype<nonnull<T>>(data)));
return bs.out<string>();
} else if (data instanceof JSON.Raw) {
serializeRaw(data);
return bs.out<string>();
} else if (data instanceof JSON.Value) {
inline.always(serializeArbitrary(data));
return bs.out<string>();
} else if (data instanceof JSON.Obj) {
inline.always(serializeObject(data));
return bs.out<string>();
} else if (data instanceof JSON.Box) {
return JSON.stringify(data.value);
} else {
throw new Error(`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
}
}
/**
* Parses valid JSON strings into their original format
* ```js
* JSON.parse<T>(data)
* ```
* @param data string
* @returns T
*/
// @ts-ignore: inline
export function parse<T>(data: string): T {
const dataSize = bytes(data);
const dataPtr = changetype<usize>(data);
if (isBoolean<T>()) {
return deserializeBoolean(dataPtr, dataPtr + dataSize) as T;
} else if (isInteger<T>()) {
return deserializeInteger<T>(dataPtr, dataPtr + dataSize);
} else if (isFloat<T>()) {
return deserializeFloat<T>(dataPtr, dataPtr + dataSize);
} else if (isNullable<T>() && dataSize == 8 && load<u64>(dataPtr) == 30399761348886638) {
// @ts-ignore
return null;
} else if (isString<T>()) {
if (dataSize < 4) throw new Error("Cannot parse data as string because it was formatted incorrectly!");
// if (ASC_FEATURE_SIMD) {
// // @ts-ignore
// return changetype<string>(deserializeString_SIMD(dataPtr, dataPtr + dataSize, __new(dataSize - 4, idof<string>())));
// } else {
// @ts-ignore
return deserializeString(dataPtr, dataPtr + dataSize, __new(dataSize - 4, idof<string>()));
// }
} else if (isArray<T>()) {
// @ts-ignore
return inline.always(deserializeArray<nonnull<T>>(dataPtr, dataPtr + dataSize, changetype<usize>(instantiate<T>())));
} else {
let type: nonnull<T> = changetype<nonnull<T>>(0);
// @ts-ignore: Defined by transform
if (isDefined(type.__DESERIALIZE)) {
const out = changetype<nonnull<T>>(__new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
// @ts-ignore: Defined by transform
if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
// @ts-ignore
return out.__DESERIALIZE(dataPtr, dataPtr + dataSize, out);
} else if (type instanceof Map) {
// @ts-ignore
return inline.always(deserializeMap<nonnull<T>>(dataPtr, dataPtr + dataSize, 0));
} else if (type instanceof Date) {
// @ts-ignore
return deserializeDate(dataPtr, dataPtr + dataSize);
} else if (type instanceof JSON.Raw) {
// @ts-ignore: type
return deserializeRaw(dataPtr, dataPtr + dataSize);
} else if (type instanceof JSON.Value) {
// should cut out whitespace here
// @ts-ignore
return inline.always(deserializeArbitrary(dataPtr, dataPtr + dataSize, 0));
} else if (type instanceof JSON.Obj) {
// @ts-ignore
return inline.always(deserializeObject(dataPtr, dataPtr + dataSize, 0));
} else if (type instanceof JSON.Box) {
// @ts-ignore
return new JSON.Box(parseBox(data, changetype<nonnull<T>>(0).value));
} else {
throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
}
}
}
/**
* Enum representing the different types supported by JSON.
*/
export enum Types {
Raw = 0,
U8 = 1,
U16 = 2,
U32 = 3,
U64 = 4,
F32 = 5,
F64 = 6,
Null = 7,
Bool = 8,
String = 9,
Object = 10,
Array = 12,
Struct = 13,
}
export class Raw {
public data: string;
constructor(data: string) {
this.data = data;
}
set(data: string): void {
this.data = data;
}
toString(): string {
return this.data;
}
// @ts-ignore: inline
static from(data: string): JSON.Raw {
return new JSON.Raw(data);
}
}
export class Value {
static METHODS: Map<u32, u32> = new Map<u32, u32>();
public type: i32;
private storage: u64;
private constructor() {
unreachable();
}
/**
* Creates an JSON.Value instance with no set value.
* @returns An instance of JSON.Value.
*/
static empty(): JSON.Value {
return changetype<JSON.Value>(__new(offsetof<JSON.Value>(), idof<JSON.Value>()));
}
/**
* Creates an JSON.Value instance from a given value.
* @param value - The value to be encapsulated.
* @returns An instance of JSON.Value.
*/
static from<T>(value: T): JSON.Value {
if (value instanceof JSON.Value) {
return value;
}
const out = changetype<JSON.Value>(__new(offsetof<JSON.Value>(), idof<JSON.Value>()));
out.set<T>(value);
return out;
}
/**
* Sets the value of the JSON.Value instance.
* @param value - The value to be set.
*/
set<T>(value: T): void {
if (isBoolean<T>()) {
this.type = JSON.Types.Bool;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (isInteger<T>() && !isSigned<T>() && changetype<usize>(value) == 0 && nameof<T>() == "usize") {
this.type = JSON.Types.Null;
store<usize>(changetype<usize>(this), 0, STORAGE);
} else if (value instanceof u8 || value instanceof i8) {
this.type = JSON.Types.U8;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (value instanceof u16 || value instanceof i16) {
this.type = JSON.Types.U16;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (value instanceof u32 || value instanceof i32) {
this.type = JSON.Types.U32;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (value instanceof u64 || value instanceof i64) {
this.type = JSON.Types.U64;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (value instanceof f32) {
this.type = JSON.Types.F32;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (value instanceof f64) {
this.type = JSON.Types.F64;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (isString<T>()) {
this.type = JSON.Types.String;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (value instanceof JSON.Raw) {
this.type = JSON.Types.Raw;
store<T>(changetype<usize>(this), value, STORAGE);
} else if (value instanceof Map) {
if (idof<T>() !== idof<Map<string, JSON.Value>>()) {
abort("Maps must be of type Map<string, JSON.Value>!");
}
this.type = JSON.Types.Struct;
store<T>(changetype<usize>(this), value, STORAGE);
// @ts-ignore: supplied by transform
} else if (isDefined(value.__SERIALIZE) && isManaged<T>(value)) {
this.type = idof<T>() + JSON.Types.Struct;
// @ts-ignore
if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
// @ts-ignore
store<usize>(changetype<usize>(this), changetype<usize>(value), STORAGE);
} else if (value instanceof JSON.Obj) {
this.type = JSON.Types.Object;
store<T>(changetype<usize>(this), value, STORAGE);
// @ts-ignore
} else if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) {
// @ts-ignore: T satisfies constraints of any[]
this.type = JSON.Types.Array;
store<T>(changetype<usize>(this), value, STORAGE);
}
}
/**
* Gets the value of the JSON.Value instance.
* @returns The encapsulated value.
*/
get<T>(): T {
return load<T>(changetype<usize>(this), STORAGE);
}
/**
* Gets the value of the JSON.Value instance.
* Alias for .get<T>()
* @returns The encapsulated value.
*/
as<T>(): T {
return load<T>(changetype<usize>(this), STORAGE);
}
/**
* Converts the JSON.Value to a string representation.
* @returns The string representation of the JSON.Value.
*/
toString(): string {
switch (this.type) {
case JSON.Types.U8:
return this.get<u8>().toString();
case JSON.Types.U16:
return this.get<u16>().toString();
case JSON.Types.U32:
return this.get<u32>().toString();
case JSON.Types.U64:
return this.get<u64>().toString();
case JSON.Types.F32:
return this.get<f32>().toString();
case JSON.Types.F64:
return this.get<f64>().toString();
case JSON.Types.String:
return '"' + this.get<string>() + '"';
case JSON.Types.Bool:
return this.get<boolean>() ? "true" : "false";
case JSON.Types.Raw: {
return this.get<JSON.Raw>().toString();
}
case JSON.Types.Array: {
const arr = this.get<JSON.Value[]>();
if (!arr.length) return "[]";
let out = "[";
const end = arr.length - 1;
for (let i = 0; i < end; i++) {
const element = unchecked(arr[i]);
out += element.toString() + ",";
}
const element = unchecked(arr[end]);
out += element.toString() + "]";
return out.toString();
}
case JSON.Types.Object: {
return JSON.stringify(this.get<JSON.Obj>());
}
default: {
const fn = JSON.Value.METHODS.get(this.type - JSON.Types.Struct);
const value = this.get<usize>();
call_indirect<void>(fn, 0, value);
return bs.out<string>();
}
}
}
private __visit(cookie: u32): void {
if (this.type >= JSON.Types.String) {
__visit(load<usize>(changetype<usize>(this), STORAGE), cookie);
}
}
}
export class Obj {
// @ts-ignore: type
storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
constructor() {}
// @ts-ignore: decorator
get size(): i32 {
return this.storage.size;
}
// @ts-ignore: decorator
set<T>(key: string, value: T): void {
// if (!this.storage.has(key)) this.stackSize += bytes(key) + 8;
this.storage.set(key, JSON.Value.from<T>(value));
}
// @ts-ignore: decorator
get(key: string): JSON.Value | null {
if (!this.storage.has(key)) return null;
return this.storage.get(key);
}
// @ts-ignore: decorator
has(key: string): bool {
return this.storage.has(key);
}
// @ts-ignore: decorator
delete(key: string): bool {
return this.storage.delete(key);
}
// @ts-ignore: decorator
keys(): string[] {
return this.storage.keys();
}
// @ts-ignore: decorator
values(): JSON.Value[] {
return this.storage.values();
}
// @ts-ignore: decorator
toString(): string {
return JSON.stringify(this);
}
// @ts-ignore: decorator
static from<T>(value: T): JSON.Obj {
if (value instanceof JSON.Obj) return value;
const out = new JSON.Obj();
if (value instanceof Map) {
}
return out;
}
}
/**
* Box for primitive types
*/
export class Box<T> {
constructor(public value: T) {
if (!isInteger<T>() && !isFloat<T>()) ERROR("JSON.Box should only hold primitive types!");
}
/**
* Set the internal value of Box to new value
* @param value T
* @returns this
*/
set(value: T): Box<T> {
this.value = value;
return this;
}
/**
* Creates a reference to a primitive type
* This means that it can create a nullable primitive
* ```js
* JSON.stringify<Box<i32> | null>(null);
* // null
* ```
* @param from T
* @returns Box<T>
*/
static from<T>(value: T): Box<T> {
return new Box(value);
}
toString(): string {
if (isNullable<this>() && changetype<usize>(this) == null) return "null";
// @ts-ignore: type
if (isDefined(this.value.toString)) return this.value.toString();
return "null";
}
}
/**
* Serializes JSON data but writes directly to the buffer.
* Should only be used if you know what you are doing.
* @param src - T
* @returns void
*/
export function __serialize<T>(src: T): void {
if (isBoolean<T>()) {
serializeBool(src as bool);
} else if (isInteger<T>() && nameof<T>() == "usize" && src == 0) {
bs.proposeSize(8);
store<u64>(bs.offset, 30399761348886638);
bs.offset += 8;
} else if (isInteger<T>()) {
// @ts-ignore
serializeInteger<T>(src);
} else if (isFloat<T>(src)) {
// @ts-ignore
serializeFloat<T>(src);
// @ts-ignore: Function is generated by transform
} else if (isNullable<T>() && changetype<usize>(src) == <usize>0) {
bs.proposeSize(8);
store<u64>(bs.offset, 30399761348886638);
bs.offset += 8;
} else if (isString<nonnull<T>>()) {
if (ASC_FEATURE_SIMD) {
serializeString_SIMD(src as string);
} else {
serializeString(src as string);
}
// @ts-ignore: Supplied by transform
} else if (isDefined(src.__SERIALIZE_CUSTOM)) {
// @ts-ignore
return src.__SERIALIZE_CUSTOM();
// @ts-ignore: Supplied by transform
} else if (isDefined(src.__SERIALIZE)) {
// @ts-ignore
serializeStruct(changetype<nonnull<T>>(src));
} else if (src instanceof Date) {
// @ts-ignore
inline.always(serializeDate(changetype<nonnull<T>>(src)));
} else if (src instanceof Array || src instanceof StaticArray) {
// @ts-ignore
serializeArray(changetype<nonnull<T>>(src));
} else if (src instanceof Map) {
// @ts-ignore
serializeMap(changetype<nonnull<T>>(src));
} else if (src instanceof JSON.Raw) {
serializeRaw(src);
} else if (src instanceof JSON.Value) {
serializeArbitrary(src);
} else if (src instanceof JSON.Obj) {
serializeObject(src);
} else if (src instanceof JSON.Box) {
__serialize(src.value);
} else {
throw new Error(`Could not serialize provided data. Make sure to add the correct decorators to classes.`);
}
}
/**
* Deserializes JSON data directly from the buffer.
* Should only be used if you know what you are doing.
* @param srcStart - usize
* @param srcEnd - usize
* @param dst - usize
* @returns void
*/
export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
if (isBoolean<T>()) {
// @ts-ignore: type
return deserializeBoolean(srcStart, srcEnd);
} else if (isInteger<T>()) {
return atoi<T>(srcStart, srcEnd);
} else if (isFloat<T>()) {
return deserializeFloat<T>(srcStart, srcEnd);
} else if (isString<T>()) {
if (srcEnd - srcStart < 4) throw new Error("Cannot parse data as string because it was formatted incorrectly!");
// @ts-ignore: type
return deserializeString(srcStart, srcEnd, dst);
} else if (isNullable<T>() && srcEnd - srcStart == 8 && load<u64>(srcStart) == 30399761348886638) {
// @ts-ignore
return null;
} else if (isArray<T>()) {
// @ts-ignore: type
return deserializeArray<T>(srcStart, srcEnd, dst);
} else {
let type: nonnull<T> = changetype<nonnull<T>>(0);
// @ts-ignore: Defined by transform
if (isDefined(type.__DESERIALIZE)) {
const out = changetype<nonnull<T>>(dst || __new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
// @ts-ignore: Defined by transform
if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
// @ts-ignore: Defined by transform
return out.__DESERIALIZE(srcStart, srcEnd, out);
} else if (type instanceof Map) {
// @ts-ignore: type
return deserializeMap<T>(srcStart, srcEnd, dst);
} else if (type instanceof Date) {
// @ts-ignore: type
return deserializeDate(srcStart, srcEnd);
} else if (type instanceof JSON.Raw) {
// @ts-ignore: type
return deserializeRaw(srcStart, srcEnd);
} else if (type instanceof JSON.Value) {
// @ts-ignore: type
return deserializeArbitrary(srcStart, srcEnd, 0);
} else if (type instanceof JSON.Obj) {
// @ts-ignore: type
return deserializeObject(srcStart, srcEnd, 0);
} else if (type instanceof JSON.Box) {
// @ts-ignore: type
return new JSON.Box(deserializeBox(srcStart, srcEnd, dst, changetype<nonnull<T>>(0).value));
}
}
throw new Error(`Could not deserialize data '${ptrToStr(srcStart, srcEnd).slice(0, 100)}' to type. Make sure to add the correct decorators to classes.`);
}
export namespace Util {
// @ts-ignore: decorator
export function isSpace(code: u16): boolean {
return code == 0x20 || code - 9 <= 4;
}
// @ts-ignore: decorator
export function ptrToStr(start: usize, end: usize): string {
const size = end - start;
const out = __new(size, idof<string>());
memory.copy(out, start, size);
return changetype<string>(out);
}
}
/**
* Methods for use when using JSON methods inside another JSON method or custom serializer/deserializer.
*/
export namespace internal {
/**
* Serializes JSON data. Don't use this directly, use `JSON.stringify` instead.
* @param data - T
* @param out - string | null
* @returns - string
*/
// @ts-ignore: inline
export function stringify<T>(data: T, out: string | null = null): string {
if (isBoolean<T>()) {
if (out) {
if (<bool>data == true) {
out = changetype<string>(__renew(changetype<usize>(out), 8));
store<u64>(changetype<usize>(out), 28429475166421108);
} else {
out = changetype<string>(__renew(changetype<usize>(out), 10));
store<u64>(changetype<usize>(out), 32370086184550502);
store<u16>(changetype<usize>(out), 101, 8);
}
return out;
}
return data ? "true" : "false";
} else if (isInteger<T>() && !isSigned<T>() && nameof<T>() == "usize" && data == 0) {
if (out) {
out = changetype<string>(__renew(changetype<usize>(out), 8));
store<u64>(changetype<usize>(out), 30399761348886638);
return out;
}
return NULL_WORD;
} else if (isInteger<T>(data)) {
if (out) {
out = changetype<string>(__renew(changetype<usize>(out), sizeof<T>() << 3));
// @ts-ignore
const bytes = itoa_buffered(changetype<usize>(out), data) << 1;
return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
}
return data.toString();
} else if (isFloat<T>(data)) {
if (out) {
out = changetype<string>(__renew(changetype<usize>(out), 64));
// @ts-ignore
const bytes = dtoa_buffered(changetype<usize>(out), data) << 1;
return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
}
return data.toString();
// @ts-ignore: Function is generated by transform
} else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
if (out) {
out = changetype<string>(__renew(changetype<usize>(out), 8));
store<u64>(changetype<usize>(out), 30399761348886638);
return out;
}
return NULL_WORD;
// @ts-ignore
} else if (isString<nonnull<T>>()) {
// if (out) {
// out = changetype<string>(__renew(changetype<usize>(out), bytes(data) + 4));
// // const oldSize = bs.byteLength;
// const oldBuf = bs.buffer;
// const newSize = bytes(data) + 4;
// const newBuf = __new(newSize, idof<string>());
// bs.setBuffer(newBuf);
// serializeString(changetype<string>(data));
// bs.setBuffer(oldBuf);
// return changetype<string>(newBuf);
// }
if (ASC_FEATURE_SIMD) {
serializeString_SIMD(data as string);
} else {
bs.saveState();
serializeString(data as string);
}
return bs.cpyOut<string>();
// @ts-ignore: Supplied by transform
} else if (isDefined(data.__SERIALIZE)) {
bs.saveState();
// @ts-ignore
inline.always(data.__SERIALIZE(changetype<usize>(data)));
return bs.cpyOut<string>();
// @ts-ignore: Supplied by transform
} else if (data instanceof Date) {
out = out ? changetype<string>(__renew(changetype<usize>(out), 52)) : changetype<string>(__new(52, idof<string>()));
store<u16>(changetype<usize>(out), QUOTE);
memory.copy(changetype<usize>(out) + 2, changetype<usize>(data.toISOString()), 48);
store<u16>(changetype<usize>(out), QUOTE, 50);
return changetype<string>(out);
} else if (data instanceof Array || data instanceof StaticArray) {
bs.saveState();
// @ts-ignore
inline.always(serializeArray(changetype<nonnull<T>>(data)));
return bs.cpyOut<string>();
} else if (data instanceof Map) {
bs.saveState();
// @ts-ignore
inline.always(serializeMap(changetype<nonnull<T>>(data)));
return bs.cpyOut<string>();
} else if (data instanceof JSON.Raw) {
bs.saveState();
serializeRaw(data);
return bs.cpyOut<string>();
} else if (data instanceof JSON.Value) {
bs.saveState();
inline.always(serializeArbitrary(data));
return bs.cpyOut<string>();
} else if (data instanceof JSON.Obj) {
bs.saveState();
inline.always(serializeObject(data));
return bs.cpyOut<string>();
} else if (data instanceof JSON.Box) {
return JSON.internal.stringify(data.value);
} else {
throw new Error(`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
}
}
}
}
// @ts-ignore: decorator
function parseBox<T>(data: string, ty: T): T {
return JSON.parse<T>(data);
}
// @ts-ignore: inline
function deserializeBox<T>(srcStart: usize, srcEnd: usize, dst: usize, ty: T): T {
return JSON.__deserialize<T>(srcStart, srcEnd, dst);
}
// @ts-ignore: inline
export function toRaw(data: string): JSON.Raw {
return new JSON.Raw(data);
}
// @ts-ignore: inline
export function fromRaw(data: JSON.Raw): string {
return data.data;
}
// @ts-ignore: inline
export function toBox<T>(data: T): JSON.Box<T> {
return new JSON.Box<T>(data);
}