X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/cb5a5ceca492121141a12d921afc78dbde7fbfa1..3d2a5e40eaf384aee6b9699bc71af015fd2cb2e9:/base64.js diff --git a/base64.js b/base64.js deleted file mode 100644 index e9661b7..0000000 --- a/base64.js +++ /dev/null @@ -1,232 +0,0 @@ -// ♓🌟 Piscēs ∷ base64.js -// ==================================================================== -// -// Copyright © 2020–2022 Lady [@ Lady’s Computer]. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at . - -import { fill, map, reduce } from "./collection.js"; -import { bind, call } from "./function.js"; -import { ceil, floor } from "./numeric.js"; -import { hasOwnProperty, objectCreate } from "./object.js"; -import { - getCodeUnit, - rawString, - stringFromCodeUnits, - stringReplace, -} from "./string.js"; - -const Buffer = ArrayBuffer; -const View = DataView; -const TypedArray = Object.getPrototypeOf(Uint8Array); -const { prototype: arrayPrototype } = Array; -const { prototype: bufferPrototype } = Buffer; -const { iterator: iteratorSymbol } = Symbol; -const { prototype: rePrototype } = RegExp; -const { prototype: typedArrayPrototype } = TypedArray; -const { prototype: viewPrototype } = View; - -const { [iteratorSymbol]: arrayIterator } = arrayPrototype; -const { - next: arrayIteratorNext, -} = Object.getPrototypeOf([][iteratorSymbol]()); -const getBufferByteLength = - Object.getOwnPropertyDescriptor(bufferPrototype, "byteLength").get; -const getTypedArrayBuffer = - Object.getOwnPropertyDescriptor(typedArrayPrototype, "buffer").get; -const getViewBuffer = - Object.getOwnPropertyDescriptor(viewPrototype, "buffer").get; -const { exec: reExec } = rePrototype; -const { - getUint8: viewGetUint8, - setUint8: viewSetUint8, - setUint16: viewSetUint16, -} = viewPrototype; - -const base64CodeUnitIterablePrototype = { - [iteratorSymbol]() { - return { - next: bind( - arrayIteratorNext, - call(arrayIterator, this, []), - [], - ), - }; - }, -}; - -/** - * Returns an ArrayBuffer generated from the provided Base64. - * - * This function can also be used as a tag for a template literal. The - * literal will be interpreted akin to `String.raw`. - */ -export const a2b = ($, ...$s) => { - const source = stringReplace( - typeof $ == "string" - ? $ - : hasOwnProperty($, "raw") - ? rawString($, ...$s) - : `${$}`, - /[\t\n\f\r ]+/gu, - "", - ); - const u6s = map( - source.length % 4 == 0 - ? stringReplace(source, /={1,2}$/u, "") - : source, - (ucsCharacter) => { - const code = getCodeUnit(ucsCharacter, 0); - const result = code >= 0x41 && code <= 0x5A - ? code - 65 - : code >= 0x61 && code <= 0x7A - ? code - 71 - : code >= 0x30 && code <= 0x39 - ? code + 4 - : code == 0x2B - ? 62 - : code == 0x2F - ? 63 - : -1; - if (result < 0) { - throw new RangeError( - `Piscēs: Invalid character in Base64: ${character}.`, - ); - } else { - return result; - } - }, - ); - const { length } = u6s; - const dataView = new View(new Buffer(floor(length * 3 / 4))); - for (let index = 0; index < length - 1;) { - const dataIndex = ceil(index * 3 / 4); - const remainder = index % 3; - if (remainder == 0) { - call(viewSetUint8, dataView, [ - dataIndex, - (u6s[index] << 2) + (u6s[++index] >> 4), - ]); - } else if (remainder == 1) { - call(viewSetUint8, dataView, [ - dataIndex, - ((u6s[index] & 0xF) << 4) + (u6s[++index] >> 2), - ]); - } else { - call(viewSetUint8, dataView, [ - dataIndex, - ((u6s[index] & 0x3) << 6) + u6s[++index], - ]); - } - } - return call(getViewBuffer, dataView, []); -}; - -/** - * Returns a (big‐endian) base64 string created from a typed array, - * buffer, or string. - * - * This function can also be used as a tag for a template literal. The - * literal will be interpreted akin to `String.raw`. - */ -export const b2a = ($, ...$s) => { - const buffer = $ instanceof Buffer - ? $ - : $ instanceof View - ? call(getViewBuffer, $, []) - : $ instanceof TypedArray - ? call(getTypedArrayBuffer, $, []) - : ((string) => - call( - getViewBuffer, - reduce( - string, - (result, ucsCharacter, index) => ( - call(viewSetUint16, result, [ - index * 2, - getCodeUnit(ucsCharacter, 0), - ]), result - ), - new View(new Buffer(string.length * 2)), - ), - [], - ))( - typeof $ == "string" - ? $ - : hasOwnProperty($, "raw") - ? rawString($, ...$s) - : `${$}`, - ); - const dataView = new View(buffer); - const byteLength = call(getBufferByteLength, buffer, []); - const minimumLengthOfResults = ceil(byteLength * 4 / 3); - const resultingCodeUnits = fill( - objectCreate( - base64CodeUnitIterablePrototype, - { - length: { - value: minimumLengthOfResults + - (4 - (minimumLengthOfResults % 4)) % 4, - }, - }, - ), - 0x3D, - ); - for (let index = 0; index < byteLength;) { - const codeUnitIndex = ceil(index * 4 / 3); - const currentIndex = codeUnitIndex + +( - index % 3 == 0 && resultingCodeUnits[codeUnitIndex] != 0x3D - ); - const remainder = currentIndex % 4; - const u6 = remainder == 0 - ? call(viewGetUint8, dataView, [index]) >> 2 - : remainder == 1 - ? ((call(viewGetUint8, dataView, [index++]) & 0x3) << 4) + - (index < byteLength - ? call(viewGetUint8, dataView, [index]) >> 4 - : 0) - : remainder == 2 - ? ((call(viewGetUint8, dataView, [index++]) & 0xF) << 2) + - (index < byteLength - ? call(viewGetUint8, dataView, [index]) >> 6 - : 0) - : call(viewGetUint8, dataView, [index++]) & 0x3F; - const result = u6 < 26 - ? u6 + 65 - : u6 < 52 - ? u6 + 71 - : u6 < 62 - ? u6 - 4 - : u6 < 63 - ? 43 - : u6 < 64 - ? 47 - : -1; - if (result < 0) { - throw new RangeError(`Piscēs: Unexpected Base64 value: ${u6}.`); - } else { - resultingCodeUnits[currentIndex] = result; - } - } - return stringFromCodeUnits(...resultingCodeUnits); -}; - -/** - * Returns whether the provided value is a Base64 string. - * - * Returns false if the provided value is not a string primitive. - */ -export const isBase64 = ($) => { - if (typeof $ !== "string") { - return false; - } else { - const source = stringReplace($, /[\t\n\f\r ]+/gu, ""); - const trimmed = source.length % 4 == 0 - ? stringReplace(source, /={1,2}$/u, "") - : source; - return trimmed.length % 4 != 1 && - call(reExec, /[^0-9A-Za-z+\/]/u, [trimmed]) == null; - } -};