/**
* @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
Alphabet
- Standard - The standard alphabet, referred to as Ascii85
- Z85 (ZeroMQ) - A string-safe variant of Base85, which avoids quote marks and backslash characters
- IPv6 - A variant of Base85 suitable for encoding IPv6 addresses (RFC 1924)
Include 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;