Skip to content

Commit

Permalink
feat(*): Add support for ArrayBuffer (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
darrachequesne authored May 16, 2017
1 parent 8d7ce87 commit 9eec8dc
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 6 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
language: node_js
sudo: false
node_js:
- "0.10"
- "0.12"
- "4"
- "6"
- "node"
script: "npm run-script test-travis"
after_script: "npm install coveralls && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls"
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ A fast [Node.js](http://nodejs.org) implementation of the latest [MessagePack](h
* This implementation is not backwards compatible with those that use the older spec. It is recommended that this library is only used in isolated systems.
* `undefined` is encoded as `fixext 1 [0, 0]`, i.e. `<Buffer d4 00 00>`
* `Date` objects are encoded as `fixext 8 [0, ms]`, e.g. `new Date('2000-06-13T00:00:00.000Z')` => `<Buffer d7 00 00 00 00 df b7 62 9c 00>`
* `ArrayBuffer` are encoded as `ext 8/16/32 [0, data]`, e.g. `Uint8Array.of(1, 2, 3, 4)` => `<Buffer c7 04 00 01 02 03 04>`

## Install

Expand Down
19 changes: 19 additions & 0 deletions lib/decode.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ Decoder.prototype.bin = function (length) {
return value;
};

Decoder.prototype.arraybuffer = function (length) {
var buffer = new ArrayBuffer(length);
var view = new Uint8Array(buffer);
for (var j = 0; j < length; j++) {
view[j] = this.buffer[this.offset + j];
}
this.offset += length;
return buffer;
};

Decoder.prototype.parse = function () {
var prefix = this.buffer[this.offset++];
var value, length = 0, type = 0, hi = 0, lo = 0;
Expand Down Expand Up @@ -90,16 +100,25 @@ Decoder.prototype.parse = function () {
length = this.buffer.readUInt8(this.offset);
type = this.buffer.readInt8(this.offset + 1);
this.offset += 2;
if (type === 0) { // ArrayBuffer
return this.arraybuffer(length);
}
return [type, this.bin(length)];
case 0xc8:
length = this.buffer.readUInt16BE(this.offset);
type = this.buffer.readInt8(this.offset + 2);
this.offset += 3;
if (type === 0) { // ArrayBuffer
return this.arraybuffer(length);
}
return [type, this.bin(length)];
case 0xc9:
length = this.buffer.readUInt32BE(this.offset);
type = this.buffer.readInt8(this.offset + 4);
this.offset += 5;
if (type === 0) { // ArrayBuffer
return this.arraybuffer(length);
}
return [type, this.bin(length)];

// float
Expand Down
30 changes: 30 additions & 0 deletions lib/encode.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,31 @@ function _encode(bytes, defers, value) {
return size + length;
}

if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {
var arraybuffer = value.buffer || value;
length = arraybuffer.byteLength;

// ext 8
if (length < 0x100) {
bytes.push(0xc7, length, 0);
size = 3;
} else
// ext 16
if (length < 0x10000) {
bytes.push(0xc8, length >> 8, length, 0);
size = 4;
} else
// ext 32
if (length < 0x100000000) {
bytes.push(0xc9, length >> 24, length >> 16, length >> 8, length, 0);
size = 6;
} else {
throw new Error('ArrayBuffer too large');
}
defers.push({ arraybuffer: arraybuffer, length: length, offset: bytes.length });
return size + length;
}

var keys = [], key = '';

var allKeys = Object.keys(value);
Expand Down Expand Up @@ -312,6 +337,11 @@ function encode(value) {
}
} else if (defer.float) {
buf.writeDoubleBE(defer.float, offset);
} else if (defer.arraybuffer) {
var arr = new Uint8Array(defer.arraybuffer);
for (var k = 0; k < deferLength; k++) {
buf[offset + k] = arr[k];
}
}
deferIndex++;
deferWritten += deferLength;
Expand Down
12 changes: 8 additions & 4 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,23 @@ describe('notepack', function () {
check(new Buffer('a'.repeat(65536)), 'c6' + '00010000' + '61'.repeat(65536));
});

// ext 8, ext 16, ext 32
// There is currently no way to encode extension types

it('ext 8', function () {
checkDecode([127, new Buffer('hello')], 'c7' + '05' + '7f' + '68656c6c6f');
check(Uint8Array.of(1, 2, 3, 4).buffer, 'c7' + '04' + '00' + '01020304');
});

it('ext 16', function () {
checkDecode([0, new Buffer('a'.repeat(256))], 'c8' + '0100' + '00' + '61'.repeat(256));
checkDecode([1, new Buffer('a'.repeat(256))], 'c8' + '0100' + '01' + '61'.repeat(256));
var array = new Uint8Array(256);
array.fill(8);
check(array.buffer, 'c8' + '0100' + '00' + '08'.repeat(256));
});

it('ext 32', function () {
checkDecode([-128, new Buffer('a'.repeat(65536))], 'c9' + '00010000' + '80' + '61'.repeat(65536));
var array = new Uint8Array(65536);
array.fill(9);
check(array.buffer, 'c9' + '00010000' + '00' + '09'.repeat(65536));
});

// float 32
Expand Down

0 comments on commit 9eec8dc

Please sign in to comment.