UNPKG

@fedify/fedify

Version:

An ActivityPub server framework

80 lines (79 loc) 2.54 kB
const decode = (string, alphabet, bitsPerChar) => { // Build the character lookup table: const codes = {}; for (let i = 0; i < alphabet.length; ++i) { codes[alphabet[i]] = i; } // Count the padding bytes: let end = string.length; while (string[end - 1] === "=") { --end; } // Allocate the output: const out = new Uint8Array((end * bitsPerChar / 8) | 0); // Parse the data: let bits = 0; // Number of bits currently in the buffer let buffer = 0; // Bits waiting to be written out, MSB first let written = 0; // Next byte to write for (let i = 0; i < end; ++i) { // Read one character from the string: const value = codes[string[i]]; if (value === undefined) { throw new SyntaxError("Invalid character " + string[i]); } // Append the bits to the buffer: buffer = (buffer << bitsPerChar) | value; bits += bitsPerChar; // Write out some bits if the buffer has a byte's worth: if (bits >= 8) { bits -= 8; out[written++] = 0xff & (buffer >> bits); } } // Verify that we have received just enough bits: if (bits >= bitsPerChar || 0xff & (buffer << (8 - bits))) { throw new SyntaxError("Unexpected end of data"); } return out; }; const encode = (data, alphabet, bitsPerChar) => { const pad = alphabet[alphabet.length - 1] === "="; const mask = (1 << bitsPerChar) - 1; let out = ""; let bits = 0; // Number of bits currently in the buffer let buffer = 0; // Bits waiting to be written out, MSB first for (let i = 0; i < data.length; ++i) { // Slurp data into the buffer: buffer = (buffer << 8) | data[i]; bits += 8; // Write out as much as we can: while (bits > bitsPerChar) { bits -= bitsPerChar; out += alphabet[mask & (buffer >> bits)]; } } // Partial character: if (bits) { out += alphabet[mask & (buffer << (bitsPerChar - bits))]; } // Add padding characters until we hit a byte boundary: if (pad) { while ((out.length * bitsPerChar) & 7) { out += "="; } } return out; }; /** * RFC4648 Factory */ export const rfc4648 = (bitsPerChar) => (alphabet) => { return { encode(input) { return encode(input, alphabet, bitsPerChar); }, decode(input) { return decode(input, alphabet, bitsPerChar); }, }; };