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 344x 342x 342x 100x 100x 28x 28x 72x 34x 34x     342x 342x 342x 342x 342x 67x 67x 275x 86x 86x   342x 342x 342x 342x 4961x 4961x 4961x 4961x 4961x 4861x 4861x 4861x 4861x   242x 67x 67x 67x 67x 175x 86x 86x 86x 86x 86x 86x   242x      
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;
  };
};