From b99572d378744897ebe7949a8b8fde7391b90f53 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Tue, 22 Dec 2015 19:39:29 -0600 Subject: [PATCH 01/10] package.json: update for next development cycle --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5bf6dc..e1f2b13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## [Unreleased] + + ## [0.9.0] - 2015-12-22 * **API** Support inferring [Sequence][doc:Sequence.count] and @@ -73,6 +76,7 @@ * Initial release. +[Unreleased]: https://github.com/pabigot/buffer-layout/compare/v0.9.0...next [0.9.0]: https://github.com/pabigot/buffer-layout/compare/v0.8.0...v0.9.0 [0.8.0]: https://github.com/pabigot/buffer-layout/compare/v0.7.0...v0.8.0 [0.7.1]: https://github.com/pabigot/buffer-layout/compare/v0.7.0...v0.7.1 diff --git a/package.json b/package.json index d985ac1..448fbdc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "buffer-layout", - "version": "0.9.0", + "version": "0.10.0-dev", "description": "Translation between JavaScript values and Buffers", "keywords": [ "Buffer", From c0a2211a2d31505355b8f200c7ed9ea5d303fb3c Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 27 Dec 2015 13:53:51 -0600 Subject: [PATCH 02/10] package.json: change name of jsdoc rule --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 448fbdc..6b7f414 100644 --- a/package.json +++ b/package.json @@ -34,10 +34,10 @@ "coverage": "istanbul cover _mocha -- -u tdd", "coveralls": "istanbul cover _mocha --report lcovonly -- -u tdd && cat ./coverage/lcov.info | coveralls", "jscs": "jscs lib/ test/", + "jsdoc": "jsdoc -c jsdoc/conf.json", "jslint": "jslint lib/Layout.js || true", "lint": "jshint lib/*.js test/*.js || true", "lint.strict": "jshint lib/Layout.js", - "mkdoc": "jsdoc -c jsdoc/conf.json", "test": "mocha -u tdd" }, "jshintConfig": { From 6ac1f7d9a555e01aeb4a9b86139a157d9a494484 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 16 Jan 2016 09:35:23 -0600 Subject: [PATCH 03/10] package.json: update modules --- package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 6b7f414..f55dd02 100644 --- a/package.json +++ b/package.json @@ -18,14 +18,14 @@ "author": "Peter A. Bigot ", "main": "./lib/Layout.js", "devDependencies": { - "coveralls": "~2.11.4", - "istanbul": "~0.4.0", - "jscs": "~2.7.0", - "jsdoc": "~3.3.3", - "jshint": "^2.8.0", - "jslint": "~0.9.3", - "lodash": "~3.9.3", - "mocha": "~2.2.5" + "coveralls": "~2.11.6", + "istanbul": "~0.4.2", + "jscs": "~2.8.0", + "jsdoc": "~3.4.0", + "jshint": "^2.9.1", + "jslint": "~0.9.6", + "lodash": "~4.0.0", + "mocha": "~2.3.4" }, "engines": { "node": ">=0.12" From a6c9620592a9b5fc27775fb9847300e921d0414b Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 23 Jan 2016 07:42:32 -0600 Subject: [PATCH 04/10] Layout: correct test for CString encode parameter type --- lib/Layout.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Layout.js b/lib/Layout.js index 93e8c15..f70c96b 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -2080,7 +2080,7 @@ CString.prototype.encode = function(src, b, offset) { /* Must force this to a string, lest it be a number and the * "utf8-encoding" below actually allocate a buffer of length * src */ - if (!(src instanceof String)) { + if ('string' !== typeof src) { src = src.toString(); } var srcb = new Buffer(src, 'utf8'); From 9817275dbde9b3d623dc762f529002446fd82c29 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 23 Jan 2016 08:17:10 -0600 Subject: [PATCH 05/10] LayoutTest: total coverage of library Mostly missed handling of encode/decode offsets, rarely used factory functions, and variable-length structures. --- test/LayoutTest.js | 181 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 2 deletions(-) diff --git a/test/LayoutTest.js b/test/LayoutTest.js index a6b8510..bf36660 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -83,6 +83,13 @@ suite('Layout', function() { assert.equal(Buffer('3412', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x1234); }); + test('u24', function() { + var d = lo.u24('t'); + var b = new Buffer(3); + assert.equal(d.span, 3); + assert.equal(0x563412, d.decode(Buffer('123456', 'hex'))); + assert.throws(function() { d.encode(0x1234567, b); }); + }); test('u48', function() { var d = lo.u48('t'); var b = new Buffer(6); @@ -97,6 +104,14 @@ suite('Layout', function() { assert.equal(Buffer('bc9a78563412', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x123456789abc); }); + test('offset', function() { + var b = new Buffer(4); + b.fill(0xa5); + var d = lo.u16('t'); + d.encode(0x3412, b, 1); + assert.equal(Buffer('A51234A5', 'hex').compare(b), 0); + assert.equal(0xA534, d.decode(b, 2)); + }); test('invalid ctor', function() { assert.throws(function() { new lo.UInt(8); }, TypeError); }); @@ -115,6 +130,30 @@ suite('Layout', function() { assert.equal(Buffer('1234', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x1234); }); + test('u24be', function() { + var d = lo.u24be('t'); + var b = new Buffer(3); + assert.equal(d.span, 3); + assert.equal(0x123456, d.decode(Buffer('123456', 'hex'))); + assert.throws(function() { d.encode(0x1234567, b); }); + assert.throws(function() { d.encode(-1, b); }); + }); + test('u32be', function() { + var d = lo.u32be('t'); + var b = new Buffer(4); + assert.equal(d.span, 4); + assert.equal(0x12345678, d.decode(Buffer('12345678', 'hex'))); + assert.throws(function() { d.encode(0x123456789, b); }); + assert.throws(function() { d.encode(-1, b); }); + }); + test('u40be', function() { + var d = lo.u40be('t'); + var b = new Buffer(5); + assert.equal(d.span, 5); + assert.equal(0x123456789a, d.decode(Buffer('123456789a', 'hex'))); + assert.throws(function() { d.encode(0x123456789ab, b); }); + assert.throws(function() { d.encode(-1, b); }); + }); test('u48be', function() { var d = lo.u48be('t'); var b = new Buffer(6); @@ -128,6 +167,14 @@ suite('Layout', function() { assert.equal(Buffer('123456789abc', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x123456789abc); }); + test('offset', function() { + var b = new Buffer(4); + b.fill(0xa5); + var d = lo.u16be('t'); + d.encode(0x1234, b, 1); + assert.equal(Buffer('A51234A5', 'hex').compare(b), 0); + assert.equal(0x34A5, d.decode(b, 2)); + }); test('invalid ctor', function() { assert.throws(function() { new lo.UIntBE(8); }, TypeError); }); @@ -168,6 +215,26 @@ suite('Layout', function() { assert.equal(lo.u16().decode(b), 0xcfc7); assert.equal(lo.u16be().decode(b), 0xc7cf); }); + test('s24', function() { + var d = lo.s24('t'); + var b = new Buffer(3); + assert.equal(d.span, 3); + assert.equal(0x563412, d.decode(Buffer('123456', 'hex'))); + assert.equal(-1, d.decode(Buffer('FFFFFF', 'hex'))); + assert.equal(-0x800000, d.decode(Buffer('000080', 'hex'))); + assert.throws(function() { d.encode(0x800000, b); }); + assert.throws(function() { d.encode(-0x800001, b); }); + }); + test('s40', function() { + var d = lo.s40('t'); + var b = new Buffer(5); + assert.equal(d.span, 5); + assert.equal(0x123456789a, d.decode(Buffer('9a78563412', 'hex'))); + assert.equal(-1, d.decode(Buffer('FFFFFFFFFF', 'hex'))); + assert.equal(-0x8000000000, d.decode(Buffer('0000000080', 'hex'))); + assert.throws(function() { d.encode(0x8000000000, b); }); + assert.throws(function() { d.encode(-0x8000000001, b); }); + }); test('s48', function() { var d = lo.s48('t'); var b = new Buffer(6); @@ -192,7 +259,7 @@ suite('Layout', function() { }); }); suite('IntBE', function() { - test('s16', function() { + test('s16be', function() { var d = lo.s16be('t'); var b = new Buffer(2); assert(d instanceof lo.IntBE); @@ -211,7 +278,37 @@ suite('Layout', function() { assert.equal(lo.u16be().decode(b), 0xcfc7); assert.equal(lo.u16().decode(b), 0xc7cf); }); - test('s48', function() { + test('s24be', function() { + var d = lo.s24be('t'); + var b = new Buffer(3); + assert.equal(d.span, 3); + assert.equal(0x123456, d.decode(Buffer('123456', 'hex'))); + assert.equal(-1, d.decode(Buffer('FFFFFF', 'hex'))); + assert.equal(-0x800000, d.decode(Buffer('800000', 'hex'))); + assert.throws(function() { d.encode(0x800000, b); }); + assert.throws(function() { d.encode(-0x800001, b); }); + }); + test('s32be', function() { + var d = lo.s32be('t'); + var b = new Buffer(4); + assert.equal(d.span, 4); + assert.equal(0x12345678, d.decode(Buffer('12345678', 'hex'))); + assert.equal(-1, d.decode(Buffer('FFFFFFFF', 'hex'))); + assert.equal(-0x80000000, d.decode(Buffer('80000000', 'hex'))); + assert.throws(function() { d.encode(0x80000000, b); }); + assert.throws(function() { d.encode(-0x80000001, b); }); + }); + test('s40be', function() { + var d = lo.s40be('t'); + var b = new Buffer(5); + assert.equal(d.span, 5); + assert.equal(0x123456789a, d.decode(Buffer('123456789a', 'hex'))); + assert.equal(-1, d.decode(Buffer('FFFFFFFFFF', 'hex'))); + assert.equal(-0x8000000000, d.decode(Buffer('8000000000', 'hex'))); + assert.throws(function() { d.encode(0x8000000000, b); }); + assert.throws(function() { d.encode(-0x8000000001, b); }); + }); + test('s48be', function() { var d = lo.s48be('t'); var b = new Buffer(6); assert(d instanceof lo.IntBE); @@ -294,6 +391,15 @@ suite('Layout', function() { assert.equal(be.decode(eb), ev); assert.equal(le.encode(v, eb), 8); assert.equal(le.decode(eb), ev); + + b = new Buffer(10); + b.fill(0xa5); + le.encode(1, b, 1); + assert.equal(Buffer('a50100000000000000a5', 'hex').compare(b), 0); + assert.equal(1, le.decode(b, 1)); + be.encode(1, b, 1); + assert.equal(Buffer('a50000000000000001a5', 'hex').compare(b), 0); + assert.equal(1, be.decode(b, 1)); }); test('RoundedInt64', function() { var be = lo.ns64be('be'); @@ -355,6 +461,15 @@ suite('Layout', function() { assert.equal(be.decode(eb), ev); assert.equal(le.encode(v, eb), 8); assert.equal(le.decode(eb), ev); + + b = new Buffer(10); + b.fill(0xa5); + le.encode(1, b, 1); + assert.equal(Buffer('a50100000000000000a5', 'hex').compare(b), 0); + assert.equal(1, le.decode(b, 1)); + be.encode(1, b, 1); + assert.equal(Buffer('a50000000000000001a5', 'hex').compare(b), 0); + assert.equal(1, be.decode(b, 1)); }); test('Float', function() { var be = lo.f32be('eff'); @@ -382,6 +497,15 @@ suite('Layout', function() { assert.equal(Buffer('47f12010', 'hex').compare(b), 0); assert.equal(be.decode(b), f); assert.equal(le.decode(b), fe); + + b = new Buffer(6); + b.fill(0xa5); + le.encode(f, b, 1); + assert.equal(Buffer('a51020f147a5', 'hex').compare(b), 0); + assert.equal(f, le.decode(b, 1)); + be.encode(f, b, 1); + assert.equal(Buffer('a547f12010a5', 'hex').compare(b), 0); + assert.equal(f, be.decode(b, 1)); }); test('Double', function() { var be = lo.f64be('dee'); @@ -408,6 +532,15 @@ suite('Layout', function() { assert.equal(Buffer('43b12210f4c10f30', 'hex').compare(b), 0); assert.equal(be.decode(b), f); assert.equal(le.decode(b), fe); + + b = new Buffer(10); + b.fill(0xa5); + le.encode(f, b, 1); + assert.equal(Buffer('a5300fc1f41022b143a5', 'hex').compare(b), 0); + assert.equal(f, le.decode(b, 1)); + be.encode(f, b, 1); + assert.equal(Buffer('a543b12210f4c10f30a5', 'hex').compare(b), 0); + assert.equal(f, be.decode(b, 1)); }); suite('Sequence', function() { test('invalid ctor', function() { @@ -607,6 +740,17 @@ suite('Layout', function() { assert.equal(st.span, 0); assert.deepEqual(st.decode(b), {}); }); + test('offset-variant', function() { + var st = lo.struct([lo.cstr('s')], 'st'); + assert(0 > st.span); + var b = new Buffer(5); + b.fill(0xa5); + var obj = {s: 'ab'}; + st.encode(obj, b, 1); + assert.equal(Buffer('a5616200a5', 'hex').compare(b), 0); + assert.equal(3, st.getSpan(b, 1)); + assert.deepEqual(st.decode(b, 1), obj); + }); }); suite('replicate', function() { test('uint', function() { @@ -784,6 +928,8 @@ suite('Layout', function() { test('invalid ctor', function() { assert.throws(function() { new lo.UnionLayoutDiscriminator('hi'); }, TypeError); + assert.throws(function() { lo.unionLayoutDiscriminator('hi'); }, + TypeError); assert.throws(function() { new lo.UnionLayoutDiscriminator(lo.f32()); }, TypeError); assert.throws(function() { @@ -954,6 +1100,7 @@ suite('Layout', function() { assert.strictEqual(clo.fields, vlo.fields); assert.deepEqual(obj.content, {payload: [0,1,2,3,4,5,6,7]}); assert.equal(obj.tag, 8); + assert.equal(9, un.getSpan(b)); }); test('issue#7.internal.named2', function() { var dlo = lo.u8('vid'); @@ -1100,6 +1247,29 @@ suite('Layout', function() { b[0] = 5; assert.throws(function() { un.getSpan(b); }, Error); + + b.fill(0xa5); + assert.equal(un.encode(obj, b, 1), 1 + 3 + 1); + assert.equal(v3.getSpan(b, 1), 5); + assert.equal(un.getSpan(b, 1), 5); + assert.equal(Buffer('a50368692100a5', 'hex') + .compare(b.slice(0, 5 + 2)), 0); + assert.deepEqual(un.decode(b, 1), obj); + }); + test('variable-external', function() { + var dlo = lo.u8('v'); + var ud = lo.unionLayoutDiscriminator(lo.offset(dlo, -1)); + var un = lo.union(ud, null, 'u'); + assert(0 > un.span); + assert(!un.usesPrefixDiscriminator); + var st = lo.struct([dlo, un], 'st'); + var v1 = un.addVariant(1, lo.cstr(), 's'); + var obj = {v: v1.variant, u: {s: 'hi'}}; + var b = new Buffer(6); + b.fill(0xa5); + st.encode(obj, b, 1); + assert.equal(Buffer('a501686900a5', 'hex').compare(b), 0); + assert.deepEqual(st.decode(b, 1), obj); }); }); test('fromArray', function() { @@ -1168,6 +1338,12 @@ suite('Layout', function() { assert.equal(bs._packedGetValue(), 0xFFFF); assert.throws(function() { bf6.encode('hi', b); }, Error); assert.throws(function() { bf6.encode(1 << 6, b); }, Error); + + b = new Buffer(2 + bs.span); + b.fill(0xa5); + bs.encode(obj, b, 1); + assert.equal(Buffer('a5ffffa5', 'hex').compare(b), 0); + assert.deepEqual(bs.decode(b, 1), obj); }); test('basic LSB', function() { var pbl = lo.u32(); @@ -1336,6 +1512,7 @@ suite('Layout', function() { assert.equal(bv.length, bl.span); assert.equal(Buffer('010203', 'hex').compare(bv), 0); bv = bl.decode(b, 2); + assert.equal(bl.getSpan(b), bl.span); assert.equal(Buffer('030405', 'hex').compare(bv), 0); assert.equal(bl.encode(Buffer('112233', 'hex'), b, 1), 3); assert.equal(Buffer('0111223305', 'hex').compare(b), 0); From bfb5e726bda701abb0fd37ace54d2f7f75d2c99b Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 23 Jan 2016 10:01:33 -0600 Subject: [PATCH 06/10] Layout: clean up encode return values Missed an explicit zero on GreedyCount; document that BitField.encode is not Layout.encode and does not return a value. --- lib/Layout.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Layout.js b/lib/Layout.js index f70c96b..b7d3c87 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -409,7 +409,7 @@ GreedyCount.prototype.decode = function(b, offset) { }; /** Implement {@link Layout#encode|encode} for {@link GreedyCount|GreedyCount}. */ GreedyCount.prototype.encode = function(src, b, offset) { - return; + return 0; }; /** An {@link ExternalLayout|ExternalLayout} that supports accessing a @@ -1940,7 +1940,10 @@ BitField.prototype.decode = function() { return value; }; /** Store a value into the corresponding subsequence of the containing - * bit field. */ + * bit field. + * + * **NOTE** This is not a specialization of {@link + * Layout#encode|Layout.encode} and there is no return value. */ BitField.prototype.encode = function(value) { if ((!Number.isInteger(value)) || (value != fixBitwiseResult(value & this.valueMask))) { From 208ca5c3caa4bb77493a1226c7ec34709a30ffab Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 23 Jan 2016 10:18:30 -0600 Subject: [PATCH 07/10] Layout: add bit fields with boolean representation Closes #14. --- README.md | 8 ++++---- lib/Layout.js | 49 ++++++++++++++++++++++++++++++++++++++++++++-- test/LayoutTest.js | 16 +++++++++++++++ test/examples.js | 6 +++--- 4 files changed, 70 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e0def7a..652c552 100644 --- a/README.md +++ b/README.md @@ -144,13 +144,13 @@ The buffer-layout way: See [Union](http://pabigot.github.io/buffer-layout/module-Layout-Union.html). -#### Packed bit fields on a little-endian machine +### Packed bit fields on a little-endian machine The C definition: struct ds { unsigned int b00l03: 3; - unsigned int b03l01: 1; + unsigned int flg03: 1; unsigned int b04l18: 24; unsigned int b1Cl04: 4; } st; @@ -160,14 +160,14 @@ The buffer-layout way: var ds = lo.bits(lo.u32()); var b = new Buffer(4); ds.addField(3, 'b00l03'); - ds.addField(1, 'b03l01'); + ds.addBoolean('flg03'); ds.addField(24, 'b04l18'); ds.addField(4, 'b1Cl04'); b.fill(0xff); assert.equal(ds.encode({b00l03: 3, b04l18: 24, b1Cl04: 4}, b), 4); assert.equal(Buffer('8b010040', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), - {b00l03: 3, b03l01: 1, b04l18: 24, b1Cl04: 4}); + {b00l03: 3, flg03: true, b04l18: 24, b1Cl04: 4}); See [BitStructure](http://pabigot.github.io/buffer-layout/module-Layout-BitStructure.html). diff --git a/lib/Layout.js b/lib/Layout.js index b7d3c87..c615155 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -118,6 +118,7 @@ * @local VariantLayout * @local BitStructure * @local BitField + * @local Boolean * @local Blob * @local CString * @local Constant @@ -1738,10 +1739,11 @@ function fixBitwiseResult(v) { * BitField|BitField} instances that provide the extracted properties. * The container simply defines the aggregate representation and its * bit ordering. The representation is an object containing - * properties with numeric values. + * properties with numeric or {@link Boolean|boolean} values. * * {@link BitField|BitField}s are added with the {@link - * BitStructure#addField|addField} method. + * BitStructure#addField|addField} and {@link + * BitStructure#addBoolean|addBoolean} methods. * @param {Layout} word - initializer for {@link * BitStructure#word|word}. The parameter must be an instance of @@ -1855,6 +1857,18 @@ BitStructure.prototype.addField = function(bits, property) { this.fields.push(bf); return bf; }; +/** As with {@link BitStructure#addField|addField} for single-bit + * fields with `boolean` value representation. + * + * @param {string} property - initializer for {@link + * Layout#property|property}. + * + * @return {Boolean} */ +BitStructure.prototype.addBoolean = function(property) { + var bf = new Boolean(this, property); + this.fields.push(bf); + return bf; +}; /** Represent a sequence of bits within a {@link * BitStructure|BitStructure}. @@ -1955,6 +1969,36 @@ BitField.prototype.encode = function(value) { | wordValue); }; +/** Represent a single bit within a {@link + * BitStructure|BitStructure} as a JavaScript boolean. + * + * **NOTE** User code should not invoke this construtor directly. Use + * the container {@link BitStructure#addBoolean|addBoolean} helper + * method. + * + * @param {BitStructure} container - initializer for {@link + * BitField#container|container}. + * + * @param {string} [property] - initializer for {@link + * Layout#property|property}. + * + * @constructor + * @augments {BitField} + */ +function Boolean(container, property) { + BitField.call(this, container, 1, property); +}; +Boolean.prototype = Object.create(BitField.prototype); +Boolean.prototype.constructor = Boolean; +/** Override {@link BitField#decode|decode} for {@link Boolean|Boolean}. + * + * @returns {boolean} */ +Boolean.prototype.decode = function(b, offset) { + return !!BitField.prototype.decode.call(this, b, offset); +}; +/* There is no override for Boolean.encode since the `src` parameter + * is interpreted as truthy. */ + /** Contain a fixed-length block of arbitrary data, represented as a * Buffer. * @@ -2160,6 +2204,7 @@ exports.Union = Union; exports.VariantLayout = VariantLayout; exports.BitStructure = BitStructure; exports.BitField = BitField; +exports.Boolean = Boolean; exports.Blob = Blob; exports.CString = CString; exports.Constant = Constant; diff --git a/test/LayoutTest.js b/test/LayoutTest.js index bf36660..3fab90c 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -1489,6 +1489,22 @@ suite('Layout', function() { assert.equal(msb.encode(mb, b), 3); assert.equal(Buffer('a569a5', 'hex').compare(b), 0); }); + test('boolean', function() { + var bs = lo.bits(lo.u8()); + bs.addField(1, 'v'); + bs.addBoolean('b'); + var b = new Buffer(bs.span); + b[0] = 0x3; + var obj = bs.decode(b); + assert.strictEqual(1, obj.v); + assert.notStrictEqual(1, obj.b); + assert.strictEqual(true, obj.b); + assert.notStrictEqual(true, obj.v); + bs.encode({v:1,b:1}, b); + assert.equal(b[0], 3); + bs.encode({v:0,b:0}, b); + assert.equal(b[0], 0); + }); }); suite('Blob', function() { test('invalid ctor', function() { diff --git a/test/examples.js b/test/examples.js index 7fce441..cfb0fa5 100644 --- a/test/examples.js +++ b/test/examples.js @@ -74,7 +74,7 @@ struct { /* struct ds { unsigned int b00l03: 3; - unsigned int b03l01: 1; + unsigned int flg03: 1; unsigned int b04l18: 24; unsigned int b1Cl04: 4; } st; @@ -82,14 +82,14 @@ struct ds { var ds = lo.bits(lo.u32()); var b = new Buffer(4); ds.addField(3, 'b00l03'); - ds.addField(1, 'b03l01'); + ds.addBoolean('flg03'); ds.addField(24, 'b04l18'); ds.addField(4, 'b1Cl04'); b.fill(0xff); assert.equal(ds.encode({b00l03: 3, b04l18: 24, b1Cl04: 4}, b), 4); assert.equal(Buffer('8b010040', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), - {b00l03: 3, b03l01: 1, b04l18: 24, b1Cl04: 4}); + {b00l03: 3, flg03: true, b04l18: 24, b1Cl04: 4}); }); test('64-bit values', function() { /* From bfef65763c511dbfd43799a73c73933888c50a0f Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 23 Jan 2016 10:24:02 -0600 Subject: [PATCH 08/10] Layout: refine exceptions Change a few TypeError to RangeError, and finesse the fact that some TypeErrors might be unacceptable values. Closes #12. --- lib/Layout.js | 16 ++++++++-------- test/LayoutTest.js | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/Layout.js b/lib/Layout.js index c615155..819b9c3 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -382,7 +382,7 @@ function GreedyCount(elementSpan, property) { elementSpan = 1; } if ((!Number.isInteger(elementSpan)) || (0 >= elementSpan)) { - throw new TypeError('elementSpan must be a positive integer'); + throw new TypeError('elementSpan must be a (positive) integer'); } ExternalLayout.call(this, -1, property); @@ -500,7 +500,7 @@ OffsetLayout.prototype.encode = function(src, b, offset) { function UInt(span, property) { Layout.call(this, span, property); if (6 < this.span) { - throw new TypeError('span must not exceed 6 bytes'); + throw new RangeError('span must not exceed 6 bytes'); } Object.freeze(this); } @@ -540,7 +540,7 @@ UInt.prototype.encode = function(src, b, offset) { function UIntBE(span, property) { Layout.call(this, span, property); if (6 < this.span) { - throw new TypeError('span must not exceed 6 bytes'); + throw new RangeError('span must not exceed 6 bytes'); } Object.freeze(this); } @@ -580,7 +580,7 @@ UIntBE.prototype.encode = function(src, b, offset) { function Int(span, property) { Layout.call(this, span, property); if (6 < this.span) { - throw new TypeError('span must not exceed 6 bytes'); + throw new RangeError('span must not exceed 6 bytes'); } Object.freeze(this); } @@ -620,7 +620,7 @@ Int.prototype.encode = function(src, b, offset) { function IntBE(span, property) { Layout.call(this, span, property); if (6 < this.span) { - throw new TypeError('span must not exceed 6 bytes'); + throw new RangeError('span must not exceed 6 bytes'); } Object.freeze(this); } @@ -1617,7 +1617,7 @@ function VariantLayout(union, throw new TypeError('union must be a Union'); } if ((!Number.isInteger(variant)) || (0 > variant)) { - throw new TypeError('variant must be a non-negative integer'); + throw new TypeError('variant must be a (non-negative) integer'); } if (!(layout instanceof Layout)) { throw new TypeError('layout must be a Layout'); @@ -1765,7 +1765,7 @@ function BitStructure(word, msb, property) { throw new TypeError('word must be a UInt or UIntBE layout'); } if (4 < word.span) { - throw new Error('word cannot exceed 32 bits'); + throw new RangeError('word cannot exceed 32 bits'); } Layout.call(this, word.span, property); @@ -2066,7 +2066,7 @@ Blob.prototype.encode = function(src, b, offset) { } if (!((src instanceof Buffer) && (span === src.length))) { - throw new Error('Blob.encode requires length ' + span + ' Buffer as src'); + throw new Error('Blob.encode requires (length ' + span + ') Buffer as src'); } if ((offset + span) > b.length) { throw new RangeError('encoding overruns Buffer'); diff --git a/test/LayoutTest.js b/test/LayoutTest.js index 3fab90c..18a2ea2 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -113,7 +113,7 @@ suite('Layout', function() { assert.equal(0xA534, d.decode(b, 2)); }); test('invalid ctor', function() { - assert.throws(function() { new lo.UInt(8); }, TypeError); + assert.throws(function() { new lo.UInt(8); }, RangeError); }); }); suite('UIntBE', function() { @@ -176,7 +176,7 @@ suite('Layout', function() { assert.equal(0x34A5, d.decode(b, 2)); }); test('invalid ctor', function() { - assert.throws(function() { new lo.UIntBE(8); }, TypeError); + assert.throws(function() { new lo.UIntBE(8); }, RangeError); }); }); suite('Int', function() { @@ -255,7 +255,7 @@ suite('Layout', function() { assert.equal(lo.u48be().decode(b), 0x8720f279b78f); }); test('invalid ctor', function() { - assert.throws(function() { new lo.Int(8); }, TypeError); + assert.throws(function() { new lo.Int(8); }, RangeError); }); }); suite('IntBE', function() { @@ -328,7 +328,7 @@ suite('Layout', function() { assert.equal(lo.u48().decode(b), 0x8720f279b78f); }); test('invalid ctor', function() { - assert.throws(function() { new lo.IntBE(8, 'u64'); }, TypeError); + assert.throws(function() { new lo.IntBE(8, 'u64'); }, RangeError); }); }); test('RoundedUInt64', function() { From b648a53549aa4e0a6fac318f5f7c27d7cb653007 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 23 Jan 2016 10:27:53 -0600 Subject: [PATCH 09/10] CHANGELOG.md: add recent changes --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1f2b13..53a284c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## [Unreleased] +* **API** Change some exceptions (especially integer value spans) to + throw `RangeError` instead of `TypeError`, resolving + [issue #12][issue#12]. +* **API** [Add][issue#14] [boolean-valued bit fields][doc:Boolean]. +* Increase coverage of primary module to 100%. +* Update dev dependency modules. +* Fix always-false pre-convert type check. ## [0.9.0] - 2015-12-22 @@ -90,6 +97,7 @@ [doc:BitStructure]: http://pabigot.github.io/buffer-layout/module-Layout-BitStructure.html [doc:Blob]: http://pabigot.github.io/buffer-layout/module-Layout-Blob.html [doc:Blob.length]: http://pabigot.github.io/buffer-layout/module-Layout-Blob.html#length +[doc:Boolean]: http://pabigot.github.io/buffer-layout/module-Layout-Boolean.html [doc:Constant]: http://pabigot.github.io/buffer-layout/module-Layout-Constant.html [doc:CString]: http://pabigot.github.io/buffer-layout/module-Layout-CString.html [doc:Layout.encode]: http://pabigot.github.io/buffer-layout/module-Layout-Layout.html#encode @@ -117,6 +125,7 @@ [issue#11]: https://github.com/pabigot/buffer-layout/issues/11 [issue#12]: https://github.com/pabigot/buffer-layout/issues/12 [issue#13]: https://github.com/pabigot/buffer-layout/issues/13 +[issue#14]: https://github.com/pabigot/buffer-layout/issues/14 [ci:travis]: https://travis-ci.org/pabigot/buffer-layout [ci:coveralls]: https://coveralls.io/github/pabigot/buffer-layout [node:issue#3992]: https://github.com/nodejs/node/issues/3992 From 95df889188e03296027fba46e34b9b396356f6b9 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 23 Jan 2016 10:38:49 -0600 Subject: [PATCH 10/10] passim: update for release --- CHANGELOG.md | 5 ++++- package.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53a284c..28ef985 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +## [0.10.0] - 2016-01-23 + * **API** Change some exceptions (especially integer value spans) to throw `RangeError` instead of `TypeError`, resolving [issue #12][issue#12]. @@ -83,7 +85,8 @@ * Initial release. -[Unreleased]: https://github.com/pabigot/buffer-layout/compare/v0.9.0...next +[Unreleased]: https://github.com/pabigot/buffer-layout/compare/v0.10.0...next +[0.10.0]: https://github.com/pabigot/buffer-layout/compare/v0.9.0...v0.10.0 [0.9.0]: https://github.com/pabigot/buffer-layout/compare/v0.8.0...v0.9.0 [0.8.0]: https://github.com/pabigot/buffer-layout/compare/v0.7.0...v0.8.0 [0.7.1]: https://github.com/pabigot/buffer-layout/compare/v0.7.0...v0.7.1 diff --git a/package.json b/package.json index f55dd02..5e93907 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "buffer-layout", - "version": "0.10.0-dev", + "version": "0.10.0", "description": "Translation between JavaScript values and Buffers", "keywords": [ "Buffer",