@endo/base64
Version:
73 lines (67 loc) • 1.97 kB
JavaScript
// @ts-check
/* eslint no-bitwise: ["off"] */
/* global globalThis */
import { alphabet64, padding } from './common.js';
/**
* XSnap is a JavaScript engine based on Moddable/XS.
* The algorithm below is orders of magnitude too slow on this VM, but it
* arranges a native binding on the global object.
* We use that if it is available instead.
*
* This function is exported from this *file* for use in benchmarking,
* but is not part of the *module*'s public API.
*
* @param {Uint8Array} data
* @returns {string} base64 encoding
*/
export const jsEncodeBase64 = data => {
// A cursory benchmark shows that string concatenation is about 25% faster
// than building an array and joining it in v8, in 2020, for strings of about
// 100 long.
let string = '';
let register = 0;
let quantum = 0;
for (let i = 0; i < data.length; i += 1) {
const b = data[i];
register = (register << 8) | b;
quantum += 8;
if (quantum === 24) {
string +=
alphabet64[(register >>> 18) & 0x3f] +
alphabet64[(register >>> 12) & 0x3f] +
alphabet64[(register >>> 6) & 0x3f] +
alphabet64[(register >>> 0) & 0x3f];
register = 0;
quantum = 0;
}
}
switch (quantum) {
case 0:
break;
case 8:
string +=
alphabet64[(register >>> 2) & 0x3f] +
alphabet64[(register << 4) & 0x3f] +
padding +
padding;
break;
case 16:
string +=
alphabet64[(register >>> 10) & 0x3f] +
alphabet64[(register >>> 4) & 0x3f] +
alphabet64[(register << 2) & 0x3f] +
padding;
break;
default:
throw Error(`internal: bad quantum ${quantum}`);
}
return string;
};
/**
* Encodes bytes into a Base64 string, as specified in
* https://tools.ietf.org/html/rfc4648#section-4
*
* @type {typeof jsEncodeBase64}
*/
export const encodeBase64 =
globalThis.Base64 !== undefined ? globalThis.Base64.encode : jsEncodeBase64;