From: Lady Date: Mon, 26 Jun 2023 01:54:33 +0000 (-0700) Subject: Apply various minor updates to binary.js X-Git-Tag: 0.4.0~3 X-Git-Url: https://git.ladys.computer/Pisces/commitdiff_plain/32ed653b76c0cb255c7ba8f0152740e39d951846?hp=3e02a3609121cc8f06684cc0e38f9b8705099f73 Apply various minor updates to binary.js --- diff --git a/binary.js b/binary.js index 686d3a2..f6d8cab 100644 --- a/binary.js +++ b/binary.js @@ -55,13 +55,13 @@ const binaryCodeUnitIterablePrototype = { }, }; +const { exec: reExec } = rePrototype; 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, @@ -129,10 +129,13 @@ const decodeBase16 = (source) => { ? code - 87 : -1; if (result < 0) { + // The source contains an invalid character. throw new RangeError( `Piscēs: Invalid character in Base64: ${ucsCharacter}.`, ); } else { + // The source contains a valid character with a recognized + // mapping. return result; } }, @@ -148,6 +151,8 @@ const decodeBase16 = (source) => { // Every letter contributes at least some bits to the result. const dataView = new View(new Buffer(floor(length / 2))); for (let index = 0; index < length - 1;) { + // Iterate over the characters and assign their bits to the + // buffer. call(viewSetUint8, dataView, [ floor(index / 2), (u4s[index] << 4) | u4s[++index, index++], @@ -222,10 +227,13 @@ const decodeBase32 = (source, wrmg) => { ? code - 24 // digits 2–7 map to 26–31 : -1; if (result < 0) { + // The source contains an invalid character. throw new RangeError( `Piscēs: Invalid character in Base32: ${ucsCharacter}.`, ); } else { + // The source contains a valid character with a recognized + // mapping. return result; } }, @@ -242,37 +250,26 @@ const decodeBase32 = (source, wrmg) => { // Every letter contributes at least some bits to the result. const dataView = new View(new Buffer(floor(length * 5 / 8))); for (let index = 0; index < length - 1;) { + // Iterate over the characters and assign their bits to the + // buffer. + // // The final index is not handled; if the string is not divisible // by 8, some bits might be dropped. This matches the “forgiving // decode” behaviour specified by WhatW·G for base64. const dataIndex = ceil(index * 5 / 8); const remainder = index % 8; - if (remainder === 0) { - call(viewSetUint8, dataView, [ - dataIndex, - u5s[index] << 3 | u5s[++index] >> 2, - ]); - } else if (remainder === 1) { - call(viewSetUint8, dataView, [ - dataIndex, - u5s[index] << 6 | u5s[++index] << 1 | u5s[++index] >> 4, - ]); - } else if (remainder === 3) { - call(viewSetUint8, dataView, [ - dataIndex, - u5s[index] << 4 | u5s[++index] >> 1, - ]); - } else if (remainder === 4) { - call(viewSetUint8, dataView, [ - dataIndex, - u5s[index] << 7 | u5s[++index] << 2 | u5s[++index] >> 3, - ]); - } else { // remainder === 6 - call(viewSetUint8, dataView, [ - dataIndex, - u5s[index] << 5 | u5s[++index, index++], - ]); - } + call(viewSetUint8, dataView, [ + dataIndex, + remainder === 0 + ? u5s[index] << 3 | u5s[++index] >> 2 + : remainder === 1 + ? u5s[index] << 6 | u5s[++index] << 1 | u5s[++index] >> 4 + : remainder === 3 + ? u5s[index] << 4 | u5s[++index] >> 1 + : remainder === 4 + ? u5s[index] << 7 | u5s[++index] << 2 | u5s[++index] >> 3 + : u5s[index] << 5 | u5s[++index, index++], // remainder === 6 + ]); } return call(getViewBuffer, dataView, []); } @@ -303,10 +300,13 @@ const decodeBase64 = (source, safe = false) => { ? 63 : -1; if (result < 0) { + // The source contains an invalid character. throw new RangeError( `Piscēs: Invalid character in Base64: ${ucsCharacter}.`, ); } else { + // The source contains a valid character with a recognized + // mapping. return result; } }, @@ -322,27 +322,22 @@ const decodeBase64 = (source, safe = false) => { // Every letter contributes at least some bits to the result. const dataView = new View(new Buffer(floor(length * 3 / 4))); for (let index = 0; index < length - 1;) { + // Iterate over the characters and assign their bits to the + // buffer. + // // The final index is not handled; if the string is not divisible // by 4, some bits might be dropped. This matches the “forgiving // decode” behaviour specified by WhatW·G for base64. const dataIndex = ceil(index * 3 / 4); const remainder = index % 4; - if (remainder === 0) { - call(viewSetUint8, dataView, [ - dataIndex, - u6s[index] << 2 | u6s[++index] >> 4, - ]); - } else if (remainder === 1) { - call(viewSetUint8, dataView, [ - dataIndex, - u6s[index] << 4 | u6s[++index] >> 2, - ]); - } else { // remainder === 2 - call(viewSetUint8, dataView, [ - dataIndex, - u6s[index] << 6 | u6s[++index, index++], - ]); - } + call(viewSetUint8, dataView, [ + dataIndex, + remainder === 0 + ? u6s[index] << 2 | u6s[++index] >> 4 + : remainder === 1 + ? u6s[index] << 4 | u6s[++index] >> 2 + : u6s[index] << 6 | u6s[++index, index++], // remainder === 2 + ]); } return call(getViewBuffer, dataView, []); } @@ -366,17 +361,23 @@ const encodeBase16 = (buffer) => { 0x3D, ); for (let index = 0; index < byteLength;) { + // Iterate over the bytes and generate code units for them. const codeUnitIndex = index * 2; const datum = call(viewGetUint8, dataView, [index++]); const u4s = [datum >> 4, datum & 0xF]; for (let u4i = 0; u4i < 2; ++u4i) { + // Handle the high four bits, then the low four bits. const u4 = u4s[u4i]; const result = u4 < 10 ? u4 + 48 : u4 < 16 ? u4 + 55 : -1; if (result < 0) { + // No mapping exists for these four bits. + // + // ※ This shouldn’t be possible! throw new RangeError( `Piscēs: Unexpected Base16 value: ${u4}.`, ); } else { + // A mapping exists for the bits. resultingCodeUnits[codeUnitIndex + u4i] = result; } } @@ -408,6 +409,7 @@ const encodeBase32 = (buffer, wrmg = false) => { fillByte, ); for (let index = 0; index < byteLength;) { + // Iterate over the bytes and generate code units for them. const codeUnitIndex = ceil(index * 8 / 5); const currentIndex = codeUnitIndex + +( 0b01011 & 1 << index % 5 && @@ -457,8 +459,12 @@ const encodeBase32 = (buffer, wrmg = false) => { ? u5 + 24 : -1; if (result < 0) { + // No mapping exists for these five bits. + // + // ※ This shouldn’t be possible! throw new RangeError(`Piscēs: Unexpected Base32 value: ${u5}.`); } else { + // A mapping exists for the bits. resultingCodeUnits[currentIndex] = result; } } @@ -489,6 +495,7 @@ const encodeBase64 = (buffer, safe = false) => { 0x3D, ); for (let index = 0; index < byteLength;) { + // Iterate over the bytes and generate code units for them. const codeUnitIndex = ceil(index * 4 / 3); const currentIndex = codeUnitIndex + +( index % 3 === 0 && resultingCodeUnits[codeUnitIndex] != 0x3D @@ -518,8 +525,12 @@ const encodeBase64 = (buffer, safe = false) => { ? (safe ? 0x5F : 0x2F) : -1; if (result < 0) { + // No mapping exists for these six bits. + // + // ※ This shouldn’t be possible! throw new RangeError(`Piscēs: Unexpected Base64 value: ${u6}.`); } else { + // A mapping exists for the bits. resultingCodeUnits[currentIndex] = result; } } @@ -651,8 +662,9 @@ export const isArrayBuffer = ($) => { return call(getBufferByteLength, $, []), true; } catch { // The provided argument does not have array buffer internal slots. - return false; + /* do nothing */ } + return false; }; /** @@ -663,8 +675,10 @@ export const isArrayBuffer = ($) => { */ export const isBase16 = ($) => { if (typeof $ !== "string") { + // The provided value is not a string. return false; } else { + // The provided value is a string. const source = stringReplace($, /[\t\n\f\r ]+/gu, ""); return source.length % 2 !== 1 && call(reExec, /[^0-9A-F]/iu, [source]) === null; @@ -679,8 +693,10 @@ export const isBase16 = ($) => { */ export const isBase32 = ($) => { if (typeof $ !== "string") { + // The provided value is not a string. return false; } else { + // The provided value is a string. const source = stringReplace($, /[\t\n\f\r ]+/gu, ""); const trimmed = source.length % 8 === 0 ? stringReplace(source, /(?:=|={3,4}|={6})$/u, "") @@ -698,8 +714,10 @@ export const isBase32 = ($) => { */ export const isBase64 = ($) => { if (typeof $ !== "string") { + // The provided value is not a string. return false; } else { + // The provided value is a string. const source = stringReplace($, /[\t\n\f\r ]+/gu, ""); const trimmed = source.length % 4 === 0 ? stringReplace(source, /={1,2}$/u, "") @@ -729,8 +747,10 @@ export const isDataView = ($) => { */ export const isFilenameSafeBase64 = ($) => { if (typeof $ !== "string") { + // The provided value is not a string. return false; } else { + // The provided value is a string. const source = stringReplace($, /[\t\n\f\r ]+/gu, ""); const trimmed = source.length % 4 === 0 ? stringReplace(source, /={1,2}$/u, "") @@ -761,8 +781,10 @@ export const isTypedArray = ($) => { */ export const isWRMGBase32 = ($) => { if (typeof $ !== "string") { + // The provided value is not a string. return false; } else { + // The provided value is a string. const source = stringReplace($, /[\t\n\f\r ]+/gu, ""); const trimmed = stringReplace(source, /-/gu, ""); return trimmed.length % 8 !== 1 && @@ -777,19 +799,25 @@ export const isWRMGBase32 = ($) => { * typed array. */ export const toArrayBuffer = ($) => { - try { + if (isArrayBuffer($)) { // The provided argument has array buffer internal slots. - return call(getBufferByteLength, $, []), $; - } catch {} - try { - // The provided argument has typed array internal slots. - return call(getTypedArrayBuffer, $, []); - } catch {} - try { - // The provided argument has data view internal slots. - return call(getViewBuffer, $, []); - } catch {} - throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`); + return $; + } else { + // The provided argument does not have array buffer internal slots. + try { + // The provided argument has typed array internal slots. + return call(getTypedArrayBuffer, $, []); + } catch { + /* do nothing */ + } + try { + // The provided argument has data view internal slots. + return call(getViewBuffer, $, []); + } catch { + /* do nothing */ + } + throw new TypeError(`Piscēs: Not an array buffer or view: ${$}.`); + } }; /**