diff --git a/extensions/essentials/src/binary-slice.ts b/extensions/essentials/src/binary-slice.ts index dbf8048..bee1f89 100644 --- a/extensions/essentials/src/binary-slice.ts +++ b/extensions/essentials/src/binary-slice.ts @@ -68,7 +68,7 @@ const execute: OperationExecuteExport = (request) => { // Transform the array of bytes to an array of bits and slice them // precisely to create the bit slice - const bitSlice = transformUnitSize(byteSlice, 8, 1).slice( + const bitSlice = transformUnitSize(byteSlice, 8, 1, true).slice( bitSliceArgs.start - byteSliceStart * 8, bitSliceArgs.end - byteSliceStart * 8 ) @@ -76,7 +76,7 @@ const execute: OperationExecuteExport = (request) => { // Fill up the first byte with zero bits and turn the bits back into bytes const paddingBits = bitSlice.length % 8 > 0 ? 8 - bitSlice.length % 8 : 0 const sliceBitsPadded = new Array(paddingBits).fill(0).concat(bitSlice) - const sliceBytes = transformUnitSize(sliceBitsPadded, 1, 8) + const sliceBytes = transformUnitSize(sliceBitsPadded, 8, 1, false) slice = new Uint8Array(sliceBytes).buffer break } diff --git a/extensions/essentials/src/binary-to-text.ts b/extensions/essentials/src/binary-to-text.ts index a80ee86..2e54987 100644 --- a/extensions/essentials/src/binary-to-text.ts +++ b/extensions/essentials/src/binary-to-text.ts @@ -149,7 +149,7 @@ const execute: OperationExecuteExport = (request) => { )) // Transform unit size (encode) - const encodedUnits = transformUnitSize(units, inUnitSize, outUnitSize) + const encodedUnits = transformUnitSize(units, inUnitSize, outUnitSize, true) const encodedCodePoints = encodedUnits.map(unit => alphabet[unit]) // Apply padding @@ -195,7 +195,7 @@ const execute: OperationExecuteExport = (request) => { encodedUnits = encodedUnits.slice(0, j) // Transform unit size (decode) - const units = transformUnitSize(encodedUnits, outUnitSize, inUnitSize) + const units = transformUnitSize(encodedUnits, inUnitSize, outUnitSize, false) const buffer = Uint8Array.from(units).buffer // Add an issue if foreign characters were encountered diff --git a/extensions/essentials/src/lib/binary.ts b/extensions/essentials/src/lib/binary.ts index f0b92d4..212b0c5 100644 --- a/extensions/essentials/src/lib/binary.ts +++ b/extensions/essentials/src/lib/binary.ts @@ -75,7 +75,8 @@ export const isBigEndianEnvironment = (): boolean => export const transformUnitSize = ( inputUnits: number[], inUnitSize: number, - outUnitSize: number + outUnitSize: number, + forward: boolean ): number[] => { if (inUnitSize === outUnitSize) { return inputUnits @@ -84,11 +85,18 @@ export const transformUnitSize = ( return [] } + // Some bits may not hold any information when decoding, see issue #40 + if (!forward) { + [inUnitSize, outUnitSize] = [outUnitSize, inUnitSize] + } + const commonSize = lcm(inUnitSize, outUnitSize) const inUnits = commonSize / inUnitSize const outUnits = commonSize / outUnitSize - const outputUnitsLength = Math.ceil((outUnits * inputUnits.length) / inUnits) + const outputUnitsLength = forward + ? Math.ceil((outUnits * inputUnits.length) / inUnits) + : Math.floor((outUnits * inputUnits.length) / inUnits) const outputUnits = new Array(outputUnitsLength) let remainingInBits, inUnit, moveBits @@ -104,6 +112,12 @@ export const transformUnitSize = ( // If the current out unit is full, move to the next one if (remainingOutBits === 0) { outputUnits[o++] = outUnit + // If the remaining input bits contain no information, don't add a null unit (only occurs when decoding) + // TODO: This works, but I, anderium, don't like that this `if` executes on each iteration. + if (o === outputUnitsLength) { + o-- + break + } outUnit = 0 remainingOutBits = outUnitSize }