diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fe12e6..85a6c62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - archive: Support semantic methods for subscribing to unarchive events (onExtract), [Issue #47](https://github.com/codedread/bitjs/issues/47). +- io: Added a getData() method to ByteBuffer to retrieve a copy of the bytes that have been written. ### Changed diff --git a/io/bitstream.js b/io/bitstream.js index b6db701..22906fd 100644 --- a/io/bitstream.js +++ b/io/bitstream.js @@ -20,7 +20,7 @@ const BITMASK = [0, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; * * Bit reading always proceeds from the first byte in the buffer, to the * second byte, and so on. The MTL flag controls which bit is considered - * first *inside* the byte. + * first *inside* the byte. The default is least-to-most direction. * * An Example for how Most-To-Least vs Least-to-Most mode works: * diff --git a/io/bytebuffer.js b/io/bytebuffer.js index 0ef3135..e2a0078 100644 --- a/io/bytebuffer.js +++ b/io/bytebuffer.js @@ -30,17 +30,31 @@ export class ByteBuffer { this.data = new Uint8Array(numBytes); /** + * Points to the byte that will next be written. * @type {number} * @public */ this.ptr = 0; } + /** + * Returns an exact copy of all the data that has been written to the ByteBuffer. + * @returns {Uint8Array} + */ + getData() { + const dataCopy = new Uint8Array(this.ptr); + dataCopy.set(this.data.subarray(0, this.ptr)); + return dataCopy; + } /** * @param {number} b The byte to insert. */ insertByte(b) { + if (this.ptr + 1 > this.data.byteLength) { + throw `Cannot insert a byte, the buffer is full.`; + } + // TODO: throw if byte is invalid? this.data[this.ptr++] = b; } @@ -49,6 +63,10 @@ export class ByteBuffer { * @param {Array.|Uint8Array|Int8Array} bytes The bytes to insert. */ insertBytes(bytes) { + if (this.ptr + bytes.length > this.data.byteLength) { + throw `Cannot insert ${bytes.length} bytes, the buffer is full.`; + } + // TODO: throw if bytes is invalid? this.data.set(bytes, this.ptr); this.ptr += bytes.length; diff --git a/io/bytestream.js b/io/bytestream.js index 1353d61..ed7d8ba 100644 --- a/io/bytestream.js +++ b/io/bytestream.js @@ -66,13 +66,13 @@ export class ByteStream { this.littleEndian_ = true; } - /** @returns {boolean} Whether the stream is little-endian. */ + /** @returns {boolean} Whether the stream is little-endian (least significant byte is first). */ isLittleEndian() { return this.littleEndian_; } /** - * Big-Endian is sometimes called Motorola-style. + * Big-Endian means the most significant byte is first. it is sometimes called Motorola-style. * @param {boolean=} val The value to set. If not present, the stream is set to big-endian. */ setBigEndian(val = true) { @@ -80,7 +80,7 @@ export class ByteStream { } /** - * Little-Endian is sometimes called Intel-style. + * Little-Endian means the least significant byte is ifrst. is sometimes called Intel-style. * @param {boolean=} val The value to set. If not present, the stream is set to little-endian. */ setLittleEndian(val = true) { diff --git a/tests/io-bytebuffer.spec.js b/tests/io-bytebuffer.spec.js index a954df8..cee2379 100644 --- a/tests/io-bytebuffer.spec.js +++ b/tests/io-bytebuffer.spec.js @@ -18,10 +18,35 @@ describe('bitjs.io.ByteBuffer', () => { buffer = new ByteBuffer(4); }); + describe('getData()', () => { + it('returns an empty array when nothing has been written', () => { + expect(buffer.getData().byteLength).equals(0); + }); + + it('is sized correctly', () => { + buffer.insertByte(42); + buffer.insertByte(81); + const data = buffer.getData(); + expect(data.byteLength).equals(2); + expect(data[0]).equals(42); + expect(data[1]).equals(81); + }); + }); + it('throws when initialized incorrectly', () => { expect(() => new ByteBuffer()).throws(); }); + describe('Buffer overflow', () => { + it('insertByte() throws when buffer exceeded', () => { + buffer.insertBytes([0, 2, 4, 6]); + expect(() => buffer.insertByte(1)).throws(); + }); + it('insertBytes() throws when buffer exceeded', () => { + expect(() => buffer.insertBytes([0, 2, 4, 6, 8])).throws(); + }); + }); + it('insertByte()', () => { buffer.insertByte(192); expect(buffer.ptr).equals(1);