From f87079f7337d9a4bc2e36a47b090feb6c2a7e68f Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 27 Mar 2016 12:06:58 -0500 Subject: [PATCH 01/17] passim: update for next development cycle --- CHANGELOG.md | 4 +++- package.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a050b57..67e483b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## [Unreleased] + ## [0.13.0] - 2016-03-27 * **API** Add [fieldFor][doc:BitStructure.fieldFor]. @@ -104,7 +106,7 @@ * Initial release. -[0.13.0]: https://github.com/pabigot/buffer-layout/compare/v0.12.1...v0.13.0 +[Unreleased]: https://github.com/pabigot/buffer-layout/compare/v0.13.0...next [0.12.0]: https://github.com/pabigot/buffer-layout/compare/v0.11.0...v0.12.0 [0.11.0]: https://github.com/pabigot/buffer-layout/compare/v0.10.0...v0.11.0 [0.10.0]: https://github.com/pabigot/buffer-layout/compare/v0.9.0...v0.10.0 diff --git a/package.json b/package.json index 542854d..86763db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "buffer-layout", - "version": "0.13.0", + "version": "0.14.0-next", "description": "Translation between JavaScript values and Buffers", "keywords": [ "Buffer", From d085b3177bc6ad5a650c4881c6c2ac957c7c0728 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Wed, 18 May 2016 14:04:08 -0500 Subject: [PATCH 02/17] Layout: clarify documentation of Bitfield#valueMask --- lib/Layout.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Layout.js b/lib/Layout.js index a0f9efa..b629139 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -2091,7 +2091,10 @@ function BitField(container, bits, property) { this.bits = bits; /** A mask of {@link BitField#bits|bits} bits isolating value bits - * that fit within the field. */ + * that fit within the field. + * + * That is, it masks a value that has not yet been shifted into + * position within its containing packed integer. */ this.valueMask = (1 << bits) - 1; if (32 == bits) { // shifted value out of range this.valueMask = 0xFFFFFFFF; From 74693ab9afeedf56f5c3cffc68fb7c8d55ecd317 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 9 Oct 2016 08:41:46 -0500 Subject: [PATCH 03/17] LayoutTest: check S64 with high bit in low word --- test/LayoutTest.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/LayoutTest.js b/test/LayoutTest.js index ae36710..38bfd81 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -485,6 +485,9 @@ suite('Layout', function() { be.encode(1, b, 1); assert.equal(Buffer('a50000000000000001a5', 'hex').compare(b), 0); assert.equal(1, be.decode(b, 1)); + + assert.equal(le.decode(Buffer('0000007001000000', 'hex')), 6174015488); + assert.equal(le.decode(Buffer('0000008001000000', 'hex')), 6442450944); }); test('Float', function() { var be = lo.f32be('eff'); From 98b048067bad5fc006f498a7104bfe98cfdd6783 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 9 Oct 2016 06:33:55 -0500 Subject: [PATCH 04/17] travis.yml: update to cover all stable Node.js releases Drop 0.12 which is EOL. --- .travis.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index ed4b407..ac9a772 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,9 @@ language: node_js node_js: - - "5.6" - - "5.5" - - "5.4" - - "5.3" - - "5.2" - - "5.1" - - "5.0" - - "4.3" - - "4.2" - - "4.1" - - "4.0" - - "0.12" + - "node" + - "8" + - "6" + - "4" after_success: - npm run lint.strict - npm run jscs From a6f132a20db2233373841b76668b28c074280fb3 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 9 Oct 2016 08:43:13 -0500 Subject: [PATCH 05/17] package.json: replace jscs and jshint with eslint --- .eslintrc.js | 36 ++++++++++++++++++++++++++++++++++++ .travis.yml | 3 +-- package.json | 46 ++++------------------------------------------ 3 files changed, 41 insertions(+), 44 deletions(-) create mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..f5d6254 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,36 @@ +module.exports = { + extends: 'google', + env: { + node: true, + mocha: true + }, + plugins: [ + 'pabigot' + ], + rules: { + camelcase: 'off', + curly: 'error', + 'guard-for-in': 'off', + 'max-len': ['error', {code: 120, tabWidth: 2}], + 'new-cap': 'off', + 'no-constant-condition': 'off', + 'no-implicit-coercion': 'off', + 'operator-linebreak': ['error', 'before'], + 'pabigot/affixed-ids': ['error', { + allowedSuffixes: [ + '_dCel', + '_ppt' + ] + }], + quotes: ['error', 'single', { + avoidEscape: true, + allowTemplateLiterals: true + }], + 'require-jsdoc': 'off', + 'valid-jsdoc': 'off', + yoda: ['error', 'always', {exceptRange: true}] + }, + parserOptions: { + sourceType: 'module' + } +} diff --git a/.travis.yml b/.travis.yml index ac9a772..77ce389 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,5 @@ node_js: - "6" - "4" after_success: - - npm run lint.strict - - npm run jscs + - npm run eslint - npm run coveralls diff --git a/package.json b/package.json index 86763db..8797268 100644 --- a/package.json +++ b/package.json @@ -19,11 +19,11 @@ "main": "./lib/Layout.js", "devDependencies": { "coveralls": "~2.11.6", + "eslint": "~3.7.1", + "eslint-config-google": "~0.6.0", + "eslint-plugin-pabigot": "~1.0.0", "istanbul": "~0.4.2", - "jscs": "~2.11.0", "jsdoc": "~3.4.0", - "jshint": "^2.9.1", - "jslint": "~0.9.6", "lodash": "~4.0.0", "mocha": "~2.4.0" }, @@ -33,46 +33,8 @@ "scripts": { "coverage": "istanbul cover _mocha -- -u tdd", "coveralls": "istanbul cover _mocha --report lcovonly -- -u tdd && cat ./coverage/lcov.info | coveralls", - "jscs": "jscs lib/ test/", + "eslint": "eslint 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", "test": "mocha -u tdd" - }, - "jshintConfig": { - "node": true, - "laxbreak": true - }, - "jscsConfig": { - "preset": "google", - "requireOperatorBeforeLineBreak": false, - "maximumLineLength": { - "value": 120, - "allExcept": ["comments", "regex"] - }, - "requireCamelCaseOrUpperCaseIdentifiers": { - "allowedSuffixes": [ - "_dCel", - "_ppt" - ] - }, - "jsDoc": { - "checkAnnotations": { - "preset": "jsdoc3", - "extra": { - "local": true - } - }, - "checkParamNames": true, - "requireParamTypes": true, - "checkRedundantParams": true, - "checkReturnTypes": true, - "checkRedundantReturns": true, - "requireReturnTypes": true, - "checkTypes": true, - "checkRedundantAccess": true, - "requireNewlineAfterDescription": true - } } } From f2b926e715b9623f2e4752a701698c7c7b923d00 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 9 Oct 2016 08:54:36 -0500 Subject: [PATCH 06/17] passim: auto-fix eslint issues node_modules/.bin/eslint --fix lib/ test/ --- lib/Layout.js | 20 +++++------- lib/patchIssue3992.js | 2 +- test/LayoutTest.js | 74 +++++++++++++++++++++---------------------- test/examples.js | 2 +- 4 files changed, 47 insertions(+), 51 deletions(-) diff --git a/lib/Layout.js b/lib/Layout.js index b629139..1b38cb1 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -129,10 +129,6 @@ * @see {@link https://github.com/pabigot/buffer-layout|buffer-layout on GitHub} */ -/*jslint - bitwise:true, this:true, white:true - */ -/*jshint -W034 */ // don't whine about explicit "use strict" 'use strict'; var assert = require('assert'); @@ -140,11 +136,11 @@ var util = require('util'); require('./patchIssue3992'); -/* jscs:disable */ +/* eslint-disable */ /* istanbul ignore next */ /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger */ Number.isInteger = Number.isInteger || function(value) { - return typeof value === "number" && + return 'number' === typeof value && isFinite(value) && Math.floor(value) === value; }; @@ -158,14 +154,14 @@ if (!Object.assign) { writable: true, value: function(target) { 'use strict'; - if (target === undefined || target === null) { + if (target === undefined || null === target) { throw new TypeError('Cannot convert first argument to object'); } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; - if (nextSource === undefined || nextSource === null) { + if (nextSource === undefined || null === nextSource) { continue; } nextSource = Object(nextSource); @@ -183,7 +179,7 @@ if (!Object.assign) { } }); } -/* jscs:enable */ +/* eslint-enable */ /** * Base class for layout objects. @@ -754,8 +750,8 @@ var V2E32 = Math.pow(2, 32); function divmodInt64(src) { var hi32 = Math.floor(src / V2E32); var lo32 = src - (hi32 * V2E32); - //assert.equal(roundedInt64(hi32, lo32), src); - //assert(0 <= lo32); + // assert.equal(roundedInt64(hi32, lo32), src); + // assert(0 <= lo32); return {hi32: hi32, lo32: lo32}; } @@ -1786,7 +1782,7 @@ function VariantLayout(union, variant, layout, property) { && (layout.span > union.defaultLayout.span)) { throw new Error('variant span exceeds span of containing union'); } - if (typeof property != 'string') { + if ('string' != typeof property) { throw new TypeError('variant must have a String property'); } var span = union.span; diff --git a/lib/patchIssue3992.js b/lib/patchIssue3992.js index 4e2ed63..d4c5e9c 100644 --- a/lib/patchIssue3992.js +++ b/lib/patchIssue3992.js @@ -35,7 +35,7 @@ IN THE SOFTWARE. * @license MIT */ -/* jscs:disable requireCurlyBraces */ // silence whining about code from Node.js +/* eslint-disable */ /* Test whether Buffer.writeIntLE() gets the right answer for * problematic negative integers */ diff --git a/test/LayoutTest.js b/test/LayoutTest.js index 38bfd81..2207a9d 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -584,17 +584,17 @@ suite('Layout', function() { assert.equal(seq.getSpan(), seq.span); assert.equal(seq.property, 'id'); b.fill(0); - assert.deepEqual(seq.decode(b), [0,0,0,0]); - assert.equal(seq.encode([1,2,3,4], b), 4); - assert.deepEqual(seq.decode(b), [1,2,3,4]); - assert.equal(seq.encode([5,6], b, 1), 2); - assert.deepEqual(seq.decode(b), [1,5,6,4]); + assert.deepEqual(seq.decode(b), [0, 0, 0, 0]); + assert.equal(seq.encode([1, 2, 3, 4], b), 4); + assert.deepEqual(seq.decode(b), [1, 2, 3, 4]); + assert.equal(seq.encode([5, 6], b, 1), 2); + assert.deepEqual(seq.decode(b), [1, 5, 6, 4]); }); test('in struct', function() { var seq = lo.seq(lo.u8(), 4, 'id'); var str = lo.struct([seq]); var d = str.decode(Buffer('01020304', 'hex')); - assert.deepEqual(d, {id: [1,2,3,4]}); + assert.deepEqual(d, {id: [1, 2, 3, 4]}); }); test('struct elts', function() { var st = new lo.Structure([lo.u8('u8'), @@ -610,7 +610,7 @@ suite('Layout', function() { assert.equal(Buffer('0110270000000000000003bcfeffff', 'hex').compare(b), 0); assert.deepEqual(seq.decode(b), tv); - assert.equal(seq.encode([{u8: 2,s32: 0x12345678}], b, st.span), + assert.equal(seq.encode([{u8: 2, s32: 0x12345678}], b, st.span), 1 * st.span); assert.equal(Buffer('0110270000027856341203bcfeffff', 'hex').compare(b), 0); @@ -622,9 +622,9 @@ suite('Layout', function() { var b = Buffer('03010203', 'hex'); var obj = st.decode(b); assert.equal(obj.n, 3); - assert.deepEqual(obj.a, [1,2,3]); + assert.deepEqual(obj.a, [1, 2, 3]); b = new Buffer(10); - obj = {n: 3, a: [5,6,7,8,9]}; + obj = {n: 3, a: [5, 6, 7, 8, 9]}; assert.equal(st.encode(obj, b), 6); var span = st.getSpan(b); assert.equal(span, 6); @@ -737,13 +737,13 @@ suite('Layout', function() { var cst = new lo.Structure([lo.u32('u32'), st, lo.s24('s24')]); - var obj = {'u32': 0x12345678, - 'st': { + var obj = {u32: 0x12345678, + st: { u8: 23, u16: 65432, s16be: -12345 }, - 's24': -123456}; + s24: -123456}; var b = new Buffer(12); assert.equal(st.span, 5); assert.equal(st.property, 'st'); @@ -928,7 +928,7 @@ suite('Layout', function() { var el = new lo.greedy(); var b = new Buffer(10); assert.equal(el.decode(b), b.length); - assert.equal(el.decode(b,3), b.length - 3); + assert.equal(el.decode(b, 3), b.length - 3); var nel = new lo.greedy(3); assert.equal(nel.decode(b), 3); @@ -1034,7 +1034,7 @@ suite('Layout', function() { b.fill(0); var o = un.decode(b); assert.equal(o.variant, 0); - assert.deepEqual(o.content, [0,0,0,0, 0,0,0,0]); + assert.deepEqual(o.content, [0, 0, 0, 0, 0, 0, 0, 0]); o.variant = 5; o.content[3] = 3; o.content[7] = 7; @@ -1048,7 +1048,7 @@ suite('Layout', function() { var b = new Buffer(5); assert.strictEqual(un.getVariant(1), undefined); b.fill(0); - assert.deepEqual(un.decode(b), {v: 0, c: [0,0,0,0]}); + assert.deepEqual(un.decode(b), {v: 0, c: [0, 0, 0, 0]}); var lo1 = lo.u32(); var v1 = un.addVariant(1, lo1, 'v1'); assert(v1 instanceof lo.VariantLayout); @@ -1106,7 +1106,7 @@ suite('Layout', function() { var obj = st.decode(b); assert.equal(obj.u16, 0x0100); assert.equal(obj.u.uid, 2); - assert.deepEqual(obj.u.payload, [3,4,5]); + assert.deepEqual(obj.u.payload, [3, 4, 5]); assert.equal(obj.s16, 1798); obj.u16 = 0x5432; obj.s16 = -3; @@ -1122,12 +1122,12 @@ suite('Layout', function() { var b = Buffer('000102030405060708', 'hex'); var obj = un.decode(b); assert.equal(obj.number, 0); - assert.deepEqual(obj.payload, [1,2,3,4,5,6,7,8]); + assert.deepEqual(obj.payload, [1, 2, 3, 4, 5, 6, 7, 8]); var b2 = new Buffer(un.span); assert.equal(un.encode(obj, b2), dlo.span + vlo.span); assert.equal(b2.toString('hex'), b.toString('hex')); - var obj2 = {'variant': obj.number, - 'content': obj.payload}; + var obj2 = {variant: obj.number, + content: obj.payload}; assert.throws(function() { un.encode(obj2, b2); }); }); test('issue#7.internal.anon', function() { @@ -1145,7 +1145,7 @@ suite('Layout', function() { assert.notStrictEqual(clo, vlo); assert(clo instanceof vlo.constructor); assert.strictEqual(clo.fields, vlo.fields); - assert.deepEqual(obj.content, {payload: [0,1,2,3,4,5,6,7]}); + assert.deepEqual(obj.content, {payload: [0, 1, 2, 3, 4, 5, 6, 7]}); assert.equal(obj.variant, 8); }); test('issue#7.internal.named', function() { @@ -1164,7 +1164,7 @@ suite('Layout', function() { assert.notStrictEqual(clo, vlo); assert(clo instanceof vlo.constructor); assert.strictEqual(clo.fields, vlo.fields); - assert.deepEqual(obj.content, {payload: [0,1,2,3,4,5,6,7]}); + assert.deepEqual(obj.content, {payload: [0, 1, 2, 3, 4, 5, 6, 7]}); assert.equal(obj.tag, 8); assert.equal(9, un.getSpan(b)); }); @@ -1183,7 +1183,7 @@ suite('Layout', function() { assert.notStrictEqual(clo, vlo); assert(clo instanceof vlo.constructor); assert.strictEqual(clo.fields, vlo.fields); - assert.deepEqual(obj.content, {payload: [0,1,2,3,4,5,6,7], vid: 8}); + assert.deepEqual(obj.content, {payload: [0, 1, 2, 3, 4, 5, 6, 7], vid: 8}); assert.equal(obj.vid, 8); }); test('issue#7.external', function() { @@ -1243,7 +1243,7 @@ suite('Layout', function() { assert.equal(un.encode(src, b), un.span); assert.equal(Buffer('010000d441', 'hex').compare(b), 0); - src = {'u8.4': [1,2,3,4]}; + src = {'u8.4': [1, 2, 3, 4]}; vlo = un.getSourceVariant(src); assert.strictEqual(vlo, v2); assert.equal(vlo.encode(src, b), un.span); @@ -1281,7 +1281,7 @@ suite('Layout', function() { var v2 = un.addVariant(2, lo.f64(), 'f64'); var v3 = un.addVariant(3, lo.cstr(), 'str'); var b = new Buffer(16); - assert(un.span < 0); + assert(0 > un.span); b.fill(0xFF); assert.throws(function() { un.decode(b); }, Error); @@ -1341,15 +1341,15 @@ suite('Layout', function() { test('fromArray', function() { assert.strictEqual(lo.u8().fromArray([1]), undefined); var st = new lo.Structure([lo.u8('a'), lo.u8('b'), lo.u16('c')]); - assert.deepEqual(st.fromArray([1,2,3]), {a: 1, b: 2, c: 3}); - assert.deepEqual(st.fromArray([1,2]), {a: 1, b: 2}); + assert.deepEqual(st.fromArray([1, 2, 3]), {a: 1, b: 2, c: 3}); + assert.deepEqual(st.fromArray([1, 2]), {a: 1, b: 2}); var un = new lo.Union(lo.u8('v'), lo.u32('c')); - assert.strictEqual(un.fromArray([1,2,3]), undefined); + assert.strictEqual(un.fromArray([1, 2, 3]), undefined); var v1 = un.addVariant(1, st, 'v1'); var v2 = un.addVariant(2, lo.f32(), 'v2'); assert(v1 instanceof lo.VariantLayout); - assert.deepEqual(un.getVariant(1).fromArray([1,2,3]), {a: 1, b: 2, c: 3}); - assert.strictEqual(un.getVariant(2).fromArray([1,2,3]), undefined); + assert.deepEqual(un.getVariant(1).fromArray([1, 2, 3]), {a: 1, b: 2, c: 3}); + assert.strictEqual(un.getVariant(2).fromArray([1, 2, 3]), undefined); }); suite('BitStructure', function() { test('invalid ctor', function() { @@ -1695,16 +1695,16 @@ suite('Layout', function() { assert.equal(expectedBlob.compare(du.blob), 0); var dp = pkt.decode(b); /* This is what I want, but can't get. */ - //assert.equal(dp.id, 1); - //assert.equal(dp.ver, 2); - //assert.equal(expectedBlob.compare(dp.blob), 0); + // assert.equal(dp.id, 1); + // assert.equal(dp.ver, 2); + // assert.equal(expectedBlob.compare(dp.blob), 0); var v3 = pld.addVariant(2, new lo.Sequence(lo.u32(), 2, 'u32'), 'v3'); assert.deepEqual(pld.decode(b, 2), {v3: [0x13121110, 0x17161514]}); dp = pkt.decode(b); /* Ditto on want */ - //assert.deepEqual(dp, {id:1, ver:2, u32: [0x13121110, 0x17161514]}); + // assert.deepEqual(dp, {id:1, ver:2, u32: [0x13121110, 0x17161514]}); }); }); suite('factories', function() { @@ -1767,13 +1767,13 @@ suite('Layout', function() { assert.equal(st.getSpan(b), 5); assert.deepEqual(st.decode(b), {k: 'a', v: '23'}); b.fill(0xff); - assert.equal(st.encode({'k': 'a', 'v': 23}, b), (1 + 1) + (2 + 1)); + assert.equal(st.encode({k: 'a', v: 23}, b), (1 + 1) + (2 + 1)); }); test('in seq', function() { var seq = lo.seq(lo.cstr(), 3); var b = Buffer('61006263003500', 'hex'); assert.deepEqual(seq.decode(b), ['a', 'bc', '5']); - assert.equal(seq.encode(['hi','u','c'], b), (1 + 1) + (2 + 1) + (1 + 1)); + assert.equal(seq.encode(['hi', 'u', 'c'], b), (1 + 1) + (2 + 1) + (1 + 1)); assert.equal(Buffer('68690075006300', 'hex').compare(b), 0); }); }); @@ -1936,9 +1936,9 @@ suite('Layout', function() { assert(u instanceof VStruct); assert(u instanceof Union); assert(u.struct instanceof Struct); - assert.deepEqual(u.struct, {'u32': 0x01020304, 'u16': 0x2122, 's16': -32382}); + assert.deepEqual(u.struct, {u32: 0x01020304, u16: 0x2122, s16: -32382}); - u.struct = new Struct(1,2,-3); + u.struct = new Struct(1, 2, -3); assert.equal(Union.layout_.span, Union.layout_.encode(u, b)); assert.equal(Buffer('03010000000200fdff', 'hex').compare(b), 0); }); diff --git a/test/examples.js b/test/examples.js index 4542bb4..f890df0 100644 --- a/test/examples.js +++ b/test/examples.js @@ -188,7 +188,7 @@ struct ds { var b = Buffer('21010002030405', 'hex'); assert.deepEqual(st.decode(b), {prop: 33, data: [0x0001, 0x0302, 0x0504]}); b.fill(0xFF); - assert.equal(st.encode({prop: 9, data: [5,6]}, b), 1 + 2 * 2); + assert.equal(st.encode({prop: 9, data: [5, 6]}, b), 1 + 2 * 2); assert.equal(Buffer('0905000600FFFF', 'hex').compare(b), 0); }); test('variable-length union', function() { From ad95b6329d1bace16cd73ffb88cc381790db438f Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 9 Oct 2016 09:16:44 -0500 Subject: [PATCH 07/17] passim: manual fix eslint issues --- lib/Layout.js | 36 ++++++++++++++++++++++++------------ test/LayoutTest.js | 43 +++++++++++++++++++------------------------ test/examples.js | 1 + 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/lib/Layout.js b/lib/Layout.js index 1b38cb1..f63f4ca 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -240,7 +240,9 @@ function Layout(span, property) { * * See {@link module:Layout.bindConstructorLayout|bindConstructorLayout()}. */ - this.makeDestinationObject = function() { return {}; }; + this.makeDestinationObject = function() { + return {}; + }; } /** @@ -410,7 +412,9 @@ exports.bindConstructorLayout = function(ctor, layout) { ctor.layout_ = layout; layout.boundConstructor_ = ctor; // jscs:disable requireCapitalizedConstructors - layout.makeDestinationObject = function() { return new ctor(); }; + layout.makeDestinationObject = function() { + return new ctor(); + }; // jscs:enable requireCapitalizedConstructors Object.defineProperty(ctor.prototype, 'encode', { configurable: false, @@ -1192,7 +1196,9 @@ function Structure(fields, property) { var span = -1; try { - span = fields.reduce(function(v, fd) { return v + fd.getSpan(); }, 0); + span = fields.reduce(function(v, fd) { + return v + fd.getSpan(); + }, 0); } catch (e) { } Layout.call(this, span, property); @@ -1236,7 +1242,7 @@ Structure.prototype.decode = function(b, offset) { if (undefined === offset) { offset = 0; } - this.fields.map(function(fd) { + this.fields.forEach(function(fd) { if (undefined !== fd.property) { dest[fd.property] = fd.decode(b, offset); } @@ -1580,7 +1586,9 @@ function Union(discr, defaultLayout, property) { * @returns {(undefined|VariantLayout)} The default variant * (`undefined`) or first registered variant that uses a property * available in `src`. */ - this.getSourceVariant = function(src) { return boundGetSourceVariant(src); }; + this.getSourceVariant = function(src) { + return boundGetSourceVariant(src); + }; /** Function to override the implementation of {@link * Union#getSourceVariant|getSourceVariant}. @@ -1782,7 +1790,7 @@ function VariantLayout(union, variant, layout, property) { && (layout.span > union.defaultLayout.span)) { throw new Error('variant span exceeds span of containing union'); } - if ('string' != typeof property) { + if ('string' !== typeof property) { throw new TypeError('variant must have a String property'); } var span = union.span; @@ -1848,7 +1856,6 @@ VariantLayout.prototype.encode = function(src, b, offset) { offset = 0; } var contentOffset = 0; - var clo = this.union.defaultLayout; if (this.union.usesPrefixDiscriminator) { contentOffset = this.union.discriminator.layout.span; } @@ -1966,7 +1973,7 @@ BitStructure.prototype.decode = function(b, offset) { } var value = this.word.decode(b, offset); this._packedSetValue(value); - this.fields.map(function(fd) { + this.fields.forEach(function(fd) { if (undefined !== fd.property) { dest[fd.property] = fd.decode(value); } @@ -2016,6 +2023,8 @@ BitStructure.prototype.addField = function(bits, property) { * * @return {Boolean} */ BitStructure.prototype.addBoolean = function(property) { + // This is my Boolean, not the Javascript one. + // eslint-disable-next-line no-new-wrappers var bf = new Boolean(this, property); this.fields.push(bf); return bf; @@ -2071,7 +2080,9 @@ function BitField(container, bits, property) { throw new TypeError('bits must be positive integer'); } var totalBits = 8 * container.span; - function bitsSum(c, fd) { return c + fd.bits; } + function bitsSum(c, fd) { + return c + fd.bits; + } var usedBits = container.fields.reduce(bitsSum, 0); if ((bits + usedBits) > totalBits) { throw new Error('bits too long for span remainder (' @@ -2092,7 +2103,7 @@ function BitField(container, bits, property) { * That is, it masks a value that has not yet been shifted into * position within its containing packed integer. */ this.valueMask = (1 << bits) - 1; - if (32 == bits) { // shifted value out of range + if (32 === bits) { // shifted value out of range this.valueMask = 0xFFFFFFFF; } @@ -2135,7 +2146,7 @@ BitField.prototype.decode = function() { * Layout#encode|Layout.encode} and there is no return value. */ BitField.prototype.encode = function(value) { if ((!Number.isInteger(value)) - || (value != fixBitwiseResult(value & this.valueMask))) { + || (value !== fixBitwiseResult(value & this.valueMask))) { throw new TypeError(nameWithProperty('BitField.encode', this) + ' value must be integer not exceeding ' + this.valueMask); } @@ -2162,6 +2173,7 @@ BitField.prototype.encode = function(value) { * @constructor * @augments {BitField} */ +/* eslint-disable no-extend-native */ function Boolean(container, property) { BitField.call(this, container, 1, property); } @@ -2180,6 +2192,7 @@ Boolean.prototype.encode = function(value) { } return BitField.prototype.encode.call(this, value); }; +/* eslint-enable no-extend-native */ /** * Contain a fixed-length block of arbitrary data, represented as a @@ -2287,7 +2300,6 @@ CString.prototype.getSpan = function(b, offset) { if (undefined === offset) { offset = 0; } - var span = 0; var idx = offset; while ((idx < b.length) && (0 !== b[idx])) { idx += 1; diff --git a/test/LayoutTest.js b/test/LayoutTest.js index 2207a9d..776b1fe 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -1,3 +1,5 @@ +/* eslint-disable brace-style, max-statements-per-line, no-new */ + var assert = require('assert'); var util = require('util'); var _ = require('lodash'); @@ -1212,7 +1214,7 @@ suite('Layout', function() { assert.equal(obj.u.v0, 0x06050403); var flo = lo.f32('f32'); - var vf = un.addVariant(1, flo, 'vf'); + un.addVariant(1, flo, 'vf'); var fb = Buffer('01234500805a429876', 'hex'); var fobj = st.decode(fb); assert.equal(fobj.vid, 1); @@ -1346,7 +1348,7 @@ suite('Layout', function() { var un = new lo.Union(lo.u8('v'), lo.u32('c')); assert.strictEqual(un.fromArray([1, 2, 3]), undefined); var v1 = un.addVariant(1, st, 'v1'); - var v2 = un.addVariant(2, lo.f32(), 'v2'); + un.addVariant(2, lo.f32(), 'v2'); assert(v1 instanceof lo.VariantLayout); assert.deepEqual(un.getVariant(1).fromArray([1, 2, 3]), {a: 1, b: 2, c: 3}); assert.strictEqual(un.getVariant(2).fromArray([1, 2, 3]), undefined); @@ -1367,22 +1369,22 @@ suite('Layout', function() { test('invalid add', function() { assert.throws(function() { var bs = lo.bits(lo.u32()); - var bf1 = bs.addField(30); - var bf2 = bs.addField(3); + bs.addField(30); + bs.addField(3); }, Error); assert.throws(function() { var bs = lo.bits(lo.u8()); - var bf1 = addField(2); - var bf2 = addField(7); + bs.addField(2); + bs.addField(7); }, Error); assert.throws(function() { var bs = lo.bits(lo.u8()); - var bf1 = addField(0); + bs.addField(0); }, Error); assert.throws(function() { var bs = lo.bits(lo.u8()); - var bf1 = addField(6); - var bf2 = addField(-2); + bs.addField(6); + bs.addField(-2); }, Error); }); test('size', function() { @@ -1536,9 +1538,9 @@ suite('Layout', function() { test('fieldFor', function() { var d = new lo.BitStructure(lo.u32(), true); var b = d.addBoolean('b'); - var b4 = d.addField(4, 'b4'); + d.addField(4, 'b4'); var c11 = d.addField(11, 'c11'); - var d16 = d.addField(16, 'd16'); + d.addField(16, 'd16'); assert.strictEqual(d.fieldFor(), undefined); assert.strictEqual(d.fieldFor('b'), b); assert.strictEqual(d.fieldFor('c11'), c11); @@ -1673,7 +1675,7 @@ suite('Layout', function() { assert.equal(dp.u.ver, 2); assert.equal(expectedBlob.compare(dp.u.blob), 0); - var v3 = pld.addVariant(2, new lo.Sequence(lo.u32(), 2, 'u32'), 'v3'); + pld.addVariant(2, new lo.Sequence(lo.u32(), 2, 'u32'), 'v3'); assert.deepEqual(pld.decode(b, 2), {v3: [0x13121110, 0x17161514]}); dp = pkt.decode(b); @@ -1686,23 +1688,21 @@ suite('Layout', function() { lo.u8('ver')]); var pld = new lo.Union(lo.offset(ver, -ver.span), new lo.Blob(8, 'blob')); - var pkt = new lo.Structure([hdr, pld]); var expectedBlob = Buffer('1011121314151617', 'hex'); var b = Buffer('01021011121314151617', 'hex'); assert.deepEqual(hdr.decode(b), {id: 1, ver: 2}); var du = pld.decode(b, 2); assert.equal(du.ver, 2); assert.equal(expectedBlob.compare(du.blob), 0); - var dp = pkt.decode(b); /* This is what I want, but can't get. */ + // var dp = pkt.decode(b); // assert.equal(dp.id, 1); // assert.equal(dp.ver, 2); // assert.equal(expectedBlob.compare(dp.blob), 0); - var v3 = pld.addVariant(2, new lo.Sequence(lo.u32(), 2, 'u32'), 'v3'); + pld.addVariant(2, new lo.Sequence(lo.u32(), 2, 'u32'), 'v3'); assert.deepEqual(pld.decode(b, 2), {v3: [0x13121110, 0x17161514]}); - dp = pkt.decode(b); /* Ditto on want */ // assert.deepEqual(dp, {id:1, ver:2, u32: [0x13121110, 0x17161514]}); }); @@ -1713,9 +1713,6 @@ suite('Layout', function() { var hdr = lo.struct([lo.u8('id'), lo.u8('ver')]); var pld = lo.union(lo.offset(ver, -ver.span), lo.blob(8, 'blob')); - var pkt = lo.struct([hdr, pld]); - var expectedBlob = Buffer('1011121314151617', 'hex'); - var b = Buffer('01021011121314151617', 'hex'); assert(hdr instanceof lo.Structure); assert(pld instanceof lo.Union); assert(pld.defaultLayout instanceof lo.Blob); @@ -1909,11 +1906,9 @@ suite('Layout', function() { this.struct = v; } util.inherits(VStruct, Union); - { - var str = lo.struct([lo.u32('u32'), lo.u16('u16'), lo.s16('s16')]); - lo.bindConstructorLayout(Struct, str); - lo.bindConstructorLayout(VStruct, Union.layout_.addVariant(3, str, 'struct')); - } + var str = lo.struct([lo.u32('u32'), lo.u16('u16'), lo.s16('s16')]); + lo.bindConstructorLayout(Struct, str); + lo.bindConstructorLayout(VStruct, Union.layout_.addVariant(3, str, 'struct')); var b = new Buffer(Union.layout_.span); b.fill(0); var u = Union.decode(b); diff --git a/test/examples.js b/test/examples.js index f890df0..d209cf0 100644 --- a/test/examples.js +++ b/test/examples.js @@ -1,3 +1,4 @@ +/* eslint-disable brace-style, max-statements-per-line, no-unused-vars */ var assert = require('assert'); var util = require('util'); var lo = require('../lib/Layout'); From 4a92d337ec1bb0437424ab584a8dd21838f9987e Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 9 Oct 2016 08:46:11 -0500 Subject: [PATCH 08/17] package.json: update dependencies --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8797268..ae2eca5 100644 --- a/package.json +++ b/package.json @@ -18,14 +18,14 @@ "author": "Peter A. Bigot ", "main": "./lib/Layout.js", "devDependencies": { - "coveralls": "~2.11.6", + "coveralls": "~2.11.14", "eslint": "~3.7.1", "eslint-config-google": "~0.6.0", "eslint-plugin-pabigot": "~1.0.0", - "istanbul": "~0.4.2", - "jsdoc": "~3.4.0", - "lodash": "~4.0.0", - "mocha": "~2.4.0" + "istanbul": "~0.4.5", + "jsdoc": "~3.4.2", + "lodash": "~4.16.4", + "mocha": "~3.1.0" }, "engines": { "node": ">=0.12" From c97ebbf5c9c235060771b92d3fba549b36d28c39 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 9 Oct 2016 09:32:33 -0500 Subject: [PATCH 09/17] passim: update minimum Node version to 4 --- README.md | 5 +++-- package.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8661ffe..d074ed4 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,9 @@ Layout support is provided for these types of data: ## Installation -Development and testing is done using Node.js, supporting versions 0.12 -and later. Install with `npm install buffer-layout`. +Development and testing is done using Node.js, supporting versions 4 and +later (earlier versions may work). Install with `npm install +buffer-layout`. ## Examples diff --git a/package.json b/package.json index ae2eca5..d1ae315 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "mocha": "~3.1.0" }, "engines": { - "node": ">=0.12" + "node": ">=4" }, "scripts": { "coverage": "istanbul cover _mocha -- -u tdd", From 2422a4cd35a8acb5272afe5e09af1bef771050bf Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 16 Dec 2017 09:58:37 -0600 Subject: [PATCH 10/17] package.json: update dependencies --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index d1ae315..1dc85ae 100644 --- a/package.json +++ b/package.json @@ -18,14 +18,14 @@ "author": "Peter A. Bigot ", "main": "./lib/Layout.js", "devDependencies": { - "coveralls": "~2.11.14", - "eslint": "~3.7.1", - "eslint-config-google": "~0.6.0", - "eslint-plugin-pabigot": "~1.0.0", + "coveralls": "~3.0.0", + "eslint": "~4.13.1", + "eslint-config-google": "~0.9.1", + "eslint-plugin-pabigot": "~1.1.0", "istanbul": "~0.4.5", - "jsdoc": "~3.4.2", - "lodash": "~4.16.4", - "mocha": "~3.1.0" + "jsdoc": "~3.5.5", + "lodash": "~4.17.4", + "mocha": "~4.0.1" }, "engines": { "node": ">=4" From e46348f1a5981bd9e7d9427c709867b2f4144283 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 16 Dec 2017 09:59:19 -0600 Subject: [PATCH 11/17] passim: basic cleanup for new eslint version no-var and some other rules are ignored until we rework this to ES6. --- .eslintrc.js | 15 +++- lib/Layout.js | 4 +- test/LayoutTest.js | 213 +++++++++++++++++++++++---------------------- test/examples.js | 7 +- 4 files changed, 126 insertions(+), 113 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index f5d6254..dd75f83 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,13 +8,22 @@ module.exports = { 'pabigot' ], rules: { + 'guard-for-in': 'off', + 'new-cap': 'off', + 'no-var': 'off', + 'prefer-rest-params': 'off', + 'prefer-spread': 'off', + __temporary: 'off', + 'arrow-parens': ['error', 'as-needed'], camelcase: 'off', curly: 'error', - 'guard-for-in': 'off', + eqeqeq: 'error', 'max-len': ['error', {code: 120, tabWidth: 2}], - 'new-cap': 'off', 'no-constant-condition': 'off', + 'no-fallthrough': ['error', {commentPattern: 'FALLTHRU'}], 'no-implicit-coercion': 'off', + 'no-irregular-whitespace': ['error', {skipComments: true}], + 'no-multi-spaces': ['error', {ignoreEOLComments: true}], 'operator-linebreak': ['error', 'before'], 'pabigot/affixed-ids': ['error', { allowedSuffixes: [ @@ -26,7 +35,9 @@ module.exports = { avoidEscape: true, allowTemplateLiterals: true }], + radix: ['error', 'as-needed'], 'require-jsdoc': 'off', + 'spaced-comment': ['error', 'always', {line: {markers: ['#']}}], 'valid-jsdoc': 'off', yoda: ['error', 'always', {exceptRange: true}] }, diff --git a/lib/Layout.js b/lib/Layout.js index f63f4ca..d327f44 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -422,7 +422,7 @@ exports.bindConstructorLayout = function(ctor, layout) { value: function(b, offset) { return layout.encode(this, b, offset); }, - writable: true + writable: true, }); Object.defineProperty(ctor, 'decode', { configurable: false, @@ -430,7 +430,7 @@ exports.bindConstructorLayout = function(ctor, layout) { value: function(b, offset) { return layout.decode(b, offset); }, - writable: true + writable: true, }); }; diff --git a/test/LayoutTest.js b/test/LayoutTest.js index 776b1fe..186fff6 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -56,19 +56,19 @@ suite('Layout', function() { assert.equal(d.property, 'tag'); }); test('invalid ctor', function() { - assert.throws(function() { new lo.Layout(); }, TypeError); - assert.throws(function() { new lo.Layout('3'); }, TypeError); - assert.throws(function() { new lo.Layout('three'); }, TypeError); + assert.throws(function() {new lo.Layout();}, TypeError); + assert.throws(function() {new lo.Layout('3');}, TypeError); + assert.throws(function() {new lo.Layout('three');}, TypeError); }); test('abstractness', function() { var d = new lo.Layout(3); var b = new Buffer(3); - assert.throws(function() { d.decode(b); }); - assert.throws(function() { d.encode('sth', b); }); + assert.throws(function() {d.decode(b);}); + assert.throws(function() {d.encode('sth', b);}); }); test('#getSpan', function() { assert.equal((new lo.Layout(3)).getSpan(), 3); - assert.throws(function() { (new lo.Layout(-1)).getSpan(); }, RangeError); + assert.throws(function() {(new lo.Layout(-1)).getSpan();}, RangeError); }); }); suite('UInt', function() { @@ -105,7 +105,7 @@ suite('Layout', function() { 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); }); + assert.throws(function() {d.encode(0x1234567, b);}); }); test('u48', function() { var d = lo.u48('t'); @@ -130,7 +130,7 @@ suite('Layout', function() { assert.equal(0xA534, d.decode(b, 2)); }); test('invalid ctor', function() { - assert.throws(function() { new lo.UInt(8); }, RangeError); + assert.throws(function() {new lo.UInt(8);}, RangeError); }); }); suite('UIntBE', function() { @@ -152,24 +152,24 @@ suite('Layout', function() { 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); }); + 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); }); + 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); }); + assert.throws(function() {d.encode(0x123456789ab, b);}); + assert.throws(function() {d.encode(-1, b);}); }); test('u48be', function() { var d = lo.u48be('t'); @@ -193,7 +193,7 @@ suite('Layout', function() { assert.equal(0x34A5, d.decode(b, 2)); }); test('invalid ctor', function() { - assert.throws(function() { new lo.UIntBE(8); }, RangeError); + assert.throws(function() {new lo.UIntBE(8);}, RangeError); }); }); suite('Int', function() { @@ -239,8 +239,8 @@ suite('Layout', function() { 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); }); + assert.throws(function() {d.encode(0x800000, b);}); + assert.throws(function() {d.encode(-0x800001, b);}); }); test('s40', function() { var d = lo.s40('t'); @@ -249,8 +249,8 @@ suite('Layout', function() { 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); }); + assert.throws(function() {d.encode(0x8000000000, b);}); + assert.throws(function() {d.encode(-0x8000000001, b);}); }); test('s48', function() { var d = lo.s48('t'); @@ -272,7 +272,7 @@ suite('Layout', function() { assert.equal(lo.u48be().decode(b), 0x8720f279b78f); }); test('invalid ctor', function() { - assert.throws(function() { new lo.Int(8); }, RangeError); + assert.throws(function() {new lo.Int(8);}, RangeError); }); }); suite('IntBE', function() { @@ -302,8 +302,8 @@ suite('Layout', function() { 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); }); + assert.throws(function() {d.encode(0x800000, b);}); + assert.throws(function() {d.encode(-0x800001, b);}); }); test('s32be', function() { var d = lo.s32be('t'); @@ -312,8 +312,8 @@ suite('Layout', function() { 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); }); + assert.throws(function() {d.encode(0x80000000, b);}); + assert.throws(function() {d.encode(-0x80000001, b);}); }); test('s40be', function() { var d = lo.s40be('t'); @@ -322,8 +322,8 @@ suite('Layout', function() { 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); }); + assert.throws(function() {d.encode(0x8000000000, b);}); + assert.throws(function() {d.encode(-0x8000000001, b);}); }); test('s48be', function() { var d = lo.s48be('t'); @@ -345,7 +345,7 @@ suite('Layout', function() { assert.equal(lo.u48().decode(b), 0x8720f279b78f); }); test('invalid ctor', function() { - assert.throws(function() { new lo.IntBE(8, 'u64'); }, RangeError); + assert.throws(function() {new lo.IntBE(8, 'u64');}, RangeError); }); }); test('RoundedUInt64', function() { @@ -564,15 +564,15 @@ suite('Layout', function() { }); suite('Sequence', function() { test('invalid ctor', function() { - assert.throws(function() { new lo.Sequence(); }, TypeError); - assert.throws(function() { new lo.Sequence(lo.u8()); }, TypeError); - assert.throws(function() { new lo.Sequence(lo.u8(), - '5 is not an integer'); }, + assert.throws(function() {new lo.Sequence();}, TypeError); + assert.throws(function() {new lo.Sequence(lo.u8());}, TypeError); + assert.throws(function() {new lo.Sequence(lo.u8(), + '5 is not an integer');}, TypeError); - assert.throws(function() { new lo.Sequence(lo.u8(), lo.u8()); }, + assert.throws(function() {new lo.Sequence(lo.u8(), lo.u8());}, TypeError); - assert.throws(function() { new lo.Sequence(lo.u8(), - lo.offset(lo.f32())); }, + assert.throws(function() {new lo.Sequence(lo.u8(), + lo.offset(lo.f32()));}, TypeError); }); test('basics', function() { @@ -670,11 +670,11 @@ suite('Layout', function() { }); suite('Structure', function() { test('invalid ctor', function() { - assert.throws(function() { new lo.Structure(); }, TypeError); - assert.throws(function() { new lo.Structure('stuff'); }, TypeError); - assert.throws(function() { new lo.Structure(['stuff']); }, TypeError); + assert.throws(function() {new lo.Structure();}, TypeError); + assert.throws(function() {new lo.Structure('stuff');}, TypeError); + assert.throws(function() {new lo.Structure(['stuff']);}, TypeError); // no unnamed variable-length fields - assert.throws(function() { new lo.Structure([lo.cstr()]); }, Error); + assert.throws(function() {new lo.Structure([lo.cstr()]);}, Error); }); test('basics', function() { var st = new lo.Structure([lo.u8('u8'), @@ -743,7 +743,7 @@ suite('Layout', function() { st: { u8: 23, u16: 65432, - s16be: -12345 + s16be: -12345, }, s24: -123456}; var b = new Buffer(12); @@ -863,17 +863,17 @@ suite('Layout', function() { suite('VariantLayout', function() { test('invalid ctor', function() { var un = new lo.Union(lo.u8(), lo.u32()); - assert.throws(function() { new lo.VariantLayout(); }, TypeError); - assert.throws(function() { new lo.VariantLayout('other'); }, TypeError); - assert.throws(function() { new lo.VariantLayout(un); }, TypeError); - assert.throws(function() { new lo.VariantLayout(un, 1.2); }, TypeError); - assert.throws(function() { new lo.VariantLayout(un, 'str'); }, TypeError); - assert.throws(function() { new lo.VariantLayout(un, 1); }, TypeError); - assert.throws(function() { new lo.VariantLayout(un, 1, 'other'); }, + assert.throws(function() {new lo.VariantLayout();}, TypeError); + assert.throws(function() {new lo.VariantLayout('other');}, TypeError); + assert.throws(function() {new lo.VariantLayout(un);}, TypeError); + assert.throws(function() {new lo.VariantLayout(un, 1.2);}, TypeError); + assert.throws(function() {new lo.VariantLayout(un, 'str');}, TypeError); + assert.throws(function() {new lo.VariantLayout(un, 1);}, TypeError); + assert.throws(function() {new lo.VariantLayout(un, 1, 'other');}, TypeError); - assert.throws(function() { new lo.VariantLayout(un, 1, lo.f64()); }, + assert.throws(function() {new lo.VariantLayout(un, 1, lo.f64());}, Error); - assert.throws(function() { new lo.VariantLayout(un, 1, lo.f32()); }, + assert.throws(function() {new lo.VariantLayout(un, 1, lo.f32());}, TypeError); }); test('ctor', function() { @@ -894,10 +894,10 @@ suite('Layout', function() { assert.equal(un.getSpan(b), 5); assert.equal(Buffer('0168692100', 'hex').compare(b.slice(0, 5)), 0); // This one overruns the Buffer - assert.throws(function() { d.encode({s: 'far too long'}, b); }, + assert.throws(function() {d.encode({s: 'far too long'}, b);}, RangeError); // This one fits in the buffer but overruns the union - assert.throws(function() { d.encode({s: 'too long'}, b); }, Error); + assert.throws(function() {d.encode({s: 'too long'}, b);}, Error); }); }); suite('ExternalLayout', function() { @@ -906,7 +906,7 @@ suite('Layout', function() { assert(el instanceof lo.ExternalLayout); assert(el instanceof lo.Layout); assert.equal(el.property, 'prop'); - assert.throws(function() { el.isCount(); }, Error); + assert.throws(function() {el.isCount();}, Error); }); }); suite('GreedyCount', function() { @@ -923,8 +923,8 @@ suite('Layout', function() { assert.equal(nel.elementSpan, 5); assert.equal(nel.property, 'name'); - assert.throws(function() { lo.greedy('hi'); }, TypeError); - assert.throws(function() { lo.greedy(0); }, TypeError); + assert.throws(function() {lo.greedy('hi');}, TypeError); + assert.throws(function() {lo.greedy(0);}, TypeError); }); test('#decode', function() { var el = new lo.greedy(); @@ -966,21 +966,21 @@ suite('Layout', function() { var b = Buffer('0001020304050607', 'hex'); assert.equal(u8.decode(b), 0); assert.equal(al.decode(b), 1); - assert.throws(function() { bl.decode(b); }, RangeError); + assert.throws(function() {bl.decode(b);}, RangeError); assert.equal(u8.decode(b, 4), 4); assert.equal(al.decode(b, 4), 5); assert.equal(bl.decode(b, 4), 3); assert.equal(u8.encode(0x80, b), 1); assert.equal(al.encode(0x91, b), 1); - assert.throws(function() { bl.encode(0x70, b); }, RangeError); + assert.throws(function() {bl.encode(0x70, b);}, RangeError); assert.equal(u8.encode(0x84, b, 4), 1); assert.equal(al.encode(0x94, b, 4), 1); assert.equal(bl.encode(0x74, b, 4), 1); assert.equal(Buffer('8091027484940607', 'hex').compare(b), 0); }); test('invalid ctor', function() { - assert.throws(function() { new lo.OffsetLayout('hi'); }, TypeError); - assert.throws(function() { new lo.OffsetLayout(lo.u8(), 'hi'); }, + assert.throws(function() {new lo.OffsetLayout('hi');}, TypeError); + assert.throws(function() {new lo.OffsetLayout(lo.u8(), 'hi');}, TypeError); }); }); @@ -988,17 +988,17 @@ suite('Layout', function() { test('abstract', function() { var ud = new lo.UnionDiscriminator('p'); assert.equal(ud.property, 'p'); - assert.throws(function() { ud.decode(Buffer('00', 'hex')); }, Error); - assert.throws(function() { ud.encode(0, new Buffer(1)); }, Error); + assert.throws(function() {ud.decode(Buffer('00', 'hex'));}, Error); + assert.throws(function() {ud.encode(0, new Buffer(1));}, Error); }); }); suite('UnionLayoutDiscriminator', function() { test('invalid ctor', function() { - assert.throws(function() { new lo.UnionLayoutDiscriminator('hi'); }, + assert.throws(function() {new lo.UnionLayoutDiscriminator('hi');}, TypeError); - assert.throws(function() { lo.unionLayoutDiscriminator('hi'); }, + assert.throws(function() {lo.unionLayoutDiscriminator('hi');}, TypeError); - assert.throws(function() { new lo.UnionLayoutDiscriminator(lo.f32()); }, + assert.throws(function() {new lo.UnionLayoutDiscriminator(lo.f32());}, TypeError); assert.throws(function() { new lo.UnionLayoutDiscriminator(lo.u8(), 'hi'); @@ -1007,11 +1007,11 @@ suite('Layout', function() { }); suite('Union', function() { test('invalid ctor', function() { - assert.throws(function() { new lo.Union(); }, TypeError); - assert.throws(function() { new lo.Union('other'); }, TypeError); - assert.throws(function() { new lo.Union(lo.f32()); }, TypeError); - assert.throws(function() { new lo.Union(lo.u8(), 'other'); }, TypeError); - assert.throws(function() { new lo.Union(lo.u8(), lo.cstr()); }, Error); + assert.throws(function() {new lo.Union();}, TypeError); + assert.throws(function() {new lo.Union('other');}, TypeError); + assert.throws(function() {new lo.Union(lo.f32());}, TypeError); + assert.throws(function() {new lo.Union(lo.u8(), 'other');}, TypeError); + assert.throws(function() {new lo.Union(lo.u8(), lo.cstr());}, Error); }); test('basics', function() { var dlo = lo.u8(); @@ -1080,8 +1080,8 @@ suite('Layout', function() { assert.notEqual(un.span, vlo.span + lo3.span); assert.deepEqual(un.decode(b), obj); assert.equal(Buffer('0305060406', 'hex').compare(b), 0); - assert.throws(function() { v2.encode(obj, b); }, TypeError); - assert.throws(function() { v2.decode(b); }, Error); + assert.throws(function() {v2.encode(obj, b);}, TypeError); + assert.throws(function() {v2.decode(b);}, Error); }); test('custom default', function() { var dlo = lo.u8('number'); @@ -1130,7 +1130,7 @@ suite('Layout', function() { assert.equal(b2.toString('hex'), b.toString('hex')); var obj2 = {variant: obj.number, content: obj.payload}; - assert.throws(function() { un.encode(obj2, b2); }); + assert.throws(function() {un.encode(obj2, b2);}); }); test('issue#7.internal.anon', function() { var dlo = lo.u8(); @@ -1253,7 +1253,7 @@ suite('Layout', function() { assert.equal(un.encode(src, b), un.span); assert.equal(Buffer('0201020304', 'hex').compare(b), 0); - assert.throws(function() { un.getSourceVariant({other: 3}); }, Error); + assert.throws(function() {un.getSourceVariant({other: 3});}, Error); src = {str: 'hi'}; vlo = un.getSourceVariant(src); assert.strictEqual(vlo, v3); @@ -1270,6 +1270,7 @@ suite('Layout', function() { var csrc; un.configGetSourceVariant(function(src) { csrc = src; + // eslint-disable-next-line no-invalid-this return this.defaultGetSourceVariant(src); }); var src = {v: 3, u32: 29}; @@ -1286,7 +1287,7 @@ suite('Layout', function() { assert(0 > un.span); b.fill(0xFF); - assert.throws(function() { un.decode(b); }, Error); + assert.throws(function() {un.decode(b);}, Error); var obj = {u32: 0x12345678}; assert.equal(un.encode(obj, b), 1 + 4); assert.equal(v1.getSpan(b), 5); @@ -1314,7 +1315,7 @@ suite('Layout', function() { assert.deepEqual(un.decode(b), obj); b[0] = 5; - assert.throws(function() { un.getSpan(b); }, Error); + assert.throws(function() {un.getSpan(b);}, Error); b.fill(0xa5); assert.equal(un.encode(obj, b, 1), 1 + 3 + 1); @@ -1355,16 +1356,16 @@ suite('Layout', function() { }); suite('BitStructure', function() { test('invalid ctor', function() { - assert.throws(function() { new lo.BitStructure(); }, TypeError); - assert.throws(function() { new lo.BitStructure(lo.f32()); }, TypeError); - assert.throws(function() { new lo.BitStructure(lo.s32()); }, TypeError); - assert.throws(function() { new lo.BitStructure(lo.u40()); }, Error); + assert.throws(function() {new lo.BitStructure();}, TypeError); + assert.throws(function() {new lo.BitStructure(lo.f32());}, TypeError); + assert.throws(function() {new lo.BitStructure(lo.s32());}, TypeError); + assert.throws(function() {new lo.BitStructure(lo.u40());}, Error); var bs = new lo.BitStructure(lo.u32()); - assert.throws(function() { new lo.BitField(lo.u32(), 8); }, TypeError); - assert.throws(function() { new lo.BitField(bs, 'hi'); }, TypeError); - assert.throws(function() { new lo.BitField(bs, 0); }, TypeError); - assert.throws(function() { new lo.BitField(bs, 40); }, Error); + assert.throws(function() {new lo.BitField(lo.u32(), 8);}, TypeError); + assert.throws(function() {new lo.BitField(bs, 'hi');}, TypeError); + assert.throws(function() {new lo.BitField(bs, 0);}, TypeError); + assert.throws(function() {new lo.BitField(bs, 40);}, Error); }); test('invalid add', function() { assert.throws(function() { @@ -1404,8 +1405,8 @@ suite('Layout', function() { bf10.encode((1 << 10) - 1); bf6.encode((1 << 6) - 1); assert.equal(bs._packedGetValue(), 0xFFFF); - assert.throws(function() { bf6.encode('hi', b); }, Error); - assert.throws(function() { bf6.encode(1 << 6, b); }, Error); + 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); @@ -1442,7 +1443,7 @@ suite('Layout', function() { assert.equal(bf2.valueMask, 0x03); assert.equal(bf2.wordMask, 0x06); - assert.throws(function() { bs.addField(30); }); + assert.throws(function() {bs.addField(30);}); bs.addField(29, 'x'); var bf3 = bs.fields[2]; assert.equal(bf3.bits, 29); @@ -1480,7 +1481,7 @@ suite('Layout', function() { assert.equal(bf2.valueMask, 0x3); assert.equal(bf2.wordMask, 0x60000000); - assert.throws(function() { bs.addField(30); }); + assert.throws(function() {bs.addField(30);}); bs.addField(29, 'x'); var bf3 = bs.fields[2]; assert.equal(bf3.bits, 29); @@ -1589,19 +1590,19 @@ suite('Layout', function() { assert.equal(b[0], 0); bs.encode({}, b); assert.equal(b[0], 0); - assert.throws(function() { bs.encode({v: false}, b); }, - function(err) { return checkError(err, TypeError, /BitField.encode\[v\] value must be integer/); }); - assert.throws(function() { bs.encode({v: 1.2}, b); }, - function(err) { return checkError(err, TypeError, /BitField.encode\[v\] value must be integer/); }); - assert.throws(function() { bs.encode({b: 1.2}, b); }, - function(err) { return checkError(err, TypeError, /BitField.encode\[b\] value must be integer/); }); + assert.throws(function() {bs.encode({v: false}, b);}, + function(err) {return checkError(err, TypeError, /BitField.encode\[v\] value must be integer/);}); + assert.throws(function() {bs.encode({v: 1.2}, b);}, + function(err) {return checkError(err, TypeError, /BitField.encode\[v\] value must be integer/);}); + assert.throws(function() {bs.encode({b: 1.2}, b);}, + function(err) {return checkError(err, TypeError, /BitField.encode\[b\] value must be integer/);}); }); }); suite('Blob', function() { test('invalid ctor', function() { - assert.throws(function() { new lo.Blob(); }, TypeError); - assert.throws(function() { new lo.Blob(lo.u8()); }, TypeError); - assert.throws(function() { new lo.Blob(lo.offset(lo.f32())); }, + assert.throws(function() {new lo.Blob();}, TypeError); + assert.throws(function() {new lo.Blob(lo.u8());}, TypeError); + assert.throws(function() {new lo.Blob(lo.offset(lo.f32()));}, TypeError); }); test('ctor', function() { @@ -1623,8 +1624,8 @@ suite('Layout', function() { 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); - assert.throws(function() { bl.encode('ABC', b); }, Error); - assert.throws(function() { bl.encode(Buffer('0102', 'hex'), b); }, + assert.throws(function() {bl.encode('ABC', b);}, Error); + assert.throws(function() {bl.encode(Buffer('0102', 'hex'), b);}, Error); }); test('var length', function() { @@ -1726,7 +1727,7 @@ suite('Layout', function() { }); test('#getSpan', function() { var cst = new lo.CString(); - assert.throws(function() { cst.getSpan(); }, TypeError); + assert.throws(function() {cst.getSpan();}, TypeError); assert.equal(cst.getSpan(Buffer('00', 'hex')), 1); assert.equal(cst.getSpan(Buffer('4100', 'hex')), 2); assert.equal(cst.getSpan(Buffer('4100', 'hex'), 1), 1); @@ -1752,13 +1753,13 @@ suite('Layout', function() { assert.equal(Buffer('414200ff', 'hex').compare(b), 0); assert.equal(cst.encode(5, b), 1 + 1); assert.equal(Buffer('350000ff', 'hex').compare(b), 0); - assert.throws(function() { cst.encode('too long', b); }, RangeError); + assert.throws(function() {cst.encode('too long', b);}, RangeError); }); test('in struct', function() { var st = lo.struct([lo.cstr('k'), lo.cstr('v')]); var b = Buffer('6100323300', 'hex'); - assert.throws(function() { st.getSpan(); }, RangeError); + assert.throws(function() {st.getSpan();}, RangeError); assert.equal(st.fields[0].getSpan(b), 2); assert.equal(st.fields[1].getSpan(b, 2), 3); assert.equal(st.getSpan(b), 5); @@ -1797,16 +1798,16 @@ suite('Layout', function() { suite('objectConstructor', function() { test('invalid ctor', function() { function Class() {} - assert.throws(function() { lo.bindConstructorLayout(4); }, TypeError); - assert.throws(function() { lo.bindConstructorLayout(Class); }, TypeError); - assert.throws(function() { lo.bindConstructorLayout(Class, 4); }, TypeError); + assert.throws(function() {lo.bindConstructorLayout(4);}, TypeError); + assert.throws(function() {lo.bindConstructorLayout(Class);}, TypeError); + assert.throws(function() {lo.bindConstructorLayout(Class, 4);}, TypeError); var clo = lo.struct([lo.u8('u8')]); lo.bindConstructorLayout(Class, clo); assert(Class.hasOwnProperty('layout_')); assert(clo.hasOwnProperty('boundConstructor_')); - assert.throws(function() { lo.bindConstructorLayout(Class, clo); }, Error); + assert.throws(function() {lo.bindConstructorLayout(Class, clo);}, Error); function Class2() {} - assert.throws(function() { lo.bindConstructorLayout(Class2, clo); }, Error); + assert.throws(function() {lo.bindConstructorLayout(Class2, clo);}, Error); }); test('struct', function() { function Sample(temp_dCel, humidity_ppt) { @@ -1864,7 +1865,7 @@ suite('Layout', function() { assert.deepEqual(po, p); }); test('bits', function() { - function Header() { } + function Header() {} Header.prototype.power = function() { return ['off', 'lo', 'med', 'hi'][this.pwr]; }; @@ -1883,7 +1884,7 @@ suite('Layout', function() { assert.equal(b.compare(nb), 0); }); test('union', function() { - function Union() { } + function Union() {} lo.bindConstructorLayout(Union, lo.union(lo.u8('var'), lo.blob(8, 'unk'))); function VFloat(v) { this.f32 = v; diff --git a/test/examples.js b/test/examples.js index d209cf0..12e71a9 100644 --- a/test/examples.js +++ b/test/examples.js @@ -79,17 +79,17 @@ struct { lo.bindConstructorLayout(Union, lo.union(lo.u8('t'), lo.seq(lo.u8(), 4, 'u8'))); - function Vu32(v) { this.u32 = v; } + function Vu32(v) {this.u32 = v;} util.inherits(Vu32, Union); lo.bindConstructorLayout(Vu32, Union.layout_.addVariant('w'.charCodeAt(0), lo.u32(), 'u32')); - function Vs16(v) { this.s16 = v; } + function Vs16(v) {this.s16 = v;} util.inherits(Vs16, Union); lo.bindConstructorLayout(Vs16, Union.layout_.addVariant('h'.charCodeAt(0), lo.seq(lo.s16(), 2), 's16')); - function Vf32(v) { this.f32 = v; } + function Vf32(v) {this.f32 = v;} util.inherits(Vf32, Union); lo.bindConstructorLayout(Vf32, Union.layout_.addVariant('f'.charCodeAt(0), lo.f32(), 'f32')); @@ -205,6 +205,7 @@ struct ds { if (src.hasOwnProperty('b')) { return src.b ? tr : fa; } + // eslint-disable-next-line no-invalid-this return this.defaultGetSourceVariant(src); }); From f0475ef7a8731e30a238db5fc026ffc92382ce58 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 16 Dec 2017 10:34:33 -0600 Subject: [PATCH 12/17] Layout: ES6 conversion: classes A few let/const as well, but not complete. --- lib/Layout.js | 2947 +++++++++++++++++++++++++------------------------ 1 file changed, 1498 insertions(+), 1449 deletions(-) diff --git a/lib/Layout.js b/lib/Layout.js index d327f44..3f55818 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -131,56 +131,10 @@ 'use strict'; -var assert = require('assert'); -var util = require('util'); +const assert = require('assert'); require('./patchIssue3992'); -/* eslint-disable */ -/* istanbul ignore next */ -/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger */ -Number.isInteger = Number.isInteger || function(value) { - return 'number' === typeof value && - isFinite(value) && - Math.floor(value) === value; -}; - -/* istanbul ignore next */ -/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign */ -if (!Object.assign) { - Object.defineProperty(Object, 'assign', { - enumerable: false, - configurable: true, - writable: true, - value: function(target) { - 'use strict'; - if (target === undefined || null === target) { - throw new TypeError('Cannot convert first argument to object'); - } - - var to = Object(target); - for (var i = 1; i < arguments.length; i++) { - var nextSource = arguments[i]; - if (nextSource === undefined || null === nextSource) { - continue; - } - nextSource = Object(nextSource); - - var keysArray = Object.keys(nextSource); - for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { - var nextKey = keysArray[nextIndex]; - var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); - if (desc !== undefined && desc.enumerable) { - to[nextKey] = nextSource[nextKey]; - } - } - } - return to; - } - }); -} -/* eslint-enable */ - /** * Base class for layout objects. * @@ -198,32 +152,34 @@ if (!Object.assign) { * @constructor * @abstract */ -function Layout(span, property) { - if (!Number.isInteger(span)) { - throw new TypeError('span must be an integer'); - } - - /** The span of the layout in bytes. - * - * Positive values are generally expected. - * - * Zero will only appear in {@link Constant|Constant}s and in - * {@link Sequence|Sequence}s where the {@link - * Sequence#count|count} is zero. - * - * A negative value indicates that the span is value-specific, and - * must be obtained using {@link Layout#getSpan|getSpan}. */ - this.span = span; +class Layout { + constructor(span, property) { + if (!Number.isInteger(span)) { + throw new TypeError('span must be an integer'); + } - /** The property name used when this layout is represented in an - * Object. - * - * Used only for layouts that {@link Layout#decode|decode} to Object - * instances. If left undefined the span of the unnamed layout will - * be treated as padding: it will not be mutated by {@link - * Layout#encode|encode} nor represented as a property in the - * decoded Object. */ - this.property = property; + /** The span of the layout in bytes. + * + * Positive values are generally expected. + * + * Zero will only appear in {@link Constant|Constant}s and in + * {@link Sequence|Sequence}s where the {@link + * Sequence#count|count} is zero. + * + * A negative value indicates that the span is value-specific, and + * must be obtained using {@link Layout#getSpan|getSpan}. */ + this.span = span; + + /** The property name used when this layout is represented in an + * Object. + * + * Used only for layouts that {@link Layout#decode|decode} to Object + * instances. If left undefined the span of the unnamed layout will + * be treated as padding: it will not be mutated by {@link + * Layout#encode|encode} nor represented as a property in the + * decoded Object. */ + this.property = property; + } /** Function to create an Object into which decoded properties will * be written. @@ -240,52 +196,123 @@ function Layout(span, property) { * * See {@link module:Layout.bindConstructorLayout|bindConstructorLayout()}. */ - this.makeDestinationObject = function() { + makeDestinationObject() { return {}; - }; -} + } -/** - * Decode from a Buffer into an JavaScript value. - * - * @param {Buffer} b - the buffer from which encoded data is read. - * - * @param {Number} [offset] - the offset at which the encoded data - * starts. If absent a zero offset is inferred. - * - * @returns {(Number|Array|Object)} - the value of the decoded data. - * - * @abstract - */ -Layout.prototype.decode = function(b, offset) { - throw new Error('Layout is abstract'); -}; + /** + * Decode from a Buffer into an JavaScript value. + * + * @param {Buffer} b - the buffer from which encoded data is read. + * + * @param {Number} [offset] - the offset at which the encoded data + * starts. If absent a zero offset is inferred. + * + * @returns {(Number|Array|Object)} - the value of the decoded data. + * + * @abstract + */ + decode(b, offset) { + throw new Error('Layout is abstract'); + } -/** - * Encode a JavaScript value into a Buffer. - * - * @param {(Number|Array|Object)} src - the value to be encoded into - * the buffer. The type accepted depends on the (sub-)type of {@link - * Layout|Layout}. - * - * @param {Buffer} b - the buffer into which encoded data will be - * written. - * - * @param {Number} [offset] - the offset at which the encoded data - * starts. If absent a zero offset is inferred. - * - * @returns {Number} - the number of bytes encoded, including the - * space skipped for internal padding, but excluding data such as - * {@link Sequence#count|lengths} when stored {@link - * ExternalLayout|externally}. This is the adjustment to `offset` - * producing the offset where data for the next layout would be - * written. - * - * @abstract - */ -Layout.prototype.encode = function(src, b, offset) { - throw new Error('Layout is abstract'); -}; + /** + * Encode a JavaScript value into a Buffer. + * + * @param {(Number|Array|Object)} src - the value to be encoded into + * the buffer. The type accepted depends on the (sub-)type of {@link + * Layout|Layout}. + * + * @param {Buffer} b - the buffer into which encoded data will be + * written. + * + * @param {Number} [offset] - the offset at which the encoded data + * starts. If absent a zero offset is inferred. + * + * @returns {Number} - the number of bytes encoded, including the + * space skipped for internal padding, but excluding data such as + * {@link Sequence#count|lengths} when stored {@link + * ExternalLayout|externally}. This is the adjustment to `offset` + * producing the offset where data for the next layout would be + * written. + * + * @abstract + */ + encode(src, b, offset) { + throw new Error('Layout is abstract'); + } + + /** + * Calculate the span of a specific instance of a layout. + * + * @param {Buffer} b - the buffer that contains an encoded instance. + * + * @param {Number} [offset] - the offset at which the encoded instance + * starts. If absent a zero offset is inferred. + * + * @return {Number} - the number of bytes covered by the layout + * instance. If this method is not overridden in a subclass the + * definition-time constant {@link Layout#span|span} will be + * returned. + * + * @throws {RangeError} - if the length of the value cannot be + * determined. + */ + getSpan(b, offset) { + if (0 > this.span) { + throw new RangeError('indeterminate span'); + } + return this.span; + } + + /** + * Replicate the layout using a new property. + * + * This function must be used to get a structurally-equivalent layout + * with a different name since all {@link Layout|Layout} instances are + * immutable. + * + * **NOTE** This is a shallow copy. All fields except {@link + * Layout#property|property} are strictly equal to the origin layout. + * + * @param {String} property - the value for {@link + * Layout#property|property} in the replica. + * + * @returns {Layout} - the copy with {@link Layout#property|property} + * set to `property`. + */ + replicate(property) { + const rv = Object.create(this.constructor.prototype); + Object.assign(rv, this); + rv.property = property; + return rv; + } + + /** + * Create an object from layout properties and an array of values. + * + * **NOTE** This function returns `undefined` if invoked on a layout + * that does not return its value as an Object. Objects are returned + * for things that are a {@link Structure|Structure}, which includes + * {@link VariantLayout|variant layouts} if they are structures, and + * excludes {@link Union|Union}s. If you want this feature for a + * union you must use {@link Union.getVariant|getVariant} to select + * the desired layout. + * + * @param {Array} values - an array of values that correspond to the + * default order for properties. As with {@link Layout#decode|decode} + * layout elements that have no property name are skipped when + * iterating over the array values. Only the top-level properties are + * assigned; arguments are not assigned to properties of contained + * layouts. Any unused values are ignored. + * + * @return {(Object|undefined)} + */ + fromArray(values) { + return undefined; + } +} +exports.Layout = Layout; /* Provide text that carries a name (such as for a function that will * be throwing an error) annotated with the property of a given layout @@ -300,76 +327,6 @@ function nameWithProperty(name, lo) { } exports.nameWithProperty = nameWithProperty; -/** - * Calculate the span of a specific instance of a layout. - * - * @param {Buffer} b - the buffer that contains an encoded instance. - * - * @param {Number} [offset] - the offset at which the encoded instance - * starts. If absent a zero offset is inferred. - * - * @return {Number} - the number of bytes covered by the layout - * instance. If this method is not overridden in a subclass the - * definition-time constant {@link Layout#span|span} will be - * returned. - * - * @throws {RangeError} - if the length of the value cannot be - * determined. - */ -Layout.prototype.getSpan = function(b, offset) { - if (0 > this.span) { - throw new RangeError('indeterminate span'); - } - return this.span; -}; - -/** - * Replicate the layout using a new property. - * - * This function must be used to get a structurally-equivalent layout - * with a different name since all {@link Layout|Layout} instances are - * immutable. - * - * **NOTE** This is a shallow copy. All fields except {@link - * Layout#property|property} are strictly equal to the origin layout. - * - * @param {String} property - the value for {@link - * Layout#property|property} in the replica. - * - * @returns {Layout} - the copy with {@link Layout#property|property} - * set to `property`. - */ -Layout.prototype.replicate = function(property) { - var rv = Object.create(this.constructor.prototype); - Object.assign(rv, this); - rv.property = property; - return rv; -}; - -/** - * Create an object from layout properties and an array of values. - * - * **NOTE** This function returns `undefined` if invoked on a layout - * that does not return its value as an Object. Objects are returned - * for things that are a {@link Structure|Structure}, which includes - * {@link VariantLayout|variant layouts} if they are structures, and - * excludes {@link Union|Union}s. If you want this feature for a - * union you must use {@link Union.getVariant|getVariant} to select - * the desired layout. - * - * @param {Array} values - an array of values that correspond to the - * default order for properties. As with {@link Layout#decode|decode} - * layout elements that have no property name are skipped when - * iterating over the array values. Only the top-level properties are - * assigned; arguments are not assigned to properties of contained - * layouts. Any unused values are ignored. - * - * @return {(Object|undefined)} - */ -Layout.prototype.fromArray = function(values) { - return undefined; -}; - /** * Augment a constructor so that instances can be encoded/decoded * using a given layout. @@ -411,11 +368,9 @@ exports.bindConstructorLayout = function(ctor, layout) { } ctor.layout_ = layout; layout.boundConstructor_ = ctor; - // jscs:disable requireCapitalizedConstructors layout.makeDestinationObject = function() { return new ctor(); }; - // jscs:enable requireCapitalizedConstructors Object.defineProperty(ctor.prototype, 'encode', { configurable: false, enumerable: false, @@ -453,28 +408,25 @@ exports.bindConstructorLayout = function(ctor, layout) { * @param {string} [property] - initializer for {@link * Layout#property|property}. * - * @constructor * @abstract * @augments {Layout} */ -function ExternalLayout(span, property) { - Layout.call(this, span, property); +class ExternalLayout extends Layout { + /** + * Return `true` iff the external layout decodes to an unsigned + * integer layout. + * + * In that case it can be used as the source of {@link + * Sequence#count|Sequence counts}, {@link Blob#length|Blob lengths}, + * or as {@link UnionLayoutDiscriminator#layout|external union + * discriminators}. + * + * @abstract + */ + isCount() { + throw new Error('ExternalLayout is abstract'); + } } -util.inherits(ExternalLayout, Layout); -/** - * Return `true` iff the external layout decodes to an unsigned - * integer layout. - * - * In that case it can be used as the source of {@link - * Sequence#count|Sequence counts}, {@link Blob#length|Blob lengths}, - * or as {@link UnionLayoutDiscriminator#layout|external union - * discriminators}. - * - * @abstract - */ -ExternalLayout.prototype.isCount = function() { - throw new Error('ExternalLayout is abstract'); -}; /** * An {@link ExternalLayout|ExternalLayout} that determines its {@link @@ -492,34 +444,41 @@ ExternalLayout.prototype.isCount = function() { * @constructor * @augments {ExternalLayout} */ -function GreedyCount(elementSpan, property) { - if (undefined === elementSpan) { - elementSpan = 1; +class GreedyCount extends ExternalLayout { + constructor(elementSpan, property) { + if (undefined === elementSpan) { + elementSpan = 1; + } + if ((!Number.isInteger(elementSpan)) || (0 >= elementSpan)) { + throw new TypeError('elementSpan must be a (positive) integer'); + } + super(-1, property); + + /** The layout for individual elements of the sequence. The value + * must be a positive integer. If not provided, the value will be + * 1. */ + this.elementSpan = elementSpan; } - if ((!Number.isInteger(elementSpan)) || (0 >= elementSpan)) { - throw new TypeError('elementSpan must be a (positive) integer'); + + /** @override */ + isCount() { + return true; } - ExternalLayout.call(this, -1, property); - /** The layout for individual elements of the sequence. The value - * must be a positive integer. If not provided, the value will be - * 1. */ - this.elementSpan = elementSpan; -} -util.inherits(GreedyCount, ExternalLayout); -GreedyCount.prototype.isCount = function() { - return true; -}; -GreedyCount.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + const rem = b.length - offset; + return Math.floor(rem / this.elementSpan); } - var rem = b.length - offset; - return Math.floor(rem / this.elementSpan); -}; -GreedyCount.prototype.encode = function(src, b, offset) { - return 0; -}; + + /** @override */ + encode(src, b, offset) { + return 0; + } +} /** * An {@link ExternalLayout|ExternalLayout} that supports accessing a @@ -543,50 +502,54 @@ GreedyCount.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function OffsetLayout(layout, offset, property) { - if (!(layout instanceof Layout)) { - throw new TypeError('layout must be a Layout'); - } +class OffsetLayout extends ExternalLayout { + constructor(layout, offset, property) { + if (!(layout instanceof Layout)) { + throw new TypeError('layout must be a Layout'); + } - if (undefined === offset) { - offset = 0; - } else if (!Number.isInteger(offset)) { - throw new TypeError('offset must be integer or undefined'); - } + if (undefined === offset) { + offset = 0; + } else if (!Number.isInteger(offset)) { + throw new TypeError('offset must be integer or undefined'); + } - ExternalLayout.call(this, layout.span, property || layout.property); + super(layout.span, property || layout.property); - /** The subordinated layout. */ - this.layout = layout; + /** The subordinated layout. */ + this.layout = layout; - /** The location of {@link OffsetLayout#layout} relative to the - * start of another layout. - * - * The value may be positive or negative, but an error will thrown - * if at the point of use it goes outside the span of the Buffer - * being accessed. */ - this.offset = offset; -} -util.inherits(OffsetLayout, ExternalLayout); -/** @inheritdoc */ -OffsetLayout.prototype.isCount = function() { - return ((this.layout instanceof UInt) - || (this.layout instanceof UIntBE)); -}; -/** @inheritdoc */ -OffsetLayout.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; + /** The location of {@link OffsetLayout#layout} relative to the + * start of another layout. + * + * The value may be positive or negative, but an error will thrown + * if at the point of use it goes outside the span of the Buffer + * being accessed. */ + this.offset = offset; } - return this.layout.decode(b, offset + this.offset); -}; -/** @inheritdoc */ -OffsetLayout.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + isCount() { + return ((this.layout instanceof UInt) + || (this.layout instanceof UIntBE)); } - return this.layout.encode(src, b, offset + this.offset); -}; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return this.layout.decode(b, offset + this.offset); + } + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + return this.layout.encode(src, b, offset + this.offset); + } +} /** * Represent an unsigned integer in little-endian format. @@ -605,28 +568,31 @@ OffsetLayout.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function UInt(span, property) { - Layout.call(this, span, property); - if (6 < this.span) { - throw new RangeError('span must not exceed 6 bytes'); +class UInt extends Layout { + constructor(span, property) { + super(span, property); + if (6 < this.span) { + throw new RangeError('span must not exceed 6 bytes'); + } } -} -util.inherits(UInt, Layout); -/** @override */ -UInt.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return b.readUIntLE(offset, this.span); } - return b.readUIntLE(offset, this.span); -}; -/** @override */ -UInt.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + b.writeUIntLE(src, offset, this.span); + return this.span; } - b.writeUIntLE(src, offset, this.span); - return this.span; -}; +} /** * Represent an unsigned integer in big-endian format. @@ -645,28 +611,31 @@ UInt.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function UIntBE(span, property) { - Layout.call(this, span, property); - if (6 < this.span) { - throw new RangeError('span must not exceed 6 bytes'); +class UIntBE extends Layout { + constructor(span, property) { + super( span, property); + if (6 < this.span) { + throw new RangeError('span must not exceed 6 bytes'); + } } -} -util.inherits(UIntBE, Layout); -/** @override */ -UIntBE.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return b.readUIntBE(offset, this.span); } - return b.readUIntBE(offset, this.span); -}; -/** @override */ -UIntBE.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + b.writeUIntBE(src, offset, this.span); + return this.span; } - b.writeUIntBE(src, offset, this.span); - return this.span; -}; +} /** * Represent a signed integer in little-endian format. @@ -685,28 +654,31 @@ UIntBE.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function Int(span, property) { - Layout.call(this, span, property); - if (6 < this.span) { - throw new RangeError('span must not exceed 6 bytes'); +class Int extends Layout { + constructor(span, property) { + super(span, property); + if (6 < this.span) { + throw new RangeError('span must not exceed 6 bytes'); + } } -} -util.inherits(Int, Layout); -/** @override */ -Int.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return b.readIntLE(offset, this.span); } - return b.readIntLE(offset, this.span); -}; -/** @override */ -Int.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + b.writeIntLE(src, offset, this.span); + return this.span; } - b.writeIntLE(src, offset, this.span); - return this.span; -}; +} /** * Represent a signed integer in big-endian format. @@ -725,30 +697,34 @@ Int.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function IntBE(span, property) { - Layout.call(this, span, property); - if (6 < this.span) { - throw new RangeError('span must not exceed 6 bytes'); +class IntBE extends Layout { + constructor(span, property) { + super(span, property); + if (6 < this.span) { + throw new RangeError('span must not exceed 6 bytes'); + } } -} -util.inherits(IntBE, Layout); -/** @override */ -IntBE.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return b.readIntBE(offset, this.span); } - return b.readIntBE(offset, this.span); -}; -/** @override */ -IntBE.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + b.writeIntBE(src, offset, this.span); + return this.span; } - b.writeIntBE(src, offset, this.span); - return this.span; -}; +} + +const V2E32 = Math.pow(2, 32); -var V2E32 = Math.pow(2, 32); /* True modulus high and low 32-bit words, where low word is always * non-negative. */ function divmodInt64(src) { @@ -776,29 +752,32 @@ function roundedInt64(hi32, lo32) { * @constructor * @augments {Layout} */ -function NearUInt64(property) { - Layout.call(this, 8, property); +class NearUInt64 extends Layout { + constructor(property) { + super(8, property); + } + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + const lo32 = b.readUInt32LE(offset); + const hi32 = b.readUInt32LE(offset + 4); + return roundedInt64(hi32, lo32); + } + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + const split = divmodInt64(src); + b.writeUInt32LE(split.lo32, offset); + b.writeUInt32LE(split.hi32, offset + 4); + return 8; + } } -util.inherits(NearUInt64, Layout); -/** @override */ -NearUInt64.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; - } - var lo32 = b.readUInt32LE(offset); - var hi32 = b.readUInt32LE(offset + 4); - return roundedInt64(hi32, lo32); -}; -/** @override */ -NearUInt64.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var split = divmodInt64(src); - b.writeUInt32LE(split.lo32, offset); - b.writeUInt32LE(split.hi32, offset + 4); - return 8; -}; /** * Represent an unsigned 64-bit integer in big-endian format when @@ -812,29 +791,32 @@ NearUInt64.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function NearUInt64BE(property) { - Layout.call(this, 8, property); +class NearUInt64BE extends Layout { + constructor(property) { + super(8, property); + } + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + const hi32 = b.readUInt32BE(offset); + const lo32 = b.readUInt32BE(offset + 4); + return roundedInt64(hi32, lo32); + } + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + const split = divmodInt64(src); + b.writeUInt32BE(split.hi32, offset); + b.writeUInt32BE(split.lo32, offset + 4); + return 8; + } } -util.inherits(NearUInt64BE, Layout); -/** @override */ -NearUInt64BE.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; - } - var hi32 = b.readUInt32BE(offset); - var lo32 = b.readUInt32BE(offset + 4); - return roundedInt64(hi32, lo32); -}; -/** @override */ -NearUInt64BE.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var split = divmodInt64(src); - b.writeUInt32BE(split.hi32, offset); - b.writeUInt32BE(split.lo32, offset + 4); - return 8; -}; /** * Represent a signed 64-bit integer in little-endian format when @@ -848,29 +830,32 @@ NearUInt64BE.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function NearInt64(property) { - Layout.call(this, 8, property); +class NearInt64 extends Layout { + constructor(property) { + super(8, property); + } + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + const lo32 = b.readUInt32LE(offset); + const hi32 = b.readInt32LE(offset + 4); + return roundedInt64(hi32, lo32); + } + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + const split = divmodInt64(src); + b.writeUInt32LE(split.lo32, offset); + b.writeInt32LE(split.hi32, offset + 4); + return 8; + } } -util.inherits(NearInt64, Layout); -/** @override */ -NearInt64.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; - } - var lo32 = b.readUInt32LE(offset); - var hi32 = b.readInt32LE(offset + 4); - return roundedInt64(hi32, lo32); -}; -/** @override */ -NearInt64.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var split = divmodInt64(src); - b.writeUInt32LE(split.lo32, offset); - b.writeInt32LE(split.hi32, offset + 4); - return 8; -}; /** * Represent a signed 64-bit integer in big-endian format when @@ -884,60 +869,66 @@ NearInt64.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function NearInt64BE(property) { - Layout.call(this, 8, property); -} -util.inherits(NearInt64BE, Layout); -/** @override */ -NearInt64BE.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; - } - var hi32 = b.readInt32BE(offset); - var lo32 = b.readUInt32BE(offset + 4); - return roundedInt64(hi32, lo32); -}; -/** @override */ -NearInt64BE.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var split = divmodInt64(src); - b.writeInt32BE(split.hi32, offset); - b.writeUInt32BE(split.lo32, offset + 4); - return 8; -}; +class NearInt64BE extends Layout { + constructor(property) { + super(8, property); + } -/** - * Represent a 32-bit floating point number in little-endian format. - * - * *Factory*: {@link module:Layout.f32|f32} - * + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + const hi32 = b.readInt32BE(offset); + const lo32 = b.readUInt32BE(offset + 4); + return roundedInt64(hi32, lo32); + } + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + const split = divmodInt64(src); + b.writeInt32BE(split.hi32, offset); + b.writeUInt32BE(split.lo32, offset + 4); + return 8; + } +} + +/** + * Represent a 32-bit floating point number in little-endian format. + * + * *Factory*: {@link module:Layout.f32|f32} + * * @param {string} [property] - initializer for {@link * Layout#property|property}. * * @constructor * @augments {Layout} */ -function Float(property) { - Layout.call(this, 4, property); -} -util.inherits(Float, Layout); -/** @override */ -Float.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; +class Float extends Layout { + constructor(property) { + super(4, property); } - return b.readFloatLE(offset); -}; -/** @override */ -Float.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return b.readFloatLE(offset); } - b.writeFloatLE(src, offset); - return 4; -}; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + b.writeFloatLE(src, offset); + return 4; + } +} /** * Represent a 32-bit floating point number in big-endian format. @@ -950,25 +941,28 @@ Float.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function FloatBE(property) { - Layout.call(this, 4, property); -} -util.inherits(FloatBE, Layout); -/** @override */ -FloatBE.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; +class FloatBE extends Layout { + constructor(property) { + super(4, property); } - return b.readFloatBE(offset); -}; -/** @override */ -FloatBE.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return b.readFloatBE(offset); } - b.writeFloatBE(src, offset); - return 4; -}; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + b.writeFloatBE(src, offset); + return 4; + } +} /** * Represent a 64-bit floating point number in little-endian format. @@ -981,25 +975,28 @@ FloatBE.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function Double(property) { - Layout.call(this, 8, property); -} -util.inherits(Double, Layout); -/** @override */ -Double.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; +class Double extends Layout { + constructor(property) { + super(8, property); } - return b.readDoubleLE(offset); -}; -/** @override */ -Double.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return b.readDoubleLE(offset); } - b.writeDoubleLE(src, offset); - return 8; -}; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + b.writeDoubleLE(src, offset); + return 8; + } +} /** * Represent a 64-bit floating point number in big-endian format. @@ -1012,25 +1009,28 @@ Double.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function DoubleBE(property) { - Layout.call(this, 8, property); -} -util.inherits(DoubleBE, Layout); -/** @override */ -DoubleBE.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; +class DoubleBE extends Layout { + constructor(property) { + super(8, property); } - return b.readDoubleBE(offset); -}; -/** @override */ -DoubleBE.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + return b.readDoubleBE(offset); } - b.writeDoubleBE(src, offset); - return 8; -}; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + b.writeDoubleBE(src, offset); + return 8; + } +} /** * Represent a contiguous sequence of a specific layout as an Array. @@ -1050,102 +1050,105 @@ DoubleBE.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function Sequence(elementLayout, count, property) { - if (!(elementLayout instanceof Layout)) { - throw new TypeError('elementLayout must be a Layout'); - } - if (!(((count instanceof ExternalLayout) && count.isCount()) - || (Number.isInteger(count) && (0 <= count)))) { - throw new TypeError('count must be non-negative integer ' - + 'or an unsigned integer ExternalLayout'); - } - var span = -1; - if ((!(count instanceof ExternalLayout)) - && (0 < elementLayout.span)) { - span = count * elementLayout.span; - } +class Sequence extends Layout { + constructor(elementLayout, count, property) { + if (!(elementLayout instanceof Layout)) { + throw new TypeError('elementLayout must be a Layout'); + } + if (!(((count instanceof ExternalLayout) && count.isCount()) + || (Number.isInteger(count) && (0 <= count)))) { + throw new TypeError('count must be non-negative integer ' + + 'or an unsigned integer ExternalLayout'); + } + let span = -1; + if ((!(count instanceof ExternalLayout)) + && (0 < elementLayout.span)) { + span = count * elementLayout.span; + } - Layout.call(this, span, property); + super(span, property); - /** The layout for individual elements of the sequence. */ - this.elementLayout = elementLayout; + /** The layout for individual elements of the sequence. */ + this.elementLayout = elementLayout; - /** The number of elements in the sequence. - * - * This will be either a non-negative integer or an instance of - * {@link ExternalLayout|ExternalLayout} for which {@link - * ExternalLayout#isCount|isCount()} is `true`. */ - this.count = count; -} -util.inherits(Sequence, Layout); -/** @override */ -Sequence.prototype.getSpan = function(b, offset) { - if (0 <= this.span) { - return this.span; - } - if (undefined === offset) { - offset = 0; + /** The number of elements in the sequence. + * + * This will be either a non-negative integer or an instance of + * {@link ExternalLayout|ExternalLayout} for which {@link + * ExternalLayout#isCount|isCount()} is `true`. */ + this.count = count; } - var span = 0; - var count = this.count; - if (count instanceof ExternalLayout) { - count = count.decode(b, offset); + + /** @override */ + getSpan(b, offset) { + if (0 <= this.span) { + return this.span; + } + if (undefined === offset) { + offset = 0; + } + let span = 0; + let count = this.count; + if (count instanceof ExternalLayout) { + count = count.decode(b, offset); + } + if (0 < this.elementLayout.span) { + span = count * this.elementLayout.span; + } else { + let idx = 0; + while (idx < count) { + span += this.elementLayout.getSpan(b, offset + span); + ++idx; + } + } + return span; } - if (0 < this.elementLayout.span) { - span = count * this.elementLayout.span; - } else { - var idx = 0; - while (idx < count) { - var esp = this.elementLayout.getSpan(b, offset + span); - span += esp; - ++idx; + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + const rv = []; + let i = 0; + let count = this.count; + if (count instanceof ExternalLayout) { + count = count.decode(b, offset); } + while (i < count) { + rv.push(this.elementLayout.decode(b, offset)); + offset += this.elementLayout.getSpan(b, offset); + i += 1; + } + return rv; } - return span; -}; -/** @override */ -Sequence.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; - } - var rv = []; - var i = 0; - var count = this.count; - if (count instanceof ExternalLayout) { - count = count.decode(b, offset); - } - while (i < count) { - rv.push(this.elementLayout.decode(b, offset)); - offset += this.elementLayout.getSpan(b, offset); - i += 1; - } - return rv; -}; -/** Implement {@link Layout#encode|encode} for {@link Sequence|Sequence}. - * - * **NOTE** If `src` is shorter than {@link Sequence#count|count} then - * the unused space in the buffer is left unchanged. If `src` is - * longer than {@link Sequence#count|count} the unneeded elements are - * ignored. - * - * **NOTE** If {@link Layout#count|count} is an instance of {@link - * ExternalLayout|ExternalLayout} then the length of `src` will be - * encoded as the count after `src` is encoded. */ -Sequence.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var elo = this.elementLayout; - var span = 0; - src.forEach(function(v) { - elo.encode(v, b, offset + span); - span += elo.getSpan(b, offset + span); - }); - if (this.count instanceof ExternalLayout) { - this.count.encode(src.length, b, offset); + + /** Implement {@link Layout#encode|encode} for {@link Sequence|Sequence}. + * + * **NOTE** If `src` is shorter than {@link Sequence#count|count} then + * the unused space in the buffer is left unchanged. If `src` is + * longer than {@link Sequence#count|count} the unneeded elements are + * ignored. + * + * **NOTE** If {@link Layout#count|count} is an instance of {@link + * ExternalLayout|ExternalLayout} then the length of `src` will be + * encoded as the count after `src` is encoded. */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + const elo = this.elementLayout; + let span = 0; + src.forEach(function(v) { + elo.encode(v, b, offset + span); + span += elo.getSpan(b, offset + span); + }); + if (this.count instanceof ExternalLayout) { + this.count.encode(src.length, b, offset); + } + return span; } - return span; -}; +} /** * Represent a contiguous sequence of arbitrary layout elements as an @@ -1177,178 +1180,184 @@ Sequence.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function Structure(fields, property) { - function allLayouts(v, fd) { - return v && (fd instanceof Layout); - } - if ((!(fields instanceof Array)) - || (!fields.reduce(allLayouts, true))) { - throw new TypeError('fields must be array of Layout instances'); - } - - /* Verify absence of unnamed variable-length fields. */ - fields.forEach(function(fd) { - if ((0 > fd.span) - && (undefined === fd.property)) { - throw new Error('fields cannot contain unnamed variable-length layout'); +class Structure extends Layout { + constructor(fields, property) { + function allLayouts(v, fd) { + return v && (fd instanceof Layout); + } + if ((!(fields instanceof Array)) + || (!fields.reduce(allLayouts, true))) { + throw new TypeError('fields must be array of Layout instances'); } - }); - var span = -1; - try { - span = fields.reduce(function(v, fd) { - return v + fd.getSpan(); - }, 0); - } catch (e) { - } - Layout.call(this, span, property); + /* Verify absence of unnamed variable-length fields. */ + fields.forEach(function(fd) { + if ((0 > fd.span) + && (undefined === fd.property)) { + throw new Error('fields cannot contain unnamed variable-length layout'); + } + }); - /** The sequence of {@link Layout|Layout} values that comprise the - * structure. - * - * The individual elements need not be the same type, and may be - * either scalar or aggregate layouts. If a member layout leaves - * its {@link Layout#property|property} undefined the - * corresponding region of the buffer associated with the element - * will not be mutated. - * - * @type {Layout[]} */ - this.fields = fields; -} -util.inherits(Structure, Layout); -/** @override */ -Structure.prototype.getSpan = function(b, offset) { - if (0 <= this.span) { - return this.span; - } - if (undefined === offset) { - offset = 0; - } - var span = 0; - try { - span = this.fields.reduce(function(v, fd) { - var fsp = fd.getSpan(b, offset); - offset += fsp; - return v + fsp; - }, 0); - } catch (e) { - throw new RangeError('indeterminate span'); - } - return span; -}; -/** @override */ -Structure.prototype.decode = function(b, offset) { - var dest = this.makeDestinationObject(); - if (undefined === offset) { - offset = 0; - } - this.fields.forEach(function(fd) { - if (undefined !== fd.property) { - dest[fd.property] = fd.decode(b, offset); + let span = -1; + try { + span = fields.reduce(function(v, fd) { + return v + fd.getSpan(); + }, 0); + } catch (e) { } - offset += fd.getSpan(b, offset); - }); - return dest; -}; -/** Implement {@link Layout#encode|encode} for {@link Structure|Structure}. - * - * If `src` is missing a property for a member with a defined {@link - * Layout#property|property} the corresponding region of the buffer is - * left unmodified. */ -Structure.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var firstOffset = offset; - var lastOffset = 0; - var lastWrote = 0; - this.fields.forEach(function(fd) { - var span = fd.span; - lastWrote = (0 < span) ? span : 0; - if (undefined === fd.property) { - /* By construction the field must be fixed-length (because - * unnamed variable-length fields are disallowed when - * encoding). But check it anyway. */ - assert(0 < span); - } else { - var fv = src[fd.property]; - if (undefined !== fv) { - lastWrote = fd.encode(fv, b, offset); - if (0 > span) { - /* Read the as-encoded span, which is not necessarily the - * same as what we wrote. */ - span = fd.getSpan(b, offset); - } - } + super(span, property); + + /** The sequence of {@link Layout|Layout} values that comprise the + * structure. + * + * The individual elements need not be the same type, and may be + * either scalar or aggregate layouts. If a member layout leaves + * its {@link Layout#property|property} undefined the + * corresponding region of the buffer associated with the element + * will not be mutated. + * + * @type {Layout[]} */ + this.fields = fields; + } + + /** @override */ + getSpan(b, offset) { + if (0 <= this.span) { + return this.span; } - lastOffset = offset; - offset += span; - }); - /* Use (lastOffset + lastWrote) instead of offset because the last - * item may have had a dynamic length and we don't want to include - * the padding between it and the end of the space reserved for - * it. */ - return (lastOffset + lastWrote) - firstOffset; -}; -/** @override */ -Structure.prototype.fromArray = function(values) { - var dest = this.makeDestinationObject(); - this.fields.forEach(function(fd) { - if ((undefined !== fd.property) - && (0 < values.length)) { - dest[fd.property] = values.shift(); + if (undefined === offset) { + offset = 0; } - }); - return dest; -}; -/** - * Get access to the layout of a given property. - * - * @param {String} property - the structure member of interest. - * - * @return {Layout} - the layout associated with `property`, or - * undefined if there is no such property. - */ -Structure.prototype.layoutFor = function(property) { - var rv; - if (property) { + let span = 0; + try { + span = this.fields.reduce(function(v, fd) { + const fsp = fd.getSpan(b, offset); + offset += fsp; + return v + fsp; + }, 0); + } catch (e) { + throw new RangeError('indeterminate span'); + } + return span; + } + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + const dest = this.makeDestinationObject(); this.fields.forEach(function(fd) { - if (fd.property === property) { - rv = fd; + if (undefined !== fd.property) { + dest[fd.property] = fd.decode(b, offset); } + offset += fd.getSpan(b, offset); }); + return dest; } - return rv; -}; -/** - * Get the offset of a structure member. - * - * @param {String} property - the structure member of interest. - * - * @return {Number} - the offset in bytes to the start of `property` - * within the structure, or undefined if `property` is not a field - * within the structure. If the property is a member but follows a - * variable-length structure member a negative number will be - * returned. - */ -Structure.prototype.offsetOf = function(property) { - var rv; - var offset = 0; - if (property) { + /** Implement {@link Layout#encode|encode} for {@link Structure|Structure}. + * + * If `src` is missing a property for a member with a defined {@link + * Layout#property|property} the corresponding region of the buffer is + * left unmodified. */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + const firstOffset = offset; + let lastOffset = 0; + let lastWrote = 0; this.fields.forEach(function(fd) { - if (fd.property === property) { - rv = offset; + let span = fd.span; + lastWrote = (0 < span) ? span : 0; + if (undefined === fd.property) { + /* By construction the field must be fixed-length (because + * unnamed variable-length fields are disallowed when + * encoding). But check it anyway. */ + assert(0 < span); + } else { + var fv = src[fd.property]; + if (undefined !== fv) { + lastWrote = fd.encode(fv, b, offset); + if (0 > span) { + /* Read the as-encoded span, which is not necessarily the + * same as what we wrote. */ + span = fd.getSpan(b, offset); + } + } } - if (0 > fd.span) { - offset = -1; - } else if (0 <= offset) { - offset += fd.span; + lastOffset = offset; + offset += span; + }); + /* Use (lastOffset + lastWrote) instead of offset because the last + * item may have had a dynamic length and we don't want to include + * the padding between it and the end of the space reserved for + * it. */ + return (lastOffset + lastWrote) - firstOffset; + } + + /** @override */ + fromArray(values) { + const dest = this.makeDestinationObject(); + this.fields.forEach(function(fd) { + if ((undefined !== fd.property) + && (0 < values.length)) { + dest[fd.property] = values.shift(); } }); + return dest; } - return rv; -}; + + /** + * Get access to the layout of a given property. + * + * @param {String} property - the structure member of interest. + * + * @return {Layout} - the layout associated with `property`, or + * undefined if there is no such property. + */ + layoutFor(property) { + let rv; + if (property) { + this.fields.forEach(function(fd) { + if (fd.property === property) { + rv = fd; + } + }); + } + return rv; + }; + + /** + * Get the offset of a structure member. + * + * @param {String} property - the structure member of interest. + * + * @return {Number} - the offset in bytes to the start of `property` + * within the structure, or undefined if `property` is not a field + * within the structure. If the property is a member but follows a + * variable-length structure member a negative number will be + * returned. + */ + offsetOf(property) { + let rv; + let offset = 0; + if (property) { + this.fields.forEach(function(fd) { + if (fd.property === property) { + rv = offset; + } + if (0 > fd.span) { + offset = -1; + } else if (0 <= offset) { + offset += fd.span; + } + }); + } + return rv; + } +} /** * An object that can provide a {@link @@ -1365,27 +1374,31 @@ Structure.prototype.offsetOf = function(property) { * @constructor * @abstract */ -function UnionDiscriminator(property) { - /** The {@link Layout#property|property} to be used when the - * discriminator is referenced in isolation (generally when {@link - * Union#decode|Union decode} cannot delegate to a specific - * variant). */ - this.property = property; +class UnionDiscriminator { + constructor(property) { + /** The {@link Layout#property|property} to be used when the + * discriminator is referenced in isolation (generally when {@link + * Union#decode|Union decode} cannot delegate to a specific + * variant). */ + this.property = property; + } + + /** Analog to {@link Layout#decode|Layout decode} for union discriminators. + * + * The implementation of this method need not reference the buffer if + * variant information is available through other means. */ + decode() { + throw new Error('UnionDiscriminator is abstract'); + } + + /** Analog to {@link Layout#decode|Layout encode} for union discriminators. + * + * The implementation of this method need not store the value if + * variant information is maintained through other means. */ + encode() { + throw new Error('UnionDiscriminator is abstract'); + } } -/** Analog to {@link Layout#decode|Layout decode} for union discriminators. - * - * The implementation of this method need not reference the buffer if - * variant information is available through other means. */ -UnionDiscriminator.prototype.decode = function() { - throw new Error('UnionDiscriminator is abstract'); -}; -/** Analog to {@link Layout#decode|Layout encode} for union discriminators. - * - * The implementation of this method need not store the value if - * variant information is maintained through other means. */ -UnionDiscriminator.prototype.encode = function() { - throw new Error('UnionDiscriminator is abstract'); -}; /** * An object that can provide a {@link @@ -1405,29 +1418,30 @@ UnionDiscriminator.prototype.encode = function() { * @constructor * @augments {UnionDiscriminator} */ -function UnionLayoutDiscriminator(layout, property) { - if (!((layout instanceof ExternalLayout) - && layout.isCount())) { - throw new TypeError('layout must be an unsigned integer ExternalLayout'); +class UnionLayoutDiscriminator extends UnionDiscriminator { + constructor(layout, property) { + if (!((layout instanceof ExternalLayout) + && layout.isCount())) { + throw new TypeError('layout must be an unsigned integer ExternalLayout'); + } + + super(property || layout.property || 'variant'); + + /** The {@link ExternalLayout|ExternalLayout} used to access the + * discriminator value. */ + this.layout = layout; } - /** The {@link ExternalLayout|ExternalLayout} used to access the - * discriminator value. */ - this.layout = layout; + /** Delegate decoding to {@link UnionLayoutDiscriminator#layout|layout}. */ + decode(b, offset) { + return this.layout.decode(b, offset); + } - UnionDiscriminator.call(this, property || layout.property || 'variant'); + /** Delegate encoding to {@link UnionLayoutDiscriminator#layout|layout}. */ + encode(src, b, offset) { + return this.layout.encode(src, b, offset); + } } -UnionLayoutDiscriminator.prototype - = Object.create(UnionDiscriminator.prototype); -UnionLayoutDiscriminator.prototype.constructor = UnionLayoutDiscriminator; -/** Delegate decoding to {@link UnionLayoutDiscriminator#layout|layout}. */ -UnionLayoutDiscriminator.prototype.decode = function(b, offset) { - return this.layout.decode(b, offset); -}; -/** Delegate encoding to {@link UnionLayoutDiscriminator#layout|layout}. */ -UnionLayoutDiscriminator.prototype.encode = function(src, b, offset) { - return this.layout.encode(src, b, offset); -}; /** * Represent any number of span-compatible layouts. @@ -1490,262 +1504,269 @@ UnionLayoutDiscriminator.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function Union(discr, defaultLayout, property) { - var upv = ((discr instanceof UInt) - || (discr instanceof UIntBE)); - if (upv) { - discr = new UnionLayoutDiscriminator(new OffsetLayout(discr)); - } else if ((discr instanceof ExternalLayout) - && discr.isCount()) { - discr = new UnionLayoutDiscriminator(discr); - } else if (!(discr instanceof UnionDiscriminator)) { - throw new TypeError('discr must be a UnionDiscriminator ' - + 'or an unsigned integer layout'); - } - if (undefined === defaultLayout) { - defaultLayout = null; - } - if (!((null === defaultLayout) - || (defaultLayout instanceof Layout))) { - throw new TypeError('defaultLayout must be null or a Layout'); - } - if (null !== defaultLayout) { - if (0 > defaultLayout.span) { - throw new Error('defaultLayout must have constant span'); +class Union extends Layout { + constructor(discr, defaultLayout, property) { + var upv = ((discr instanceof UInt) + || (discr instanceof UIntBE)); + if (upv) { + discr = new UnionLayoutDiscriminator(new OffsetLayout(discr)); + } else if ((discr instanceof ExternalLayout) + && discr.isCount()) { + discr = new UnionLayoutDiscriminator(discr); + } else if (!(discr instanceof UnionDiscriminator)) { + throw new TypeError('discr must be a UnionDiscriminator ' + + 'or an unsigned integer layout'); } - if (undefined === defaultLayout.property) { - defaultLayout = defaultLayout.replicate('content'); + if (undefined === defaultLayout) { + defaultLayout = null; + } + if (!((null === defaultLayout) + || (defaultLayout instanceof Layout))) { + throw new TypeError('defaultLayout must be null or a Layout'); + } + if (null !== defaultLayout) { + if (0 > defaultLayout.span) { + throw new Error('defaultLayout must have constant span'); + } + if (undefined === defaultLayout.property) { + defaultLayout = defaultLayout.replicate('content'); + } } - } - /* The union span can be estimated only if there's a default - * layout. The union spans its default layout, plus any prefix - * variant layout. By construction both layouts, if present, have - * non-negative span. */ - var span = -1; - if (defaultLayout) { - span = defaultLayout.span; - if ((0 <= span) && upv) { - span += discr.layout.span; + /* The union span can be estimated only if there's a default + * layout. The union spans its default layout, plus any prefix + * variant layout. By construction both layouts, if present, have + * non-negative span. */ + var span = -1; + if (defaultLayout) { + span = defaultLayout.span; + if ((0 <= span) && upv) { + span += discr.layout.span; + } + } + super(span, property); + + /** The interface for the discriminator value in isolation. + * + * This a {@link UnionDiscriminator|UnionDiscriminator} either + * passed to the constructor or synthesized from the `discr` + * constructor argument. {@link + * Union#usesPrefixDiscriminator|usesPrefixDiscriminator} will be + * `true` iff the `discr` parameter was a non-offset {@link + * Layout|Layout} instance. */ + this.discriminator = discr; + + /** `true` if the {@link Union#discriminator|discriminator} is the + * first field in the union. + * + * If `false` the discriminator is obtained from somewhere + * else. */ + this.usesPrefixDiscriminator = upv; + + /** The layout for non-discriminator content when the value of the + * discriminator is not recognized. + * + * This is the value passed to the constructor. It is + * structurally equivalent to the second component of {@link + * Union#layout|layout} but may have a different property + * name. */ + this.defaultLayout = defaultLayout; + + /** A registry of allowed variants. + * + * The keys are unsigned integers which should be compatible with + * {@link Union.discriminator|discriminator}. The property value + * is the corresponding {@link VariantLayout|VariantLayout} + * instances assigned to this union by {@link + * Union#addVariant|addVariant}. + * + * **NOTE** The registry remains mutable so that variants can be + * {@link Union#addVariant|added} at any time. Users should not + * manipulate the content of this property. */ + this.registry = {}; + + /* Private variable used when invoking getSourceVariant */ + var boundGetSourceVariant = this.defaultGetSourceVariant.bind(this); + + /** Function to infer the variant selected by a source object. + * + * Defaults to {@link + * Union#defaultGetSourceVariant|defaultGetSourceVariant} but may + * be overridden using {@link + * Union#configGetSourceVariant|configGetSourceVariant}. + * + * @param {Object} src - as with {@link + * Union#defaultGetSourceVariant|defaultGetSourceVariant}. + * + * @returns {(undefined|VariantLayout)} The default variant + * (`undefined`) or first registered variant that uses a property + * available in `src`. */ + this.getSourceVariant = function(src) { + return boundGetSourceVariant(src); + }; + + /** Function to override the implementation of {@link + * Union#getSourceVariant|getSourceVariant}. + * + * Use this if the desired variant cannot be identified using the + * algorithm of {@link + * Union#defaultGetSourceVariant|defaultGetSourceVariant}. + * + * **NOTE** The provided function will be invoked bound to this + * Union instance, providing local access to {@link + * Union#registry|registry}. + * + * @param {Function} gsv - a function that follows the API of + * {@link Union#defaultGetSourceVariant|defaultGetSourceVariant}. */ + this.configGetSourceVariant = function(gsv) { + boundGetSourceVariant = gsv.bind(this); + }; + } + + /** @override */ + getSpan(b, offset) { + if (0 <= this.span) { + return this.span; + } + if (undefined === offset) { + offset = 0; } + /* Default layouts always have non-negative span, so we don't have + * one and we have to recognize the variant which will in turn + * determine the span. */ + var vlo = this.getVariant(b, offset); + if (!vlo) { + throw new Error('unable to determine span for unrecognized variant'); + } + return vlo.getSpan(b, offset); } - Layout.call(this, span, property); - /** The interface for the discriminator value in isolation. + /** + * Method to infer a registered Union variant compatible with `src`. * - * This a {@link UnionDiscriminator|UnionDiscriminator} either - * passed to the constructor or synthesized from the `discr` - * constructor argument. {@link - * Union#usesPrefixDiscriminator|usesPrefixDiscriminator} will be - * `true` iff the `discr` parameter was a non-offset {@link - * Layout|Layout} instance. */ - this.discriminator = discr; - - /** `true` if the {@link Union#discriminator|discriminator} is the - * first field in the union. + * @param {Object} src - an object presumed to be compatible with the content of the Union. * - * If `false` the discriminator is obtained from somewhere - * else. */ - this.usesPrefixDiscriminator = upv; - - /** The layout for non-discriminator content when the value of the - * discriminator is not recognized. + * @return {(undefined|VariantLayout)} - If `src` has properties + * matching the Union discriminator and default layout properties this + * returns `undefined`. Otherwise, if `src` has a property matching a + * {@link VariantLayout#property|variant property} that variant is + * returned. Otherwise an error is thrown. * - * This is the value passed to the constructor. It is - * structurally equivalent to the second component of {@link - * Union#layout|layout} but may have a different property - * name. */ - this.defaultLayout = defaultLayout; + * @throws {Error} - if `src` cannot be associated with a default or + * registered variant. + */ + defaultGetSourceVariant(src) { + if (src.hasOwnProperty(this.discriminator.property) + && src.hasOwnProperty(this.defaultLayout.property)) { + return undefined; + } + for (var k in this.registry) { + var lo = this.registry[k]; + if (src.hasOwnProperty(lo.property)) { + return lo; + } + } + throw new Error('unable to infer src variant'); + } - /** A registry of allowed variants. - * - * The keys are unsigned integers which should be compatible with - * {@link Union.discriminator|discriminator}. The property value - * is the corresponding {@link VariantLayout|VariantLayout} - * instances assigned to this union by {@link - * Union#addVariant|addVariant}. + /** Implement {@link Layout#decode|decode} for {@link Union|Union}. * - * **NOTE** The registry remains mutable so that variants can be - * {@link Union#addVariant|added} at any time. Users should not - * manipulate the content of this property. */ - this.registry = {}; + * If the variant is {@link Union#addVariant|registered} the return + * value is an instance of that variant, with no explicit + * discriminator. Otherwise the {@link Union#defaultLayout|default + * layout} is used to decode the content. */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + var dest; + var dlo = this.discriminator; + var discr = dlo.decode(b, offset); + var clo = this.registry[discr]; + if (undefined === clo) { + var contentOffset = 0; + clo = this.defaultLayout; + if (this.usesPrefixDiscriminator) { + contentOffset = dlo.layout.span; + } + dest = this.makeDestinationObject(); + dest[dlo.property] = discr; + dest[clo.property] = this.defaultLayout.decode(b, offset + contentOffset); + } else { + dest = clo.decode(b, offset); + } + return dest; + } - /* Private variable used when invoking getSourceVariant */ - var boundGetSourceVariant = this.defaultGetSourceVariant.bind(this); + /** Implement {@link Layout#encode|encode} for {@link Union|Union}. + * + * This API assumes the `src` object is consistent with the union's + * {@link Union#defaultLayout|default layout}. To encode variants + * use the appropriate variant-specific {@link VariantLayout#encode} + * method. */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + var vlo = this.getSourceVariant(src); + if (undefined === vlo) { + var dlo = this.discriminator; + var clo = this.defaultLayout; + var contentOffset = 0; + if (this.usesPrefixDiscriminator) { + contentOffset = dlo.layout.span; + } + dlo.encode(src[dlo.property], b, offset); + return contentOffset + clo.encode(src[clo.property], b, + offset + contentOffset); + } + return vlo.encode(src, b, offset); + } - /** Function to infer the variant selected by a source object. + /** Register a new variant structure within a union. The newly + * created variant is returned. * - * Defaults to {@link - * Union#defaultGetSourceVariant|defaultGetSourceVariant} but may - * be overridden using {@link - * Union#configGetSourceVariant|configGetSourceVariant}. + * @param {Number} variant - initializer for {@link + * VariantLayout#variant|variant}. * - * @param {Object} src - as with {@link - * Union#defaultGetSourceVariant|defaultGetSourceVariant}. + * @param {Layout} layout - initializer for {@link + * VariantLayout#layout|layout}. * - * @returns {(undefined|VariantLayout)} The default variant - * (`undefined`) or first registered variant that uses a property - * available in `src`. */ - this.getSourceVariant = function(src) { - return boundGetSourceVariant(src); - }; + * @param {String} property - initializer for {@link + * Layout#property|property}. + * + * @return {VariantLayout} */ + addVariant(variant, layout, property) { + var rv = new VariantLayout(this, variant, layout, property); + this.registry[variant] = rv; + return rv; + } - /** Function to override the implementation of {@link - * Union#getSourceVariant|getSourceVariant}. + /** + * Get the layout associated with a registered variant. * - * Use this if the desired variant cannot be identified using the - * algorithm of {@link - * Union#defaultGetSourceVariant|defaultGetSourceVariant}. + * If `vb` does not produce a registered variant the function returns + * `undefined`. * - * **NOTE** The provided function will be invoked bound to this - * Union instance, providing local access to {@link - * Union#registry|registry}. + * @param {(Number|Buffer)} vb - either the variant number, or a + * buffer from which the discriminator is to be read. * - * @param {Function} gsv - a function that follows the API of - * {@link Union#defaultGetSourceVariant|defaultGetSourceVariant}. */ - this.configGetSourceVariant = function(gsv) { - boundGetSourceVariant = gsv.bind(this); - }; -} -util.inherits(Union, Layout); -/** @override */ -Union.prototype.getSpan = function(b, offset) { - if (0 <= this.span) { - return this.span; - } - if (undefined === offset) { - offset = 0; - } - /* Default layouts always have non-negative span, so we don't have - * one and we have to recognize the variant which will in turn - * determine the span. */ - var vlo = this.getVariant(b, offset); - if (!vlo) { - throw new Error('unable to determine span for unrecognized variant'); - } - return vlo.getSpan(b, offset); -}; -/** - * Method to infer a registered Union variant compatible with `src`. - * - * @param {Object} src - an object presumed to be compatible with the content of the Union. - * - * @return {(undefined|VariantLayout)} - If `src` has properties - * matching the Union discriminator and default layout properties this - * returns `undefined`. Otherwise, if `src` has a property matching a - * {@link VariantLayout#property|variant property} that variant is - * returned. Otherwise an error is thrown. - * - * @throws {Error} - if `src` cannot be associated with a default or - * registered variant. - */ -Union.prototype.defaultGetSourceVariant = function(src) { - if (src.hasOwnProperty(this.discriminator.property) - && src.hasOwnProperty(this.defaultLayout.property)) { - return undefined; - } - for (var k in this.registry) { - var lo = this.registry[k]; - if (src.hasOwnProperty(lo.property)) { - return lo; - } - } - throw new Error('unable to infer src variant'); -}; -/** Implement {@link Layout#decode|decode} for {@link Union|Union}. - * - * If the variant is {@link Union#addVariant|registered} the return - * value is an instance of that variant, with no explicit - * discriminator. Otherwise the {@link Union#defaultLayout|default - * layout} is used to decode the content. */ -Union.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; - } - var dest; - var dlo = this.discriminator; - var discr = dlo.decode(b, offset); - var clo = this.registry[discr]; - if (undefined === clo) { - var contentOffset = 0; - clo = this.defaultLayout; - if (this.usesPrefixDiscriminator) { - contentOffset = dlo.layout.span; - } - dest = this.makeDestinationObject(); - dest[dlo.property] = discr; - dest[clo.property] = this.defaultLayout.decode(b, offset + contentOffset); - } else { - dest = clo.decode(b, offset); - } - return dest; -}; -/** Implement {@link Layout#encode|encode} for {@link Union|Union}. - * - * This API assumes the `src` object is consistent with the union's - * {@link Union#defaultLayout|default layout}. To encode variants - * use the appropriate variant-specific {@link VariantLayout#encode} - * method. */ -Union.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var vlo = this.getSourceVariant(src); - if (undefined === vlo) { - var dlo = this.discriminator; - var clo = this.defaultLayout; - var contentOffset = 0; - if (this.usesPrefixDiscriminator) { - contentOffset = dlo.layout.span; - } - dlo.encode(src[dlo.property], b, offset); - return contentOffset + clo.encode(src[clo.property], b, - offset + contentOffset); - } - return vlo.encode(src, b, offset); -}; -/** Register a new variant structure within a union. The newly - * created variant is returned. - * - * @param {Number} variant - initializer for {@link - * VariantLayout#variant|variant}. - * - * @param {Layout} layout - initializer for {@link - * VariantLayout#layout|layout}. - * - * @param {String} property - initializer for {@link - * Layout#property|property}. - * - * @return {VariantLayout} */ -Union.prototype.addVariant = function(variant, layout, property) { - var rv = new VariantLayout(this, variant, layout, property); - this.registry[variant] = rv; - return rv; -}; -/** - * Get the layout associated with a registered variant. - * - * If `vb` does not produce a registered variant the function returns - * `undefined`. - * - * @param {(Number|Buffer)} vb - either the variant number, or a - * buffer from which the discriminator is to be read. - * - * @param {Number} offset - offset into `vb` for the start of the - * union. Used only when `vb` is an instance of {Buffer}. - * - * @return {({VariantLayout}|undefined)} - */ -Union.prototype.getVariant = function(vb, offset) { - var variant = vb; - if (vb instanceof Buffer) { - if (undefined === offset) { - offset = 0; + * @param {Number} offset - offset into `vb` for the start of the + * union. Used only when `vb` is an instance of {Buffer}. + * + * @return {({VariantLayout}|undefined)} + */ + getVariant(vb, offset) { + var variant = vb; + if (vb instanceof Buffer) { + if (undefined === offset) { + offset = 0; + } + variant = this.discriminator.decode(vb, offset); } - variant = this.discriminator.decode(vb, offset); + return this.registry[variant]; } - return this.registry[variant]; -}; +} /** * Represent a specific variant within a containing union. @@ -1775,107 +1796,111 @@ Union.prototype.getVariant = function(vb, offset) { * @constructor * @augments {Layout} */ -function VariantLayout(union, variant, layout, property) { - if (!(union instanceof 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'); - } - if (!(layout instanceof Layout)) { - throw new TypeError('layout must be a Layout'); - } - if ((null !== union.defaultLayout) - && (0 <= layout.span) - && (layout.span > union.defaultLayout.span)) { - throw new Error('variant span exceeds span of containing union'); - } - if ('string' !== typeof property) { - throw new TypeError('variant must have a String property'); - } - var span = union.span; - if (0 > union.span) { - span = layout.span; - if ((0 <= span) && union.usesPrefixDiscriminator) { - span += union.discriminator.layout.span; +class VariantLayout extends Layout { + constructor(union, variant, layout, property) { + if (!(union instanceof Union)) { + throw new TypeError('union must be a Union'); } - } - Layout.call(this, span, property); + if ((!Number.isInteger(variant)) || (0 > variant)) { + throw new TypeError('variant must be a (non-negative) integer'); + } + if (!(layout instanceof Layout)) { + throw new TypeError('layout must be a Layout'); + } + if ((null !== union.defaultLayout) + && (0 <= layout.span) + && (layout.span > union.defaultLayout.span)) { + throw new Error('variant span exceeds span of containing union'); + } + if ('string' !== typeof property) { + throw new TypeError('variant must have a String property'); + } + var span = union.span; + if (0 > union.span) { + span = layout.span; + if ((0 <= span) && union.usesPrefixDiscriminator) { + span += union.discriminator.layout.span; + } + } + super(span, property); - /** The {@link Union|Union} to which this variant belongs. */ - this.union = union; + /** The {@link Union|Union} to which this variant belongs. */ + this.union = union; - /** The unsigned integral value identifying this variant within - * the {@link Union#discriminator|discriminator} of the containing - * union. */ - this.variant = variant; + /** The unsigned integral value identifying this variant within + * the {@link Union#discriminator|discriminator} of the containing + * union. */ + this.variant = variant; - /** The {@link Layout|Layout} to be used when reading/writing the - * non-discriminator part of the {@link - * VariantLayout#union|union}. */ - this.layout = layout; -} -util.inherits(VariantLayout, Layout); -/** @override */ -VariantLayout.prototype.getSpan = function(b, offset) { - if (0 <= this.span) { - /* Will be equal to the containing union span if that is not - * variable. */ - return this.span; - } - if (undefined === offset) { - offset = 0; + /** The {@link Layout|Layout} to be used when reading/writing the + * non-discriminator part of the {@link + * VariantLayout#union|union}. */ + this.layout = layout; } - var contentOffset = 0; - if (this.union.usesPrefixDiscriminator) { - contentOffset = this.union.discriminator.layout.span; + + /** @override */ + getSpan(b, offset) { + if (0 <= this.span) { + /* Will be equal to the containing union span if that is not + * variable. */ + return this.span; + } + if (undefined === offset) { + offset = 0; + } + var contentOffset = 0; + if (this.union.usesPrefixDiscriminator) { + contentOffset = this.union.discriminator.layout.span; + } + /* Span is defined solely by the variant (and prefix discriminator) */ + return contentOffset + this.layout.getSpan(b, offset + contentOffset); } - /* Span is defined solely by the variant (and prefix discriminator) */ - return contentOffset + this.layout.getSpan(b, offset + contentOffset); -}; -/** @override */ -VariantLayout.prototype.decode = function(b, offset) { - var dest = this.makeDestinationObject(); - if (undefined === offset) { - offset = 0; + /** @override */ + decode(b, offset) { + var dest = this.makeDestinationObject(); + if (undefined === offset) { + offset = 0; + } + if (this !== this.union.getVariant(b, offset)) { + throw new Error('variant mismatch'); + } + var contentOffset = 0; + if (this.union.usesPrefixDiscriminator) { + contentOffset = this.union.discriminator.layout.span; + } + dest[this.property] = this.layout.decode(b, offset + contentOffset); + return dest; } - if (this !== this.union.getVariant(b, offset)) { - throw new Error('variant mismatch'); + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + var contentOffset = 0; + if (this.union.usesPrefixDiscriminator) { + contentOffset = this.union.discriminator.layout.span; + } + if (!src.hasOwnProperty(this.property)) { + throw new TypeError('variant lacks property ' + this.property); + } + this.union.discriminator.encode(this.variant, b, offset); + this.layout.encode(src[this.property], b, offset + contentOffset); + var span = contentOffset + this.layout.getSpan(b, offset + contentOffset); + if ((0 <= this.union.span) + && (span > this.union.span)) { + throw new Error('encoded variant overruns containing union'); + } + return span; } - var contentOffset = 0; - if (this.union.usesPrefixDiscriminator) { - contentOffset = this.union.discriminator.layout.span; + + /** Delegate {@link Layout#fromArray|fromArray} to {@link + * VariantLayout#layout|layout}. */ + fromArray(values) { + return this.layout.fromArray(values); } - dest[this.property] = this.layout.decode(b, offset + contentOffset); - return dest; -}; -/** @override */ -VariantLayout.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var contentOffset = 0; - if (this.union.usesPrefixDiscriminator) { - contentOffset = this.union.discriminator.layout.span; - } - if (!src.hasOwnProperty(this.property)) { - throw new TypeError('variant lacks property ' + this.property); - } - this.union.discriminator.encode(this.variant, b, offset); - this.layout.encode(src[this.property], b, offset + contentOffset); - var span = contentOffset + this.layout.getSpan(b, offset + contentOffset); - if ((0 <= this.union.span) - && (span > this.union.span)) { - throw new Error('encoded variant overruns containing union'); - } - return span; -}; -/** Delegate {@link Layout#fromArray|fromArray} to {@link - * VariantLayout#layout|layout}. */ -VariantLayout.prototype.fromArray = function(values) { - return this.layout.fromArray(values); -}; +} /** JavaScript chose to define bitwise operations as operating on * signed 32-bit values in 2's complement form, meaning any integer @@ -1920,134 +1945,140 @@ function fixBitwiseResult(v) { * @constructor * @augments {Layout} */ -function BitStructure(word, msb, property) { - if (!((word instanceof UInt) - || (word instanceof UIntBE))) { - throw new TypeError('word must be a UInt or UIntBE layout'); +class BitStructure extends Layout { + constructor(word, msb, property) { + if (!((word instanceof UInt) + || (word instanceof UIntBE))) { + throw new TypeError('word must be a UInt or UIntBE layout'); + } + if (4 < word.span) { + throw new RangeError('word cannot exceed 32 bits'); + } + super(word.span, property); + + /** The layout used for the packed value. {@link + * BitField|BitField} instances are packed sequentially depending + * on {@link BitStructure#msb|msb}. */ + this.word = word; + + /** Whether the bit sequences are packed starting at the most + * significant bit growing down (`true`), or the least significant + * bit growing up (`false`). + * + * **NOTE** Regardless of this value, the least significant bit of + * any {@link BitField|BitField} value is the least significant + * bit of the corresponding section of the packed value. */ + this.msb = !!msb; + + /** The sequence of {@link BitField|BitField} layouts that + * comprise the packed structure. + * + * **NOTE** The array remains mutable to allow fields to be {@link + * BitStructure#addField|added} after construction. Users should + * not manipulate the content of this property.*/ + this.fields = []; + + /* Storage for the value. Capture a variable instead of using an + * instance property because we don't want anything to change the + * value without going through the mutator. */ + var value = 0; + this._packedSetValue = function(v) { + value = fixBitwiseResult(v); + return this; + }; + this._packedGetValue = function() { + return value; + }; + } + + /** @override */ + decode(b, offset) { + var dest = this.makeDestinationObject(); + if (undefined === offset) { + offset = 0; + } + var value = this.word.decode(b, offset); + this._packedSetValue(value); + this.fields.forEach(function(fd) { + if (undefined !== fd.property) { + dest[fd.property] = fd.decode(value); + } + }); + return dest; } - if (4 < word.span) { - throw new RangeError('word cannot exceed 32 bits'); + + /** Implement {@link Layout#encode|encode} for {@link BitStructure|BitStructure}. + * + * If `src` is missing a property for a member with a defined {@link + * Layout#property|property} the corresponding region of the packed + * value is left unmodified. Unused bits are also left unmodified. */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + var value = this.word.decode(b, offset); + this._packedSetValue(value); + this.fields.forEach(function(fd) { + if (undefined !== fd.property) { + var fv = src[fd.property]; + if (undefined !== fv) { + fd.encode(fv); + } + } + }); + return this.word.encode(this._packedGetValue(), b, offset); } - Layout.call(this, word.span, property); - /** The layout used for the packed value. {@link - * BitField|BitField} instances are packed sequentially depending - * on {@link BitStructure#msb|msb}. */ - this.word = word; + /** Register a new bitfield with a containing bit structure. The + * resulting bitfield is returned. + * + * @param {Number} bits - initializer for {@link BitField#bits|bits}. + * + * @param {string} property - initializer for {@link + * Layout#property|property}. + * + * @return {BitField} */ + addField(bits, property) { + var bf = new BitField(this, bits, property); + this.fields.push(bf); + return bf; + } - /** Whether the bit sequences are packed starting at the most - * significant bit growing down (`true`), or the least significant - * bit growing up (`false`). + /** As with {@link BitStructure#addField|addField} for single-bit + * fields with `boolean` value representation. + * + * @param {string} property - initializer for {@link + * Layout#property|property}. * - * **NOTE** Regardless of this value, the least significant bit of - * any {@link BitField|BitField} value is the least significant - * bit of the corresponding section of the packed value. */ - this.msb = !!msb; + * @return {Boolean} */ + addBoolean(property) { + // This is my Boolean, not the Javascript one. + // eslint-disable-next-line no-new-wrappers + var bf = new Boolean(this, property); + this.fields.push(bf); + return bf; + } - /** The sequence of {@link BitField|BitField} layouts that - * comprise the packed structure. + /** + * Get access to the bit field for a given property. * - * **NOTE** The array remains mutable to allow fields to be {@link - * BitStructure#addField|added} after construction. Users should - * not manipulate the content of this property.*/ - this.fields = []; - - /* Storage for the value. Capture a variable instead of using an - * instance property because we don't want anything to change the - * value without going through the mutator. */ - var value = 0; - this._packedSetValue = function(v) { - value = fixBitwiseResult(v); - return this; - }; - this._packedGetValue = function() { - return value; - }; -} -util.inherits(BitStructure, Layout); -/** @override */ -BitStructure.prototype.decode = function(b, offset) { - var dest = this.makeDestinationObject(); - if (undefined === offset) { - offset = 0; - } - var value = this.word.decode(b, offset); - this._packedSetValue(value); - this.fields.forEach(function(fd) { - if (undefined !== fd.property) { - dest[fd.property] = fd.decode(value); - } - }); - return dest; -}; -/** Implement {@link Layout#encode|encode} for {@link BitStructure|BitStructure}. - * - * If `src` is missing a property for a member with a defined {@link - * Layout#property|property} the corresponding region of the packed - * value is left unmodified. Unused bits are also left unmodified. */ -BitStructure.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - var value = this.word.decode(b, offset); - this._packedSetValue(value); - this.fields.forEach(function(fd) { - if (undefined !== fd.property) { - var fv = src[fd.property]; - if (undefined !== fv) { - fd.encode(fv); - } + * @param {String} property - the bit field of interest. + * + * @return {BitField} - the field associated with `property`, or + * undefined if there is no such property. + */ + fieldFor(property) { + var rv; + if (property) { + this.fields.forEach(function(fd) { + if (fd.property === property) { + rv = fd; + } + }); } - }); - return this.word.encode(this._packedGetValue(), b, offset); -}; -/** Register a new bitfield with a containing bit structure. The - * resulting bitfield is returned. - * - * @param {Number} bits - initializer for {@link BitField#bits|bits}. - * - * @param {string} property - initializer for {@link - * Layout#property|property}. - * - * @return {BitField} */ -BitStructure.prototype.addField = function(bits, property) { - var bf = new BitField(this, 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) { - // This is my Boolean, not the Javascript one. - // eslint-disable-next-line no-new-wrappers - var bf = new Boolean(this, property); - this.fields.push(bf); - return bf; -}; -/** - * Get access to the bit field for a given property. - * - * @param {String} property - the bit field of interest. - * - * @return {BitField} - the field associated with `property`, or - * undefined if there is no such property. - */ -BitStructure.prototype.fieldFor = function(property) { - var rv; - if (property) { - this.fields.forEach(function(fd) { - if (fd.property === property) { - rv = fd; - } - }); + return rv; } - return rv; -}; +} /** * Represent a sequence of bits within a {@link @@ -2072,89 +2103,93 @@ BitStructure.prototype.fieldFor = function(property) { * * @constructor */ -function BitField(container, bits, property) { - if (!(container instanceof BitStructure)) { - throw new TypeError('container must be a BitStructure'); - } - if ((!Number.isInteger(bits)) || (0 >= bits)) { - throw new TypeError('bits must be positive integer'); - } - var totalBits = 8 * container.span; - function bitsSum(c, fd) { - return c + fd.bits; - } - var usedBits = container.fields.reduce(bitsSum, 0); - if ((bits + usedBits) > totalBits) { - throw new Error('bits too long for span remainder (' - + (totalBits - usedBits) + ' of ' - + totalBits + ' remain)'); - } - - /** The {@link BitStructure|BitStructure} instance to which this - * bit field belongs. */ - this.container = container; +class BitField { + constructor(container, bits, property) { + if (!(container instanceof BitStructure)) { + throw new TypeError('container must be a BitStructure'); + } + if ((!Number.isInteger(bits)) || (0 >= bits)) { + throw new TypeError('bits must be positive integer'); + } + var totalBits = 8 * container.span; + function bitsSum(c, fd) { + return c + fd.bits; + } + var usedBits = container.fields.reduce(bitsSum, 0); + if ((bits + usedBits) > totalBits) { + throw new Error('bits too long for span remainder (' + + (totalBits - usedBits) + ' of ' + + totalBits + ' remain)'); + } - /** The span of this value in bits. */ - this.bits = bits; + /** The {@link BitStructure|BitStructure} instance to which this + * bit field belongs. */ + this.container = container; + + /** The span of this value in bits. */ + this.bits = bits; + + /** A mask of {@link BitField#bits|bits} bits isolating value bits + * that fit within the field. + * + * That is, it masks a value that has not yet been shifted into + * position within its containing packed integer. */ + this.valueMask = (1 << bits) - 1; + if (32 === bits) { // shifted value out of range + this.valueMask = 0xFFFFFFFF; + } - /** A mask of {@link BitField#bits|bits} bits isolating value bits - * that fit within the field. - * - * That is, it masks a value that has not yet been shifted into - * position within its containing packed integer. */ - this.valueMask = (1 << bits) - 1; - if (32 === bits) { // shifted value out of range - this.valueMask = 0xFFFFFFFF; - } + /** The offset of the value within the containing packed unsigned + * integer. The least significant bit of the packed value is at + * offset zero, regardless of bit ordering used. */ + this.start = usedBits; + if (this.container.msb) { + this.start = totalBits - usedBits - bits; + } - /** The offset of the value within the containing packed unsigned - * integer. The least significant bit of the packed value is at - * offset zero, regardless of bit ordering used. */ - this.start = usedBits; - if (this.container.msb) { - this.start = totalBits - usedBits - bits; + /** A mask of {@link BitField#bits|bits} isolating the field value + * within the containing packed unsigned integer. */ + this.wordMask = fixBitwiseResult(this.valueMask << this.start); + + /** The property name used when this bitfield is represented in an + * Object. + * + * Intended to be functionally equivalent to {@link + * Layout#property}. + * + * If left undefined the corresponding span of bits will be + * treated as padding: it will not be mutated by {@link + * Layout#encode|encode} nor represented as a property in the + * decoded Object. */ + this.property = property; + } + + /** Store a value into the corresponding subsequence of the containing + * bit field. */ + decode() { + var word = this.container._packedGetValue(); + var wordValue = fixBitwiseResult(word & this.wordMask); + var value = wordValue >>> this.start; + return value; } - /** A mask of {@link BitField#bits|bits} isolating the field value - * within the containing packed unsigned integer. */ - this.wordMask = fixBitwiseResult(this.valueMask << this.start); - - /** The property name used when this bitfield is represented in an - * Object. - * - * Intended to be functionally equivalent to {@link - * Layout#property}. + /** Store a value into the corresponding subsequence of the containing + * bit field. * - * If left undefined the corresponding span of bits will be - * treated as padding: it will not be mutated by {@link - * Layout#encode|encode} nor represented as a property in the - * decoded Object. */ - this.property = property; + * **NOTE** This is not a specialization of {@link + * Layout#encode|Layout.encode} and there is no return value. */ + encode(value) { + if ((!Number.isInteger(value)) + || (value !== fixBitwiseResult(value & this.valueMask))) { + throw new TypeError(nameWithProperty('BitField.encode', this) + + ' value must be integer not exceeding ' + this.valueMask); + } + var word = this.container._packedGetValue(); + var wordValue = fixBitwiseResult(value << this.start); + this.container._packedSetValue(fixBitwiseResult(word & ~this.wordMask) + | wordValue); + }; } -/** Store a value into the corresponding subsequence of the containing - * bit field. */ -BitField.prototype.decode = function() { - var word = this.container._packedGetValue(); - var wordValue = fixBitwiseResult(word & this.wordMask); - var value = wordValue >>> this.start; - return value; -}; -/** Store a value into the corresponding subsequence of the containing - * 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))) { - throw new TypeError(nameWithProperty('BitField.encode', this) - + ' value must be integer not exceeding ' + this.valueMask); - } - var word = this.container._packedGetValue(); - var wordValue = fixBitwiseResult(value << this.start); - this.container._packedSetValue(fixBitwiseResult(word & ~this.wordMask) - | wordValue); -}; /** * Represent a single bit within a {@link BitStructure|BitStructure} @@ -2174,24 +2209,27 @@ BitField.prototype.encode = function(value) { * @augments {BitField} */ /* eslint-disable no-extend-native */ -function Boolean(container, property) { - BitField.call(this, container, 1, property); -} -util.inherits(Boolean, BitField); -/** 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); -}; -/** @override */ -Boolean.prototype.encode = function(value) { - if ('boolean' === typeof value) { - // BitField requires integer values - value = +value; +class Boolean extends BitField { + constructor(container, property) { + super(container, 1, property); } - return BitField.prototype.encode.call(this, value); -}; + + /** Override {@link BitField#decode|decode} for {@link Boolean|Boolean}. + * + * @returns {boolean} */ + decode(b, offset) { + return !!BitField.prototype.decode.call(this, b, offset); + } + + /** @override */ + encode(value) { + if ('boolean' === typeof value) { + // BitField requires integer values + value = +value; + } + return BitField.prototype.encode.call(this, value); + } +} /* eslint-enable no-extend-native */ /** @@ -2209,70 +2247,74 @@ Boolean.prototype.encode = function(value) { * @constructor * @augments {Layout} */ -function Blob(length, property) { - if (!(((length instanceof ExternalLayout) && length.isCount()) - || (Number.isInteger(length) && (0 <= length)))) { - throw new TypeError('length must be positive integer ' - + 'or an unsigned integer ExternalLayout'); - } +class Blob extends Layout { + constructor(length, property) { + if (!(((length instanceof ExternalLayout) && length.isCount()) + || (Number.isInteger(length) && (0 <= length)))) { + throw new TypeError('length must be positive integer ' + + 'or an unsigned integer ExternalLayout'); + } - /** The number of bytes in the blob. - * - * This may be a non-negative integer, or an instance of {@link - * ExternalLayout|ExternalLayout} that satisfies {@link - * ExternalLayout#isCount|isCount()}. */ - this.length = length; + var span = -1; + if (!(length instanceof ExternalLayout)) { + span = length; + } + super(span, property); - var span = -1; - if (!(length instanceof ExternalLayout)) { - span = length; - } - Layout.call(this, span, property); -} -util.inherits(Blob, Layout); -/** @override */ -Blob.prototype.getSpan = function(b, offset) { - var span = this.span; - if (0 > span) { - span = this.length.decode(b, offset); - } - return span; -}; -/** @override */ -Blob.prototype.decode = function(b, offset) { - if (undefined === offset) { - offset = 0; - } - var span = this.span; - if (0 > span) { - span = this.length.decode(b, offset); + /** The number of bytes in the blob. + * + * This may be a non-negative integer, or an instance of {@link + * ExternalLayout|ExternalLayout} that satisfies {@link + * ExternalLayout#isCount|isCount()}. */ + this.length = length; } - return b.slice(offset, offset + span); -}; -/** Implement {@link Layout#encode|encode} for {@link Blob|Blob}. - * - * **NOTE** If {@link Layout#count|count} is an instance of {@link - * ExternalLayout|ExternalLayout} then the length of `src` will be encoded - * as the count after `src` is encoded. */ -Blob.prototype.encode = function(src, b, offset) { - var span = this.length; - if (this.length instanceof ExternalLayout) { - span = src.length; - } - if (!((src instanceof Buffer) - && (span === src.length))) { - throw new TypeError(nameWithProperty('Blob.encode', this) - + ' requires (length ' + span + ') Buffer as src'); + + /** @override */ + getSpan(b, offset) { + var span = this.span; + if (0 > span) { + span = this.length.decode(b, offset); + } + return span; } - if ((offset + span) > b.length) { - throw new RangeError('encoding overruns Buffer'); + + /** @override */ + decode(b, offset) { + if (undefined === offset) { + offset = 0; + } + var span = this.span; + if (0 > span) { + span = this.length.decode(b, offset); + } + return b.slice(offset, offset + span); } - b.write(src.toString('hex'), offset, span, 'hex'); - if (this.length instanceof ExternalLayout) { - this.length.encode(span, b, offset); + + /** Implement {@link Layout#encode|encode} for {@link Blob|Blob}. + * + * **NOTE** If {@link Layout#count|count} is an instance of {@link + * ExternalLayout|ExternalLayout} then the length of `src` will be encoded + * as the count after `src` is encoded. */ + encode(src, b, offset) { + var span = this.length; + if (this.length instanceof ExternalLayout) { + span = src.length; + } + if (!((src instanceof Buffer) + && (span === src.length))) { + throw new TypeError(nameWithProperty('Blob.encode', this) + + ' requires (length ' + span + ') Buffer as src'); + } + if ((offset + span) > b.length) { + throw new RangeError('encoding overruns Buffer'); + } + b.write(src.toString('hex'), offset, span, 'hex'); + if (this.length instanceof ExternalLayout) { + this.length.encode(span, b, offset); + } + return span; } - return span; -}; +} /** * Contain a `NUL`-terminated UTF8 string. @@ -2288,52 +2330,56 @@ Blob.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function CString(property) { - Layout.call(this, -1, property); -} -util.inherits(CString, Layout); -/** @override */ -CString.prototype.getSpan = function(b, offset) { - if (!(b instanceof Buffer)) { - throw new TypeError('b must be a Buffer'); +class CString extends Layout { + constructor(property) { + super(-1, property); } - if (undefined === offset) { - offset = 0; + + /** @override */ + getSpan(b, offset) { + if (!(b instanceof Buffer)) { + throw new TypeError('b must be a Buffer'); + } + if (undefined === offset) { + offset = 0; + } + var idx = offset; + while ((idx < b.length) && (0 !== b[idx])) { + idx += 1; + } + return 1 + idx - offset; } - var idx = offset; - while ((idx < b.length) && (0 !== b[idx])) { - idx += 1; + + /** @override */ + decode(b, offset, dest) { + if (undefined === offset) { + offset = 0; + } + var span = this.getSpan(b, offset); + return b.slice(offset, offset + span - 1).toString('utf-8'); } - return 1 + idx - offset; -}; -/** @override */ -CString.prototype.decode = function(b, offset, dest) { - if (undefined === offset) { - offset = 0; + + /** @override */ + encode(src, b, offset) { + if (undefined === offset) { + offset = 0; + } + /* Must force this to a string, lest it be a number and the + * "utf8-encoding" below actually allocate a buffer of length + * src */ + if ('string' !== typeof src) { + src = src.toString(); + } + var srcb = new Buffer(src, 'utf8'); + var span = srcb.length; + if ((offset + span) > b.length) { + throw new RangeError('encoding overruns Buffer'); + } + srcb.copy(b, offset); + b[offset + span] = 0; + return span + 1; } - var span = this.getSpan(b, offset); - return b.slice(offset, offset + span - 1).toString('utf-8'); -}; -/** @override */ -CString.prototype.encode = function(src, b, offset) { - if (undefined === offset) { - offset = 0; - } - /* Must force this to a string, lest it be a number and the - * "utf8-encoding" below actually allocate a buffer of length - * src */ - if ('string' !== typeof src) { - src = src.toString(); - } - var srcb = new Buffer(src, 'utf8'); - var span = srcb.length; - if ((offset + span) > b.length) { - throw new RangeError('encoding overruns Buffer'); - } - srcb.copy(b, offset); - b[offset + span] = 0; - return span + 1; -}; +} /** * Contain a constant value. @@ -2355,31 +2401,34 @@ CString.prototype.encode = function(src, b, offset) { * @constructor * @augments {Layout} */ -function Constant(value, property) { - /** The value produced by this constant when the layout is {@link - * Constant#decode|decoded}. - * - * Any JavaScript value including `null` and `undefined` is - * permitted. - * - * **WARNING** If `value` passed in the constructor was not - * frozen, it is possible for users of decoded values to change - * the content of the value. */ - this.value = value; - Layout.call(this, 0, property); +class Constant extends Layout { + constructor(value, property) { + super(0, property); + + /** The value produced by this constant when the layout is {@link + * Constant#decode|decoded}. + * + * Any JavaScript value including `null` and `undefined` is + * permitted. + * + * **WARNING** If `value` passed in the constructor was not + * frozen, it is possible for users of decoded values to change + * the content of the value. */ + this.value = value; + } + + /** @override */ + decode(b, offset, dest) { + return this.value; + } + + /** @override */ + encode(src, b, offset) { + /* Constants take no space */ + return 0; + } } -util.inherits(Constant, Layout); -/** @override */ -Constant.prototype.decode = function(b, offset, dest) { - return this.value; -}; -/** @override */ -Constant.prototype.encode = function(src, b, offset) { - /* Constants take no space */ - return 0; -}; -exports.Layout = Layout; exports.ExternalLayout = ExternalLayout; exports.GreedyCount = GreedyCount; exports.OffsetLayout = OffsetLayout; From 9663c16235efd1c97502ae0150cd99e7418774a2 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 16 Dec 2017 10:49:25 -0600 Subject: [PATCH 13/17] Layout: ES6 conversion: let/const, object literals --- .eslintrc.js | 1 - README.md | 92 ++++++++++++++++++++--------------------- lib/Layout.js | 101 ++++++++++++++++++++++----------------------- test/LayoutTest.js | 2 +- test/examples.js | 94 ++++++++++++++++++++--------------------- 5 files changed, 145 insertions(+), 145 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index dd75f83..10d551a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,7 +10,6 @@ module.exports = { rules: { 'guard-for-in': 'off', 'new-cap': 'off', - 'no-var': 'off', 'prefer-rest-params': 'off', 'prefer-spread': 'off', __temporary: 'off', diff --git a/README.md b/README.md index d074ed4..a33092d 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ buffer-layout`. All examples are from the `test/examples.js` unit test and assume the following context: - var assert = require('assert'); - var util = require('util'); - var lo = require('buffer-layout'); + const assert = require('assert'); + const util = require('util'); + const lo = require('buffer-layout'); The examples give only a taste of what can be done. Structures, unions, and sequences can nest; [union @@ -57,8 +57,8 @@ The C definition: The buffer-layout way: - var ds = lo.seq(lo.s16(), 4); - var b = new Buffer(8); + const ds = lo.seq(lo.s16(), 4); + const b = new Buffer(8); assert.equal(ds.encode([1, -1, 3, -3], b), 4 * 2); assert.equal(Buffer('0100ffff0300fdff', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), [1, -1, 3, -3]); @@ -77,11 +77,11 @@ The C definition: The buffer-layout way: - var ds = lo.struct([lo.u8('v'), + const ds = lo.struct([lo.u8('v'), lo.seq(lo.u8(), 3), // alignment padding lo.u32('u32')]); assert.equal(ds.offsetOf('u32'), 4); - var b = new Buffer(8); + const b = new Buffer(8); b.fill(0xbd); assert.equal(ds.encode({v: 1, u32: 0x12345678}, b), 1 + 3 + 4); assert.equal(Buffer('01bdbdbd78563412', 'hex').compare(b), 0); @@ -105,10 +105,10 @@ The C definition: The buffer-layout way: - var ds = lo.struct([lo.u8('v'), + const ds = lo.struct([lo.u8('v'), lo.u32('u32')]); assert.equal(ds.offsetOf('u32'), 1); - var b = new Buffer(5); + const b = new Buffer(5); b.fill(0xbd); assert.equal(ds.encode({v: 1, u32: 0x12345678}, b), 1 + 4); assert.equal(Buffer('0178563412', 'hex').compare(b), 0); @@ -131,12 +131,12 @@ four bytes depends on the first byte. The C definition: The buffer-layout way: - var t = lo.u8('t'); - var un = lo.union(t, lo.seq(lo.u8(), 4, 'u8')); - var u32 = un.addVariant('w'.charCodeAt(0), lo.u32(), 'u32'); - var s16 = un.addVariant('h'.charCodeAt(0), lo.seq(lo.s16(), 2), 's16'); - var f32 = un.addVariant('f'.charCodeAt(0), lo.f32(), 'f32'); - var b = new Buffer(un.span); + const t = lo.u8('t'); + const un = lo.union(t, lo.seq(lo.u8(), 4, 'u8')); + const u32 = un.addVariant('w'.charCodeAt(0), lo.u32(), 'u32'); + const s16 = un.addVariant('h'.charCodeAt(0), lo.seq(lo.s16(), 2), 's16'); + const f32 = un.addVariant('f'.charCodeAt(0), lo.f32(), 'f32'); + const b = new Buffer(un.span); assert.deepEqual(un.decode(Buffer('7778563412', 'hex')), {u32: 0x12345678}); assert.deepEqual(un.decode(Buffer('660000bd41', 'hex')), @@ -172,7 +172,7 @@ representing the union and the variants: lo.bindConstructorLayout(Vf32, Union.layout_.addVariant('f'.charCodeAt(0), lo.f32(), 'f32')); - var v = Union.decode(Buffer('7778563412', 'hex')); + let v = Union.decode(Buffer('7778563412', 'hex')); assert(v instanceof Vu32); assert(v instanceof Union); assert.equal(v.u32, 0x12345678); @@ -182,7 +182,7 @@ representing the union and the variants: assert.equal(v.t, 0xa5); assert.deepEqual(v.u8, [0xa5, 0xa5, 0xa5, 0xa5]); - var b = new Buffer(Union.layout_.span); + const b = new Buffer(Union.layout_.span); v = new Vf32(23.625); v.encode(b); assert.equal(Buffer('660000bd41', 'hex').compare(b), 0); @@ -205,8 +205,8 @@ The C definition: The buffer-layout way: - var ds = lo.bits(lo.u32()); - var b = new Buffer(4); + const ds = lo.bits(lo.u32()); + const b = new Buffer(4); ds.addField(3, 'b00l03'); ds.addBoolean('flg03'); ds.addField(24, 'b04l18'); @@ -227,10 +227,10 @@ The C definition: The buffer-layout way: - var ds = lo.nu64be(); - var b = Buffer('0102030405060708', 'hex'); - var v = 72623859790382856; - var nv = v - 6; + const ds = lo.nu64be(); + const b = Buffer('0102030405060708', 'hex'); + const v = 72623859790382856; + const nv = v - 6; assert.equal(v, nv); assert.equal(ds.decode(b), nv); @@ -248,10 +248,10 @@ The C definition: The buffer-layout way: - var ds = lo.cstr(); - var b = new Buffer(8); + const ds = lo.cstr(); + const b = new Buffer(8); assert.equal(ds.encode('hi!', b), 3 + 1); - var slen = ds.getSpan(b); + const slen = ds.getSpan(b); assert.equal(slen, 4); assert.equal(Buffer('68692100', 'hex').compare(b.slice(0, slen)), 0); assert.equal(ds.decode(b), 'hi!'); @@ -262,8 +262,8 @@ See [CString](http://pabigot.github.io/buffer-layout/module-Layout-CString.html) The buffer-layout way: - var ds = lo.blob(4); - var b = Buffer('0102030405060708', 'hex'); + const ds = lo.blob(4); + const b = Buffer('0102030405060708', 'hex'); assert.equal(Buffer('03040506', 'hex').compare(ds.decode(b, 2)), 0); See [Blob](http://pabigot.github.io/buffer-layout/module-Layout-Blob.html). @@ -272,15 +272,15 @@ See [Blob](http://pabigot.github.io/buffer-layout/module-Layout-Blob.html). The buffer-layout way: - var pr = lo.seq(lo.cstr(), 2); - var n = lo.u8('n'); - var vla = lo.seq(pr, lo.offset(n, -1), 'a'); - var st = lo.struct([n, vla], 'st'); - var b = new Buffer(32); - var arr = [['k1', 'v1'], ['k2', 'v2'], ['k3', 'etc']]; + const pr = lo.seq(lo.cstr(), 2); + const n = lo.u8('n'); + const vla = lo.seq(pr, lo.offset(n, -1), 'a'); + const st = lo.struct([n, vla], 'st'); + const b = new Buffer(32); + const arr = [['k1', 'v1'], ['k2', 'v2'], ['k3', 'etc']]; b.fill(0); assert.equal(st.encode({a: arr}, b), 1 + (2 * ((2 + 1) + (2 + 1)) + (2 + 1) + (3 + 1))); - var span = st.getSpan(b); + const span = st.getSpan(b); assert.equal(span, 20); assert.equal(Buffer('036b31007631006b32007632006b330065746300', 'hex') .compare(b.slice(0, span)), 0); @@ -302,12 +302,12 @@ The C definition: The buffer-layout way: - var st = lo.struct([lo.u8('prop'), + const st = lo.struct([lo.u8('prop'), lo.seq(lo.u16(), lo.greedy(lo.u16().span), 'data')], 'ds'); - var b = Buffer('21010002030405', 'hex'); + const b = Buffer('21010002030405', 'hex'); assert.deepEqual(st.decode(b), {prop: 33, data: [0x0001, 0x0302, 0x0504]}); b.fill(0xFF); assert.equal(st.encode({prop: 9, data: [5,6]}, b), 1 + 2 * 2); @@ -326,14 +326,14 @@ encoded union. This could be used to make something similar to Here's the code that defines the union, the variants, and the recognition of `true` and `false` values for `b` as distinct variants: - var un = lo.union(lo.u8('t')); - var u8 = un.addVariant('B'.charCodeAt(0), lo.u8(), 'u8'); - var s16 = un.addVariant('h'.charCodeAt(0), lo.s16(), 's16'); - var s48 = un.addVariant('Q'.charCodeAt(0), lo.s48(), 's48'); - var cstr = un.addVariant('s'.charCodeAt(0), lo.cstr(), 'str'); - var tr = un.addVariant('T'.charCodeAt(0), lo.const(true), 'b'); - var fa = un.addVariant('F'.charCodeAt(0), lo.const(false), 'b'); - var b = new Buffer(1 + 6); + const un = lo.union(lo.u8('t')); + const u8 = un.addVariant('B'.charCodeAt(0), lo.u8(), 'u8'); + const s16 = un.addVariant('h'.charCodeAt(0), lo.s16(), 's16'); + const s48 = un.addVariant('Q'.charCodeAt(0), lo.s48(), 's48'); + const cstr = un.addVariant('s'.charCodeAt(0), lo.cstr(), 'str'); + const tr = un.addVariant('T'.charCodeAt(0), lo.const(true), 'b'); + const fa = un.addVariant('F'.charCodeAt(0), lo.const(false), 'b'); + const b = new Buffer(1 + 6); un.configGetSourceVariant(function(src) { if (src.hasOwnProperty('b')) { return src.b ? tr : fa; @@ -357,7 +357,7 @@ decoding each of the alternatives: assert.equal(un.decode(b).s16, -32000); b.fill(0xff); - var v48 = Math.pow(2, 47) - 1; + const v48 = Math.pow(2, 47) - 1; assert.equal(un.encode({s48: v48}, b), 1 + 6); assert.equal(un.getSpan(b), 7); assert.equal(Buffer('51ffffffffff7f', 'hex').compare(b), 0); diff --git a/lib/Layout.js b/lib/Layout.js index 3f55818..fc479d1 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -728,12 +728,11 @@ const V2E32 = Math.pow(2, 32); /* True modulus high and low 32-bit words, where low word is always * non-negative. */ function divmodInt64(src) { - var hi32 = Math.floor(src / V2E32); - var lo32 = src - (hi32 * V2E32); + const hi32 = Math.floor(src / V2E32); + const lo32 = src - (hi32 * V2E32); // assert.equal(roundedInt64(hi32, lo32), src); // assert(0 <= lo32); - return {hi32: hi32, - lo32: lo32}; + return {hi32, lo32}; } /* Reconstruct Number from quotient and non-negative remainder */ function roundedInt64(hi32, lo32) { @@ -1277,7 +1276,7 @@ class Structure extends Layout { * encoding). But check it anyway. */ assert(0 < span); } else { - var fv = src[fd.property]; + const fv = src[fd.property]; if (undefined !== fv) { lastWrote = fd.encode(fv, b, offset); if (0 > span) { @@ -1506,7 +1505,7 @@ class UnionLayoutDiscriminator extends UnionDiscriminator { */ class Union extends Layout { constructor(discr, defaultLayout, property) { - var upv = ((discr instanceof UInt) + const upv = ((discr instanceof UInt) || (discr instanceof UIntBE)); if (upv) { discr = new UnionLayoutDiscriminator(new OffsetLayout(discr)); @@ -1537,7 +1536,7 @@ class Union extends Layout { * layout. The union spans its default layout, plus any prefix * variant layout. By construction both layouts, if present, have * non-negative span. */ - var span = -1; + let span = -1; if (defaultLayout) { span = defaultLayout.span; if ((0 <= span) && upv) { @@ -1586,7 +1585,7 @@ class Union extends Layout { this.registry = {}; /* Private variable used when invoking getSourceVariant */ - var boundGetSourceVariant = this.defaultGetSourceVariant.bind(this); + let boundGetSourceVariant = this.defaultGetSourceVariant.bind(this); /** Function to infer the variant selected by a source object. * @@ -1634,7 +1633,7 @@ class Union extends Layout { /* Default layouts always have non-negative span, so we don't have * one and we have to recognize the variant which will in turn * determine the span. */ - var vlo = this.getVariant(b, offset); + const vlo = this.getVariant(b, offset); if (!vlo) { throw new Error('unable to determine span for unrecognized variant'); } @@ -1660,8 +1659,8 @@ class Union extends Layout { && src.hasOwnProperty(this.defaultLayout.property)) { return undefined; } - for (var k in this.registry) { - var lo = this.registry[k]; + for (const k in this.registry) { + const lo = this.registry[k]; if (src.hasOwnProperty(lo.property)) { return lo; } @@ -1679,12 +1678,12 @@ class Union extends Layout { if (undefined === offset) { offset = 0; } - var dest; - var dlo = this.discriminator; - var discr = dlo.decode(b, offset); - var clo = this.registry[discr]; + let dest; + const dlo = this.discriminator; + const discr = dlo.decode(b, offset); + let clo = this.registry[discr]; if (undefined === clo) { - var contentOffset = 0; + let contentOffset = 0; clo = this.defaultLayout; if (this.usesPrefixDiscriminator) { contentOffset = dlo.layout.span; @@ -1708,11 +1707,11 @@ class Union extends Layout { if (undefined === offset) { offset = 0; } - var vlo = this.getSourceVariant(src); + const vlo = this.getSourceVariant(src); if (undefined === vlo) { - var dlo = this.discriminator; - var clo = this.defaultLayout; - var contentOffset = 0; + const dlo = this.discriminator; + const clo = this.defaultLayout; + let contentOffset = 0; if (this.usesPrefixDiscriminator) { contentOffset = dlo.layout.span; } @@ -1737,7 +1736,7 @@ class Union extends Layout { * * @return {VariantLayout} */ addVariant(variant, layout, property) { - var rv = new VariantLayout(this, variant, layout, property); + const rv = new VariantLayout(this, variant, layout, property); this.registry[variant] = rv; return rv; } @@ -1757,7 +1756,7 @@ class Union extends Layout { * @return {({VariantLayout}|undefined)} */ getVariant(vb, offset) { - var variant = vb; + let variant = vb; if (vb instanceof Buffer) { if (undefined === offset) { offset = 0; @@ -1815,7 +1814,7 @@ class VariantLayout extends Layout { if ('string' !== typeof property) { throw new TypeError('variant must have a String property'); } - var span = union.span; + let span = union.span; if (0 > union.span) { span = layout.span; if ((0 <= span) && union.usesPrefixDiscriminator) { @@ -1848,7 +1847,7 @@ class VariantLayout extends Layout { if (undefined === offset) { offset = 0; } - var contentOffset = 0; + let contentOffset = 0; if (this.union.usesPrefixDiscriminator) { contentOffset = this.union.discriminator.layout.span; } @@ -1858,14 +1857,14 @@ class VariantLayout extends Layout { /** @override */ decode(b, offset) { - var dest = this.makeDestinationObject(); + const dest = this.makeDestinationObject(); if (undefined === offset) { offset = 0; } if (this !== this.union.getVariant(b, offset)) { throw new Error('variant mismatch'); } - var contentOffset = 0; + let contentOffset = 0; if (this.union.usesPrefixDiscriminator) { contentOffset = this.union.discriminator.layout.span; } @@ -1878,7 +1877,7 @@ class VariantLayout extends Layout { if (undefined === offset) { offset = 0; } - var contentOffset = 0; + let contentOffset = 0; if (this.union.usesPrefixDiscriminator) { contentOffset = this.union.discriminator.layout.span; } @@ -1887,7 +1886,7 @@ class VariantLayout extends Layout { } this.union.discriminator.encode(this.variant, b, offset); this.layout.encode(src[this.property], b, offset + contentOffset); - var span = contentOffset + this.layout.getSpan(b, offset + contentOffset); + const span = contentOffset + this.layout.getSpan(b, offset + contentOffset); if ((0 <= this.union.span) && (span > this.union.span)) { throw new Error('encoded variant overruns containing union'); @@ -1981,7 +1980,7 @@ class BitStructure extends Layout { /* Storage for the value. Capture a variable instead of using an * instance property because we don't want anything to change the * value without going through the mutator. */ - var value = 0; + let value = 0; this._packedSetValue = function(v) { value = fixBitwiseResult(v); return this; @@ -1993,11 +1992,11 @@ class BitStructure extends Layout { /** @override */ decode(b, offset) { - var dest = this.makeDestinationObject(); + const dest = this.makeDestinationObject(); if (undefined === offset) { offset = 0; } - var value = this.word.decode(b, offset); + const value = this.word.decode(b, offset); this._packedSetValue(value); this.fields.forEach(function(fd) { if (undefined !== fd.property) { @@ -2016,11 +2015,11 @@ class BitStructure extends Layout { if (undefined === offset) { offset = 0; } - var value = this.word.decode(b, offset); + const value = this.word.decode(b, offset); this._packedSetValue(value); this.fields.forEach(function(fd) { if (undefined !== fd.property) { - var fv = src[fd.property]; + const fv = src[fd.property]; if (undefined !== fv) { fd.encode(fv); } @@ -2039,7 +2038,7 @@ class BitStructure extends Layout { * * @return {BitField} */ addField(bits, property) { - var bf = new BitField(this, bits, property); + const bf = new BitField(this, bits, property); this.fields.push(bf); return bf; } @@ -2054,7 +2053,7 @@ class BitStructure extends Layout { addBoolean(property) { // This is my Boolean, not the Javascript one. // eslint-disable-next-line no-new-wrappers - var bf = new Boolean(this, property); + const bf = new Boolean(this, property); this.fields.push(bf); return bf; } @@ -2068,7 +2067,7 @@ class BitStructure extends Layout { * undefined if there is no such property. */ fieldFor(property) { - var rv; + let rv; if (property) { this.fields.forEach(function(fd) { if (fd.property === property) { @@ -2111,11 +2110,11 @@ class BitField { if ((!Number.isInteger(bits)) || (0 >= bits)) { throw new TypeError('bits must be positive integer'); } - var totalBits = 8 * container.span; + const totalBits = 8 * container.span; function bitsSum(c, fd) { return c + fd.bits; } - var usedBits = container.fields.reduce(bitsSum, 0); + const usedBits = container.fields.reduce(bitsSum, 0); if ((bits + usedBits) > totalBits) { throw new Error('bits too long for span remainder (' + (totalBits - usedBits) + ' of ' @@ -2167,9 +2166,9 @@ class BitField { /** Store a value into the corresponding subsequence of the containing * bit field. */ decode() { - var word = this.container._packedGetValue(); - var wordValue = fixBitwiseResult(word & this.wordMask); - var value = wordValue >>> this.start; + const word = this.container._packedGetValue(); + const wordValue = fixBitwiseResult(word & this.wordMask); + const value = wordValue >>> this.start; return value; } @@ -2184,8 +2183,8 @@ class BitField { throw new TypeError(nameWithProperty('BitField.encode', this) + ' value must be integer not exceeding ' + this.valueMask); } - var word = this.container._packedGetValue(); - var wordValue = fixBitwiseResult(value << this.start); + const word = this.container._packedGetValue(); + const wordValue = fixBitwiseResult(value << this.start); this.container._packedSetValue(fixBitwiseResult(word & ~this.wordMask) | wordValue); }; @@ -2255,7 +2254,7 @@ class Blob extends Layout { + 'or an unsigned integer ExternalLayout'); } - var span = -1; + let span = -1; if (!(length instanceof ExternalLayout)) { span = length; } @@ -2271,7 +2270,7 @@ class Blob extends Layout { /** @override */ getSpan(b, offset) { - var span = this.span; + let span = this.span; if (0 > span) { span = this.length.decode(b, offset); } @@ -2283,7 +2282,7 @@ class Blob extends Layout { if (undefined === offset) { offset = 0; } - var span = this.span; + let span = this.span; if (0 > span) { span = this.length.decode(b, offset); } @@ -2296,7 +2295,7 @@ class Blob extends Layout { * ExternalLayout|ExternalLayout} then the length of `src` will be encoded * as the count after `src` is encoded. */ encode(src, b, offset) { - var span = this.length; + let span = this.length; if (this.length instanceof ExternalLayout) { span = src.length; } @@ -2343,7 +2342,7 @@ class CString extends Layout { if (undefined === offset) { offset = 0; } - var idx = offset; + let idx = offset; while ((idx < b.length) && (0 !== b[idx])) { idx += 1; } @@ -2355,7 +2354,7 @@ class CString extends Layout { if (undefined === offset) { offset = 0; } - var span = this.getSpan(b, offset); + let span = this.getSpan(b, offset); return b.slice(offset, offset + span - 1).toString('utf-8'); } @@ -2370,8 +2369,8 @@ class CString extends Layout { if ('string' !== typeof src) { src = src.toString(); } - var srcb = new Buffer(src, 'utf8'); - var span = srcb.length; + const srcb = new Buffer(src, 'utf8'); + const span = srcb.length; if ((offset + span) > b.length) { throw new RangeError('encoding overruns Buffer'); } diff --git a/test/LayoutTest.js b/test/LayoutTest.js index 186fff6..0f708c9 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -1,4 +1,4 @@ -/* eslint-disable brace-style, max-statements-per-line, no-new */ +/* eslint-disable brace-style, max-statements-per-line, no-new, no-var */ var assert = require('assert'); var util = require('util'); diff --git a/test/examples.js b/test/examples.js index 12e71a9..b40e3ee 100644 --- a/test/examples.js +++ b/test/examples.js @@ -1,15 +1,17 @@ /* eslint-disable brace-style, max-statements-per-line, no-unused-vars */ -var assert = require('assert'); -var util = require('util'); -var lo = require('../lib/Layout'); +'use strict'; + +const assert = require('assert'); +const util = require('util'); +const lo = require('../lib/Layout'); suite('Examples', function() { test('4-elt array of int16_t le', function() { /* int16_t arr[4] = { 1, -1, 3, -3 }; */ - var ds = lo.seq(lo.s16(), 4); - var b = new Buffer(8); + const ds = lo.seq(lo.s16(), 4); + const b = new Buffer(8); assert.equal(ds.encode([1, -1, 3, -3], b), 4 * 2); assert.equal(Buffer('0100ffff0300fdff', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), [1, -1, 3, -3]); @@ -21,11 +23,11 @@ struct ds { uint32_t u32; } st; */ - var ds = lo.struct([lo.u8('v'), + const ds = lo.struct([lo.u8('v'), lo.seq(lo.u8(), 3), // alignment padding lo.u32('u32')]); assert.equal(ds.offsetOf('u32'), 4); - var b = new Buffer(8); + const b = new Buffer(8); b.fill(0xbd); assert.equal(ds.encode({v: 1, u32: 0x12345678}, b), 1 + 3 + 4); assert.equal(Buffer('01bdbdbd78563412', 'hex').compare(b), 0); @@ -38,10 +40,10 @@ struct ds { uint32_t u32; } __attribute__((__packed__)) st; */ - var ds = lo.struct([lo.u8('v'), + const ds = lo.struct([lo.u8('v'), lo.u32('u32')]); assert.equal(ds.offsetOf('u32'), 1); - var b = new Buffer(5); + const b = new Buffer(5); b.fill(0xbd); assert.equal(ds.encode({v: 1, u32: 0x12345678}, b), 1 + 4); assert.equal(Buffer('0178563412', 'hex').compare(b), 0); @@ -59,12 +61,12 @@ struct { } u; } __attribute__((__packed__)) un; */ - var t = lo.u8('t'); - var un = lo.union(t, lo.seq(lo.u8(), 4, 'u8')); - var u32 = un.addVariant('w'.charCodeAt(0), lo.u32(), 'u32'); - var s16 = un.addVariant('h'.charCodeAt(0), lo.seq(lo.s16(), 2), 's16'); - var f32 = un.addVariant('f'.charCodeAt(0), lo.f32(), 'f32'); - var b = new Buffer(un.span); + const t = lo.u8('t'); + const un = lo.union(t, lo.seq(lo.u8(), 4, 'u8')); + const u32 = un.addVariant('w'.charCodeAt(0), lo.u32(), 'u32'); + const s16 = un.addVariant('h'.charCodeAt(0), lo.seq(lo.s16(), 2), 's16'); + const f32 = un.addVariant('f'.charCodeAt(0), lo.f32(), 'f32'); + const b = new Buffer(un.span); assert.deepEqual(un.decode(Buffer('7778563412', 'hex')), {u32: 0x12345678}); assert.deepEqual(un.decode(Buffer('660000bd41', 'hex')), @@ -94,7 +96,7 @@ struct { lo.bindConstructorLayout(Vf32, Union.layout_.addVariant('f'.charCodeAt(0), lo.f32(), 'f32')); - var v = Union.decode(Buffer('7778563412', 'hex')); + let v = Union.decode(Buffer('7778563412', 'hex')); assert(v instanceof Vu32); assert(v instanceof Union); assert.equal(v.u32, 0x12345678); @@ -104,7 +106,7 @@ struct { assert.equal(v.t, 0xa5); assert.deepEqual(v.u8, [0xa5, 0xa5, 0xa5, 0xa5]); - var b = new Buffer(Union.layout_.span); + const b = new Buffer(Union.layout_.span); v = new Vf32(23.625); v.encode(b); assert.equal(Buffer('660000bd41', 'hex').compare(b), 0); @@ -118,8 +120,8 @@ struct ds { unsigned int b1Cl04: 4; } st; */ - var ds = lo.bits(lo.u32()); - var b = new Buffer(4); + const ds = lo.bits(lo.u32()); + const b = new Buffer(4); ds.addField(3, 'b00l03'); ds.addBoolean('flg03'); ds.addField(24, 'b04l18'); @@ -134,10 +136,10 @@ struct ds { /* uint64_t v = 0x0102030405060708ULL; */ - var ds = lo.nu64be(); - var b = Buffer('0102030405060708', 'hex'); - var v = 72623859790382856; - var nv = v - 6; + const ds = lo.nu64be(); + const b = Buffer('0102030405060708', 'hex'); + const v = 72623859790382856; + const nv = v - 6; assert.equal(v, nv); assert.equal(ds.decode(b), nv); }); @@ -145,30 +147,30 @@ uint64_t v = 0x0102030405060708ULL; /* const char str[] = "hi!"; */ - var ds = lo.cstr(); - var b = new Buffer(8); + const ds = lo.cstr(); + const b = new Buffer(8); assert.equal(ds.encode('hi!', b), 3 + 1); - var slen = ds.getSpan(b); + const slen = ds.getSpan(b); assert.equal(slen, 4); assert.equal(Buffer('68692100', 'hex').compare(b.slice(0, slen)), 0); assert.equal(ds.decode(b), 'hi!'); }); test('Fixed-len blob at offset', function() { - var ds = lo.blob(4); - var b = Buffer('0102030405060708', 'hex'); + const ds = lo.blob(4); + const b = Buffer('0102030405060708', 'hex'); assert.equal(Buffer('03040506', 'hex').compare(ds.decode(b, 2)), 0); }); test('variable-length array of pairs of C strings', function() { - var pr = lo.seq(lo.cstr(), 2); - var n = lo.u8('n'); - var vla = lo.seq(pr, lo.offset(n, -1), 'a'); - var st = lo.struct([n, vla], 'st'); - var b = new Buffer(32); - var arr = [['k1', 'v1'], ['k2', 'v2'], ['k3', 'etc']]; + const pr = lo.seq(lo.cstr(), 2); + const n = lo.u8('n'); + const vla = lo.seq(pr, lo.offset(n, -1), 'a'); + const st = lo.struct([n, vla], 'st'); + const b = new Buffer(32); + const arr = [['k1', 'v1'], ['k2', 'v2'], ['k3', 'etc']]; b.fill(0); assert.equal(st.encode({a: arr}, b), 1 + (2 * ((2 + 1) + (2 + 1)) + (2 + 1) + (3 + 1))); - var span = st.getSpan(b); + const span = st.getSpan(b); assert.equal(span, 20); assert.equal(Buffer('036b31007631006b32007632006b330065746300', 'hex') .compare(b.slice(0, span)), 0); @@ -181,26 +183,26 @@ struct ds { uint16_t data[]; }; */ - var st = lo.struct([lo.u8('prop'), + const st = lo.struct([lo.u8('prop'), lo.seq(lo.u16(), lo.greedy(lo.u16().span), 'data')], 'ds'); - var b = Buffer('21010002030405', 'hex'); + const b = Buffer('21010002030405', 'hex'); assert.deepEqual(st.decode(b), {prop: 33, data: [0x0001, 0x0302, 0x0504]}); b.fill(0xFF); assert.equal(st.encode({prop: 9, data: [5, 6]}, b), 1 + 2 * 2); assert.equal(Buffer('0905000600FFFF', 'hex').compare(b), 0); }); test('variable-length union', function() { - var un = lo.union(lo.u8('t')); - var u8 = un.addVariant('B'.charCodeAt(0), lo.u8(), 'u8'); - var s16 = un.addVariant('h'.charCodeAt(0), lo.s16(), 's16'); - var s48 = un.addVariant('Q'.charCodeAt(0), lo.s48(), 's48'); - var cstr = un.addVariant('s'.charCodeAt(0), lo.cstr(), 'str'); - var tr = un.addVariant('T'.charCodeAt(0), lo.const(true), 'b'); - var fa = un.addVariant('F'.charCodeAt(0), lo.const(false), 'b'); - var b = new Buffer(1 + 6); + const un = lo.union(lo.u8('t')); + const u8 = un.addVariant('B'.charCodeAt(0), lo.u8(), 'u8'); + const s16 = un.addVariant('h'.charCodeAt(0), lo.s16(), 's16'); + const s48 = un.addVariant('Q'.charCodeAt(0), lo.s48(), 's48'); + const cstr = un.addVariant('s'.charCodeAt(0), lo.cstr(), 'str'); + const tr = un.addVariant('T'.charCodeAt(0), lo.const(true), 'b'); + const fa = un.addVariant('F'.charCodeAt(0), lo.const(false), 'b'); + const b = new Buffer(1 + 6); un.configGetSourceVariant(function(src) { if (src.hasOwnProperty('b')) { return src.b ? tr : fa; @@ -222,7 +224,7 @@ struct ds { assert.equal(un.decode(b).s16, -32000); b.fill(0xff); - var v48 = Math.pow(2, 47) - 1; + const v48 = Math.pow(2, 47) - 1; assert.equal(un.encode({s48: v48}, b), 1 + 6); assert.equal(un.getSpan(b), 7); assert.equal(Buffer('51ffffffffff7f', 'hex').compare(b), 0); From ecad2fcde90a1e2b3af91d2ba1fcd3978050b38d Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 16 Dec 2017 11:12:36 -0600 Subject: [PATCH 14/17] passim: eslint new-cap, update minimum Node version to 4.5 We need the safe Buffer API which became availble in 4.5.0. --- .eslintrc.js | 1 - README.md | 80 ++++---- lib/Layout.js | 43 ++--- lib/patchIssue3992.js | 119 ------------ package.json | 2 +- test/LayoutTest.js | 440 +++++++++++++++++++++--------------------- test/examples.js | 64 +++--- 7 files changed, 313 insertions(+), 436 deletions(-) delete mode 100644 lib/patchIssue3992.js diff --git a/.eslintrc.js b/.eslintrc.js index 10d551a..76dcc0a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,6 @@ module.exports = { ], rules: { 'guard-for-in': 'off', - 'new-cap': 'off', 'prefer-rest-params': 'off', 'prefer-spread': 'off', __temporary: 'off', diff --git a/README.md b/README.md index a33092d..de05017 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,8 @@ Layout support is provided for these types of data: ## Installation -Development and testing is done using Node.js, supporting versions 4 and -later (earlier versions may work). Install with `npm install -buffer-layout`. +Development and testing is done using Node.js, supporting versions 4.5 +and later. Install with `npm install buffer-layout`. ## Examples @@ -58,9 +57,9 @@ The C definition: The buffer-layout way: const ds = lo.seq(lo.s16(), 4); - const b = new Buffer(8); + const b = Buffer.alloc(8); assert.equal(ds.encode([1, -1, 3, -3], b), 4 * 2); - assert.equal(Buffer('0100ffff0300fdff', 'hex').compare(b), 0); + assert.equal(Buffer.from('0100ffff0300fdff', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), [1, -1, 3, -3]); See [Int](http://pabigot.github.io/buffer-layout/module-Layout-Int.html) @@ -81,10 +80,10 @@ The buffer-layout way: lo.seq(lo.u8(), 3), // alignment padding lo.u32('u32')]); assert.equal(ds.offsetOf('u32'), 4); - const b = new Buffer(8); + const b = Buffer.alloc(8); b.fill(0xbd); assert.equal(ds.encode({v: 1, u32: 0x12345678}, b), 1 + 3 + 4); - assert.equal(Buffer('01bdbdbd78563412', 'hex').compare(b), 0); + assert.equal(Buffer.from('01bdbdbd78563412', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), {v: 1, u32: 0x12345678}); Note that the C language requires padding which must be explicitly added @@ -108,10 +107,10 @@ The buffer-layout way: const ds = lo.struct([lo.u8('v'), lo.u32('u32')]); assert.equal(ds.offsetOf('u32'), 1); - const b = new Buffer(5); + const b = Buffer.alloc(5); b.fill(0xbd); assert.equal(ds.encode({v: 1, u32: 0x12345678}, b), 1 + 4); - assert.equal(Buffer('0178563412', 'hex').compare(b), 0); + assert.equal(Buffer.from('0178563412', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), {v: 1, u32: 0x12345678}); ### A tagged union of 4-byte values @@ -136,15 +135,15 @@ The buffer-layout way: const u32 = un.addVariant('w'.charCodeAt(0), lo.u32(), 'u32'); const s16 = un.addVariant('h'.charCodeAt(0), lo.seq(lo.s16(), 2), 's16'); const f32 = un.addVariant('f'.charCodeAt(0), lo.f32(), 'f32'); - const b = new Buffer(un.span); - assert.deepEqual(un.decode(Buffer('7778563412', 'hex')), + const b = Buffer.alloc(un.span); + assert.deepEqual(un.decode(Buffer.from('7778563412', 'hex')), {u32: 0x12345678}); - assert.deepEqual(un.decode(Buffer('660000bd41', 'hex')), + assert.deepEqual(un.decode(Buffer.from('660000bd41', 'hex')), {f32: 23.625}); - assert.deepEqual(un.decode(Buffer('a5a5a5a5a5', 'hex')), + assert.deepEqual(un.decode(Buffer.from('a5a5a5a5a5', 'hex')), {t: 0xa5, u8: [0xa5, 0xa5, 0xa5, 0xa5]}); assert.equal(s16.encode({s16: [123, -123]}, b), 1 + 2 * 2); - assert.equal(Buffer('687b0085ff', 'hex').compare(b), 0); + assert.equal(Buffer.from('687b0085ff', 'hex').compare(b), 0); See [Union](http://pabigot.github.io/buffer-layout/module-Layout-Union.html). @@ -172,20 +171,20 @@ representing the union and the variants: lo.bindConstructorLayout(Vf32, Union.layout_.addVariant('f'.charCodeAt(0), lo.f32(), 'f32')); - let v = Union.decode(Buffer('7778563412', 'hex')); + let v = Union.decode(Buffer.from('7778563412', 'hex')); assert(v instanceof Vu32); assert(v instanceof Union); assert.equal(v.u32, 0x12345678); - v = Union.decode(Buffer('a5a5a5a5a5', 'hex')); + v = Union.decode(Buffer.from('a5a5a5a5a5', 'hex')); assert(v instanceof Union); assert.equal(v.t, 0xa5); assert.deepEqual(v.u8, [0xa5, 0xa5, 0xa5, 0xa5]); - const b = new Buffer(Union.layout_.span); + const b = Buffer.alloc(Union.layout_.span); v = new Vf32(23.625); v.encode(b); - assert.equal(Buffer('660000bd41', 'hex').compare(b), 0); + assert.equal(Buffer.from('660000bd41', 'hex').compare(b), 0); See [Layout.makeDestinationObject()](http://pabigot.github.io/buffer-layout/module-Layout-Layout.html#makeDestinationObject) @@ -206,14 +205,14 @@ The C definition: The buffer-layout way: const ds = lo.bits(lo.u32()); - const b = new Buffer(4); + const b = Buffer.alloc(4); ds.addField(3, 'b00l03'); 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.equal(Buffer.from('8b010040', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), {b00l03: 3, flg03: true, b04l18: 24, b1Cl04: 4}); @@ -228,7 +227,7 @@ The C definition: The buffer-layout way: const ds = lo.nu64be(); - const b = Buffer('0102030405060708', 'hex'); + const b = Buffer.from('0102030405060708', 'hex'); const v = 72623859790382856; const nv = v - 6; assert.equal(v, nv); @@ -249,11 +248,11 @@ The C definition: The buffer-layout way: const ds = lo.cstr(); - const b = new Buffer(8); + const b = Buffer.alloc(8); assert.equal(ds.encode('hi!', b), 3 + 1); const slen = ds.getSpan(b); assert.equal(slen, 4); - assert.equal(Buffer('68692100', 'hex').compare(b.slice(0, slen)), 0); + assert.equal(Buffer.from('68692100', 'hex').compare(b.slice(0, slen)), 0); assert.equal(ds.decode(b), 'hi!'); See [CString](http://pabigot.github.io/buffer-layout/module-Layout-CString.html). @@ -263,8 +262,8 @@ See [CString](http://pabigot.github.io/buffer-layout/module-Layout-CString.html) The buffer-layout way: const ds = lo.blob(4); - const b = Buffer('0102030405060708', 'hex'); - assert.equal(Buffer('03040506', 'hex').compare(ds.decode(b, 2)), 0); + const b = Buffer.from('0102030405060708', 'hex'); + assert.equal(Buffer.from('03040506', 'hex').compare(ds.decode(b, 2)), 0); See [Blob](http://pabigot.github.io/buffer-layout/module-Layout-Blob.html). @@ -276,13 +275,14 @@ The buffer-layout way: const n = lo.u8('n'); const vla = lo.seq(pr, lo.offset(n, -1), 'a'); const st = lo.struct([n, vla], 'st'); - const b = new Buffer(32); + const b = Buffer.alloc(32); const arr = [['k1', 'v1'], ['k2', 'v2'], ['k3', 'etc']]; b.fill(0); - assert.equal(st.encode({a: arr}, b), 1 + (2 * ((2 + 1) + (2 + 1)) + (2 + 1) + (3 + 1))); + assert.equal(st.encode({a: arr}, b), + 1 + (2 * ((2 + 1) + (2 + 1)) + (2 + 1) + (3 + 1))); const span = st.getSpan(b); assert.equal(span, 20); - assert.equal(Buffer('036b31007631006b32007632006b330065746300', 'hex') + assert.equal(Buffer.from('036b31007631006b32007632006b330065746300', 'hex') .compare(b.slice(0, span)), 0); assert.deepEqual(st.decode(b), {n: 3, a: arr}); @@ -307,11 +307,11 @@ The buffer-layout way: lo.greedy(lo.u16().span), 'data')], 'ds'); - const b = Buffer('21010002030405', 'hex'); + const b = Buffer.from('21010002030405', 'hex'); assert.deepEqual(st.decode(b), {prop: 33, data: [0x0001, 0x0302, 0x0504]}); b.fill(0xFF); - assert.equal(st.encode({prop: 9, data: [5,6]}, b), 1 + 2 * 2); - assert.equal(Buffer('0905000600FFFF', 'hex').compare(b), 0); + assert.equal(st.encode({prop: 9, data: [5, 6]}, b), 1 + 2 * 2); + assert.equal(Buffer.from('0905000600FFFF', 'hex').compare(b), 0); ### Tagged values, or variable-length unions @@ -333,7 +333,7 @@ recognition of `true` and `false` values for `b` as distinct variants: const cstr = un.addVariant('s'.charCodeAt(0), lo.cstr(), 'str'); const tr = un.addVariant('T'.charCodeAt(0), lo.const(true), 'b'); const fa = un.addVariant('F'.charCodeAt(0), lo.const(false), 'b'); - const b = new Buffer(1 + 6); + const b = Buffer.alloc(1 + 6); un.configGetSourceVariant(function(src) { if (src.hasOwnProperty('b')) { return src.b ? tr : fa; @@ -347,36 +347,34 @@ decoding each of the alternatives: b.fill(0xff); assert.equal(un.encode({u8: 1}, b), 1 + 1); assert.equal(un.getSpan(b), 2); - assert.equal(Buffer('4201ffffffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('4201ffffffffff', 'hex').compare(b), 0); assert.equal(un.decode(b).u8, 1); b.fill(0xff); assert.equal(un.encode({s16: -32000}, b), 1 + 2); assert.equal(un.getSpan(b), 3); - assert.equal(Buffer('680083ffffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('680083ffffffff', 'hex').compare(b), 0); assert.equal(un.decode(b).s16, -32000); b.fill(0xff); const v48 = Math.pow(2, 47) - 1; assert.equal(un.encode({s48: v48}, b), 1 + 6); assert.equal(un.getSpan(b), 7); - assert.equal(Buffer('51ffffffffff7f', 'hex').compare(b), 0); + assert.equal(Buffer.from('51ffffffffff7f', 'hex').compare(b), 0); assert.equal(un.decode(b).s48, v48); b.fill(0xff); assert.equal(un.encode({b: true}, b), 1); assert.equal(un.getSpan(b), 1); - assert.equal(Buffer('54ffffffffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('54ffffffffffff', 'hex').compare(b), 0); assert.strictEqual(un.decode(b).b, true); b.fill(0xff); assert.equal(un.encode({b: false}, b), 1); assert.equal(un.getSpan(b), 1); - assert.equal(Buffer('46ffffffffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('46ffffffffffff', 'hex').compare(b), 0); assert.strictEqual(un.decode(b).b, false); **NOTE** This code tickles a long-standing [bug in -Buffer.writeInt{L,B}E](https://github.com/nodejs/node/pull/3994). `buffer-layout` -provides a [module that patches -`Buffer`](http://pabigot.github.io/buffer-layout/module-patchIssue3992.html) -to fix the bug if it detects that the running Node has the error. +Buffer.writeInt{L,B}E](https://github.com/nodejs/node/pull/3994); if you +are using Node prior to 4.2.4 or 5.2.0 you should update. diff --git a/lib/Layout.js b/lib/Layout.js index fc479d1..87e2a8d 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -133,8 +133,6 @@ const assert = require('assert'); -require('./patchIssue3992'); - /** * Base class for layout objects. * @@ -328,37 +326,38 @@ function nameWithProperty(name, lo) { exports.nameWithProperty = nameWithProperty; /** - * Augment a constructor so that instances can be encoded/decoded - * using a given layout. + * Augment a class so that instances can be encoded/decoded using a + * given layout. * - * Calling this function couples `ctor` with `layout` in several ways: + * Calling this function couples `Class` with `layout` in several ways: * - * * `ctor.layout_` becomes a static member property equal to `layout`; + * * `Class.layout_` becomes a static member property equal to `layout`; * * `layout.boundConstructor_` becomes a static member property equal - * to `ctor`; + * to `Class`; * * The {@link Layout#makeDestinationObject|makeDestinationObject()} * property of `layout` is set to a function that returns a `new - * ctor()`; - * * `ctor.decode(b, offset)` becomes a static member function that + * Class()`; + * * `Class.decode(b, offset)` becomes a static member function that * delegates to {@link Layout#decode|layout.decode}. The * synthesized function may be captured and extended. - * * `ctor.prototype.encode(b, offset)` provides an instance member + * * `Class.prototype.encode(b, offset)` provides an instance member * function that delegates to {@link Layout#encode|layout.encode} * with `src` set to `this`. The synthesized function may be * captured and extended, but when the extension is invoked `this` * must be explicitly bound to the instance. * - * @param {constructor} ctor - the constructor for a JavaScript class. + * @param {class} Class - a JavaScript class with a nullary + * constructor. * * @param {Layout} layout - the {@link Layout|Layout} instance used to - * encode instances of `ctor`. + * encode instances of `Class`. */ -exports.bindConstructorLayout = function(ctor, layout) { - if ('function' !== typeof ctor) { - throw new TypeError('ctor must be constructor'); +exports.bindConstructorLayout = function(Class, layout) { + if ('function' !== typeof Class) { + throw new TypeError('Class must be constructor'); } - if (ctor.hasOwnProperty('layout_')) { - throw new Error('ctor is already bound to a layout'); + if (Class.hasOwnProperty('layout_')) { + throw new Error('Class is already bound to a layout'); } if (!(layout && (layout instanceof Layout))) { throw new TypeError('layout must be a Layout'); @@ -366,12 +365,12 @@ exports.bindConstructorLayout = function(ctor, layout) { if (layout.hasOwnProperty('boundConstructor_')) { throw new Error('layout is already bound to a constructor'); } - ctor.layout_ = layout; - layout.boundConstructor_ = ctor; + Class.layout_ = layout; + layout.boundConstructor_ = Class; layout.makeDestinationObject = function() { - return new ctor(); + return new Class(); }; - Object.defineProperty(ctor.prototype, 'encode', { + Object.defineProperty(Class.prototype, 'encode', { configurable: false, enumerable: false, value: function(b, offset) { @@ -379,7 +378,7 @@ exports.bindConstructorLayout = function(ctor, layout) { }, writable: true, }); - Object.defineProperty(ctor, 'decode', { + Object.defineProperty(Class, 'decode', { configurable: false, enumerable: false, value: function(b, offset) { diff --git a/lib/patchIssue3992.js b/lib/patchIssue3992.js deleted file mode 100644 index d4c5e9c..0000000 --- a/lib/patchIssue3992.js +++ /dev/null @@ -1,119 +0,0 @@ -/* Material in this file modified from Node.js under LICENSE: - -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - */ - -/** Determine whether {@link - * https://github.com/nodejs/node/issues/3992|Node.js issue #3992} is - * fixed, and if not replace the Buffer functions with ones that work - * correctly. - * - * This module exports no behavior. It may modify the Buffer - * prototype. - * - * This module originates from {@link - * https://github.com/pabigot/buffer-layout|buffer-layout on GitHub}. - * - * @module patchIssue3992 - * @license MIT - */ - -/* eslint-disable */ - -/* Test whether Buffer.writeIntLE() gets the right answer for - * problematic negative integers */ -var issue3992IsResolved = (function() { - var buf = new Buffer(2); - buf.writeIntLE(-0x100, 0, 2); - // The value would be 0xFE if the bug is present - return (0xFF === buf[1]); -})(); - -/* NB: Backfill code modified from node lib/buffer.js as of - * 8bc80386879538de63cd6f2aef288f59324eb004 (2015-11-20) */ -/* istanbul ignore next */ -function checkInt(buffer, value, offset, ext, max, min) { - if (!(buffer instanceof Buffer)) - throw new TypeError('"buffer" argument must be a Buffer instance'); - if (value > max || value < min) - throw new TypeError('"value" argument is out of bounds'); - if (offset + ext > buffer.length) - throw new RangeError('Index out of range'); -} - -/* The grotesquery here is because jshint whines about strict mode - * violations if the function doesn't appear to be a method, and about - * defining functions within a block if the test is in an if - * statement. */ -/* istanbul ignore next */ -Buffer.prototype.writeIntLE = issue3992IsResolved - ? Buffer.prototype.writeIntLE - : function(value, offset, byteLength, noAssert) { - value = +value; - offset = offset >>> 0; - if (!noAssert) { - checkInt(this, - value, - offset, - byteLength, - Math.pow(2, 8 * byteLength - 1) - 1, - -Math.pow(2, 8 * byteLength - 1)); - } - - var i = 0; - var mul = 1; - var sub = 0; - this[offset] = value; - while (++i < byteLength && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) - sub = 1; - this[offset + i] = ((value / mul) >> 0) - sub; - } - - return offset + byteLength; -}; - -/* istanbul ignore next */ -Buffer.prototype.writeIntBE = issue3992IsResolved - ? Buffer.prototype.writeIntBE - : function(value, offset, byteLength, noAssert) { - value = +value; - offset = offset >>> 0; - if (!noAssert) { - checkInt(this, - value, - offset, - byteLength, - Math.pow(2, 8 * byteLength - 1) - 1, - -Math.pow(2, 8 * byteLength - 1)); - } - - var i = byteLength - 1; - var mul = 1; - var sub = 0; - this[offset + i] = value; - while (--i >= 0 && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) - sub = 1; - this[offset + i] = ((value / mul) >> 0) - sub; - } - - return offset + byteLength; -}; diff --git a/package.json b/package.json index 1dc85ae..a568c19 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "mocha": "~4.0.1" }, "engines": { - "node": ">=4" + "node": ">=4.5" }, "scripts": { "coverage": "istanbul cover _mocha -- -u tdd", diff --git a/test/LayoutTest.js b/test/LayoutTest.js index 0f708c9..5a8b569 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -9,7 +9,7 @@ var lo = require('../lib/Layout'); * That's not what we want. */ function reversedBuffer(b) { var ba = Array.prototype.slice.call(b); - return new Buffer(ba.reverse()); + return Buffer.from(ba.reverse()); } /* Helper to check that a thrown exception is both the expected type @@ -28,12 +28,12 @@ function checkError(exc, expect, regex) { suite('Layout', function() { test('#reversedBuffer', function() { - var b = Buffer('0102030405', 'hex'); - assert.equal(Buffer('0504030201', 'hex').compare(reversedBuffer(b)), 0); + var b = Buffer.from('0102030405', 'hex'); + assert.equal(Buffer.from('0504030201', 'hex').compare(reversedBuffer(b)), 0); }); suite('Buffer', function() { test('issue 3992', function() { - var buf = new Buffer(4); + var buf = Buffer.alloc(4); buf.writeIntLE(-0x120000, 0, 4); assert.deepEqual(buf.toJSON().data, [0x00, 0x00, 0xee, 0xff]); buf.writeIntBE(-0x120000, 0, 4); @@ -62,7 +62,7 @@ suite('Layout', function() { }); test('abstractness', function() { var d = new lo.Layout(3); - var b = new Buffer(3); + var b = Buffer.alloc(3); assert.throws(function() {d.decode(b);}); assert.throws(function() {d.encode('sth', b);}); }); @@ -74,7 +74,7 @@ suite('Layout', function() { suite('UInt', function() { test('u8', function() { var d = lo.u8('t'); - var b = new Buffer(1); + var b = Buffer.alloc(1); assert(d instanceof lo.UInt); assert(d instanceof lo.Layout); assert.equal(d.span, 1); @@ -83,12 +83,12 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(23, b), 1); - assert.equal(Buffer('17', 'hex').compare(b), 0); + assert.equal(Buffer.from('17', 'hex').compare(b), 0); assert.equal(d.decode(b), 23); }); test('u16', function() { var d = lo.u16('t'); - var b = new Buffer(2); + var b = Buffer.alloc(2); assert(d instanceof lo.UInt); assert(d instanceof lo.Layout); assert.equal(d.span, 2); @@ -97,19 +97,19 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(0x1234, b), 2); - assert.equal(Buffer('3412', 'hex').compare(b), 0); + assert.equal(Buffer.from('3412', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x1234); }); test('u24', function() { var d = lo.u24('t'); - var b = new Buffer(3); + var b = Buffer.alloc(3); assert.equal(d.span, 3); - assert.equal(0x563412, d.decode(Buffer('123456', 'hex'))); + assert.equal(0x563412, d.decode(Buffer.from('123456', 'hex'))); assert.throws(function() {d.encode(0x1234567, b);}); }); test('u48', function() { var d = lo.u48('t'); - var b = new Buffer(6); + var b = Buffer.alloc(6); assert(d instanceof lo.UInt); assert(d instanceof lo.Layout); assert.equal(d.span, 6); @@ -118,15 +118,15 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(0x123456789abc, b), 6); - assert.equal(Buffer('bc9a78563412', 'hex').compare(b), 0); + assert.equal(Buffer.from('bc9a78563412', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x123456789abc); }); test('offset', function() { - var b = new Buffer(4); + var b = Buffer.alloc(4); b.fill(0xa5); var d = lo.u16('t'); d.encode(0x3412, b, 1); - assert.equal(Buffer('A51234A5', 'hex').compare(b), 0); + assert.equal(Buffer.from('A51234A5', 'hex').compare(b), 0); assert.equal(0xA534, d.decode(b, 2)); }); test('invalid ctor', function() { @@ -136,7 +136,7 @@ suite('Layout', function() { suite('UIntBE', function() { test('u16be', function() { var d = lo.u16be('t'); - var b = new Buffer(2); + var b = Buffer.alloc(2); assert(d instanceof lo.UIntBE); assert(d instanceof lo.Layout); assert.equal(d.span, 2); @@ -144,36 +144,36 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(0x1234, b), 2); - assert.equal(Buffer('1234', 'hex').compare(b), 0); + assert.equal(Buffer.from('1234', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x1234); }); test('u24be', function() { var d = lo.u24be('t'); - var b = new Buffer(3); + var b = Buffer.alloc(3); assert.equal(d.span, 3); - assert.equal(0x123456, d.decode(Buffer('123456', 'hex'))); + assert.equal(0x123456, d.decode(Buffer.from('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); + var b = Buffer.alloc(4); assert.equal(d.span, 4); - assert.equal(0x12345678, d.decode(Buffer('12345678', 'hex'))); + assert.equal(0x12345678, d.decode(Buffer.from('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); + var b = Buffer.alloc(5); assert.equal(d.span, 5); - assert.equal(0x123456789a, d.decode(Buffer('123456789a', 'hex'))); + assert.equal(0x123456789a, d.decode(Buffer.from('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); + var b = Buffer.alloc(6); assert(d instanceof lo.UIntBE); assert(d instanceof lo.Layout); assert.equal(d.span, 6); @@ -181,15 +181,15 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(0x123456789abc, b), 6); - assert.equal(Buffer('123456789abc', 'hex').compare(b), 0); + assert.equal(Buffer.from('123456789abc', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x123456789abc); }); test('offset', function() { - var b = new Buffer(4); + var b = Buffer.alloc(4); b.fill(0xa5); var d = lo.u16be('t'); d.encode(0x1234, b, 1); - assert.equal(Buffer('A51234A5', 'hex').compare(b), 0); + assert.equal(Buffer.from('A51234A5', 'hex').compare(b), 0); assert.equal(0x34A5, d.decode(b, 2)); }); test('invalid ctor', function() { @@ -199,7 +199,7 @@ suite('Layout', function() { suite('Int', function() { test('s8', function() { var d = lo.s8('t'); - var b = new Buffer(1); + var b = Buffer.alloc(1); assert(d instanceof lo.Int); assert(d instanceof lo.Layout); assert.equal(d.span, 1); @@ -207,15 +207,15 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(23, b), 1); - assert.equal(Buffer('17', 'hex').compare(b), 0); + assert.equal(Buffer.from('17', 'hex').compare(b), 0); assert.equal(d.decode(b), 23); assert.equal(d.encode(-97, b), 1); - assert.equal(Buffer('9f', 'hex').compare(b), 0); + assert.equal(Buffer.from('9f', 'hex').compare(b), 0); assert.equal(d.decode(b), -97); }); test('s16', function() { var d = lo.s16('t'); - var b = new Buffer(2); + var b = Buffer.alloc(2); assert(d instanceof lo.Int); assert(d instanceof lo.Layout); assert.equal(d.span, 2); @@ -223,38 +223,38 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(0x1234, b), 2); - assert.equal(Buffer('3412', 'hex').compare(b), 0); + assert.equal(Buffer.from('3412', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x1234); assert.equal(lo.u16be().decode(b), 0x3412); assert.equal(d.encode(-12345, b), 2); - assert.equal(Buffer('c7cf', 'hex').compare(b), 0); + assert.equal(Buffer.from('c7cf', 'hex').compare(b), 0); assert.equal(d.decode(b), -12345); 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); + var b = Buffer.alloc(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.equal(0x563412, d.decode(Buffer.from('123456', 'hex'))); + assert.equal(-1, d.decode(Buffer.from('FFFFFF', 'hex'))); + assert.equal(-0x800000, d.decode(Buffer.from('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); + var b = Buffer.alloc(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.equal(0x123456789a, d.decode(Buffer.from('9a78563412', 'hex'))); + assert.equal(-1, d.decode(Buffer.from('FFFFFFFFFF', 'hex'))); + assert.equal(-0x8000000000, d.decode(Buffer.from('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); + var b = Buffer.alloc(6); assert(d instanceof lo.Int); assert(d instanceof lo.Layout); assert.equal(d.span, 6); @@ -262,11 +262,11 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(0x123456789abc, b), 6); - assert.equal(Buffer('bc9a78563412', 'hex').compare(b), 0); + assert.equal(Buffer.from('bc9a78563412', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x123456789abc); assert.equal(lo.u48be().decode(b), 0xbc9a78563412); assert.equal(d.encode(-123456789012345, b), 6); - assert.equal(Buffer('8720f279b78f', 'hex').compare(b), 0); + assert.equal(Buffer.from('8720f279b78f', 'hex').compare(b), 0); assert.equal(d.decode(b), -123456789012345); assert.equal(lo.u48().decode(b), 0x8fb779f22087); assert.equal(lo.u48be().decode(b), 0x8720f279b78f); @@ -278,7 +278,7 @@ suite('Layout', function() { suite('IntBE', function() { test('s16be', function() { var d = lo.s16be('t'); - var b = new Buffer(2); + var b = Buffer.alloc(2); assert(d instanceof lo.IntBE); assert(d instanceof lo.Layout); assert.equal(d.span, 2); @@ -286,48 +286,48 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(0x1234, b), 2); - assert.equal(Buffer('1234', 'hex').compare(b), 0); + assert.equal(Buffer.from('1234', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x1234); assert.equal(lo.u16().decode(b), 0x3412); assert.equal(d.encode(-12345, b), 2); - assert.equal(Buffer('cfc7', 'hex').compare(b), 0); + assert.equal(Buffer.from('cfc7', 'hex').compare(b), 0); assert.equal(d.decode(b), -12345); assert.equal(lo.u16be().decode(b), 0xcfc7); assert.equal(lo.u16().decode(b), 0xc7cf); }); test('s24be', function() { var d = lo.s24be('t'); - var b = new Buffer(3); + var b = Buffer.alloc(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.equal(0x123456, d.decode(Buffer.from('123456', 'hex'))); + assert.equal(-1, d.decode(Buffer.from('FFFFFF', 'hex'))); + assert.equal(-0x800000, d.decode(Buffer.from('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); + var b = Buffer.alloc(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.equal(0x12345678, d.decode(Buffer.from('12345678', 'hex'))); + assert.equal(-1, d.decode(Buffer.from('FFFFFFFF', 'hex'))); + assert.equal(-0x80000000, d.decode(Buffer.from('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); + var b = Buffer.alloc(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.equal(0x123456789a, d.decode(Buffer.from('123456789a', 'hex'))); + assert.equal(-1, d.decode(Buffer.from('FFFFFFFFFF', 'hex'))); + assert.equal(-0x8000000000, d.decode(Buffer.from('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); + var b = Buffer.alloc(6); assert(d instanceof lo.IntBE); assert(d instanceof lo.Layout); assert.equal(d.span, 6); @@ -335,11 +335,11 @@ suite('Layout', function() { b.fill(0); assert.equal(d.decode(b), 0); assert.equal(d.encode(0x123456789abc, b), 6); - assert.equal(Buffer('123456789abc', 'hex').compare(b), 0); + assert.equal(Buffer.from('123456789abc', 'hex').compare(b), 0); assert.equal(d.decode(b), 0x123456789abc); assert.equal(lo.u48().decode(b), 0xbc9a78563412); assert.equal(d.encode(-123456789012345, b), 6); - assert.equal(Buffer('8fb779f22087', 'hex').compare(b), 0); + assert.equal(Buffer.from('8fb779f22087', 'hex').compare(b), 0); assert.equal(d.decode(b), -123456789012345); assert.equal(lo.u48be().decode(b), 0x8fb779f22087); assert.equal(lo.u48().decode(b), 0x8720f279b78f); @@ -356,11 +356,11 @@ suite('Layout', function() { assert.equal(be.property, 'be'); assert.equal(le.property, 'le'); - var b = Buffer('0000003b2a2a873b', 'hex'); + var b = Buffer.from('0000003b2a2a873b', 'hex'); var rb = reversedBuffer(b); var v = 254110500667; var ev = v; - var eb = new Buffer(be.span); + var eb = Buffer.alloc(be.span); assert.equal(be.decode(b), ev); assert.equal(le.decode(rb), ev); assert.equal(be.encode(v, eb), 8); @@ -368,7 +368,7 @@ suite('Layout', function() { assert.equal(le.encode(v, eb), 8); assert.equal(rb.compare(eb), 0); - b = Buffer('001d9515553fdcbb', 'hex'); + b = Buffer.from('001d9515553fdcbb', 'hex'); rb = reversedBuffer(b); v = 8326693181709499; ev = v; @@ -385,7 +385,7 @@ suite('Layout', function() { /* The logic changes for the remaining cases since the exact * value cannot be represented in a Number: the encoded buffer * will not bitwise-match the original buffer. */ - b = Buffer('003b2a2aaa7fdcbb', 'hex'); + b = Buffer.from('003b2a2aaa7fdcbb', 'hex'); rb = reversedBuffer(b); v = 16653386363428027; ev = v + 1; @@ -397,7 +397,7 @@ suite('Layout', function() { assert.equal(le.encode(v, eb), 8); assert.equal(le.decode(eb), ev); - b = Buffer('eca8aaa9ffffdcbb', 'hex'); + b = Buffer.from('eca8aaa9ffffdcbb', 'hex'); rb = reversedBuffer(b); v = 17053067636159536315; ev = v + 837; @@ -409,13 +409,13 @@ suite('Layout', function() { assert.equal(le.encode(v, eb), 8); assert.equal(le.decode(eb), ev); - b = new Buffer(10); + b = Buffer.alloc(10); b.fill(0xa5); le.encode(1, b, 1); - assert.equal(Buffer('a50100000000000000a5', 'hex').compare(b), 0); + assert.equal(Buffer.from('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(Buffer.from('a50000000000000001a5', 'hex').compare(b), 0); assert.equal(1, be.decode(b, 1)); }); test('RoundedInt64', function() { @@ -426,11 +426,11 @@ suite('Layout', function() { assert.equal(be.property, 'be'); assert.equal(le.property, 'le'); - var b = Buffer('ffffffff89abcdf0', 'hex'); + var b = Buffer.from('ffffffff89abcdf0', 'hex'); var rb = reversedBuffer(b); var v = -1985229328; var ev = v; - var eb = new Buffer(be.span); + var eb = Buffer.alloc(be.span); assert.equal(be.decode(b), ev); assert.equal(le.decode(rb), ev); assert.equal(be.encode(v, eb), 8); @@ -438,7 +438,7 @@ suite('Layout', function() { assert.equal(le.encode(v, eb), 8); assert.equal(rb.compare(eb), 0); - b = Buffer('ffffc4d5d555a345', 'hex'); + b = Buffer.from('ffffc4d5d555a345', 'hex'); rb = reversedBuffer(b); v = -65052290473147; ev = v; @@ -455,7 +455,7 @@ suite('Layout', function() { /* The logic changes for the remaining cases since the exact * value cannot be represented in a Number: the encoded buffer * will not bitwise-match the original buffer. */ - b = Buffer('ff13575556002345', 'hex'); + b = Buffer.from('ff13575556002345', 'hex'); rb = reversedBuffer(b); v = -66613545453739195; ev = v + 3; @@ -467,7 +467,7 @@ suite('Layout', function() { assert.equal(le.encode(v, eb), 8); assert.equal(le.decode(eb), ev); - b = Buffer('e26aeaaac0002345', 'hex'); + b = Buffer.from('e26aeaaac0002345', 'hex'); rb = reversedBuffer(b); v = -2131633454519934139; ev = v - 69; @@ -479,24 +479,24 @@ suite('Layout', function() { assert.equal(le.encode(v, eb), 8); assert.equal(le.decode(eb), ev); - b = new Buffer(10); + b = Buffer.alloc(10); b.fill(0xa5); le.encode(1, b, 1); - assert.equal(Buffer('a50100000000000000a5', 'hex').compare(b), 0); + assert.equal(Buffer.from('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(Buffer.from('a50000000000000001a5', 'hex').compare(b), 0); assert.equal(1, be.decode(b, 1)); - assert.equal(le.decode(Buffer('0000007001000000', 'hex')), 6174015488); - assert.equal(le.decode(Buffer('0000008001000000', 'hex')), 6442450944); + assert.equal(le.decode(Buffer.from('0000007001000000', 'hex')), 6174015488); + assert.equal(le.decode(Buffer.from('0000008001000000', 'hex')), 6442450944); }); test('Float', function() { var be = lo.f32be('eff'); var le = lo.f32('ffe'); var f = 123456.125; var fe = 3.174030951333261e-29; - var b = new Buffer(4); + var b = Buffer.alloc(4); assert(be instanceof lo.FloatBE); assert(be instanceof lo.Layout); assert.equal(be.span, 4); @@ -510,21 +510,21 @@ suite('Layout', function() { assert.equal(be.decode(b), 0); assert.equal(le.decode(b), 0); assert.equal(le.encode(f, b), 4); - assert.equal(Buffer('1020f147', 'hex').compare(b), 0); + assert.equal(Buffer.from('1020f147', 'hex').compare(b), 0); assert.equal(le.decode(b), f); assert.equal(be.decode(b), fe); assert.equal(be.encode(f, b), 4); - assert.equal(Buffer('47f12010', 'hex').compare(b), 0); + assert.equal(Buffer.from('47f12010', 'hex').compare(b), 0); assert.equal(be.decode(b), f); assert.equal(le.decode(b), fe); - b = new Buffer(6); + b = Buffer.alloc(6); b.fill(0xa5); le.encode(f, b, 1); - assert.equal(Buffer('a51020f147a5', 'hex').compare(b), 0); + assert.equal(Buffer.from('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(Buffer.from('a547f12010a5', 'hex').compare(b), 0); assert.equal(f, be.decode(b, 1)); }); test('Double', function() { @@ -532,7 +532,7 @@ suite('Layout', function() { var le = lo.f64('eed'); var f = 123456789.125e+10; var fe = 3.4283031083405533e-77; - var b = new Buffer(8); + var b = Buffer.alloc(8); assert(be instanceof lo.DoubleBE); assert(be instanceof lo.Layout); assert.equal(be.span, 8); @@ -545,21 +545,21 @@ suite('Layout', function() { assert.equal(be.decode(b), 0); assert.equal(le.decode(b), 0); assert.equal(le.encode(f, b), 8); - assert.equal(Buffer('300fc1f41022b143', 'hex').compare(b), 0); + assert.equal(Buffer.from('300fc1f41022b143', 'hex').compare(b), 0); assert.equal(le.decode(b), f); assert.equal(be.decode(b), fe); assert.equal(be.encode(f, b), 8); - assert.equal(Buffer('43b12210f4c10f30', 'hex').compare(b), 0); + assert.equal(Buffer.from('43b12210f4c10f30', 'hex').compare(b), 0); assert.equal(be.decode(b), f); assert.equal(le.decode(b), fe); - b = new Buffer(10); + b = Buffer.alloc(10); b.fill(0xa5); le.encode(f, b, 1); - assert.equal(Buffer('a5300fc1f41022b143a5', 'hex').compare(b), 0); + assert.equal(Buffer.from('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(Buffer.from('a543b12210f4c10f30a5', 'hex').compare(b), 0); assert.equal(f, be.decode(b, 1)); }); suite('Sequence', function() { @@ -577,7 +577,7 @@ suite('Layout', function() { }); test('basics', function() { var seq = new lo.Sequence(lo.u8(), 4, 'id'); - var b = new Buffer(4); + var b = Buffer.alloc(4); assert(seq instanceof lo.Sequence); assert(seq instanceof lo.Layout); assert(seq.elementLayout instanceof lo.UInt); @@ -595,7 +595,7 @@ suite('Layout', function() { test('in struct', function() { var seq = lo.seq(lo.u8(), 4, 'id'); var str = lo.struct([seq]); - var d = str.decode(Buffer('01020304', 'hex')); + var d = str.decode(Buffer.from('01020304', 'hex')); assert.deepEqual(d, {id: [1, 2, 3, 4]}); }); test('struct elts', function() { @@ -603,67 +603,67 @@ suite('Layout', function() { lo.s32('s32')]); var seq = new lo.Sequence(st, 3); var tv = [{u8: 1, s32: 1e4}, {u8: 0, s32: 0}, {u8: 3, s32: -324}]; - var b = new Buffer(15); + var b = Buffer.alloc(15); assert.equal(st.span, 5); assert.equal(seq.count, 3); assert.strictEqual(seq.elementLayout, st); assert.equal(seq.span, 15); assert.equal(seq.encode(tv, b), seq.span); - assert.equal(Buffer('0110270000000000000003bcfeffff', 'hex').compare(b), + assert.equal(Buffer.from('0110270000000000000003bcfeffff', 'hex').compare(b), 0); assert.deepEqual(seq.decode(b), tv); assert.equal(seq.encode([{u8: 2, s32: 0x12345678}], b, st.span), 1 * st.span); - assert.equal(Buffer('0110270000027856341203bcfeffff', 'hex').compare(b), + assert.equal(Buffer.from('0110270000027856341203bcfeffff', 'hex').compare(b), 0); }); test('var count', function() { var clo = lo.u8('n'); var seq = lo.seq(lo.u8(), lo.offset(clo, -1), 'a'); var st = lo.struct([clo, seq]); - var b = Buffer('03010203', 'hex'); + var b = Buffer.from('03010203', 'hex'); var obj = st.decode(b); assert.equal(obj.n, 3); assert.deepEqual(obj.a, [1, 2, 3]); - b = new Buffer(10); + b = Buffer.alloc(10); obj = {n: 3, a: [5, 6, 7, 8, 9]}; assert.equal(st.encode(obj, b), 6); var span = st.getSpan(b); assert.equal(span, 6); - assert.equal(Buffer('050506070809', 'hex').compare(b.slice(0, span)), 0); + assert.equal(Buffer.from('050506070809', 'hex').compare(b.slice(0, span)), 0); }); // For variable span alone see CString in seq test('var count+span', function() { var clo = lo.u8('n'); var seq = lo.seq(lo.cstr(), lo.offset(clo, -1), 'a'); var st = lo.struct([clo, seq]); - var b = Buffer('036100620063646500', 'hex'); + var b = Buffer.from('036100620063646500', 'hex'); var obj = st.decode(b); assert.equal(obj.n, 3); assert.deepEqual(obj.a, ['a', 'b', 'cde']); - b = new Buffer(10); + b = Buffer.alloc(10); obj = {n: 6, a: ['one', 'two']}; assert.equal(st.encode(obj, b), clo.span + 8); var span = st.getSpan(b); assert.equal(span, 9); - assert.equal(Buffer('026f6e650074776f00', 'hex') + assert.equal(Buffer.from('026f6e650074776f00', 'hex') .compare(b.slice(0, span)), 0); }); test('zero-count', function() { var seq = lo.seq(lo.u8(), 0); - var b = Buffer('', 'hex'); + var b = Buffer.from('', 'hex'); assert.equal(seq.span, 0); assert.deepEqual(seq.decode(b), []); }); test('greedy', function() { var seq = lo.seq(lo.u16(), lo.greedy(2), 'a'); - var b = Buffer('ABCDE'); - var db = new Buffer(6); + var b = Buffer.from('ABCDE'); + var db = Buffer.alloc(6); assert.equal(seq.getSpan(b), 4); assert.deepEqual(seq.decode(b), [0x4241, 0x4443]); db.fill('-'.charAt(0)); assert.equal(seq.encode(seq.decode(b), db, 1), 4); - assert.equal(Buffer('-ABCD-').compare(db), 0); + assert.equal(Buffer.from('-ABCD-').compare(db), 0); assert.equal(seq.getSpan(b, 1), 4); assert.deepEqual(seq.decode(b, 1), [0x4342, 0x4544]); }); @@ -680,7 +680,7 @@ suite('Layout', function() { var st = new lo.Structure([lo.u8('u8'), lo.u16('u16'), lo.s16be('s16be')]); - var b = new Buffer(5); + var b = Buffer.alloc(5); assert(st instanceof lo.Structure); assert(st instanceof lo.Layout); assert.equal(st.span, 5); @@ -691,14 +691,14 @@ suite('Layout', function() { assert.deepEqual(obj, {u8: 0, u16: 0, s16be: 0}); obj = {u8: 21, u16: 0x1234, s16be: -5432}; assert.equal(st.encode(obj, b), st.span); - assert.equal(Buffer('153412eac8', 'hex').compare(b), 0); + assert.equal(Buffer.from('153412eac8', 'hex').compare(b), 0); assert.deepEqual(st.decode(b), obj); }); test('padding', function() { var st = new lo.Structure([lo.u16('u16'), lo.u8(), lo.s16be('s16be')]); - var b = new Buffer(5); + var b = Buffer.alloc(5); assert.equal(st.span, 5); b.fill(0); var obj = st.decode(b); @@ -706,14 +706,14 @@ suite('Layout', function() { b.fill(0xFF); obj = {u16: 0x1234, s16be: -5432}; assert.equal(st.encode(obj, b), st.span); - assert.equal(Buffer('3412ffeac8', 'hex').compare(b), 0); + assert.equal(Buffer.from('3412ffeac8', 'hex').compare(b), 0); assert.deepEqual(st.decode(b), obj); }); test('missing', function() { var st = new lo.Structure([lo.u16('u16'), lo.u8('u8'), lo.s16be('s16be')]); - var b = new Buffer(5); + var b = Buffer.alloc(5); assert.equal(st.span, 5); b.fill(0); var obj = st.decode(b); @@ -721,14 +721,14 @@ suite('Layout', function() { b.fill(0xa5); obj = {u16: 0x1234, s16be: -5432}; assert.equal(st.encode(obj, b), st.span); - assert.equal(Buffer('3412a5eac8', 'hex').compare(b), 0); + assert.equal(Buffer.from('3412a5eac8', 'hex').compare(b), 0); assert.deepEqual(st.decode(b), _.extend(obj, {u8: 0xa5})); }); test('update', function() { var st = new lo.Structure([lo.u8('u8'), lo.u16('u16'), lo.s16be('s16be')]); - var b = Buffer('153412eac8', 'hex'); + var b = Buffer.from('153412eac8', 'hex'); var rc = st.decode(b, 0); assert.deepEqual(rc, {u8: 21, u16: 0x1234, s16be: -5432}); }); @@ -746,42 +746,42 @@ suite('Layout', function() { s16be: -12345, }, s24: -123456}; - var b = new Buffer(12); + var b = Buffer.alloc(12); assert.equal(st.span, 5); assert.equal(st.property, 'st'); assert.equal(cst.span, 12); assert.equal(cst.encode(obj, b), cst.span); - assert.equal(Buffer('785634121798ffcfc7c01dfe', 'hex').compare(b), 0); + assert.equal(Buffer.from('785634121798ffcfc7c01dfe', 'hex').compare(b), 0); assert.deepEqual(cst.decode(b), obj); }); test('empty', function() { var st = lo.struct([], 'st'); - var b = Buffer('', 'hex'); + var b = Buffer.from('', 'hex'); 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); + var b = Buffer.alloc(5); b.fill(0xa5); var obj = {s: 'ab'}; st.encode(obj, b, 1); - assert.equal(Buffer('a5616200a5', 'hex').compare(b), 0); + assert.equal(Buffer.from('a5616200a5', 'hex').compare(b), 0); assert.equal(3, st.getSpan(b, 1)); assert.deepEqual(st.decode(b, 1), obj); }); test('empty encode fixed span', function() { var slo = lo.struct([lo.u8('a'), lo.u8('b')]); assert.equal(slo.span, 2); - var b = new Buffer(10); + var b = Buffer.alloc(10); assert.equal(slo.encode({}, b), slo.span); assert.equal(slo.encode({}, b, 1), slo.span); }); test('empty encode variable span', function() { var slo = lo.struct([lo.u8('a'), lo.cstr('s')]); assert.equal(slo.span, -1); - var b = new Buffer(10); + var b = Buffer.alloc(10); assert.equal(slo.encode({}, b), 1); assert.equal(slo.encode({}, b, 5), 1); assert.equal(slo.encode({a: 5}, b), 1); @@ -889,10 +889,10 @@ suite('Layout', function() { test('span', function() { var un = new lo.Union(lo.u8(), lo.u32()); var d = new lo.VariantLayout(un, 1, lo.cstr(), 's'); - var b = new Buffer(12); + var b = Buffer.alloc(12); assert.equal(d.encode({s: 'hi!'}, b), 5); assert.equal(un.getSpan(b), 5); - assert.equal(Buffer('0168692100', 'hex').compare(b.slice(0, 5)), 0); + assert.equal(Buffer.from('0168692100', 'hex').compare(b.slice(0, 5)), 0); // This one overruns the Buffer assert.throws(function() {d.encode({s: 'far too long'}, b);}, RangeError); @@ -911,13 +911,13 @@ suite('Layout', function() { }); suite('GreedyCount', function() { test('ctor', function() { - var el = new lo.greedy(); + var el = lo.greedy(); assert(el instanceof lo.GreedyCount); assert(el instanceof lo.ExternalLayout); assert.equal(el.elementSpan, 1); assert.strictEqual(el.property, undefined); - var nel = new lo.greedy(5, 'name'); + var nel = lo.greedy(5, 'name'); assert(nel instanceof lo.GreedyCount); assert(nel instanceof lo.ExternalLayout); assert.equal(nel.elementSpan, 5); @@ -927,12 +927,12 @@ suite('Layout', function() { assert.throws(function() {lo.greedy(0);}, TypeError); }); test('#decode', function() { - var el = new lo.greedy(); - var b = new Buffer(10); + var el = lo.greedy(); + var b = Buffer.alloc(10); assert.equal(el.decode(b), b.length); assert.equal(el.decode(b, 3), b.length - 3); - var nel = new lo.greedy(3); + var nel = lo.greedy(3); assert.equal(nel.decode(b), 3); assert.equal(nel.decode(b, 1), 3); assert.equal(nel.decode(b, 2), 2); @@ -963,7 +963,7 @@ suite('Layout', function() { var u8 = lo.u8(); var bl = lo.offset(u8, -1, 'bl'); var al = lo.offset(u8, 1, 'al'); - var b = Buffer('0001020304050607', 'hex'); + var b = Buffer.from('0001020304050607', 'hex'); assert.equal(u8.decode(b), 0); assert.equal(al.decode(b), 1); assert.throws(function() {bl.decode(b);}, RangeError); @@ -976,7 +976,7 @@ suite('Layout', function() { assert.equal(u8.encode(0x84, b, 4), 1); assert.equal(al.encode(0x94, b, 4), 1); assert.equal(bl.encode(0x74, b, 4), 1); - assert.equal(Buffer('8091027484940607', 'hex').compare(b), 0); + assert.equal(Buffer.from('8091027484940607', 'hex').compare(b), 0); }); test('invalid ctor', function() { assert.throws(function() {new lo.OffsetLayout('hi');}, TypeError); @@ -988,8 +988,8 @@ suite('Layout', function() { test('abstract', function() { var ud = new lo.UnionDiscriminator('p'); assert.equal(ud.property, 'p'); - assert.throws(function() {ud.decode(Buffer('00', 'hex'));}, Error); - assert.throws(function() {ud.encode(0, new Buffer(1));}, Error); + assert.throws(function() {ud.decode(Buffer.from('00', 'hex'));}, Error); + assert.throws(function() {ud.encode(0, Buffer.alloc(1));}, Error); }); }); suite('UnionLayoutDiscriminator', function() { @@ -1018,7 +1018,7 @@ suite('Layout', function() { var vlo = new lo.Sequence(lo.u8(), 8); var un = new lo.Union(dlo, vlo); var clo = un.defaultLayout; - var b = new Buffer(9); + var b = Buffer.alloc(9); assert(un instanceof lo.Union); assert(un instanceof lo.Layout); assert.equal(un.span, 9); @@ -1041,13 +1041,13 @@ suite('Layout', function() { o.content[3] = 3; o.content[7] = 7; assert.equal(un.encode(o, b), dlo.span + vlo.span); - assert.equal(Buffer('050000000300000007', 'hex').compare(b), 0); + assert.equal(Buffer.from('050000000300000007', 'hex').compare(b), 0); }); test('variants', function() { var dlo = lo.u8('v'); var vlo = new lo.Sequence(lo.u8(), 4, 'c'); var un = new lo.Union(dlo, vlo); - var b = new Buffer(5); + var b = Buffer.alloc(5); assert.strictEqual(un.getVariant(1), undefined); b.fill(0); assert.deepEqual(un.decode(b), {v: 0, c: [0, 0, 0, 0]}); @@ -1073,13 +1073,13 @@ suite('Layout', function() { assert.deepEqual(v3.decode(b), {v3: {a: 1, b: 1, c: 257}}); assert.deepEqual(un.decode(b), {v3: {a: 1, b: 1, c: 257}}); assert.equal(un.discriminator.encode(v2.variant, b), dlo.span); - assert.equal(Buffer('0201010101', 'hex').compare(b), 0); + assert.equal(Buffer.from('0201010101', 'hex').compare(b), 0); var obj = {v3: {a: 5, b: 6, c: 1540}}; assert.equal(lo3.encode(obj.v3, b), lo3.span); assert.equal(v3.encode(obj, b), un.span); assert.notEqual(un.span, vlo.span + lo3.span); assert.deepEqual(un.decode(b), obj); - assert.equal(Buffer('0305060406', 'hex').compare(b), 0); + assert.equal(Buffer.from('0305060406', 'hex').compare(b), 0); assert.throws(function() {v2.encode(obj, b);}, TypeError); assert.throws(function() {v2.decode(b);}, Error); }); @@ -1104,7 +1104,7 @@ suite('Layout', function() { var st = new lo.Structure([lo.u16('u16'), un, lo.s16('s16')]); - var b = Buffer('0001020304050607', 'hex'); + var b = Buffer.from('0001020304050607', 'hex'); var obj = st.decode(b); assert.equal(obj.u16, 0x0100); assert.equal(obj.u.uid, 2); @@ -1113,19 +1113,19 @@ suite('Layout', function() { obj.u16 = 0x5432; obj.s16 = -3; obj.u.payload[1] = 23; - var b2 = new Buffer(st.span); + var b2 = Buffer.alloc(st.span); assert.equal(st.encode(obj, b2), st.span); - assert.equal(Buffer('325402031705fdff', 'hex').compare(b2), 0); + assert.equal(Buffer.from('325402031705fdff', 'hex').compare(b2), 0); }); test('issue#6', function() { var dlo = lo.u8('number'); var vlo = new lo.Sequence(lo.u8(), 8, 'payload'); var un = new lo.Union(dlo, vlo); - var b = Buffer('000102030405060708', 'hex'); + var b = Buffer.from('000102030405060708', 'hex'); var obj = un.decode(b); assert.equal(obj.number, 0); assert.deepEqual(obj.payload, [1, 2, 3, 4, 5, 6, 7, 8]); - var b2 = new Buffer(un.span); + var b2 = Buffer.alloc(un.span); assert.equal(un.encode(obj, b2), dlo.span + vlo.span); assert.equal(b2.toString('hex'), b.toString('hex')); var obj2 = {variant: obj.number, @@ -1138,7 +1138,7 @@ suite('Layout', function() { var vlo = new lo.Structure([plo, dlo]); var un = new lo.Union(lo.offset(dlo, plo.span), vlo); var clo = un.defaultLayout; - var b = Buffer('000102030405060708', 'hex'); + var b = Buffer.from('000102030405060708', 'hex'); var obj = un.decode(b); assert(!un.usesPrefixDiscriminator); assert(un.discriminator instanceof lo.UnionLayoutDiscriminator); @@ -1157,7 +1157,7 @@ suite('Layout', function() { var ud = new lo.UnionLayoutDiscriminator(lo.offset(dlo, plo.span), 'tag'); var un = new lo.Union(ud, vlo); var clo = un.defaultLayout; - var b = Buffer('000102030405060708', 'hex'); + var b = Buffer.from('000102030405060708', 'hex'); var obj = un.decode(b); assert(!un.usesPrefixDiscriminator); assert(un.discriminator instanceof lo.UnionLayoutDiscriminator); @@ -1176,7 +1176,7 @@ suite('Layout', function() { var vlo = new lo.Structure([plo, dlo]); var un = new lo.Union(lo.offset(dlo, plo.span), vlo); var clo = un.defaultLayout; - var b = Buffer('000102030405060708', 'hex'); + var b = Buffer.from('000102030405060708', 'hex'); var obj = un.decode(b); assert(!un.usesPrefixDiscriminator); assert(un.discriminator instanceof lo.UnionLayoutDiscriminator); @@ -1195,14 +1195,14 @@ suite('Layout', function() { var st = new lo.Structure([dlo, lo.u16('u16'), un, lo.s16('s16')]); assert.equal(un.span, 4); assert.equal(st.span, 9); - var b = Buffer('000102030405060708', 'hex'); + var b = Buffer.from('000102030405060708', 'hex'); var obj = st.decode(b); assert.equal(obj.vid, 0); assert.equal(obj.u16, 0x201); assert.equal(obj.s16, 0x807); assert.equal(obj.u.uid, 0); assert.equal(obj.u.u32, 0x06050403); - var b2 = new Buffer(st.span); + var b2 = Buffer.alloc(st.span); assert.equal(st.encode(obj, b2), st.span); assert.equal(b2.compare(b), 0); @@ -1215,7 +1215,7 @@ suite('Layout', function() { var flo = lo.f32('f32'); un.addVariant(1, flo, 'vf'); - var fb = Buffer('01234500805a429876', 'hex'); + var fb = Buffer.from('01234500805a429876', 'hex'); var fobj = st.decode(fb); assert.equal(fobj.vid, 1); assert.equal(fobj.u16, 0x4523); @@ -1227,7 +1227,7 @@ suite('Layout', function() { var v1 = un.addVariant(1, lo.f32(), 'f32'); var v2 = un.addVariant(2, lo.seq(lo.u8(), 4), 'u8.4'); var v3 = un.addVariant(3, lo.cstr(), 'str'); - var b = new Buffer(un.span); + var b = Buffer.alloc(un.span); assert.equal(un.span, 5); @@ -1235,23 +1235,23 @@ suite('Layout', function() { var vlo = un.getSourceVariant(src); assert.strictEqual(vlo, undefined); assert.equal(un.encode(src, b), un.span); - assert.equal(Buffer('0578563412', 'hex').compare(b), 0); + assert.equal(Buffer.from('0578563412', 'hex').compare(b), 0); src = {f32: 26.5}; vlo = un.getSourceVariant(src); assert.strictEqual(vlo, v1); assert.equal(vlo.encode(src, b), un.span); - assert.equal(Buffer('010000d441', 'hex').compare(b), 0); + assert.equal(Buffer.from('010000d441', 'hex').compare(b), 0); assert.equal(un.encode(src, b), un.span); - assert.equal(Buffer('010000d441', 'hex').compare(b), 0); + assert.equal(Buffer.from('010000d441', 'hex').compare(b), 0); src = {'u8.4': [1, 2, 3, 4]}; vlo = un.getSourceVariant(src); assert.strictEqual(vlo, v2); assert.equal(vlo.encode(src, b), un.span); - assert.equal(Buffer('0201020304', 'hex').compare(b), 0); + assert.equal(Buffer.from('0201020304', 'hex').compare(b), 0); assert.equal(un.encode(src, b), un.span); - assert.equal(Buffer('0201020304', 'hex').compare(b), 0); + assert.equal(Buffer.from('0201020304', 'hex').compare(b), 0); assert.throws(function() {un.getSourceVariant({other: 3});}, Error); src = {str: 'hi'}; @@ -1259,7 +1259,7 @@ suite('Layout', function() { assert.strictEqual(vlo, v3); b.fill(0xFF); assert.equal(vlo.encode(src, b), 1 + 2 + 1); - assert.equal(Buffer('03686900FF', 'hex').compare(b.slice(0, 5 + 2)), 0); + assert.equal(Buffer.from('03686900FF', 'hex').compare(b.slice(0, 5 + 2)), 0); assert(0 > vlo.layout.span); assert.equal(vlo.span, un.span); assert.equal(vlo.layout.getSpan(b, 1), 3); @@ -1283,7 +1283,7 @@ suite('Layout', function() { var v1 = un.addVariant(1, lo.u32(), 'u32'); var v2 = un.addVariant(2, lo.f64(), 'f64'); var v3 = un.addVariant(3, lo.cstr(), 'str'); - var b = new Buffer(16); + var b = Buffer.alloc(16); assert(0 > un.span); b.fill(0xFF); @@ -1292,7 +1292,7 @@ suite('Layout', function() { assert.equal(un.encode(obj, b), 1 + 4); assert.equal(v1.getSpan(b), 5); assert.equal(un.getSpan(b), 5); - assert.equal(Buffer('0178563412ffff', 'hex') + assert.equal(Buffer.from('0178563412ffff', 'hex') .compare(b.slice(0, 5 + 2)), 0); assert.deepEqual(un.decode(b), obj); @@ -1301,7 +1301,7 @@ suite('Layout', function() { assert.equal(un.encode(obj, b), 1 + 8); assert.equal(v2.getSpan(b), 9); assert.equal(un.getSpan(b), 9); - assert.equal(Buffer('0200000000004a9340ffff', 'hex') + assert.equal(Buffer.from('0200000000004a9340ffff', 'hex') .compare(b.slice(0, 9 + 2)), 0); assert.deepEqual(un.decode(b), obj); @@ -1310,7 +1310,7 @@ suite('Layout', function() { assert.equal(un.encode(obj, b), 1 + 3 + 1); assert.equal(v3.getSpan(b), 5); assert.equal(un.getSpan(b), 5); - assert.equal(Buffer('0368692100ffff', 'hex') + assert.equal(Buffer.from('0368692100ffff', 'hex') .compare(b.slice(0, 5 + 2)), 0); assert.deepEqual(un.decode(b), obj); @@ -1321,7 +1321,7 @@ suite('Layout', function() { 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') + assert.equal(Buffer.from('a50368692100a5', 'hex') .compare(b.slice(0, 5 + 2)), 0); assert.deepEqual(un.decode(b, 1), obj); }); @@ -1334,10 +1334,10 @@ suite('Layout', function() { 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); + var b = Buffer.alloc(6); b.fill(0xa5); st.encode(obj, b, 1); - assert.equal(Buffer('a501686900a5', 'hex').compare(b), 0); + assert.equal(Buffer.from('a501686900a5', 'hex').compare(b), 0); assert.deepEqual(st.decode(b, 1), obj); }); }); @@ -1392,26 +1392,26 @@ suite('Layout', function() { var bs = new lo.BitStructure(lo.u16()); var bf10 = bs.addField(10, 'ten'); var bf6 = bs.addField(6, 'six'); - var b = new Buffer(bs.span); + var b = Buffer.alloc(bs.span); assert.equal((1 << 10) - 1, 1023); assert.equal((1 << 6) - 1, 63); - var obj = bs.decode(Buffer('ffff', 'hex')); + var obj = bs.decode(Buffer.from('ffff', 'hex')); assert.equal(obj.ten, (1 << 10) - 1); assert.equal(obj.six, (1 << 6) - 1); assert.equal(bs.encode(obj, b), 2); - assert.equal(Buffer('ffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('ffff', 'hex').compare(b), 0); b.fill(0); - assert.equal(Buffer('0000', 'hex').compare(b), 0); + assert.equal(Buffer.from('0000', 'hex').compare(b), 0); bf10.encode((1 << 10) - 1); bf6.encode((1 << 6) - 1); 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 = Buffer.alloc(2 + bs.span); b.fill(0xa5); bs.encode(obj, b, 1); - assert.equal(Buffer('a5ffffa5', 'hex').compare(b), 0); + assert.equal(Buffer.from('a5ffffa5', 'hex').compare(b), 0); assert.deepEqual(bs.decode(b, 1), obj); }); test('basic LSB', function() { @@ -1506,7 +1506,7 @@ suite('Layout', function() { }); test('lsb coding', function() { var bs = new lo.BitStructure(lo.u32()); - var b = new Buffer(bs.span); + var b = Buffer.alloc(bs.span); bs.addField(1, 'a1'); bs.addField(4, 'b4'); bs.addField(11, 'c11'); @@ -1518,11 +1518,11 @@ suite('Layout', function() { {a1: 1, b4: 0x0F, c11: 0x7FF, d16: 0xFFFF}); assert.equal(bs.encode({a1: 0, b4: 9, c11: 0x4F1, d16: 0x8a51}, b), 4); assert.deepEqual(bs.decode(b), {a1: 0, b4: 9, c11: 0x4F1, d16: 0x8a51}); - assert.equal(Buffer('329e518a', 'hex').compare(b), 0); + assert.equal(Buffer.from('329e518a', 'hex').compare(b), 0); }); test('msb coding', function() { var bs = new lo.BitStructure(lo.u32(), true); - var b = new Buffer(bs.span); + var b = Buffer.alloc(bs.span); bs.addField(1, 'a1'); bs.addField(4, 'b4'); bs.addField(11, 'c11'); @@ -1534,7 +1534,7 @@ suite('Layout', function() { {a1: 1, b4: 0x0F, c11: 0x7FF, d16: 0xFFFF}); assert.equal(bs.encode({a1: 0, b4: 9, c11: 0x4F1, d16: 0x8a51}, b), 4); assert.deepEqual(bs.decode(b), {a1: 0, b4: 9, c11: 0x4F1, d16: 0x8a51}); - assert.equal(Buffer('518af14c', 'hex').compare(b), 0); + assert.equal(Buffer.from('518af14c', 'hex').compare(b), 0); }); test('fieldFor', function() { var d = new lo.BitStructure(lo.u32(), true); @@ -1550,7 +1550,7 @@ suite('Layout', function() { test('gap coding', function() { var lsb = new lo.BitStructure(lo.u24()); var msb = new lo.BitStructure(lo.u24(), true); - var b = new Buffer(lsb.span); + var b = Buffer.alloc(lsb.span); lsb.addField(7, 'a5'); lsb.addField(8); lsb.addField(9, 'b6'); @@ -1564,16 +1564,16 @@ suite('Layout', function() { assert.deepEqual(mb, {a5: 0x52, b6: 0x1a5}); b.fill(0x69); assert.equal(lsb.encode(lb, b), 3); - assert.equal(Buffer('25e9a5', 'hex').compare(b), 0); + assert.equal(Buffer.from('25e9a5', 'hex').compare(b), 0); b.fill(0x69); assert.equal(msb.encode(mb, b), 3); - assert.equal(Buffer('a569a5', 'hex').compare(b), 0); + assert.equal(Buffer.from('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); + var b = Buffer.alloc(bs.span); b[0] = 0x3; var obj = bs.decode(b); assert.strictEqual(1, obj.v); @@ -1614,47 +1614,47 @@ suite('Layout', function() { }); test('basics', function() { var bl = new lo.Blob(3, 'bl'); - var b = Buffer('0102030405', 'hex'); + var b = Buffer.from('0102030405', 'hex'); var bv = bl.decode(b); assert(bv instanceof Buffer); assert.equal(bv.length, bl.span); - assert.equal(Buffer('010203', 'hex').compare(bv), 0); + assert.equal(Buffer.from('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); + assert.equal(Buffer.from('030405', 'hex').compare(bv), 0); + assert.equal(bl.encode(Buffer.from('112233', 'hex'), b, 1), 3); + assert.equal(Buffer.from('0111223305', 'hex').compare(b), 0); assert.throws(function() {bl.encode('ABC', b);}, Error); - assert.throws(function() {bl.encode(Buffer('0102', 'hex'), b);}, + assert.throws(function() {bl.encode(Buffer.from('0102', 'hex'), b);}, Error); }); test('var length', function() { var llo = lo.u8('l'); var blo = lo.blob(lo.offset(llo, -1), 'b'); var st = lo.struct([llo, blo]); - var b = new Buffer(10); + var b = Buffer.alloc(10); assert(0 > st.span); assert.strictEqual(blo.length.layout, llo); - assert.equal(st.encode({b: Buffer('03040506', 'hex')}, b), llo.span + 4); + assert.equal(st.encode({b: Buffer.from('03040506', 'hex')}, b), llo.span + 4); var span = st.getSpan(b); assert.equal(span, 5); - assert.equal(Buffer('0403040506', 'hex').compare(b.slice(0, span)), 0); + assert.equal(Buffer.from('0403040506', 'hex').compare(b.slice(0, span)), 0); var obj = st.decode(b); assert.equal(obj.l, 4); assert.equal(obj.b.toString('hex'), '03040506'); assert.throws(function() { - st.encode({b: new Buffer(b.length)}, b, 1); + st.encode({b: Buffer.alloc(b.length)}, b, 1); }, RangeError); }); test('greedy', function() { var blo = lo.blob(lo.greedy(), 'b'); - var b = Buffer('ABCDx'); - assert.equal(Buffer('ABCDx').compare(blo.decode(b)), 0); - assert.equal(Buffer('Dx').compare(blo.decode(b, 3)), 0); + var b = Buffer.from('ABCDx'); + assert.equal(Buffer.from('ABCDx').compare(blo.decode(b)), 0); + assert.equal(Buffer.from('Dx').compare(blo.decode(b, 3)), 0); b.fill(0); - assert.equal(blo.encode(Buffer('0203', 'hex'), b, 2), 2); - assert.equal(Buffer('0000020300', 'hex').compare(b), 0); + assert.equal(blo.encode(Buffer.from('0203', 'hex'), b, 2), 2); + assert.equal(Buffer.from('0000020300', 'hex').compare(b), 0); }); }); suite('issue#8', function() { @@ -1665,8 +1665,8 @@ suite('Layout', function() { var pld = new lo.Union(lo.offset(ver, -ver.span), new lo.Blob(8, 'blob'), 'u'); var pkt = new lo.Structure([hdr, pld], 's'); - var expectedBlob = Buffer('1011121314151617', 'hex'); - var b = Buffer('01021011121314151617', 'hex'); + var expectedBlob = Buffer.from('1011121314151617', 'hex'); + var b = Buffer.from('01021011121314151617', 'hex'); assert.deepEqual(hdr.decode(b), {id: 1, ver: 2}); var du = pld.decode(b, 2); assert.equal(du.ver, 2); @@ -1689,8 +1689,8 @@ suite('Layout', function() { lo.u8('ver')]); var pld = new lo.Union(lo.offset(ver, -ver.span), new lo.Blob(8, 'blob')); - var expectedBlob = Buffer('1011121314151617', 'hex'); - var b = Buffer('01021011121314151617', 'hex'); + var expectedBlob = Buffer.from('1011121314151617', 'hex'); + var b = Buffer.from('01021011121314151617', 'hex'); assert.deepEqual(hdr.decode(b), {id: 1, ver: 2}); var du = pld.decode(b, 2); assert.equal(du.ver, 2); @@ -1728,37 +1728,37 @@ suite('Layout', function() { test('#getSpan', function() { var cst = new lo.CString(); assert.throws(function() {cst.getSpan();}, TypeError); - assert.equal(cst.getSpan(Buffer('00', 'hex')), 1); - assert.equal(cst.getSpan(Buffer('4100', 'hex')), 2); - assert.equal(cst.getSpan(Buffer('4100', 'hex'), 1), 1); - assert.equal(cst.getSpan(Buffer('4142', 'hex')), 3); + assert.equal(cst.getSpan(Buffer.from('00', 'hex')), 1); + assert.equal(cst.getSpan(Buffer.from('4100', 'hex')), 2); + assert.equal(cst.getSpan(Buffer.from('4100', 'hex'), 1), 1); + assert.equal(cst.getSpan(Buffer.from('4142', 'hex')), 3); }); test('#decode', function() { var cst = new lo.CString(); - assert.equal(cst.decode(Buffer('00', 'hex')), ''); - assert.equal(cst.decode(Buffer('4100', 'hex')), 'A'); - assert.equal(cst.decode(Buffer('4100', 'hex'), 1), ''); - assert.equal(cst.decode(Buffer('4142', 'hex')), 'AB'); + assert.equal(cst.decode(Buffer.from('00', 'hex')), ''); + assert.equal(cst.decode(Buffer.from('4100', 'hex')), 'A'); + assert.equal(cst.decode(Buffer.from('4100', 'hex'), 1), ''); + assert.equal(cst.decode(Buffer.from('4142', 'hex')), 'AB'); }); test('#encode', function() { var cst = new lo.CString(); - var b = new Buffer(4); + var b = Buffer.alloc(4); b.fill(0xFF); - assert.equal(Buffer('A', 'utf8').length, 1); + assert.equal(Buffer.from('A', 'utf8').length, 1); assert.equal(cst.encode('', b), 1); - assert.equal(Buffer('00ffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('00ffffff', 'hex').compare(b), 0); assert.equal(cst.encode('A', b), 1 + 1); - assert.equal(Buffer('4100ffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('4100ffff', 'hex').compare(b), 0); assert.equal(cst.encode('B', b, 1), 1 + 1); - assert.equal(Buffer('414200ff', 'hex').compare(b), 0); + assert.equal(Buffer.from('414200ff', 'hex').compare(b), 0); assert.equal(cst.encode(5, b), 1 + 1); - assert.equal(Buffer('350000ff', 'hex').compare(b), 0); + assert.equal(Buffer.from('350000ff', 'hex').compare(b), 0); assert.throws(function() {cst.encode('too long', b);}, RangeError); }); test('in struct', function() { var st = lo.struct([lo.cstr('k'), lo.cstr('v')]); - var b = Buffer('6100323300', 'hex'); + var b = Buffer.from('6100323300', 'hex'); assert.throws(function() {st.getSpan();}, RangeError); assert.equal(st.fields[0].getSpan(b), 2); assert.equal(st.fields[1].getSpan(b, 2), 3); @@ -1769,10 +1769,10 @@ suite('Layout', function() { }); test('in seq', function() { var seq = lo.seq(lo.cstr(), 3); - var b = Buffer('61006263003500', 'hex'); + var b = Buffer.from('61006263003500', 'hex'); assert.deepEqual(seq.decode(b), ['a', 'bc', '5']); assert.equal(seq.encode(['hi', 'u', 'c'], b), (1 + 1) + (2 + 1) + (1 + 1)); - assert.equal(Buffer('68690075006300', 'hex').compare(b), 0); + assert.equal(Buffer.from('68690075006300', 'hex').compare(b), 0); }); }); suite('Constant', function() { @@ -1783,7 +1783,7 @@ suite('Layout', function() { assert.equal(c.span, 0); }); test('basics', function() { - var b = Buffer('', 'hex'); + var b = Buffer.from('', 'hex'); assert.strictEqual(lo.const(true).decode(b), true); assert.strictEqual(lo.const(undefined).decode(b), undefined); var obj = {a: 23}; @@ -1848,11 +1848,11 @@ suite('Layout', function() { var po = Object.create(Sample.prototype); assert(po instanceof Sample); - var b = new Buffer(8); + var b = Buffer.alloc(8); assert(!called); p.encode(b); assert(called); - assert.equal(Buffer('df000000a0020000', 'hex').compare(b), 0); + assert.equal(Buffer.from('df000000a0020000', 'hex').compare(b), 0); po = Sample.layout_.decode(b); assert(po instanceof Sample); @@ -1872,13 +1872,13 @@ suite('Layout', function() { lo.bindConstructorLayout(Header, lo.bits(lo.u8())); Header.layout_.addField(2, 'ver'); Header.layout_.addField(2, 'pwr'); - var b = Buffer('07', 'hex'); + var b = Buffer.from('07', 'hex'); var hdr = Header.decode(b); assert(hdr instanceof Header); assert.equal(hdr.ver, 3); assert.equal(hdr.pwr, 1); assert.equal(hdr.power(), 'lo'); - var nb = new Buffer(1); + var nb = Buffer.alloc(1); nb.fill(0); assert.equal(1, hdr.encode(nb)); assert.equal(b.compare(nb), 0); @@ -1910,7 +1910,7 @@ suite('Layout', function() { var str = lo.struct([lo.u32('u32'), lo.u16('u16'), lo.s16('s16')]); lo.bindConstructorLayout(Struct, str); lo.bindConstructorLayout(VStruct, Union.layout_.addVariant(3, str, 'struct')); - var b = new Buffer(Union.layout_.span); + var b = Buffer.alloc(Union.layout_.span); b.fill(0); var u = Union.decode(b); assert(u instanceof Union); @@ -1927,7 +1927,7 @@ suite('Layout', function() { assert(u instanceof VCStr); assert(u instanceof Union); assert.equal(u.text, 'AB'); - b = Buffer('030403020122218281', 'hex'); + b = Buffer.from('030403020122218281', 'hex'); u = Union.decode(b); assert(u instanceof VStruct); assert(u instanceof Union); @@ -1936,7 +1936,7 @@ suite('Layout', function() { u.struct = new Struct(1, 2, -3); assert.equal(Union.layout_.span, Union.layout_.encode(u, b)); - assert.equal(Buffer('03010000000200fdff', 'hex').compare(b), 0); + assert.equal(Buffer.from('03010000000200fdff', 'hex').compare(b), 0); }); }); }); diff --git a/test/examples.js b/test/examples.js index b40e3ee..141e59e 100644 --- a/test/examples.js +++ b/test/examples.js @@ -11,9 +11,9 @@ suite('Examples', function() { int16_t arr[4] = { 1, -1, 3, -3 }; */ const ds = lo.seq(lo.s16(), 4); - const b = new Buffer(8); + const b = Buffer.alloc(8); assert.equal(ds.encode([1, -1, 3, -3], b), 4 * 2); - assert.equal(Buffer('0100ffff0300fdff', 'hex').compare(b), 0); + assert.equal(Buffer.from('0100ffff0300fdff', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), [1, -1, 3, -3]); }); test('native C', function() { @@ -27,10 +27,10 @@ struct ds { lo.seq(lo.u8(), 3), // alignment padding lo.u32('u32')]); assert.equal(ds.offsetOf('u32'), 4); - const b = new Buffer(8); + const b = Buffer.alloc(8); b.fill(0xbd); assert.equal(ds.encode({v: 1, u32: 0x12345678}, b), 1 + 3 + 4); - assert.equal(Buffer('01bdbdbd78563412', 'hex').compare(b), 0); + assert.equal(Buffer.from('01bdbdbd78563412', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), {v: 1, u32: 0x12345678}); }); test('packed native C', function() { @@ -43,10 +43,10 @@ struct ds { const ds = lo.struct([lo.u8('v'), lo.u32('u32')]); assert.equal(ds.offsetOf('u32'), 1); - const b = new Buffer(5); + const b = Buffer.alloc(5); b.fill(0xbd); assert.equal(ds.encode({v: 1, u32: 0x12345678}, b), 1 + 4); - assert.equal(Buffer('0178563412', 'hex').compare(b), 0); + assert.equal(Buffer.from('0178563412', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), {v: 1, u32: 0x12345678}); }); test('tagged union of 4-byte values', function() { @@ -66,15 +66,15 @@ struct { const u32 = un.addVariant('w'.charCodeAt(0), lo.u32(), 'u32'); const s16 = un.addVariant('h'.charCodeAt(0), lo.seq(lo.s16(), 2), 's16'); const f32 = un.addVariant('f'.charCodeAt(0), lo.f32(), 'f32'); - const b = new Buffer(un.span); - assert.deepEqual(un.decode(Buffer('7778563412', 'hex')), + const b = Buffer.alloc(un.span); + assert.deepEqual(un.decode(Buffer.from('7778563412', 'hex')), {u32: 0x12345678}); - assert.deepEqual(un.decode(Buffer('660000bd41', 'hex')), + assert.deepEqual(un.decode(Buffer.from('660000bd41', 'hex')), {f32: 23.625}); - assert.deepEqual(un.decode(Buffer('a5a5a5a5a5', 'hex')), + assert.deepEqual(un.decode(Buffer.from('a5a5a5a5a5', 'hex')), {t: 0xa5, u8: [0xa5, 0xa5, 0xa5, 0xa5]}); assert.equal(s16.encode({s16: [123, -123]}, b), 1 + 2 * 2); - assert.equal(Buffer('687b0085ff', 'hex').compare(b), 0); + assert.equal(Buffer.from('687b0085ff', 'hex').compare(b), 0); }); test('decode into instances', function() { function Union() { } @@ -96,20 +96,20 @@ struct { lo.bindConstructorLayout(Vf32, Union.layout_.addVariant('f'.charCodeAt(0), lo.f32(), 'f32')); - let v = Union.decode(Buffer('7778563412', 'hex')); + let v = Union.decode(Buffer.from('7778563412', 'hex')); assert(v instanceof Vu32); assert(v instanceof Union); assert.equal(v.u32, 0x12345678); - v = Union.decode(Buffer('a5a5a5a5a5', 'hex')); + v = Union.decode(Buffer.from('a5a5a5a5a5', 'hex')); assert(v instanceof Union); assert.equal(v.t, 0xa5); assert.deepEqual(v.u8, [0xa5, 0xa5, 0xa5, 0xa5]); - const b = new Buffer(Union.layout_.span); + const b = Buffer.alloc(Union.layout_.span); v = new Vf32(23.625); v.encode(b); - assert.equal(Buffer('660000bd41', 'hex').compare(b), 0); + assert.equal(Buffer.from('660000bd41', 'hex').compare(b), 0); }); test('Bit structures (lsb on little-endian)', function() { /* @@ -121,14 +121,14 @@ struct ds { } st; */ const ds = lo.bits(lo.u32()); - const b = new Buffer(4); + const b = Buffer.alloc(4); ds.addField(3, 'b00l03'); 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.equal(Buffer.from('8b010040', 'hex').compare(b), 0); assert.deepEqual(ds.decode(b), {b00l03: 3, flg03: true, b04l18: 24, b1Cl04: 4}); }); @@ -137,7 +137,7 @@ struct ds { uint64_t v = 0x0102030405060708ULL; */ const ds = lo.nu64be(); - const b = Buffer('0102030405060708', 'hex'); + const b = Buffer.from('0102030405060708', 'hex'); const v = 72623859790382856; const nv = v - 6; assert.equal(v, nv); @@ -148,31 +148,31 @@ uint64_t v = 0x0102030405060708ULL; const char str[] = "hi!"; */ const ds = lo.cstr(); - const b = new Buffer(8); + const b = Buffer.alloc(8); assert.equal(ds.encode('hi!', b), 3 + 1); const slen = ds.getSpan(b); assert.equal(slen, 4); - assert.equal(Buffer('68692100', 'hex').compare(b.slice(0, slen)), 0); + assert.equal(Buffer.from('68692100', 'hex').compare(b.slice(0, slen)), 0); assert.equal(ds.decode(b), 'hi!'); }); test('Fixed-len blob at offset', function() { const ds = lo.blob(4); - const b = Buffer('0102030405060708', 'hex'); - assert.equal(Buffer('03040506', 'hex').compare(ds.decode(b, 2)), 0); + const b = Buffer.from('0102030405060708', 'hex'); + assert.equal(Buffer.from('03040506', 'hex').compare(ds.decode(b, 2)), 0); }); test('variable-length array of pairs of C strings', function() { const pr = lo.seq(lo.cstr(), 2); const n = lo.u8('n'); const vla = lo.seq(pr, lo.offset(n, -1), 'a'); const st = lo.struct([n, vla], 'st'); - const b = new Buffer(32); + const b = Buffer.alloc(32); const arr = [['k1', 'v1'], ['k2', 'v2'], ['k3', 'etc']]; b.fill(0); assert.equal(st.encode({a: arr}, b), 1 + (2 * ((2 + 1) + (2 + 1)) + (2 + 1) + (3 + 1))); const span = st.getSpan(b); assert.equal(span, 20); - assert.equal(Buffer('036b31007631006b32007632006b330065746300', 'hex') + assert.equal(Buffer.from('036b31007631006b32007632006b330065746300', 'hex') .compare(b.slice(0, span)), 0); assert.deepEqual(st.decode(b), {n: 3, a: arr}); }); @@ -188,11 +188,11 @@ struct ds { lo.greedy(lo.u16().span), 'data')], 'ds'); - const b = Buffer('21010002030405', 'hex'); + const b = Buffer.from('21010002030405', 'hex'); assert.deepEqual(st.decode(b), {prop: 33, data: [0x0001, 0x0302, 0x0504]}); b.fill(0xFF); assert.equal(st.encode({prop: 9, data: [5, 6]}, b), 1 + 2 * 2); - assert.equal(Buffer('0905000600FFFF', 'hex').compare(b), 0); + assert.equal(Buffer.from('0905000600FFFF', 'hex').compare(b), 0); }); test('variable-length union', function() { const un = lo.union(lo.u8('t')); @@ -202,7 +202,7 @@ struct ds { const cstr = un.addVariant('s'.charCodeAt(0), lo.cstr(), 'str'); const tr = un.addVariant('T'.charCodeAt(0), lo.const(true), 'b'); const fa = un.addVariant('F'.charCodeAt(0), lo.const(false), 'b'); - const b = new Buffer(1 + 6); + const b = Buffer.alloc(1 + 6); un.configGetSourceVariant(function(src) { if (src.hasOwnProperty('b')) { return src.b ? tr : fa; @@ -214,32 +214,32 @@ struct ds { b.fill(0xff); assert.equal(un.encode({u8: 1}, b), 1 + 1); assert.equal(un.getSpan(b), 2); - assert.equal(Buffer('4201ffffffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('4201ffffffffff', 'hex').compare(b), 0); assert.equal(un.decode(b).u8, 1); b.fill(0xff); assert.equal(un.encode({s16: -32000}, b), 1 + 2); assert.equal(un.getSpan(b), 3); - assert.equal(Buffer('680083ffffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('680083ffffffff', 'hex').compare(b), 0); assert.equal(un.decode(b).s16, -32000); b.fill(0xff); const v48 = Math.pow(2, 47) - 1; assert.equal(un.encode({s48: v48}, b), 1 + 6); assert.equal(un.getSpan(b), 7); - assert.equal(Buffer('51ffffffffff7f', 'hex').compare(b), 0); + assert.equal(Buffer.from('51ffffffffff7f', 'hex').compare(b), 0); assert.equal(un.decode(b).s48, v48); b.fill(0xff); assert.equal(un.encode({b: true}, b), 1); assert.equal(un.getSpan(b), 1); - assert.equal(Buffer('54ffffffffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('54ffffffffffff', 'hex').compare(b), 0); assert.strictEqual(un.decode(b).b, true); b.fill(0xff); assert.equal(un.encode({b: false}, b), 1); assert.equal(un.getSpan(b), 1); - assert.equal(Buffer('46ffffffffffff', 'hex').compare(b), 0); + assert.equal(Buffer.from('46ffffffffffff', 'hex').compare(b), 0); assert.strictEqual(un.decode(b).b, false); }); }); From d7a574b46f5ae73141a60f98f27655e2a2aa24b3 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sat, 16 Dec 2017 11:19:59 -0600 Subject: [PATCH 15/17] package.json: fix whitespace error --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a568c19..3443585 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ ], "homepage": "https://github.com/pabigot/buffer-layout", "bugs": "https://github.com/pabigot/buffer-layout/issues", - "repository" : { + "repository": { "type": "git", "url": "https://github.com/pabigot/buffer-layout.git" }, From 6f7064ccae28f8d26c427a2a8f7008dcc6fa108c Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 17 Dec 2017 02:57:05 -0600 Subject: [PATCH 16/17] Layout: ES6 conversion: arrow functions, for-of --- lib/Layout.js | 281 +++++++++++++++------------------------------ test/LayoutTest.js | 9 +- 2 files changed, 98 insertions(+), 192 deletions(-) diff --git a/lib/Layout.js b/lib/Layout.js index 87e2a8d..457e6e5 100644 --- a/lib/Layout.js +++ b/lib/Layout.js @@ -352,7 +352,7 @@ exports.nameWithProperty = nameWithProperty; * @param {Layout} layout - the {@link Layout|Layout} instance used to * encode instances of `Class`. */ -exports.bindConstructorLayout = function(Class, layout) { +function bindConstructorLayout(Class, layout) { if ('function' !== typeof Class) { throw new TypeError('Class must be constructor'); } @@ -367,26 +367,21 @@ exports.bindConstructorLayout = function(Class, layout) { } Class.layout_ = layout; layout.boundConstructor_ = Class; - layout.makeDestinationObject = function() { - return new Class(); - }; + layout.makeDestinationObject = (() => new Class()); Object.defineProperty(Class.prototype, 'encode', { - configurable: false, - enumerable: false, value: function(b, offset) { return layout.encode(this, b, offset); }, writable: true, }); Object.defineProperty(Class, 'decode', { - configurable: false, - enumerable: false, value: function(b, offset) { return layout.decode(b, offset); }, writable: true, }); -}; +} +exports.bindConstructorLayout = bindConstructorLayout; /** * An object that behaves like a layout but does not consume space @@ -1136,11 +1131,10 @@ class Sequence extends Layout { offset = 0; } const elo = this.elementLayout; - let span = 0; - src.forEach(function(v) { + const span = src.reduce((span, v) => { elo.encode(v, b, offset + span); - span += elo.getSpan(b, offset + span); - }); + return span + elo.getSpan(b, offset + span); + }, 0); if (this.count instanceof ExternalLayout) { this.count.encode(src.length, b, offset); } @@ -1180,27 +1174,22 @@ class Sequence extends Layout { */ class Structure extends Layout { constructor(fields, property) { - function allLayouts(v, fd) { - return v && (fd instanceof Layout); - } - if ((!(fields instanceof Array)) - || (!fields.reduce(allLayouts, true))) { + if (!(Array.isArray(fields) + && fields.reduce((acc, v) => acc && (v instanceof Layout), true))) { throw new TypeError('fields must be array of Layout instances'); } /* Verify absence of unnamed variable-length fields. */ - fields.forEach(function(fd) { + for (const fd of fields) { if ((0 > fd.span) && (undefined === fd.property)) { throw new Error('fields cannot contain unnamed variable-length layout'); } - }); + } let span = -1; try { - span = fields.reduce(function(v, fd) { - return v + fd.getSpan(); - }, 0); + span = fields.reduce((span, fd) => span + fd.getSpan(), 0); } catch (e) { } super(span, property); @@ -1228,10 +1217,10 @@ class Structure extends Layout { } let span = 0; try { - span = this.fields.reduce(function(v, fd) { + span = this.fields.reduce((span, fd) => { const fsp = fd.getSpan(b, offset); offset += fsp; - return v + fsp; + return span + fsp; }, 0); } catch (e) { throw new RangeError('indeterminate span'); @@ -1245,12 +1234,12 @@ class Structure extends Layout { offset = 0; } const dest = this.makeDestinationObject(); - this.fields.forEach(function(fd) { + for (const fd of this.fields) { if (undefined !== fd.property) { dest[fd.property] = fd.decode(b, offset); } offset += fd.getSpan(b, offset); - }); + } return dest; } @@ -1266,7 +1255,7 @@ class Structure extends Layout { const firstOffset = offset; let lastOffset = 0; let lastWrote = 0; - this.fields.forEach(function(fd) { + for (const fd of this.fields) { let span = fd.span; lastWrote = (0 < span) ? span : 0; if (undefined === fd.property) { @@ -1287,7 +1276,7 @@ class Structure extends Layout { } lastOffset = offset; offset += span; - }); + } /* Use (lastOffset + lastWrote) instead of offset because the last * item may have had a dynamic length and we don't want to include * the padding between it and the end of the space reserved for @@ -1298,12 +1287,12 @@ class Structure extends Layout { /** @override */ fromArray(values) { const dest = this.makeDestinationObject(); - this.fields.forEach(function(fd) { + for (const fd of this.fields) { if ((undefined !== fd.property) && (0 < values.length)) { dest[fd.property] = values.shift(); } - }); + } return dest; } @@ -1316,16 +1305,15 @@ class Structure extends Layout { * undefined if there is no such property. */ layoutFor(property) { - let rv; - if (property) { - this.fields.forEach(function(fd) { - if (fd.property === property) { - rv = fd; - } - }); + if ('string' !== typeof property) { + throw new TypeError('property must be string'); } - return rv; - }; + for (const fd of this.fields) { + if (fd.property === property) { + return fd; + } + } + } /** * Get the offset of a structure member. @@ -1339,21 +1327,20 @@ class Structure extends Layout { * returned. */ offsetOf(property) { - let rv; + if ('string' !== typeof property) { + throw new TypeError('property must be string'); + } let offset = 0; - if (property) { - this.fields.forEach(function(fd) { - if (fd.property === property) { - rv = offset; - } - if (0 > fd.span) { - offset = -1; - } else if (0 <= offset) { - offset += fd.span; - } - }); + for (const fd of this.fields) { + if (fd.property === property) { + return offset; + } + if (0 > fd.span) { + offset = -1; + } else if (0 <= offset) { + offset += fd.span; + } } - return rv; } } @@ -1997,11 +1984,11 @@ class BitStructure extends Layout { } const value = this.word.decode(b, offset); this._packedSetValue(value); - this.fields.forEach(function(fd) { + for (const fd of this.fields) { if (undefined !== fd.property) { dest[fd.property] = fd.decode(value); } - }); + } return dest; } @@ -2016,14 +2003,14 @@ class BitStructure extends Layout { } const value = this.word.decode(b, offset); this._packedSetValue(value); - this.fields.forEach(function(fd) { + for (const fd of this.fields) { if (undefined !== fd.property) { const fv = src[fd.property]; if (undefined !== fv) { fd.encode(fv); } } - }); + } return this.word.encode(this._packedGetValue(), b, offset); } @@ -2066,15 +2053,14 @@ class BitStructure extends Layout { * undefined if there is no such property. */ fieldFor(property) { - let rv; - if (property) { - this.fields.forEach(function(fd) { - if (fd.property === property) { - rv = fd; - } - }); + if ('string' !== typeof property) { + throw new TypeError('property must be string'); + } + for (const fd of this.fields) { + if (fd.property === property) { + return fd; + } } - return rv; } } @@ -2110,10 +2096,7 @@ class BitField { throw new TypeError('bits must be positive integer'); } const totalBits = 8 * container.span; - function bitsSum(c, fd) { - return c + fd.bits; - } - const usedBits = container.fields.reduce(bitsSum, 0); + const usedBits = container.fields.reduce((sum, fd) => sum + fd.bits, 0); if ((bits + usedBits) > totalBits) { throw new Error('bits too long for span remainder (' + (totalBits - usedBits) + ' of ' @@ -2452,227 +2435,147 @@ exports.CString = CString; exports.Constant = Constant; /** Factory for {@link GreedyCount|GreedyCount}. */ -exports.greedy = function(elementSpan, property) { - return new GreedyCount(elementSpan, property); -}; +exports.greedy = ((elementSpan, property) => new GreedyCount(elementSpan, property)); /** Factory for {@link OffsetLayout|OffsetLayout}. */ -exports.offset = function(layout, offset, property) { - return new OffsetLayout(layout, offset, property); -}; +exports.offset = ((layout, offset, property) => new OffsetLayout(layout, offset, property)); /** Factory for {@link UInt|unsigned int layouts} spanning one * byte. */ -exports.u8 = function(property) { - return new UInt(1, property); -}; +exports.u8 = (property => new UInt(1, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning two bytes. */ -exports.u16 = function(property) { - return new UInt(2, property); -}; +exports.u16 = (property => new UInt(2, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning three bytes. */ -exports.u24 = function(property) { - return new UInt(3, property); -}; +exports.u24 = (property => new UInt(3, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning four bytes. */ -exports.u32 = function(property) { - return new UInt(4, property); -}; +exports.u32 = (property => new UInt(4, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning five bytes. */ -exports.u40 = function(property) { - return new UInt(5, property); -}; +exports.u40 = (property => new UInt(5, property)); /** Factory for {@link UInt|little-endian unsigned int layouts} * spanning six bytes. */ -exports.u48 = function(property) { - return new UInt(6, property); -}; +exports.u48 = (property => new UInt(6, property)); /** Factory for {@link NearUInt64|little-endian unsigned int * layouts} interpreted as Numbers. */ -exports.nu64 = function(property) { - return new NearUInt64(property); -}; +exports.nu64 = (property => new NearUInt64(property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning two bytes. */ -exports.u16be = function(property) { - return new UIntBE(2, property); -}; +exports.u16be = (property => new UIntBE(2, property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning three bytes. */ -exports.u24be = function(property) { - return new UIntBE(3, property); -}; +exports.u24be = (property => new UIntBE(3, property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning four bytes. */ -exports.u32be = function(property) { - return new UIntBE(4, property); -}; +exports.u32be = (property => new UIntBE(4, property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning five bytes. */ -exports.u40be = function(property) { - return new UIntBE(5, property); -}; +exports.u40be = (property => new UIntBE(5, property)); /** Factory for {@link UInt|big-endian unsigned int layouts} * spanning six bytes. */ -exports.u48be = function(property) { - return new UIntBE(6, property); -}; +exports.u48be = (property => new UIntBE(6, property)); /** Factory for {@link NearUInt64BE|big-endian unsigned int * layouts} interpreted as Numbers. */ -exports.nu64be = function(property) { - return new NearUInt64BE(property); -}; +exports.nu64be = (property => new NearUInt64BE(property)); /** Factory for {@link Int|signed int layouts} spanning one * byte. */ -exports.s8 = function(property) { - return new Int(1, property); -}; +exports.s8 = (property => new Int(1, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning two bytes. */ -exports.s16 = function(property) { - return new Int(2, property); -}; +exports.s16 = (property => new Int(2, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning three bytes. */ -exports.s24 = function(property) { - return new Int(3, property); -}; +exports.s24 = (property => new Int(3, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning four bytes. */ -exports.s32 = function(property) { - return new Int(4, property); -}; +exports.s32 = (property => new Int(4, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning five bytes. */ -exports.s40 = function(property) { - return new Int(5, property); -}; +exports.s40 = (property => new Int(5, property)); /** Factory for {@link Int|little-endian signed int layouts} * spanning six bytes. */ -exports.s48 = function(property) { - return new Int(6, property); -}; +exports.s48 = (property => new Int(6, property)); /** Factory for {@link NearInt64|little-endian signed int layouts} * interpreted as Numbers. */ -exports.ns64 = function(property) { - return new NearInt64(property); -}; +exports.ns64 = (property => new NearInt64(property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning two bytes. */ -exports.s16be = function(property) { - return new IntBE(2, property); -}; +exports.s16be = (property => new IntBE(2, property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning three bytes. */ -exports.s24be = function(property) { - return new IntBE(3, property); -}; +exports.s24be = (property => new IntBE(3, property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning four bytes. */ -exports.s32be = function(property) { - return new IntBE(4, property); -}; +exports.s32be = (property => new IntBE(4, property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning five bytes. */ -exports.s40be = function(property) { - return new IntBE(5, property); -}; +exports.s40be = (property => new IntBE(5, property)); /** Factory for {@link Int|big-endian signed int layouts} * spanning six bytes. */ -exports.s48be = function(property) { - return new IntBE(6, property); -}; +exports.s48be = (property => new IntBE(6, property)); /** Factory for {@link NearInt64BE|big-endian signed int layouts} * interpreted as Numbers. */ -exports.ns64be = function(property) { - return new NearInt64BE(property); -}; +exports.ns64be = (property => new NearInt64BE(property)); /** Factory for {@link Float|little-endian 32-bit floating point} values. */ -exports.f32 = function(property) { - return new Float(property); -}; +exports.f32 = (property => new Float(property)); /** Factory for {@link FloatBE|big-endian 32-bit floating point} values. */ -exports.f32be = function(property) { - return new FloatBE(property); -}; +exports.f32be = (property => new FloatBE(property)); /** Factory for {@link Double|little-endian 64-bit floating point} values. */ -exports.f64 = function(property) { - return new Double(property); -}; +exports.f64 = (property => new Double(property)); /** Factory for {@link DoubleBE|big-endian 64-bit floating point} values. */ -exports.f64be = function(property) { - return new DoubleBE(property); -}; +exports.f64be = (property => new DoubleBE(property)); /** Factory for {@link Structure|Structure} values. */ -exports.struct = function(fields, property) { - return new Structure(fields, property); -}; +exports.struct = ((fields, property) => new Structure(fields, property)); /** Factory for {@link BitStructure|BitStructure} values. */ -exports.bits = function(word, msb, property) { - return new BitStructure(word, msb, property); -}; +exports.bits = ((word, msb, property) => new BitStructure(word, msb, property)); /** Factory for {@link Sequence|Sequence} values. */ -exports.seq = function(elementLayout, count, property) { - return new Sequence(elementLayout, count, property); -}; +exports.seq = ((elementLayout, count, property) => new Sequence(elementLayout, count, property)); /** Factory for {@link Union|Union} values. */ -exports.union = function(discr, defaultLayout, property) { - return new Union(discr, defaultLayout, property); -}; +exports.union = ((discr, defaultLayout, property) => new Union(discr, defaultLayout, property)); /** Factory for {@link UnionLayoutDiscriminator|UnionLayoutDiscriminator} values. */ -exports.unionLayoutDiscriminator = function(layout, property) { - return new UnionLayoutDiscriminator(layout, property); -}; +exports.unionLayoutDiscriminator = ((layout, property) => new UnionLayoutDiscriminator(layout, property)); /** Factory for {@link Blob|Blob} values. */ -exports.blob = function(length, property) { - return new Blob(length, property); -}; +exports.blob = ((length, property) => new Blob(length, property)); /** Factory for {@link CString|CString} values. */ -exports.cstr = function(property) { - return new CString(property); -}; +exports.cstr = (property => new CString(property)); /** Factory for {@link Constant|Constant} values. */ -exports.const = function(value, property) { - return new Constant(value, property); -}; +exports.const = ((value, property) => new Constant(value, property)); diff --git a/test/LayoutTest.js b/test/LayoutTest.js index 5a8b569..9cdde63 100644 --- a/test/LayoutTest.js +++ b/test/LayoutTest.js @@ -834,7 +834,8 @@ suite('Layout', function() { var cstr = lo.cstr('cstr'); var u16 = lo.u16('u16'); var d = lo.struct([u8, s32, cstr, u16], 's'); - assert.strictEqual(d.layoutFor(), undefined); + assert.throws(() => d.layoutFor(), + err => ('property must be string' === err.message)); assert.strictEqual(d.layoutFor('u8'), u8); assert.strictEqual(d.layoutFor('cstr'), cstr); assert.strictEqual(d.layoutFor('other'), undefined); @@ -852,7 +853,8 @@ suite('Layout', function() { var cstr = lo.cstr('cstr'); var u16 = lo.u16('u16'); var d = lo.struct([u8, s32, cstr, u16], 's'); - assert.strictEqual(d.offsetOf(), undefined); + assert.throws(() => d.offsetOf(), + err => ('property must be string' === err.message)); assert.strictEqual(d.offsetOf('u8'), 0); assert.strictEqual(d.offsetOf('s32'), 1); assert.strictEqual(d.offsetOf('cstr'), 5); @@ -1542,7 +1544,8 @@ suite('Layout', function() { d.addField(4, 'b4'); var c11 = d.addField(11, 'c11'); d.addField(16, 'd16'); - assert.strictEqual(d.fieldFor(), undefined); + assert.throws(() => d.fieldFor(), + err => ('property must be string' === err.message)); assert.strictEqual(d.fieldFor('b'), b); assert.strictEqual(d.fieldFor('c11'), c11); assert.strictEqual(d.fieldFor('other'), undefined); From 39632bbe480eff8915d1e7802ae2f8fc3635dac3 Mon Sep 17 00:00:00 2001 From: "Peter A. Bigot" Date: Sun, 17 Dec 2017 03:37:50 -0600 Subject: [PATCH 17/17] passim: update for 1.0.0 release --- CHANGELOG.md | 22 ++++++++++++++++++---- lib/Layout.js | 2 +- package.json | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67e483b..8e928e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Change Log -## [Unreleased] +## [1.0.0] - 2017-12-17 + +* Minimum Node version increased to 4.5 to support dependency + on + [Buffer.alloc()](https://nodejs.org/dist/latest-v4.x/docs/api/buffer.html#buffer_class_method_buffer_alloc_size_fill_encoding). +* Removed [patch][node:issue#3994] for [ancient buffer bug][node:issue#3992] +* Update to ES6 classes and other features +* Documentation clarifications. +* Update dependent packages. +* Switch to [npm:eslint] and deal with fallout. ## [0.13.0] - 2016-03-27 @@ -12,7 +21,7 @@ * Disable coverage testing for [patchIssue3992][doc:patchIssue3992] to avoid taking a penalty on node versions that have been updated. - + ## [0.12.0] - 2016-03-08 * **API** Replace `setClassLayout` with [bindConstructorLayout][doc:bindConstructorLayout]. @@ -101,12 +110,14 @@ list. * Document [destination parameter to decode][issue#2]. * Allow [user-defined name for union discriminators][issue#1]. - + ## 0.1.0 - 2015-10-25 * Initial release. -[Unreleased]: https://github.com/pabigot/buffer-layout/compare/v0.13.0...next +[1.0.0]: https://github.com/pabigot/buffer-layout/compare/v0.13.0...v1.0.0 +[0.13.0]: https://github.com/pabigot/buffer-layout/compare/v0.12.0...v0.13.0 +[0.12.1]: https://github.com/pabigot/buffer-layout/compare/v0.12.0...v0.12.1 [0.12.0]: https://github.com/pabigot/buffer-layout/compare/v0.11.0...v0.12.0 [0.11.0]: https://github.com/pabigot/buffer-layout/compare/v0.10.0...v0.11.0 [0.10.0]: https://github.com/pabigot/buffer-layout/compare/v0.9.0...v0.10.0 @@ -122,6 +133,7 @@ [doc:bindConstructorLayout]: http://pabigot.github.io/buffer-layout/module-Layout.html#.bindConstructorLayout [doc:BitField]: http://pabigot.github.io/buffer-layout/module-Layout-BitField.html [doc:BitStructure]: http://pabigot.github.io/buffer-layout/module-Layout-BitStructure.html +[doc:BitStructure.fieldFor]: http://pabigot.github.io/buffer-layout/module-Layout-BitStructure.html#fieldFor [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 @@ -160,8 +172,10 @@ [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 +[node:issue#3994]: https://github.com/nodejs/node/issues/3994 [npm:istanbul]: https://www.npmjs.com/package/istanbul [npm:jscs]: https://www.npmjs.com/package/jscs +[npm:eslint]: https://www.npmjs.com/package/eslint