/** * @author PenguinGeorge [george@penguingeorge.com] * @copyright Crown Copyright 2018 * @license Apache-2.0 */ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import Utils from "../Utils.mjs"; import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85.mjs"; /** * To Base85 operation */ class ToBase85 extends Operation { /** * To Base85 constructor */ constructor() { super(); this.name = "To Base85"; this.module = "Default"; this.description = "Base85 (also called Ascii85) is a notation for encoding arbitrary byte data. It is usually more efficient that Base64.

This operation encodes data in an ASCII string (with an alphabet of your choosing, presets included).

e.g. hello world becomes BOu!rD]j7BEbo7

Base85 is commonly used in Adobe's PostScript and PDF file formats.

Options
AlphabetInclude delimiter
Adds a '<~' and '~>' delimiter to the start and end of the data. This is standard for Adobe's implementation of Base85."; this.infoURL = "https://wikipedia.org/wiki/Ascii85"; this.inputType = "ArrayBuffer"; this.outputType = "string"; this.args = [ { name: "Alphabet", type: "editableOption", value: ALPHABET_OPTIONS }, { name: "Include delimeter", type: "boolean", value: false } ]; } /** * @param {ArrayBuffer} input * @param {Object[]} args * @returns {string} */ run(input, args) { input = new Uint8Array(input); const alphabet = Utils.expandAlphRange(args[0]).join(""), encoding = alphabetName(alphabet), includeDelim = args[1]; let result = ""; if (alphabet.length !== 85 || [].unique.call(alphabet).length !== 85) { throw new OperationError("Error: Alphabet must be of length 85"); } if (input.length === 0) return ""; let block; for (let i = 0; i < input.length; i += 4) { block = ( ((input[i]) << 24) + ((input[i + 1] || 0) << 16) + ((input[i + 2] || 0) << 8) + ((input[i + 3] || 0)) ) >>> 0; if (encoding !== "Standard" || block > 0) { let digits = []; for (let j = 0; j < 5; j++) { digits.push(block % 85); block = Math.floor(block / 85); } digits = digits.reverse(); if (input.length < i + 4) { digits.splice(input.length - (i + 4), 4); } result += digits.map(digit => alphabet[digit]).join(""); } else { result += (encoding === "Standard") ? "z" : null; } } return includeDelim ? `<~${result}~>` : result; } } export default ToBase85;