diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6af0de1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.ts linguist-language=AssemblyScript \ No newline at end of file diff --git a/assembly/deserialize/simd/string.ts b/assembly/deserialize/simd/string.ts index a3977d2..0a69139 100644 --- a/assembly/deserialize/simd/string.ts +++ b/assembly/deserialize/simd/string.ts @@ -1,8 +1,8 @@ import { OBJECT, TOTAL_OVERHEAD } from "rt/common"; import { BACK_SLASH } from "../../custom/chars"; -import { ensureCapacity } from "../../custom/memory"; +import { JSON } from "../.."; -const ESCAPE_TABLE = memory.data([ +const ESCAPE_TABLE = memory.data([ 0, 0, 0, 0, 0, 0, 0, 0, // 0-7 0, 0, 0, 0, 0, 0, 0, 0, // 8-15 0, 0, 0, 0, 0, 0, 0, 0, // 16-23 @@ -17,13 +17,23 @@ const ESCAPE_TABLE = memory.data([ 0, 0, 0, 0, 92, 0, 0, 0, // 88-95 0, 0, 8, 0, 0, 0, 12, 0, // 96-103 0, 0, 0, 0, 0, 0, 10, 0, // 104-111 - 0, 0, 13, 0, 9, 0, 0, 0, // 112-119 + 0, 0, 13, 0, 9, 117, 0, 0, // 112-119 0, 0, 0, 0, 0, 0, 0, 0, // 120-127 0, 0, 0, 0, 0, 0, 0, 0, // 128-135 0, 0, 0, 0, 0, 0, 0, 0, // 136-143 0, 0, 0, 0, 0, 0, 0, 0, // 144-151 ]); +const ESCAPE_HEX_TABLE = memory.data([ + 0, 1, 2, 3, 4, 5, 6, 7, // 0-7 + 8, 9, 0, 0, 0, 0, 0, 0, // 8-15 + 0, 0, 0, 0, 0, 0, 0, 0, // 16-23 + 0, 0, 0, 0, 0, 0, 0, 0, // 24-31 + 0, 0, 0, 0, 0, 0, 0, 0, // 32-39 + 0, 0, 0, 0, 0, 0, 0, 0, // 40-47 + 0, 10, 11, 12, 13, 14, 15, // 48-54 +]) - 48; + const SPLAT_92 = i16x8.splat(92); /* \ */ /** @@ -46,35 +56,74 @@ const SPLAT_92 = i16x8.splat(92); /* \ */ const backslash_indices = i16x8.eq(block, SPLAT_92); let mask = i16x8.bitmask(backslash_indices); - while (mask != 0) { + + let src_skips = 0; + let dst_skips = 0; + + if (mask != 0) while (mask != 0) { const lane_index = ctz(mask) << 1; const dst_offset = dst_ptr + lane_index; const src_offset = src_ptr + lane_index; - const code = load(src_offset, 2) << 1; - const escaped = load(ESCAPE_TABLE + code); - store(dst_offset, escaped); - v128.store(dst_offset, v128.load(src_offset, 4), 2); + const code = load(src_offset, 2); + mask &= mask - 1; - dst_ptr -= 2; + if (code == 117 && load(src_offset, 4) == 3145776) { + const block = load(src_offset, 8); + const codeA = block & 0xFFFF; + const codeB = (block >> 16) & 0xFFFF; + const escapedA = load(ESCAPE_HEX_TABLE + codeA); + const escapedB = load(ESCAPE_HEX_TABLE + codeB); + const escaped = (escapedA << 4) + escapedB; + console.log("Escaped:"); + console.log(" a: " + escapedA.toString()) + console.log(" b: " + escapedB.toString()); + console.log(" c: " + escaped.toString()); + console.log(" o: " + (dst_ptr - dst).toString()); + console.log(" d: " + (lane_index).toString()) + console.log(" l: " + (lane_index).toString()) + store(dst_ptr, escaped); + v128.store(dst_offset, v128.load(src_offset, 4), 2); + dst_ptr += 2; + src_skips += 10; + dst_skips += 10; + } else { + src_skips += 2; + const escaped = load(ESCAPE_TABLE + code); + store(dst_offset, escaped); + v128.store(dst_offset, v128.load(src_offset, 4), 2); + dst_ptr += 2; + src_skips += 2; + } } - src_ptr += 16; - dst_ptr += 16; - } - - while (src_ptr < src_end) { - let code = load(src_ptr); - if (code == BACK_SLASH) { - code = load(ESCAPE_TABLE + (code << 2), 2); - store(dst_ptr, code); - dst_ptr += 2; - src_ptr += 2; - } else { - store(dst_ptr, code); - dst_ptr += 2; - src_ptr += 2; - } + src_ptr += 16 + src_skips; + dst_ptr += 16 - dst_skips; } + // while (src_ptr < src_end) { + // let code = load(src_ptr); + // if (code == BACK_SLASH) { + // code = load(ESCAPE_TABLE + load(src_ptr, 2)); + // if (code == 117 && load(src_ptr, 4) == 3145776) { + // const block = load(src_ptr, 8); + // const codeA = block & 0xFFFF; + // const codeB = (block >> 16) & 0xFFFF; + // const escapedA = load(ESCAPE_HEX_TABLE + codeA); + // const escapedB = load(ESCAPE_HEX_TABLE + codeB); + // const escaped = (escapedA << 4) + escapedB; + // store(dst_ptr, escaped); + // dst_ptr += 2; + // src_ptr += 12; + // } else { + // store(dst_ptr, code); + // dst_ptr += 2; + // src_ptr += 4; + // } + // } else { + // store(dst_ptr, code); + // dst_ptr += 2; + // src_ptr += 2; + // } + // } return dst_ptr - dst; } \ No newline at end of file diff --git a/assembly/index.ts b/assembly/index.ts index 094af2f..dac0bad 100644 --- a/assembly/index.ts +++ b/assembly/index.ts @@ -25,6 +25,7 @@ import { BLOCK_MAXSIZE, OBJECT, TOTAL_OVERHEAD } from "rt/common"; import { E_INVALIDLENGTH } from "util/error"; import { serializeString_SIMD } from "./serialize/simd/string"; import { Option } from "as-container"; +import { deserializeString_SIMD } from "./deserialize/simd/string"; // Config class SerializeOptions { @@ -157,6 +158,25 @@ export namespace JSON { throw new Error(`Could not serialize data of type ${nameof()}. Make sure to add the correct decorators to classes.`); } } + + /** + * Serializes valid JSON data and outputs it to string + * ```js + * JSON.stringify(data) + * ``` + * @param data T + * @returns string + */ + export function parseTo(data: string, out: T): T { + if (isString()) { + const oldCapacity = changetype(changetype(out) - TOTAL_OVERHEAD).rtSize; + const outPtr = setCapacity(out, oldCapacity, oldCapacity << 3); // this doesn't account for \u0000+ + out = changetype(__renew(outPtr, deserializeString_SIMD(data as string, outPtr))) as T; + return changetype(outPtr) as T; + } else { + return unreachable(); + } + } /** * Parses valid JSON strings into their original format. * ```js diff --git a/assembly/serialize/simd/string.ts b/assembly/serialize/simd/string.ts index ab02ccf..fa81d20 100644 --- a/assembly/serialize/simd/string.ts +++ b/assembly/serialize/simd/string.ts @@ -36,7 +36,7 @@ const ESCAPE_TABLE = memory.data([ 0, 0, 0, 0, 0, 0, 0, 0, // Pair 84-87 0, 0, 0, 0, 0, 0, 0, 0, // Pair 88-91 - 92, 92, // Pair 92-93 + 92, 92, // Pair 92-93 ]); const SPLAT_34 = i16x8.splat(34); /* " */ @@ -115,7 +115,7 @@ export function serializeString_SIMD(src: string, dst: usize): usize { const code = load(src_offset) << 2; const escaped = load(ESCAPE_TABLE + code); mask &= mask - 1; - + if ((escaped & 0xFFFF) != BACK_SLASH) { store(dst_offset, 13511005048209500); store(dst_offset, escaped, 8); @@ -139,9 +139,8 @@ export function serializeString_SIMD(src: string, dst: usize): usize { } if (rem & 4) { const block = load(src_ptr); - const codeA = block & 0xFFFF; - const codeB = block >> 16; + const codeB = (block >> 16) & 0xFFFF; if (codeA == 92 || codeA == 34 || codeA < 32) { const escaped = load(ESCAPE_TABLE + (codeA << 2)); diff --git a/assembly/test.ts b/assembly/test.ts index f99ceb6..09a8f85 100644 --- a/assembly/test.ts +++ b/assembly/test.ts @@ -10,15 +10,16 @@ import { JSON } from "."; // public z: T; // } -let a = "12\"345678123456"; -const b = "world"; +let a = "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007"; +let b = "000000000000000000000000000000000000000" let c = "000000000000000000000000000000000000000"; -JSON.stringifyTo(a, c) +JSON.stringifyTo(a, b) +c = JSON.parseTo(b, c); // console.log(JSON.stringifyTo(a, a)); -console.log("A: " + a.toString()); +console.log("A: " + JSON.stringify(a).toString()); console.log("B: " + b.toString()); -console.log("C: " + c.toString()); +console.log("C: " + JSON.stringify(c)); // console.log(new Vec3().__SERIALIZE())