All files / base64/src createFromBase64.ts

94.2% Statements 65/69
89.74% Branches 35/39
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 339x 330x 330x 99x 99x 28x 28x 71x 39x 39x     330x 330x 330x 330x 330x 78x 78x 252x 79x 79x   330x 330x 330x 330x 5179x 5179x 5179x 5179x 5179x 5079x 5079x 5079x 5079x   230x 78x 78x 78x 78x 152x 79x 79x 79x 79x 79x 79x   230x      
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;
  };
};