All files / base64/src createFromBase64.ts

94.2% Statements 65/69
86.2% Branches 25/29
100% Functions 2/2
100% Lines 56/56

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 672x   2x   2x 3x 3x 192x 3x 369x 192x   3x 342x 337x 337x 99x 99x 40x 40x 59x 32x 32x     337x 337x 337x 337x 337x 100x 100x 237x 71x 71x   337x 337x 337x 337x 5077x 5077x 5077x 5077x 5077x 4977x 4977x 4977x 4977x   237x 100x 100x 100x 100x 137x 71x 71x 71x 71x 71x 71x   237x      
import {alphabet} from './constants';
 
const E = '=';
 
export const createFromBase64 = (chars: string = alphabet, noPadding: boolean = false) => {
  Iif (chars.length !== 64) throw new Error('chars must be 64 characters long');
  let max = 0;
  for (let i = 0; i < chars.length; i++) max = Math.max(max, chars.charCodeAt(i));
  const table: number[] = [];
  for (let i = 0; i <= max; i += 1) table[i] = -1;
  for (let i = 0; i < chars.length; i++) table[chars.charCodeAt(i)] = i;
 
  return (encoded: string): Uint8Array => {
    if (!encoded) return new Uint8Array(0);
    let length = encoded.length;
    if (noPadding) {
      const mod = length % 4;
      if (mod === 2) {
        encoded += '==';
        length += 2;
      } else if (mod === 3) {
        encoded += '=';
        length += 1;
      }
    }
    Iif (length % 4 !== 0) throw new Error('Base64 string length must be a multiple of 4');
    const mainLength = encoded[length - 1] !== E ? length : length - 4;
    let bufferLength = (length >> 2) * 3;
    let padding = 0;
    if (encoded[length - 2] === E) {
      padding = 2;
      bufferLength -= 2;
    } else if (encoded[length - 1] === E) {
      padding = 1;
      bufferLength -= 1;
    }
    const buf = new Uint8Array(bufferLength);
    let j = 0;
    let i = 0;
    for (; i < mainLength; i += 4) {
      const sextet0 = table[encoded.charCodeAt(i)];
      const sextet1 = table[encoded.charCodeAt(i + 1)];
      const sextet2 = table[encoded.charCodeAt(i + 2)];
      const sextet3 = table[encoded.charCodeAt(i + 3)];
      if (sextet0 < 0 || sextet1 < 0 || sextet2 < 0 || sextet3 < 0) throw new Error('INVALID_BASE64_STRING');
      buf[j] = (sextet0 << 2) | (sextet1 >> 4);
      buf[j + 1] = (sextet1 << 4) | (sextet2 >> 2);
      buf[j + 2] = (sextet2 << 6) | sextet3;
      j += 3;
    }
    if (padding === 2) {
      const sextet0 = table[encoded.charCodeAt(mainLength)];
      const sextet1 = table[encoded.charCodeAt(mainLength + 1)];
      Iif (sextet0 < 0 || sextet1 < 0) throw new Error('INVALID_BASE64_STRING');
      buf[j] = (sextet0 << 2) | (sextet1 >> 4);
    } else if (padding === 1) {
      const sextet0 = table[encoded.charCodeAt(mainLength)];
      const sextet1 = table[encoded.charCodeAt(mainLength + 1)];
      const sextet2 = table[encoded.charCodeAt(mainLength + 2)];
      Iif (sextet0 < 0 || sextet1 < 0 || sextet2 < 0) throw new Error('INVALID_BASE64_STRING');
      buf[j] = (sextet0 << 2) | (sextet1 >> 4);
      buf[j + 1] = (sextet1 << 4) | (sextet2 >> 2);
    }
    return buf;
  };
};