All files / src/encodings utf8js.ts

100% Statements 49/49
100% Branches 14/14
100% Functions 2/2
100% Lines 48/48

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82    19x   64832x 64830x 576269x 576269x   539450x 539446x 36819x     4219x 4219x 4219x 4218x 32600x     26939x 26939x 26939x 26939x 26938x   5661x     5661x 5661x 5661x 5661x 5661x 5661x         41100x 41100x 372254x 372254x   347334x 347334x 24920x       3090x 3090x 3090x 21830x         18212x 18212x 18212x 18212x             3618x 3618x 3618x 3618x 3618x 3618x 3618x     41100x      
import { Encoding } from "../types";
 
export const utf8js: Encoding<string> = {
  encode(ctx, data) {
    const { length } = data;
    for (let i = 0; i < length; i++) {
      const code = data.charCodeAt(i) as number;
      if (code < 0x80) {
        // 0xxxxxxx
        ctx.view.setUint8(ctx.i, code);
        ctx.i++;
      } else if (code < 0x800) {
        // .... .aaa - aabb bbbb
        // 110a aaaa - 10bb bbbb
        const a = (code & 0x7_c0) << 2;
        const b = code & 0x3f;
        ctx.view.setUint16(ctx.i, a | b | 0xc080);
        ctx.i += 2;
      } else if (code < 0xd800 || code >= 0xe000) {
        // .... .... - .... .... - aaaa bbbb - bbcc cccc
        // 1110 aaaa - 10bb bbbb - 10cc cccc - .... ....
        const a = (code & 0xf0_00) << 12;
        const b = (code & 0xf_c0) << 10;
        const c = (code & 0x3f) << 8;
        ctx.view.setUint32(ctx.i, a | b | c | 0xe0_80_80_00);
        ctx.i += 3;
      } else {
        const code = data.codePointAt(i++) as number;
        // .... .... - .... aabb - bbbb cccc - ccdd dddd
        // 1111 00aa - 10bb bbbb - 10cc cccc - 10dd dddd
        const a = (code & 0x1c_00_00) << 6;
        const b = (code & 0x3_f0_00) << 4;
        const c = (code & 0xf_c0) << 2;
        const d = code & 0x3f;
        ctx.view.setUint32(ctx.i, a | b | c | d | 0xf0_80_80_80);
        ctx.i += 4;
      }
    }
  },
  decode(ctx, end) {
    const codes: number[] = [];
    while (ctx.i < end) {
      const s = ctx.view.getUint8(ctx.i);
      if (s < 192) {
        // 0xxxxxxx
        codes.push(s);
        ctx.i++;
      } else if (s < 224) {
        //     110a aaaa
        //     10bb bbbb
        // aaa aabb bbbb
        const b = ctx.view.getUint8(ctx.i + 1);
        ctx.i += 2;
        codes.push(((s & 0x1f) << 6) | (b & 0x3f));
      } else if (s < 240) {
        //           1110 aaaa
        //           10bb bbbb
        //           10cc cccc
        // aaaa bbbb bbcc cccc
        const b = ctx.view.getUint8(ctx.i + 1);
        const c = ctx.view.getUint8(ctx.i + 2);
        ctx.i += 3;
        codes.push(
          ((s & 0x0f) << 12) | ((b & 0x3f) << 6) | (c & 0x3f)
        );
      } else {
        // 1111 0aaa, 10bb bbbb, 10cc cccc, 10dd dddd
        //               a aabb, bbbb cccc, ccdd dddd
 
        const u = ctx.view.getUint32(ctx.i);
        const a = (s & 0x7) << 18;
        const b = (u & 0x3f_00_00) >> 4;
        const c = (u & 0x3f_00) >> 2;
        const d = u & 0x3f;
        codes.push(a | b | c | d);
        ctx.i += 4;
      }
    }
    return String.fromCodePoint.apply(null, codes);
  }
};