• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1smart-buffer  [![Build Status](https://travis-ci.org/JoshGlazebrook/smart-buffer.svg?branch=master)](https://travis-ci.org/JoshGlazebrook/smart-buffer)  [![Coverage Status](https://coveralls.io/repos/github/JoshGlazebrook/smart-buffer/badge.svg?branch=master)](https://coveralls.io/github/JoshGlazebrook/smart-buffer?branch=master)
2=============
3
4smart-buffer is a Buffer wrapper that adds automatic read & write offset tracking, string operations, data insertions, and more.
5
6![stats](https://nodei.co/npm/smart-buffer.png?downloads=true&downloadRank=true&stars=true "stats")
7
8**Key Features**:
9* Proxies all of the Buffer write and read functions
10* Keeps track of read and write offsets automatically
11* Grows the internal Buffer as needed
12* Useful string operations. (Null terminating strings)
13* Allows for inserting values at specific points in the Buffer
14* Built in TypeScript
15* Type Definitions Provided
16* Browser Support (using Webpack/Browserify)
17* Full test coverage
18
19**Requirements**:
20* Node v4.0+ is supported at this time.  (Versions prior to 2.0 will work on node 0.10)
21
22
23
24## Breaking Changes in v4.0
25
26* Old constructor patterns have been completely removed. It's now required to use the SmartBuffer.fromXXX() factory constructors.
27* rewind(), skip(), moveTo() have been removed. (see [offsets](#offsets))
28* Internal private properties are now prefixed with underscores (_)
29* **All** writeXXX() methods that are given an offset will now **overwrite data** instead of insert. (see [write vs insert](#write-vs-insert))
30* insertXXX() methods have been added for when you want to insert data at a specific offset (this replaces the old behavior of writeXXX() when an offset was provided)
31
32
33## Looking for v3 docs?
34
35Legacy documentation for version 3 and prior can be found [here](https://github.com/JoshGlazebrook/smart-buffer/blob/master/docs/README_v3.md).
36
37## Installing:
38
39`yarn add smart-buffer`
40
41or
42
43`npm install smart-buffer`
44
45Note: The published NPM package includes the built javascript library.
46If you cloned this repo and wish to build the library manually use:
47
48`npm run build`
49
50## Using smart-buffer
51
52```javascript
53// Javascript
54const SmartBuffer = require('smart-buffer').SmartBuffer;
55
56// Typescript
57import { SmartBuffer, SmartBufferOptions} from 'smart-buffer';
58```
59
60### Simple Example
61
62Building a packet that uses the following protocol specification:
63
64`[PacketType:2][PacketLength:2][Data:XX]`
65
66To build this packet using the vanilla Buffer class, you would have to count up the length of the data payload beforehand. You would also need to keep track of the current "cursor" position in your Buffer so you write everything in the right places. With smart-buffer you don't have to do either of those things.
67
68```javascript
69function createLoginPacket(username, password, age, country) {
70    const packet = new SmartBuffer();
71    packet.writeUInt16LE(0x0060); // Some packet type
72    packet.writeStringNT(username);
73    packet.writeStringNT(password);
74    packet.writeUInt8(age);
75    packet.writeStringNT(country);
76    packet.insertUInt16LE(packet.length - 2, 2);
77
78    return packet.toBuffer();
79}
80```
81With the above function, you now can do this:
82```javascript
83const login = createLoginPacket("Josh", "secret123", 22, "United States");
84
85// <Buffer 60 00 1e 00 4a 6f 73 68 00 73 65 63 72 65 74 31 32 33 00 16 55 6e 69 74 65 64 20 53 74 61 74 65 73 00>
86```
87Notice that the `[PacketLength:2]` value (1e 00) was inserted at position 2.
88
89Reading back the packet we created above is just as easy:
90```javascript
91
92const reader = SmartBuffer.fromBuffer(login);
93
94const logininfo = {
95    packetType: reader.readUInt16LE(),
96    packetLength: reader.readUInt16LE(),
97    username: reader.readStringNT(),
98    password: reader.readStringNT(),
99    age: reader.readUInt8(),
100    country: reader.readStringNT()
101};
102
103/*
104{
105    packetType: 96, (0x0060)
106    packetLength: 30,
107    username: 'Josh',
108    password: 'secret123',
109    age: 22,
110    country: 'United States'
111}
112*/
113```
114
115
116## Write vs Insert
117In prior versions of SmartBuffer, .writeXXX(value, offset) calls would insert data when an offset was provided. In version 4, this will now overwrite the data at the offset position. To insert data there are now corresponding .insertXXX(value, offset) methods.
118
119**SmartBuffer v3**:
120```javascript
121const buff = SmartBuffer.fromBuffer(new Buffer([1,2,3,4,5,6]));
122buff.writeInt8(7, 2);
123console.log(buff.toBuffer())
124
125// <Buffer 01 02 07 03 04 05 06>
126```
127
128**SmartBuffer v4**:
129```javascript
130const buff = SmartBuffer.fromBuffer(new Buffer([1,2,3,4,5,6]));
131buff.writeInt8(7, 2);
132console.log(buff.toBuffer());
133
134// <Buffer 01 02 07 04 05 06>
135```
136
137To insert you instead should use:
138```javascript
139const buff = SmartBuffer.fromBuffer(new Buffer([1,2,3,4,5,6]));
140buff.insertInt8(7, 2);
141console.log(buff.toBuffer());
142
143// <Buffer 01 02 07 03 04 05 06>
144```
145
146**Note:** Insert/Writing to a position beyond the currently tracked internal Buffer will zero pad to your offset.
147
148## Constructing a smart-buffer
149
150There are a few different ways to construct a SmartBuffer instance.
151
152```javascript
153// Creating SmartBuffer from existing Buffer
154const buff = SmartBuffer.fromBuffer(buffer); // Creates instance from buffer. (Uses default utf8 encoding)
155const buff = SmartBuffer.fromBuffer(buffer, 'ascii'); // Creates instance from buffer with ascii encoding for strings.
156
157// Creating SmartBuffer with specified internal Buffer size. (Note: this is not a hard cap, the internal buffer will grow as needed).
158const buff = SmartBuffer.fromSize(1024); // Creates instance with internal Buffer size of 1024.
159const buff = SmartBuffer.fromSize(1024, 'utf8'); // Creates instance with internal Buffer size of 1024, and utf8 encoding for strings.
160
161// Creating SmartBuffer with options object. This one specifies size and encoding.
162const buff = SmartBuffer.fromOptions({
163    size: 1024,
164    encoding: 'ascii'
165});
166
167// Creating SmartBuffer with options object. This one specified an existing Buffer.
168const buff = SmartBuffer.fromOptions({
169    buff: buffer
170});
171
172// Creating SmartBuffer from a string.
173const buff = SmartBuffer.fromBuffer(Buffer.from('some string', 'utf8'));
174
175// Just want a regular SmartBuffer with all default options?
176const buff = new SmartBuffer();
177```
178
179# Api Reference:
180
181**Note:** SmartBuffer is fully documented with Typescript definitions as well as jsdocs so your favorite editor/IDE will have intellisense.
182
183**Table of Contents**
184
1851. [Constructing](#constructing)
1862. **Numbers**
187    1. [Integers](#integers)
188    2. [Floating Points](#floating-point-numbers)
1893. **Strings**
190    1. [Strings](#strings)
191    2. [Null Terminated Strings](#null-terminated-strings)
1924. [Buffers](#buffers)
1935. [Offsets](#offsets)
1946. [Other](#other)
195
196
197## Constructing
198
199### constructor()
200### constructor([options])
201- ```options``` *{SmartBufferOptions}* An optional options object to construct a SmartBuffer with.
202
203Examples:
204```javascript
205const buff = new SmartBuffer();
206const buff = new SmartBuffer({
207    size: 1024,
208    encoding: 'ascii'
209});
210```
211
212### Class Method: fromBuffer(buffer[, encoding])
213- ```buffer``` *{Buffer}* The Buffer instance to wrap.
214- ```encoding``` *{string}* The string encoding to use. ```Default: 'utf8'```
215
216Examples:
217```javascript
218const someBuffer = Buffer.from('some string');
219const buff = SmartBuffer.fromBuffer(someBuffer); // Defaults to utf8
220const buff = SmartBuffer.fromBuffer(someBuffer, 'ascii');
221```
222
223### Class Method: fromSize(size[, encoding])
224- ```size``` *{number}* The size to initialize the internal Buffer.
225- ```encoding``` *{string}* The string encoding to use. ```Default: 'utf8'```
226
227Examples:
228```javascript
229const buff = SmartBuffer.fromSize(1024); // Defaults to utf8
230const buff = SmartBuffer.fromSize(1024, 'ascii');
231```
232
233### Class Method: fromOptions(options)
234- ```options``` *{SmartBufferOptions}* The Buffer instance to wrap.
235
236```typescript
237interface SmartBufferOptions {
238    encoding?: BufferEncoding; // Defaults to utf8
239    size?: number; // Defaults to 4096
240    buff?: Buffer;
241}
242```
243
244Examples:
245```javascript
246const buff = SmartBuffer.fromOptions({
247    size: 1024
248};
249const buff = SmartBuffer.fromOptions({
250    size: 1024,
251    encoding: 'utf8'
252});
253const buff = SmartBuffer.fromOptions({
254    encoding: 'utf8'
255});
256
257const someBuff = Buffer.from('some string', 'utf8');
258const buff = SmartBuffer.fromOptions({
259    buffer: someBuff,
260    encoding: 'utf8'
261});
262```
263
264## Integers
265
266### readInt8([offset])
267- ```offset``` *{number}* Optional position to start reading data from. **Default**: ```Auto managed offset```
268- Returns *{number}*
269
270Read a Int8 value.
271
272### buff.readInt16BE([offset])
273### buff.readInt16LE([offset])
274### buff.readUInt16BE([offset])
275### buff.readUInt16LE([offset])
276- ```offset``` *{number}* Optional position to start reading data from. **Default**: ```Auto managed offset```
277- Returns *{number}*
278
279Read a 16 bit integer value.
280
281### buff.readInt32BE([offset])
282### buff.readInt32LE([offset])
283### buff.readUInt32BE([offset])
284### buff.readUInt32LE([offset])
285- ```offset``` *{number}* Optional position to start reading data from. **Default**: ```Auto managed offset```
286- Returns *{number}*
287
288Read a 32 bit integer value.
289
290
291### buff.writeInt8(value[, offset])
292### buff.writeUInt8(value[, offset])
293- ```value``` *{number}* The value to write.
294- ```offset``` *{number}* An optional offset to write this value to. **Default:** ```Auto managed offset```
295- Returns *{this}*
296
297Write a Int8 value.
298
299### buff.insertInt8(value, offset)
300### buff.insertUInt8(value, offset)
301- ```value``` *{number}* The value to insert.
302- ```offset``` *{number}* The offset to insert this data at.
303- Returns *{this}*
304
305Insert a Int8 value.
306
307
308### buff.writeInt16BE(value[, offset])
309### buff.writeInt16LE(value[, offset])
310### buff.writeUInt16BE(value[, offset])
311### buff.writeUInt16LE(value[, offset])
312- ```value``` *{number}* The value to write.
313- ```offset``` *{number}* An optional offset to write this value to. **Default:** ```Auto managed offset```
314- Returns *{this}*
315
316Write a 16 bit integer value.
317
318### buff.insertInt16BE(value, offset)
319### buff.insertInt16LE(value, offset)
320### buff.insertUInt16BE(value, offset)
321### buff.insertUInt16LE(value, offset)
322- ```value``` *{number}* The value to insert.
323- ```offset``` *{number}* The offset to insert this data at.
324- Returns *{this}*
325
326Insert a 16 bit integer value.
327
328
329### buff.writeInt32BE(value[, offset])
330### buff.writeInt32LE(value[, offset])
331### buff.writeUInt32BE(value[, offset])
332### buff.writeUInt32LE(value[, offset])
333- ```value``` *{number}* The value to write.
334- ```offset``` *{number}* An optional offset to write this value to. **Default:** ```Auto managed offset```
335- Returns *{this}*
336
337Write a 32 bit integer value.
338
339### buff.insertInt32BE(value, offset)
340### buff.insertInt32LE(value, offset)
341### buff.insertUInt32BE(value, offset)
342### buff.nsertUInt32LE(value, offset)
343- ```value``` *{number}* The value to insert.
344- ```offset``` *{number}* The offset to insert this data at.
345- Returns *{this}*
346
347Insert a 32 bit integer value.
348
349
350## Floating Point Numbers
351
352### buff.readFloatBE([offset])
353### buff.readFloatLE([offset])
354- ```offset``` *{number}* Optional position to start reading data from. **Default**: ```Auto managed offset```
355- Returns *{number}*
356
357Read a Float value.
358
359### buff.eadDoubleBE([offset])
360### buff.readDoubleLE([offset])
361- ```offset``` *{number}* Optional position to start reading data from. **Default**: ```Auto managed offset```
362- Returns *{number}*
363
364Read a Double value.
365
366
367### buff.writeFloatBE(value[, offset])
368### buff.writeFloatLE(value[, offset])
369- ```value``` *{number}* The value to write.
370- ```offset``` *{number}* An optional offset to write this value to. **Default:** ```Auto managed offset```
371- Returns *{this}*
372
373Write a Float value.
374
375### buff.insertFloatBE(value, offset)
376### buff.insertFloatLE(value, offset)
377- ```value``` *{number}* The value to insert.
378- ```offset``` *{number}* The offset to insert this data at.
379- Returns *{this}*
380
381Insert a Float value.
382
383
384### buff.writeDoubleBE(value[, offset])
385### buff.writeDoubleLE(value[, offset])
386- ```value``` *{number}* The value to write.
387- ```offset``` *{number}* An optional offset to write this value to. **Default:** ```Auto managed offset```
388- Returns *{this}*
389
390Write a Double value.
391
392### buff.insertDoubleBE(value, offset)
393### buff.insertDoubleLE(value, offset)
394- ```value``` *{number}* The value to insert.
395- ```offset``` *{number}* The offset to insert this data at.
396- Returns *{this}*
397
398Insert a Double value.
399
400## Strings
401
402### buff.readString()
403### buff.readString(size[, encoding])
404### buff.readString(encoding)
405- ```size``` *{number}* The number of bytes to read. **Default:** ```Reads to the end of the Buffer.```
406- ```encoding``` *{string}* The string encoding to use. **Default:** ```utf8```.
407
408Read a string value.
409
410Examples:
411```javascript
412const buff = SmartBuffer.fromBuffer(Buffer.from('hello there', 'utf8'));
413buff.readString(); // 'hello there'
414buff.readString(2); // 'he'
415buff.readString(2, 'utf8'); // 'he'
416buff.readString('utf8'); // 'hello there'
417```
418
419### buff.writeString(value)
420### buff.writeString(value[, offset])
421### buff.writeString(value[, encoding])
422### buff.writeString(value[, offset[, encoding]])
423- ```value``` *{string}* The string value to write.
424- ```offset``` *{number}* The offset to write this value to. **Default:** ```Auto managed offset```
425- ```encoding``` *{string}* An optional string encoding to use. **Default:** ```utf8```
426
427Write a string value.
428
429Examples:
430```javascript
431buff.writeString('hello'); // Auto managed offset
432buff.writeString('hello', 2);
433buff.writeString('hello', 'utf8') // Auto managed offset
434buff.writeString('hello', 2, 'utf8');
435```
436
437### buff.insertString(value, offset[, encoding])
438- ```value``` *{string}* The string value to write.
439- ```offset``` *{number}* The offset to write this value to.
440- ```encoding``` *{string}* An optional string encoding to use. **Default:** ```utf8```
441
442Insert a string value.
443
444Examples:
445```javascript
446buff.insertString('hello', 2);
447buff.insertString('hello', 2, 'utf8');
448```
449
450## Null Terminated Strings
451
452### buff.readStringNT()
453### buff.readStringNT(encoding)
454- ```encoding``` *{string}* The string encoding to use. **Default:** ```utf8```.
455
456Read a null terminated string value. (If a null is not found, it will read to the end of the Buffer).
457
458Examples:
459```javascript
460const buff = SmartBuffer.fromBuffer(Buffer.from('hello\0 there', 'utf8'));
461buff.readStringNT(); // 'hello'
462
463// If we called this again:
464buff.readStringNT(); // ' there'
465```
466
467### buff.writeStringNT(value)
468### buff.writeStringNT(value[, offset])
469### buff.writeStringNT(value[, encoding])
470### buff.writeStringNT(value[, offset[, encoding]])
471- ```value``` *{string}* The string value to write.
472- ```offset``` *{number}* The offset to write this value to. **Default:** ```Auto managed offset```
473- ```encoding``` *{string}* An optional string encoding to use. **Default:** ```utf8```
474
475Write a null terminated string value.
476
477Examples:
478```javascript
479buff.writeStringNT('hello'); // Auto managed offset   <Buffer 68 65 6c 6c 6f 00>
480buff.writeStringNT('hello', 2); // <Buffer 00 00 68 65 6c 6c 6f 00>
481buff.writeStringNT('hello', 'utf8') // Auto managed offset
482buff.writeStringNT('hello', 2, 'utf8');
483```
484
485### buff.insertStringNT(value, offset[, encoding])
486- ```value``` *{string}* The string value to write.
487- ```offset``` *{number}* The offset to write this value to.
488- ```encoding``` *{string}* An optional string encoding to use. **Default:** ```utf8```
489
490Insert a null terminated string value.
491
492Examples:
493```javascript
494buff.insertStringNT('hello', 2);
495buff.insertStringNT('hello', 2, 'utf8');
496```
497
498## Buffers
499
500### buff.readBuffer([length])
501- ```length``` *{number}* The number of bytes to read into a Buffer. **Default:** ```Reads to the end of the Buffer```
502
503Read a Buffer of a specified size.
504
505### buff.writeBuffer(value[, offset])
506- ```value``` *{Buffer}* The buffer value to write.
507- ```offset``` *{number}* An optional offset to write the value to. **Default:** ```Auto managed offset```
508
509### buff.insertBuffer(value, offset)
510- ```value``` *{Buffer}* The buffer value to write.
511- ```offset``` *{number}* The offset to write the value to.
512
513
514### buff.readBufferNT()
515
516Read a null terminated Buffer.
517
518### buff.writeBufferNT(value[, offset])
519- ```value``` *{Buffer}* The buffer value to write.
520- ```offset``` *{number}* An optional offset to write the value to. **Default:** ```Auto managed offset```
521
522Write a null terminated Buffer.
523
524
525### buff.insertBufferNT(value, offset)
526- ```value``` *{Buffer}* The buffer value to write.
527- ```offset``` *{number}* The offset to write the value to.
528
529Insert a null terminated Buffer.
530
531
532## Offsets
533
534### buff.readOffset
535### buff.readOffset(offset)
536- ```offset``` *{number}* The new read offset value to set.
537- Returns: ```The current read offset```
538
539Gets or sets the current read offset.
540
541Examples:
542```javascript
543const currentOffset = buff.readOffset; // 5
544
545buff.readOffset = 10;
546
547console.log(buff.readOffset) // 10
548```
549
550### buff.writeOffset
551### buff.writeOffset(offset)
552- ```offset``` *{number}* The new write offset value to set.
553- Returns: ```The current write offset```
554
555Gets or sets the current write offset.
556
557Examples:
558```javascript
559const currentOffset = buff.writeOffset; // 5
560
561buff.writeOffset = 10;
562
563console.log(buff.writeOffset) // 10
564```
565
566### buff.encoding
567### buff.encoding(encoding)
568- ```encoding``` *{string}* The new string encoding to set.
569- Returns: ```The current string encoding```
570
571Gets or sets the current string encoding.
572
573Examples:
574```javascript
575const currentEncoding = buff.encoding; // 'utf8'
576
577buff.encoding = 'ascii';
578
579console.log(buff.encoding) // 'ascii'
580```
581
582## Other
583
584### buff.clear()
585
586Clear and resets the SmartBuffer instance.
587
588### buff.remaining()
589- Returns ```Remaining data left to be read```
590
591Gets the number of remaining bytes to be read.
592
593
594### buff.internalBuffer
595- Returns: *{Buffer}*
596
597Gets the internally managed Buffer (Includes unmanaged data).
598
599Examples:
600```javascript
601const buff = SmartBuffer.fromSize(16);
602buff.writeString('hello');
603console.log(buff.InternalBuffer); // <Buffer 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00>
604```
605
606### buff.toBuffer()
607- Returns: *{Buffer}*
608
609Gets a sliced Buffer instance of the internally managed Buffer. (Only includes managed data)
610
611Examples:
612```javascript
613const buff = SmartBuffer.fromSize(16);
614buff.writeString('hello');
615console.log(buff.toBuffer()); // <Buffer 68 65 6c 6c 6f>
616```
617
618### buff.toString([encoding])
619- ```encoding``` *{string}* The string encoding to use when converting to a string. **Default:** ```utf8```
620- Returns *{string}*
621
622Gets a string representation of all data in the SmartBuffer.
623
624### buff.destroy()
625
626Destroys the SmartBuffer instance.
627
628
629
630## License
631
632This work is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License).