From 7a07f5d8154c831f53bee6e0407749af0e534a02 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Thu, 10 Oct 2024 16:45:25 -0500 Subject: [PATCH] remove node Buffer usage from src --- packages/osc/src/bundle.ts | 29 +++++++++--- packages/osc/src/message.ts | 22 +++++++-- packages/osc/src/models.ts | 6 +-- packages/osc/src/osc-types.ts | 58 +++++++++++++++-------- packages/osc/tests/message-decode.test.js | 2 +- packages/osc/tests/message-encode.test.js | 2 +- 6 files changed, 84 insertions(+), 35 deletions(-) diff --git a/packages/osc/src/bundle.ts b/packages/osc/src/bundle.ts index d1fc671..6d4dac7 100644 --- a/packages/osc/src/bundle.ts +++ b/packages/osc/src/bundle.ts @@ -2,12 +2,12 @@ import { messageFromBuffer, messageToBuffer } from './message'; import { OSCBundle } from './models'; import { oscTypeConverterMap } from './osc-types'; -export function bundleFromBuffer(bytes: Buffer): OSCBundle | undefined { +export function bundleFromBuffer(bytes: Uint8Array): OSCBundle | undefined { if (bytes.length < 8) { throw new Error('bundle has to be at least 20 bytes'); } - if (bytes.subarray(0, 7).toString('ascii') !== '#bundle') { + if (new TextDecoder().decode(bytes.subarray(0, 7)) !== '#bundle') { throw new Error('bundle must start with #bundle'); } @@ -59,7 +59,7 @@ export function bundleFromBuffer(bytes: Buffer): OSCBundle | undefined { }; } -export function bundleToBuffer(bundle: OSCBundle): Buffer { +export function bundleToBuffer(bundle: OSCBundle): Uint8Array { const headerBuffer = oscTypeConverterMap.s.toBuffer('#bundle'); if (headerBuffer === undefined) { @@ -72,7 +72,9 @@ export function bundleToBuffer(bundle: OSCBundle): Buffer { throw new Error('problem encoding buffer time tag'); } - const contentsBuffers: Buffer[] = []; + const contentsBuffers: Uint8Array[] = []; + + let contentsBuffersTotalLength = 0; bundle.contents.forEach((bundleContent) => { if ('address' in bundleContent) { @@ -80,10 +82,25 @@ export function bundleToBuffer(bundle: OSCBundle): Buffer { const contentSizeBuffer = oscTypeConverterMap.i.toBuffer(contentBuffer.length); if (contentBuffer && contentSizeBuffer) { - contentsBuffers.push(Buffer.concat([contentSizeBuffer, contentBuffer])); + const buffer = new Uint8Array(contentSizeBuffer.length + contentBuffer.length) + buffer.set(contentSizeBuffer, 0); + buffer.set(contentBuffer, contentSizeBuffer.length) + contentsBuffers.push(buffer); + contentsBuffersTotalLength += buffer.length } } }); - return Buffer.concat([headerBuffer, timeTagBuffer, ...contentsBuffers]); + const buffer = new Uint8Array(headerBuffer.length + timeTagBuffer.length + contentsBuffersTotalLength) + let offset = 0 + buffer.set(headerBuffer, offset) + offset += headerBuffer.length + buffer.set(timeTagBuffer, offset) + offset += timeTagBuffer.length + contentsBuffers.forEach((contentBuffer)=>{ + buffer.set(contentBuffer, offset) + offset += contentBuffer.length + }) + + return buffer; } diff --git a/packages/osc/src/message.ts b/packages/osc/src/message.ts index fe51eaf..57a6b58 100644 --- a/packages/osc/src/message.ts +++ b/packages/osc/src/message.ts @@ -2,7 +2,8 @@ import { OSCMessage, OSCArg, OSCType } from './models'; import { oscTypeConverterMap } from './osc-types'; function argsToBuffer(args: OSCArg[]) { - const argBuffers: Buffer[] = []; + const argBuffers: Uint8Array[] = []; + let argBuffersTotalLength = 0; for (let index = 0; index < args.length; index += 1) { const arg = args[index]; @@ -14,12 +15,19 @@ function argsToBuffer(args: OSCArg[]) { const buffer = typeConverter.toBuffer(arg.value); if (buffer !== undefined) { argBuffers.push(buffer); + argBuffersTotalLength += buffer.length; } } - return Buffer.concat(argBuffers); + const buffer = new Uint8Array(argBuffersTotalLength) + let offset = 0; + argBuffers.forEach((argBuffer)=>{ + buffer.set(argBuffer,offset) + offset += argBuffer.length + }) + return buffer; } -export function messageToBuffer(message: OSCMessage): Buffer { +export function messageToBuffer(message: OSCMessage): Uint8Array { const addressBuffer = oscTypeConverterMap.s.toBuffer(message.address); if (addressBuffer === undefined) { throw new Error('problem encoding address'); @@ -31,10 +39,14 @@ export function messageToBuffer(message: OSCMessage): Buffer { throw new Error('problem encoding types'); } const argsBuffer = argsToBuffer(message.args); - return Buffer.concat([addressBuffer, typesBuffer, argsBuffer]); + const buffer = new Uint8Array(addressBuffer.length + typesBuffer.length + argsBuffer.length); + buffer.set(addressBuffer, 0); + buffer.set(typesBuffer, addressBuffer.length); + buffer.set(argsBuffer, addressBuffer.length + typesBuffer.length); + return buffer; } -export function messageFromBuffer(bytes: Buffer): OSCMessage | undefined { +export function messageFromBuffer(bytes: Uint8Array): OSCMessage | undefined { if (bytes[0] !== 47) { throw new Error('osc message must start with a /'); } diff --git a/packages/osc/src/models.ts b/packages/osc/src/models.ts index 41d90e7..169fdf4 100644 --- a/packages/osc/src/models.ts +++ b/packages/osc/src/models.ts @@ -1,7 +1,7 @@ export type OSCType = 's' | 'i' | 'f' | 'b' | 'T' | 'F' | 't'; export type OSCArg = { type: OSCType; - value: string | number | Buffer | boolean | OSCTimeTag; + value: string | number | Uint8Array | boolean | OSCTimeTag; }; export type OSCTimeTag = [number, number]; @@ -17,6 +17,6 @@ export type OSCMessage = { }; export type OSCTypeConverter = { - toBuffer: (value: string | number | Buffer | boolean | OSCTimeTag) => Buffer | undefined; - fromBuffer: (buffer: Buffer) => [string | number | Buffer | boolean | OSCTimeTag | undefined, Buffer]; + toBuffer: (value: string | number | Uint8Array | boolean | OSCTimeTag) => Uint8Array | undefined; + fromBuffer: (buffer: Uint8Array) => [string | number | Uint8Array | boolean | OSCTimeTag | undefined, Uint8Array]; }; diff --git a/packages/osc/src/osc-types.ts b/packages/osc/src/osc-types.ts index 6d51515..4a4d6c0 100644 --- a/packages/osc/src/osc-types.ts +++ b/packages/osc/src/osc-types.ts @@ -9,11 +9,11 @@ export const oscTypeConverterMap: { [key: string]: OSCTypeConverter } = { if (padSize < 4) { oscString = oscString.padEnd(oscString.length + padSize, '\u0000'); } - return Buffer.from(oscString, 'ascii'); + return new TextEncoder().encode(oscString); } throw new TypeError('osc type s toBuffer called with non string value'); }, - fromBuffer: (bytes: Buffer) => { + fromBuffer: (bytes) => { let stringEnd = 0; let stringPaddingEnd = 0; for (let index = 0; index < bytes.length; index++) { @@ -29,15 +29,15 @@ export const oscTypeConverterMap: { [key: string]: OSCTypeConverter } = { } } - return [bytes.toString('ascii', 0, stringEnd), bytes.subarray(stringPaddingEnd)]; + return [new TextDecoder().decode(bytes.subarray(0, stringEnd)), bytes.subarray(stringPaddingEnd)]; }, }, f: { toBuffer: (number) => { if (typeof number === 'number') { - const buffer = Buffer.alloc(4); - buffer.writeFloatBE(number); - return buffer; + const view = new DataView(new ArrayBuffer(4)); + view.setFloat32(0, number); + return new Uint8Array(view.buffer); } throw new TypeError('osc type f toBuffer called with non number value'); }, @@ -45,17 +45,22 @@ export const oscTypeConverterMap: { [key: string]: OSCTypeConverter } = { if (buffer.length < 4) { throw new Error('not enough bytes to read a osc float'); } + const view = new DataView(new ArrayBuffer(4)); - const value = buffer.readFloatBE(); + buffer.slice(0, 4).forEach((byte, index) => { + view.setUint8(index, byte); + }); + + const value = view.getFloat32(0); return [value, buffer.subarray(4)]; }, }, i: { toBuffer: (number) => { if (typeof number === 'number') { - const buffer = Buffer.alloc(4); - buffer.writeInt32BE(number); - return buffer; + const view = new DataView(new ArrayBuffer(4)); + view.setInt32(0, number); + return new Uint8Array(view.buffer); } throw new TypeError('osc type i toBuffer called with non number value'); }, @@ -64,21 +69,33 @@ export const oscTypeConverterMap: { [key: string]: OSCTypeConverter } = { throw new Error('not enough bytes to read a osc integer'); } - const value = buffer.readInt32BE(); + const view = new DataView(new ArrayBuffer(4)); + + buffer.slice(0, 4).forEach((byte, index) => { + view.setUint8(index, byte); + }); + + const value = view.getInt32(0); return [value, buffer.subarray(4)]; }, }, b: { toBuffer: (data) => { - if (Buffer.isBuffer(data)) { + if (data instanceof Uint8Array) { const sizeBuffer = oscTypeConverterMap.i.toBuffer(data.length); if (sizeBuffer) { - const padSize = 4 - (data.length % 4); - const padBuffer = padSize < 4 ? Buffer.from(Array(padSize).fill(0)) : Buffer.from([]); - return Buffer.concat([sizeBuffer, data, padBuffer]); + let padSize = 4 - (data.length % 4); + if (padSize === 4) { + padSize = 0; + } + + const buffer = new Uint8Array(4 + data.length + padSize); + buffer.set(sizeBuffer); + buffer.set(data, 4); + return buffer; } } - throw new TypeError('osc type b toBuffer called with non Buffer value'); + throw new TypeError('osc type b toBuffer called with non Uint8Array value'); }, fromBuffer: (buffer) => { const [blobLength, blobBytes] = oscTypeConverterMap.i.fromBuffer(buffer); @@ -97,7 +114,7 @@ export const oscTypeConverterMap: { [key: string]: OSCTypeConverter } = { }, T: { toBuffer: () => { - return Buffer.alloc(0); + return new Uint8Array(0); }, fromBuffer: (buffer) => { return [true, buffer]; @@ -105,7 +122,7 @@ export const oscTypeConverterMap: { [key: string]: OSCTypeConverter } = { }, F: { toBuffer: () => { - return Buffer.alloc(0); + return new Uint8Array(0); }, fromBuffer: (buffer) => { return [false, buffer]; @@ -135,7 +152,10 @@ export const oscTypeConverterMap: { [key: string]: OSCTypeConverter } = { const fractionalBuffer = oscTypeConverterMap.i.toBuffer(fractional); if (secondsBuffer && fractionalBuffer) { - return Buffer.concat([secondsBuffer, fractionalBuffer]); + const buffer = new Uint8Array(8); + buffer.set(secondsBuffer); + buffer.set(fractionalBuffer, 4); + return buffer; } }, fromBuffer: (buffer) => { diff --git a/packages/osc/tests/message-decode.test.js b/packages/osc/tests/message-decode.test.js index 2a85fd3..f7220d2 100644 --- a/packages/osc/tests/message-decode.test.js +++ b/packages/osc/tests/message-decode.test.js @@ -26,7 +26,7 @@ const tests = [ { description: 'simple address blob arg', bytes: Buffer.from('2f68656c6c6f00002c62000000000004626c6f62', 'hex'), - expected: { address: '/hello', args: [{ type: 'b', value: Buffer.from('blob') }] }, + expected: { address: '/hello', args: [{ type: 'b', value: new TextEncoder().encode('blob') }] }, }, { description: 'simple address True arg', diff --git a/packages/osc/tests/message-encode.test.js b/packages/osc/tests/message-encode.test.js index 70efb19..86f47c5 100644 --- a/packages/osc/tests/message-encode.test.js +++ b/packages/osc/tests/message-encode.test.js @@ -25,7 +25,7 @@ const tests = [ }, { description: 'simple address blob arg', - message: { address: '/hello', args: [{ type: 'b', value: Buffer.from('blob') }] }, + message: { address: '/hello', args: [{ type: 'b', value: new TextEncoder().encode('blob') }] }, expected: Buffer.from('2f68656c6c6f00002c62000000000004626c6f62', 'hex'), }, {