UNPKG

json-as

Version:

The only JSON library you'll need for AssemblyScript. SIMD enabled

90 lines (76 loc) 2.72 kB
import { bs } from "../../../lib/as-bs"; import { BACK_SLASH } from "../../custom/chars"; import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables"; import { bytes } from "../../util"; /** * Serializes strings into their JSON counterparts using SIMD operations * @param srcStart pointer to begin serializing at * @param srcEnd pointer to end serialization at */ export function serializeString_SIMD(src: string): void { const U00_MARKER = 13511005048209500; const SPLAT_34 = i16x8.splat(34); /* " */ const SPLAT_92 = i16x8.splat(92); /* \ */ const SPLAT_32 = i16x8.splat(32); /* [ESC] */ const srcSize = bytes(src); let srcStart = changetype<usize>(src); const srcEnd = srcStart + srcSize; const srcEnd16 = srcEnd - 16; bs.proposeSize(srcSize + 4); store<u8>(changetype<usize>(bs.offset), 34); /* " */ bs.offset += 2; while (srcStart <= srcEnd16) { const block = v128.load(srcStart); v128.store(bs.offset, block); const backslash_indices = i16x8.eq(block, SPLAT_92); const quote_indices = i16x8.eq(block, SPLAT_34); const escape_indices = i16x8.lt_u(block, SPLAT_32); const sieve = v128.or(v128.or(backslash_indices, quote_indices), escape_indices); let mask = i16x8.bitmask(sieve); while (mask != 0) { const lane_index = ctz(mask) << 1; const src_offset = srcStart + lane_index; const code = load<u16>(src_offset) << 2; const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + code); mask &= mask - 1; if ((escaped & 0xffff) != BACK_SLASH) { bs.growSize(10); const dst_offset = bs.offset + lane_index; store<u64>(dst_offset, U00_MARKER); store<u32>(dst_offset, escaped, 8); v128.store(dst_offset, v128.load(src_offset, 2), 12); bs.offset += 10; } else { bs.growSize(2); const dst_offset = bs.offset + lane_index; store<u32>(dst_offset, escaped); v128.store(dst_offset, v128.load(src_offset, 2), 4); bs.offset += 2; } } srcStart += 16; bs.offset += 16; } while (srcStart <= srcEnd - 2) { const code = load<u16>(srcStart); if (code == 92 || code == 34 || code < 32) { const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2)); if ((escaped & 0xffff) != BACK_SLASH) { bs.growSize(10); store<u64>(bs.offset, U00_MARKER); store<u32>(bs.offset, escaped, 8); bs.offset += 12; } else { bs.growSize(2); store<u32>(bs.offset, escaped); bs.offset += 4; } } else { store<u16>(bs.offset, code); bs.offset += 2; } srcStart += 2; } store<u8>(bs.offset, 34); /* " */ bs.offset += 2; }