Skip to content

Commit b7aefdf

Browse files
authored
Merge pull request #1 from ginkgoch/implementation-and-test
implementation and tests
2 parents 4dfe0c1 + 14f2f79 commit b7aefdf

File tree

4 files changed

+322
-1
lines changed

4 files changed

+322
-1
lines changed

README.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,59 @@
1-
# node-buffer-reader
1+
# Ginkgoch Buffer Reader for NodeJS
2+
This is a NodeJS library to help to read [Buffer](https://cn.nodejs.org/api/buffer.html) instance easily.
3+
4+
## Install
5+
```terminal
6+
npm i ginkgoch-buffer-reader --save
7+
```
8+
9+
## Example
10+
11+
**Prepare for data**
12+
```js
13+
const buffer = Buffer.alloc(4);
14+
buffer.writeInt8(8, 0);
15+
buffer.writeInt16LE(16, 1);
16+
buffer.writeUInt32LE(32, 3);
17+
buffer.writeDoubleBE(54.8765, 7);
18+
```
19+
20+
**Without `Ginkgoch Buffer Reader`**
21+
```js
22+
let i1 = buffer.readInt8(0);
23+
let i2 = buffer.readInt16LE(1);
24+
let i3 = buffer.readUInt32LE(3);
25+
let i4 = buffer.readDoubleBE(7);
26+
```
27+
28+
**With `Ginkgoch Buffer Reader`, it automatically manages the read position for you. You don't need to remember the position and the boring type length calculations.**
29+
```js
30+
let i1 = br.nextInt8();
31+
let i2 = br.nextInt16LE();
32+
let i3 = br.nextUInt32LE();
33+
let i4 = br.nextDoubleBE();
34+
```
35+
36+
## API
37+
```js
38+
constructor(buffer: Buffer);
39+
seek(offset: number, fromBeginning = true);
40+
nextBuffer(length: number);
41+
nextString(length: number, encoding = 'utf-8');
42+
nextIn8();
43+
nextUInt8();
44+
nextUInt16LE();
45+
nextUInt16BE();
46+
nextInt16LE();
47+
nextInt16BE();
48+
nextUInt32LE();
49+
nextUInt32BE();
50+
nextInt32LE();
51+
nextInt32BE();
52+
nextFloatLE();
53+
nextFloatBE();
54+
nextDoubleLE();
55+
nextDoubleBE();
56+
```
57+
58+
## Issues
59+
Contact [ginkgoch@outlook.com](mailto:ginkgoch@outlook.com) or [sumbit an issue](https://github.com/ginkgoch/node-buffer-reader/issues).

index.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
const assert = require('assert');
2+
3+
module.exports = class BufferReader {
4+
constructor(buffer) {
5+
assert(Buffer.isBuffer(buffer), 'Invalid buffer.');
6+
this.buffer = buffer;
7+
this.offset = 0;
8+
this._makeNextReadFor('Int8', 1);
9+
this._makeNextReadFor('UInt8', 1);
10+
this._makeNextReadLEBEFor('UInt16', 2);
11+
this._makeNextReadLEBEFor('Int16', 2);
12+
this._makeNextReadLEBEFor('UInt32', 4);
13+
this._makeNextReadLEBEFor('Int32', 4);
14+
this._makeNextReadLEBEFor('Float', 4);
15+
this._makeNextReadLEBEFor('Double', 8);
16+
}
17+
18+
seek(offset, fromBeginning = true) {
19+
if(!fromBeginning) {
20+
offset += this.offset;
21+
}
22+
23+
this._checkOffsetInRange(offset);
24+
this.offset = offset;
25+
}
26+
27+
nextBuffer(length) {
28+
this._checkPositive(length);
29+
this._checkOffsetInRange(this.offset + length);
30+
31+
const buffer = Buffer.alloc(length);
32+
this.buffer.copy(buffer, 0, this.offset, this.offset + length);
33+
this.offset += length;
34+
return buffer;
35+
}
36+
37+
nextString(length, encoding = 'utf-8') {
38+
this._checkPositive(length);
39+
this._checkOffsetInRange(this.offset + length);
40+
const str = this.buffer.toString(encoding, this.offset, this.offset + length);
41+
this.offset += length;
42+
return str;
43+
}
44+
45+
_makeNextReadLEBEFor(method, size) {
46+
this._makeNextReadFor(method + 'LE', size);
47+
this._makeNextReadFor(method + 'BE', size);
48+
}
49+
50+
_makeNextReadFor(method, size) {
51+
BufferReader.prototype[`next${method}`] = function() {
52+
this._checkOffsetInRange(this.offset + size, 'Offset');
53+
const val = this.buffer[`read${method}`](this.offset);
54+
this.offset += size;
55+
return val;
56+
};
57+
}
58+
59+
_checkPositive(number, name = 'Length') {
60+
assert(number >= 0, `${name} must be positive.`);
61+
}
62+
63+
_checkOffsetInRange(offset) {
64+
assert(offset >= 0 && offset <= this.buffer.length, 'Offset out of range.');
65+
}
66+
}

index.test.js

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
const BufferReader = require('./index.js');
2+
3+
describe('buffer reader tests', () => {
4+
test('init test - normal', () => {
5+
const buffer = Buffer.alloc(4);
6+
const br = new BufferReader(buffer);
7+
expect(br).not.toBeNull();
8+
expect(br).not.toBeUndefined();
9+
});
10+
11+
test('init test - not buffer', () => {
12+
const buffer = undefined;
13+
function init() { const br = new BufferReader(buffer); }
14+
expect(init).toThrow(/Invalid buffer./);
15+
});
16+
17+
test('seek from beginning - normal', () => {
18+
const buffer = Buffer.from([1, 2, 3, 4]);
19+
const br = new BufferReader(buffer);
20+
expect(br.offset).toBe(0);
21+
expect(br.buffer).not.toBeNull();
22+
expect(br.buffer).not.toBeUndefined();
23+
br.seek(2);
24+
expect(br.offset).toBe(2);
25+
});
26+
27+
test('seek from current - normal', () => {
28+
const buffer = Buffer.from([1, 2, 3, 4]);
29+
const br = new BufferReader(buffer);
30+
br.seek(1);
31+
expect(br.offset).toBe(1);
32+
br.seek(1, false);
33+
expect(br.offset).toBe(2);
34+
br.seek(1, false);
35+
expect(br.offset).toBe(3);
36+
br.seek(1);
37+
expect(br.offset).toBe(1);
38+
});
39+
40+
test('seek from beginning - out of range', () => {
41+
const buffer = Buffer.from([1, 2, 3, 4]);
42+
const br = new BufferReader(buffer);
43+
expect(() => br.seek(5)).toThrow(/Offset out of range./);
44+
});
45+
46+
test('seek from current - out of range', () => {
47+
const buffer = Buffer.from([1, 2, 3, 4]);
48+
const br = new BufferReader(buffer);
49+
br.seek(2);
50+
br.seek(3);
51+
expect(() => br.seek(2, false)).toThrow(/Offset out of range./);
52+
});
53+
54+
test('nextBuffer test - positive', () => {
55+
const buffer = Buffer.from([1, 2, 3, 4]);
56+
const br = new BufferReader(buffer);
57+
expect(() => br.nextBuffer(-1)).toThrow(/Length must be positive./);
58+
});
59+
60+
test('nextBuffer test - oor', () => {
61+
const buffer = Buffer.from([1, 2, 3, 4]);
62+
const br = new BufferReader(buffer);
63+
expect(() => br.nextBuffer(5)).toThrow(/Offset out of range./);
64+
});
65+
66+
test('nextBuffer test - normal', () => {
67+
const buffer1 = Buffer.from([1, 2, 3, 4]);
68+
const buffer2 = Buffer.from([4, 5]);
69+
const br = new BufferReader(Buffer.concat([buffer1, buffer2]));
70+
const nBuffer1 = br.nextBuffer(4);
71+
const nBuffer2 = br.nextBuffer(2);
72+
expect(Buffer.compare(buffer1, nBuffer1, 0));
73+
expect(Buffer.compare(buffer2, nBuffer2, 0));
74+
});
75+
76+
test('nextString test - normal', () => {
77+
const str = 'hello world 01!';
78+
const buffer = new Buffer(str, 'utf-8');
79+
const br = new BufferReader(Buffer.concat([Buffer.from([0, 2]), buffer]));
80+
br.seek(2);
81+
const nStr = br.nextString(15, 'utf-8');
82+
expect(nStr).toEqual(str);
83+
});
84+
85+
test('nextString test - positive', () => {
86+
const br = new BufferReader(new Buffer('hello', 'utf-8'));
87+
expect(() => br.nextString(-1)).toThrow(/Length must be positive./);
88+
});
89+
90+
test('nextString test - oor', () => {
91+
const br = new BufferReader(new Buffer('hello', 'utf-8'));
92+
expect(() => br.nextString(6)).toThrow(/Offset out of range./);
93+
});
94+
95+
test('nextInt8 test', () => {
96+
const buffer = Buffer.alloc(4);
97+
buffer.writeInt8(1, 0);
98+
buffer.writeInt8(2, 1);
99+
buffer.writeInt8(3, 2);
100+
buffer.writeInt8(4, 3);
101+
const br = new BufferReader(buffer);
102+
103+
expect(br.nextInt8()).toBe(1);
104+
expect(br.nextInt8()).toBe(2);
105+
expect(br.nextInt8()).toBe(3);
106+
expect(br.nextInt8()).toBe(4);
107+
expect(() => br.nextInt8()).toThrow(/Offset out of range./);
108+
});
109+
110+
test('nextInt16LE test', () => {
111+
const buffer = Buffer.alloc(4);
112+
buffer.writeInt16LE(16, 0);
113+
buffer.writeInt16LE(32, 2);
114+
const br = new BufferReader(buffer);
115+
116+
expect(br.nextInt16LE()).toBe(16);
117+
expect(br.nextInt16LE()).toBe(32);
118+
expect(() => br.nextInt16LE()).toThrow(/Offset out of range./);
119+
});
120+
121+
test('nextInt16BE test', () => {
122+
const buffer = Buffer.alloc(4);
123+
buffer.writeInt16BE(16, 0);
124+
buffer.writeInt16BE(32, 2);
125+
const br = new BufferReader(buffer);
126+
127+
expect(br.nextInt16BE()).toBe(16);
128+
expect(br.nextInt16BE()).toBe(32);
129+
expect(() => br.nextInt16BE()).toThrow(/Offset out of range./);
130+
});
131+
132+
test('nextUInt32LE test', () => {
133+
const buffer = Buffer.alloc(8);
134+
buffer.writeUInt32LE(16, 0);
135+
buffer.writeUInt32LE(32, 4);
136+
const br = new BufferReader(buffer);
137+
138+
expect(br.nextUInt32LE()).toBe(16);
139+
expect(br.nextUInt32LE()).toBe(32);
140+
expect(() => br.nextUInt32LE()).toThrow(/Offset out of range./);
141+
});
142+
143+
test('nextDoubleBE test', () => {
144+
const buffer = Buffer.alloc(16);
145+
const d1 = 12.3432;
146+
const d2 = 32.8976;
147+
buffer.writeDoubleBE(d1, 0);
148+
buffer.writeDoubleBE(d2, 8);
149+
const br = new BufferReader(buffer);
150+
151+
expect(br.nextDoubleBE()).toBe(d1);
152+
expect(br.nextDoubleBE()).toBe(d2);
153+
expect(() => br.nextDoubleBE()).toThrow(/Offset out of range./);
154+
});
155+
156+
test('demo test', () => {
157+
const buffer = Buffer.alloc(15);
158+
buffer.writeInt8(8, 0);
159+
buffer.writeInt16LE(16, 1);
160+
buffer.writeUInt32LE(32, 3);
161+
buffer.writeDoubleBE(54.8765, 7);
162+
163+
// original
164+
expect(buffer.readInt8(0)).toBe(8);
165+
expect(buffer.readInt16LE(1)).toBe(16);
166+
expect(buffer.readUInt32LE(3)).toBe(32);
167+
expect(buffer.readDoubleBE(7)).toBe(54.8765);
168+
169+
// new
170+
const br = new BufferReader(buffer);
171+
expect(br.nextInt8()).toBe(8);
172+
expect(br.nextInt16LE()).toBe(16);
173+
expect(br.nextUInt32LE()).toBe(32);
174+
expect(br.nextDoubleBE()).toBe(54.8765);
175+
});
176+
});

package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "ginkgoch-buffer-reader",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"scripts": {
6+
"test": "./node_modules/.bin/jest"
7+
},
8+
"author": {
9+
"name": "Ginkgoch",
10+
"email": "ginkgoch@outlook.com",
11+
"url": "https://github.com/ginkgoch/node-buffer-reader"
12+
},
13+
"keywords": [
14+
"ginkgoch", "buffer-reader", "bufferreader", "node-buffer-reader"
15+
],
16+
"license": "MIT",
17+
"description": "This is a library to help to easily read Buffer instance.",
18+
"devDependencies": {
19+
"jest": "^23.4.1"
20+
}
21+
}

0 commit comments

Comments
 (0)