UNPKG

@cloudpss/ubjson

Version:

Opinionated UBJSON encoder/decoder for CloudPSS.

207 lines 6.12 kB
const CHUNK_SIZE = 0x1000; const REPLACE_CHAR = 0xfffd; const { fromCharCode } = String; /** 解码 */ export function jsDecode(bytes, begin, end) { let offset = begin; const units = []; let result = ''; while (offset < end) { const byte1 = bytes[offset++]; if ((byte1 & 0x80) === 0) { // 1 byte units.push(byte1); } else if ((byte1 & 0xe0) === 0xc0) { // 2 bytes const byte2 = bytes[offset++] & 0x3f; units.push(((byte1 & 0x1f) << 6) | byte2); } else if ((byte1 & 0xf0) === 0xe0) { // 3 bytes const byte2 = bytes[offset++] & 0x3f; const byte3 = bytes[offset++] & 0x3f; units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3); } else if ((byte1 & 0xf8) === 0xf0) { // 4 bytes const byte2 = bytes[offset++] & 0x3f; const byte3 = bytes[offset++] & 0x3f; const byte4 = bytes[offset++] & 0x3f; let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4; if (unit > 0xffff) { unit -= 0x1_0000; units.push(((unit >>> 10) & 0x3ff) | 0xd800); unit = 0xdc00 | (unit & 0x3ff); } units.push(unit); } else { units.push(REPLACE_CHAR); } if (units.length >= CHUNK_SIZE) { result += fromCharCode(...units); units.length = 0; } } if (units.length > 0) { result += fromCharCode(...units); } return result; } /** 解码 Ascii */ export function longStringInJS(buf, begin, length) { const bytes = []; for (let i = 0; i < length; i++) { const byte = buf[begin++]; if (byte & 0x80) { return; } bytes.push(byte); } return fromCharCode(...bytes); } /** 解码 Ascii */ export function shortStringInJS(buf, begin, length) { if (length < 4) { if (length < 2) { if (length === 0) return ''; const a = buf[begin]; if ((a & 0x80) > 0) { return; } return fromCharCode(a); } const a = buf[begin++]; const b = buf[begin++]; if ((a & 0x80) > 0 || (b & 0x80) > 0) { return; } if (length < 3) return fromCharCode(a, b); const c = buf[begin++]; if ((c & 0x80) > 0) { return; } return fromCharCode(a, b, c); } const a = buf[begin++]; const b = buf[begin++]; const c = buf[begin++]; const d = buf[begin++]; if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) { return; } if (length < 6) { if (length === 4) return fromCharCode(a, b, c, d); const e = buf[begin++]; if ((e & 0x80) > 0) { return; } return fromCharCode(a, b, c, d, e); } const e = buf[begin++]; const f = buf[begin++]; if ((e & 0x80) > 0 || (f & 0x80) > 0) { return; } if (length < 8) { if (length < 7) return fromCharCode(a, b, c, d, e, f); const g = buf[begin++]; if ((g & 0x80) > 0) { return; } return fromCharCode(a, b, c, d, e, f, g); } const g = buf[begin++]; const h = buf[begin++]; if ((g & 0x80) > 0 || (h & 0x80) > 0) { return; } if (length < 10) { if (length === 8) return fromCharCode(a, b, c, d, e, f, g, h); const i = buf[begin++]; if ((i & 0x80) > 0) { return; } return fromCharCode(a, b, c, d, e, f, g, h, i); } const i = buf[begin++]; const j = buf[begin++]; if ((i & 0x80) > 0 || (j & 0x80) > 0) { return; } if (length < 12) { if (length < 11) return fromCharCode(a, b, c, d, e, f, g, h, i, j); const k = buf[begin++]; if ((k & 0x80) > 0) { return; } return fromCharCode(a, b, c, d, e, f, g, h, i, j, k); } const k = buf[begin++]; const l = buf[begin++]; if ((k & 0x80) > 0 || (l & 0x80) > 0) { return; } if (length < 14) { if (length === 12) return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l); const m = buf[begin++]; if ((m & 0x80) > 0) { begin -= 13; return; } return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m); } const m = buf[begin++]; const n = buf[begin++]; if ((m & 0x80) > 0 || (n & 0x80) > 0) { return; } if (length < 15) return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n); const o = buf[begin++]; if ((o & 0x80) > 0) { return; } return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); } let TEXT_DECODER; let TEXT_DECODER_THRESHOLD; /** 解码 */ export function nativeDecode(data, begin, end) { return TEXT_DECODER.decode(data.subarray(begin, end)); } /** 字符串解码,无缓存 */ export function decode(data, begin, end) { const length = end - begin; if (length < 16) { const result = shortStringInJS(data, begin, length); if (result != null) return result; } // 只有小字符串有优化价值 if (length < TEXT_DECODER_THRESHOLD) { // if (length < 32) { // const result = longStringInJS(data, begin, length); // if (result != null) return result; // } // 为小字符串优化 return jsDecode(data, begin, end); } // 使用系统解码 return nativeDecode(data, begin, end); } /** 重设环境 */ export function resetEnv() { TEXT_DECODER = typeof TextDecoder == 'function' ? new TextDecoder('utf8', { ignoreBOM: true, fatal: false }) : null; TEXT_DECODER_THRESHOLD = TEXT_DECODER == null ? 0xffff_ffff : 16; } resetEnv(); //# sourceMappingURL=string-decoder.js.map