diff --git a/index.js b/index.js new file mode 100644 index 0000000..dbfacce --- /dev/null +++ b/index.js @@ -0,0 +1,5 @@ +'use strict'; + +let reader = require('./lib/reader.js'); + +exports.Reader = reader; diff --git a/lib/exceptions.js b/lib/exceptions.js new file mode 100644 index 0000000..c9b5ba2 --- /dev/null +++ b/lib/exceptions.js @@ -0,0 +1,4 @@ +'use strict'; + +exports.BadValueError = +class BadValueError extends Error {} diff --git a/lib/reader.js b/lib/reader.js new file mode 100644 index 0000000..3c5bc44 --- /dev/null +++ b/lib/reader.js @@ -0,0 +1,100 @@ +'use strict'; + +let exceptions = require('./exceptions'); + +function validateLength(length) { + if (this._offset + length > this._buffer.length) { + throw exceptions.BadValueError("Reader is empty"); + } +} + +module.exports = class Reader { + constructor(value) { + if (!Buffer.isBuffer(value)) { + throw exceptions.BadValueError("value provided must be a Buffer"); + } + + this._buffer = value; + this._offset = 0; + } + + write(buffer) { + if (!Buffer.isBuffer(buffer)) { + throw exceptions.BadValueError("only Buffers may be written to Reader"); + } + + let newLength = this._buffer.length + buffer.length; + let newBuffer = new Buffer(newLength); + + this._buffer.copy(newBuffer, 0, 0); + buffer.copy(new Buffer, this._buffer.length, 0); + this._buffer = newBuffer; + } + + compact() { + let newLength = this._buffer.length - this._offset; + let newBuffer = new Buffer(newLength); + + this._buffer.copy(newBuffer, 0, this._offset); + this._buffer = newBuffer; + this._offset = 0; + } + + reset() { + this._offset = offset; + } + + length() { + return this._buffer.length - this._offset; + } + + buffer(length) { + if (!Number.isInteger(length) || length < 0) { + throw exceptions.BadValueError("Buffer length must be an integer") + } + + validateLength.call(this, length); + + let newBuffer = new Buffer(length); + this._buffer.copy(newBuffer, 0, this._offset, this._offset + length); + this._offset += length; + return newBuffer; + } + + array(length) { + if (!Number.isInteger(length) || length < 0) { + throw exceptions.BadValueError("Buffer length must be an integer"); + } + + validateLength.call(this, length); + + let array = []; + for (let i = 0; i < length; ++i) { + array.push(this._buffer[this._offset + i]); + } + this._offset += length; + return array; + } + + uint8() { + validateLength.call(this, 1); + + return this._buffer[this._offset++]; + } + + uint16le() { + validateLength.call(this, 2); + + let value = this._buffer.readUInt16LE(this._offset); + this._offset += 2; + return value; + } + + uint32le() { + validateLength.call(this, 4); + + let value = this._buffer.readUInt32LE(this._offset); + this._offset += 4; + return value; + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4748cdb --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "binpack", + "devDependencies": { + "mocha": "^2.3.3" + }, + "scripts": { + "test": "./node_modules/mocha/bin/mocha test/" + } +} diff --git a/test/reader.js b/test/reader.js new file mode 100644 index 0000000..e1c7cfe --- /dev/null +++ b/test/reader.js @@ -0,0 +1,24 @@ +'use strict'; + +let assert = require('assert'); +let binpack = require('..') +let Reader = binpack.Reader; + +describe('Reader', () => { + it('buffer', () => { + let reader = new Reader(new Buffer([0x01, 0x02, 0x03])); + + assert.equal(3, reader.length()); + + let buf = reader.buffer(2); + assert.ok(buf.equals(new Buffer([0x01, 0x02]))); + + assert.equal(1, reader.length()); + reader.compact(); + assert.equal(1, reader.length()); + + assert.throws(() => { + reader.buffer(2); + }); + }); +})