Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(*): Add support for ArrayBuffer #2

Merged
merged 1 commit into from
May 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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