Skip to content

Commit

Permalink
refactor: move swapping to ByteUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
nbbeeken committed Nov 18, 2024
1 parent e8d6062 commit a0c63c1
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 29 deletions.
28 changes: 4 additions & 24 deletions src/binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,18 +364,9 @@ export class Binary extends BSONValue {
const floatBytes = new Uint8Array(
this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position)
);
if (NumberUtils.isBigEndian) {
for (let i = 0; i < floatBytes.byteLength; i += 4) {
const byte0 = floatBytes[i];
const byte1 = floatBytes[i + 1];
const byte2 = floatBytes[i + 2];
const byte3 = floatBytes[i + 3];
floatBytes[i] = byte3;
floatBytes[i + 1] = byte2;
floatBytes[i + 2] = byte1;
floatBytes[i + 3] = byte0;
}
}

if (NumberUtils.isBigEndian) ByteUtils.swap32(floatBytes);

return new Float32Array(floatBytes.buffer);
}

Expand Down Expand Up @@ -455,18 +446,7 @@ export class Binary extends BSONValue {
const floatBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
binaryBytes.set(floatBytes, 2);

if (NumberUtils.isBigEndian) {
for (let i = 2; i < binaryBytes.byteLength; i += 4) {
const byte0 = binaryBytes[i];
const byte1 = binaryBytes[i + 1];
const byte2 = binaryBytes[i + 2];
const byte3 = binaryBytes[i + 3];
binaryBytes[i] = byte3;
binaryBytes[i + 1] = byte2;
binaryBytes[i + 2] = byte1;
binaryBytes[i + 3] = byte0;
}
}
if (NumberUtils.isBigEndian) ByteUtils.swap32(new Uint8Array(binaryBytes.buffer, 2));

return new this(binaryBytes, this.SUBTYPE_VECTOR);
}
Expand Down
2 changes: 2 additions & 0 deletions src/utils/byte_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export type ByteUtils = {
encodeUTF8Into: (destination: Uint8Array, source: string, byteOffset: number) => number;
/** Generate a Uint8Array filled with random bytes with byteLength */
randomBytes: (byteLength: number) => Uint8Array;
/** Interprets `buffer` as an array of 32-bit values and swaps the byte order in-place. */
swap32: (buffer: Uint8Array) => Uint8Array;
};

declare const Buffer: { new (): unknown; prototype?: { _isBuffer?: boolean } } | undefined;
Expand Down
7 changes: 6 additions & 1 deletion src/utils/node_byte_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type NodeJsBuffer = ArrayBufferView &
copy(target: Uint8Array, targetStart: number, sourceStart: number, sourceEnd: number): number;
toString: (this: Uint8Array, encoding: NodeJsEncoding, start?: number, end?: number) => string;
equals: (this: Uint8Array, other: Uint8Array) => boolean;
swap32: (this: NodeJsBuffer) => NodeJsBuffer;
};
type NodeJsBufferConstructor = Omit<Uint8ArrayConstructor, 'from'> & {
alloc: (size: number) => NodeJsBuffer;
Expand Down Expand Up @@ -159,5 +160,9 @@ export const nodeJsByteUtils = {
return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
},

randomBytes: nodejsRandomBytes
randomBytes: nodejsRandomBytes,

swap32(buffer: Uint8Array): NodeJsBuffer {
return nodeJsByteUtils.toLocalBufferType(buffer).swap32();
}
};
21 changes: 20 additions & 1 deletion src/utils/web_byte_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,5 +193,24 @@ export const webByteUtils = {
return bytes.byteLength;
},

randomBytes: webRandomBytes
randomBytes: webRandomBytes,

swap32(buffer: Uint8Array): Uint8Array {
if (buffer.length % 4 !== 0) {
throw new RangeError('Buffer size must be a multiple of 32-bits');
}

for (let i = 0; i < buffer.length; i += 4) {
const byte0 = buffer[i];
const byte1 = buffer[i + 1];
const byte2 = buffer[i + 2];
const byte3 = buffer[i + 3];
buffer[i] = byte3;
buffer[i + 1] = byte2;
buffer[i + 2] = byte1;
buffer[i + 3] = byte0;
}

return buffer;
}
};
27 changes: 24 additions & 3 deletions test/node/byte_utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { utf8WebPlatformSpecTests } from './data/utf8_wpt_error_cases';

type ByteUtilTest<K extends keyof ByteUtils> = {
name: string;
inputs: Parameters<ByteUtils[K]>;
inputs: Parameters<ByteUtils[K]> | (() => Parameters<ByteUtils[K]>);
expectation: (result: {
web: boolean;
output: ReturnType<ByteUtils[K]> | null;
Expand Down Expand Up @@ -500,6 +500,23 @@ const randomBytesTests: ByteUtilTest<'randomBytes'>[] = [
}
}
];
const swap32Tests: ByteUtilTest<'swap32'>[] = [
{
name: 'swaps byte order in-place',
inputs: () => [Buffer.from([1, 2, 3, 4, 5, 6, 7, 8])],
expectation({ output, error }) {
expect(error).to.be.null;
expect(output).to.deep.equal(Buffer.from([4, 3, 2, 1, 8, 7, 6, 5]));
}
},
{
name: 'throws if buffer is not a multiple of 4 bytes',
inputs: [Buffer.from([1, 2, 3])],
expectation({ error }) {
expect(error).to.be.instanceOf(RangeError);
}
}
];

const utils = new Map([
['nodeJsByteUtils', nodeJsByteUtils],
Expand All @@ -520,7 +537,8 @@ const table = new Map<keyof ByteUtils, ByteUtilTest<keyof ByteUtils>[]>([
['encodeUTF8Into', fromUTF8Tests],
['toUTF8', toUTF8Tests],
['utf8ByteLength', utf8ByteLengthTests],
['randomBytes', randomBytesTests]
['randomBytes', randomBytesTests],
['swap32', swap32Tests]
]);

describe('ByteUtils', () => {
Expand Down Expand Up @@ -790,7 +808,10 @@ describe('ByteUtils', () => {
let error = null;

try {
output = byteUtils[utility].call(null, ...test.inputs);
output = byteUtils[utility].call(
null,
...(typeof test.inputs === 'function' ? test.inputs() : test.inputs)
);
} catch (thrownError) {
error = thrownError;
}
Expand Down

0 comments on commit a0c63c1

Please sign in to comment.