Skip to content

Commit

Permalink
feat: Accept Uint8Array where previously only Buffer worked
Browse files Browse the repository at this point in the history
  • Loading branch information
motiz88 committed Jun 12, 2016
1 parent 46c880b commit e627109
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 10 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
"sinon-chai": "^2.8.0"
},
"dependencies": {
"babel-runtime": "^6.9.2"
"babel-runtime": "^6.9.2",
"safe-buffer": "^5.0.1"
},
"release": {
"verifyRelease": {
Expand Down
14 changes: 8 additions & 6 deletions src/format.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import rolandChecksum from './rolandChecksum';
import isBufferEquivalent from './utils/isBufferEquivalent';
import asBuffer from './utils/asBuffer';

function requiredSize (message) {
if (Buffer.isBuffer(message)) return message.length;
if (isBufferEquivalent(message)) return message.byteLength || message.length;
if (typeof message === 'number') return 1; // make it simple
if (!message) return 0;
switch (message.type) {
Expand Down Expand Up @@ -35,15 +37,15 @@ export default function format (message) {
if (Array.isArray(message)) {
return Buffer.concat(message.map(format));
}
if (Buffer.isBuffer(message)) return message;
if (isBufferEquivalent(message)) return asBuffer(message);
if (!message || typeof message !== 'object') throw new Error('Message must be an Object or a Buffer');
const size = requiredSize(message);
const buf = new Buffer(size);
buf.fill(0);
let i = 0;
const write = data => {
if (Buffer.isBuffer(data)) {
i += data.copy(buf, i);
if (isBufferEquivalent(data)) {
if (data.byteLength || data.length) i += asBuffer(data).copy(buf, i);
} else {
buf[i++] = data;
}
Expand All @@ -52,13 +54,13 @@ export default function format (message) {
case 'sysex':
write(0xF0);
if (message.data) {
if (Buffer.isBuffer(message.data)) {
if (isBufferEquivalent(message.data)) {
write(message.data);
} else if (message.data.vendor === 'Roland') {
write(0x41);
write(message.data.deviceId);
write(message.data.modelId);
if (Buffer.isBuffer(message.data.command)) {
if (isBufferEquivalent(message.data.command)) {
write(message.data.command);
} else {
switch (message.data.command.type) {
Expand Down
8 changes: 5 additions & 3 deletions src/parse.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import rolandHexParser from './peg/roland';
import assert from 'assert';
import isBufferEquivalent from './utils/isBufferEquivalent';
import asBuffer from './utils/asBuffer';

/**
* @param {Buffer} buf A buffer containing MIDI messages.
* @param {Buffer|Uint8Array} buf A buffer containing MIDI messages.
* @returns {Array<MIDIMessage>} - Contains SysEx messages parsed from the buffer.
*/
export default function parse (buf) {
assert(Buffer.isBuffer(buf), 'Argument should be a Buffer');
return rolandHexParser.parse(buf.toString('hex'));
assert(isBufferEquivalent(buf), 'buf must be a Buffer or Uint8Array');
return rolandHexParser.parse(asBuffer(buf).toString('hex'));
}
15 changes: 15 additions & 0 deletions src/utils/asBuffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import SafeBuffer from 'safe-buffer';

/**
* @private
* Ensure that {@link buf} is a @{link Buffer}
* @param {Buffer|TypedArray|ArrayBuffer} buf A buffer or typed array.
* @returns {Buffer}
*/
export default function asBuffer (buf) {
if (Buffer.isBuffer(buf)) return buf;
if (buf.buffer instanceof ArrayBuffer) {
return SafeBuffer.Buffer.from(buf.buffer);
}
return SafeBuffer.Buffer.from(buf);
}
9 changes: 9 additions & 0 deletions src/utils/isBufferEquivalent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @private
* Check that {@link buf} is a {@link Buffer} equivalent (e.g. a typed array)
* @param buf
* @returns {boolean}
*/
export default function isBufferEquivalent (buf) {
return Buffer.isBuffer(buf) || (buf.buffer instanceof ArrayBuffer) || (buf instanceof ArrayBuffer);
}
16 changes: 16 additions & 0 deletions test/specs/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,20 @@ describe('format()', () => {
}
}).should.deep.equal(hex `F0 41 10 6A 12 00 00 00 01 7F F7`);
});
it('should accept Uint8Array for embedded data as well as Buffer', () => {
format({
type: 'sysex',
data: {
vendor: 'Roland',
deviceId: 0x10,
modelId: 0x6A,
command: {
type: 'DT1',
address: 0x00000001,
body: new Uint8Array([]),
checksum: 0x7f
}
}
}).should.deep.equal(hex `F0 41 10 6A 12 00 00 00 01 7F F7`);
});
});
17 changes: 17 additions & 0 deletions test/specs/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,21 @@ describe('parse()', () => {
(() => parse(hex `F0 41 10 6A 12 00 00 00 01 11 F7`)).should.throw(/checksum/i);
(() => parse(hex `F0 41 10 6A 11 01 02 03 04 00 00 00 00 12 F7`)).should.throw(/checksum/i);
});
it('should parse DT1 from Uint8Array', () => {
parse(new Uint8Array([0xF0, 0x41, 0x10, 0x6A, 0x12, 0x00, 0x00, 0x00, 0x01, 0x7F, 0xF7]))
.should.deep.equal([{
type: 'sysex',
data: {
vendor: 'Roland',
deviceId: 0x10,
modelId: 0x6A,
command: {
type: 'DT1',
address: 0x000000001,
body: new Buffer([]),
checksum: 0x7f
}
}
}]);
});
});

0 comments on commit e627109

Please sign in to comment.