Skip to content

Commit e9eda95

Browse files
authored
feat: Added prepend and getBuffers methods. (#154)
* feat: Added prepend and getBuffers methods. * chore: Use common method to add and prepend. * chore: Avoid internal choices.
1 parent 1585dec commit e9eda95

File tree

4 files changed

+138
-8
lines changed

4 files changed

+138
-8
lines changed

BufferList.d.ts

+13
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ interface BufferList {
4545

4646
append(buffer: BufferListAcceptedTypes): this;
4747

48+
/**
49+
* Adds an additional buffer or BufferList at the beginning of the internal list.
50+
* this is returned so it can be chained.
51+
*
52+
* @param buffer
53+
*/
54+
prepend(buffer: BufferListAcceptedTypes): this;
55+
4856
/**
4957
* Will return the byte at the specified index.
5058
* @param index
@@ -169,6 +177,11 @@ interface BufferList {
169177
encoding?: string
170178
): number;
171179

180+
/**
181+
* Will return the internal list of buffers.
182+
*/
183+
getBuffers(): Buffer[];
184+
172185
/**
173186
* All of the standard byte-reading methods of the Buffer interface are implemented and will operate across internal Buffer boundaries transparently.
174187
* See the [Buffer](http://nodejs.org/docs/latest/api/buffer.html) documentation for how these work.

BufferList.js

+28-7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ BufferList.prototype._reverseOffset = function (blOffset) {
5353
return offset
5454
}
5555

56+
BufferList.prototype.getBuffers = function getBuffers () {
57+
return this._bufs
58+
}
59+
5660
BufferList.prototype.get = function get (index) {
5761
if (index > this.length || index < 0) {
5862
return undefined
@@ -223,21 +227,33 @@ BufferList.prototype.duplicate = function duplicate () {
223227
}
224228

225229
BufferList.prototype.append = function append (buf) {
230+
return this._attach(buf, BufferList.prototype._appendBuffer)
231+
}
232+
233+
BufferList.prototype.prepend = function prepend (buf) {
234+
return this._attach(buf, BufferList.prototype._prependBuffer, true)
235+
}
236+
237+
BufferList.prototype._attach = function _attach (buf, attacher, prepend) {
226238
if (buf == null) {
227239
return this
228240
}
229241

230242
if (buf.buffer) {
231-
// append a view of the underlying ArrayBuffer
232-
this._appendBuffer(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength))
243+
// append/prepend a view of the underlying ArrayBuffer
244+
attacher.call(this, Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength))
233245
} else if (Array.isArray(buf)) {
234-
for (let i = 0; i < buf.length; i++) {
235-
this.append(buf[i])
246+
const [starting, modifier] = prepend ? [buf.length - 1, -1] : [0, 1]
247+
248+
for (let i = starting; i >= 0 && i < buf.length; i += modifier) {
249+
this._attach(buf[i], attacher, prepend)
236250
}
237251
} else if (this._isBufferList(buf)) {
238252
// unwrap argument into individual BufferLists
239-
for (let i = 0; i < buf._bufs.length; i++) {
240-
this.append(buf._bufs[i])
253+
const [starting, modifier] = prepend ? [buf._bufs.length - 1, -1] : [0, 1]
254+
255+
for (let i = starting; i >= 0 && i < buf._bufs.length; i += modifier) {
256+
this._attach(buf._bufs[i], attacher, prepend)
241257
}
242258
} else {
243259
// coerce number arguments to strings, since Buffer(number) does
@@ -246,7 +262,7 @@ BufferList.prototype.append = function append (buf) {
246262
buf = buf.toString()
247263
}
248264

249-
this._appendBuffer(Buffer.from(buf))
265+
attacher.call(this, Buffer.from(buf))
250266
}
251267

252268
return this
@@ -257,6 +273,11 @@ BufferList.prototype._appendBuffer = function appendBuffer (buf) {
257273
this.length += buf.length
258274
}
259275

276+
BufferList.prototype._prependBuffer = function prependBuffer (buf) {
277+
this._bufs.unshift(buf)
278+
this.length += buf.length
279+
}
280+
260281
BufferList.prototype.indexOf = function (search, offset, encoding) {
261282
if (encoding === undefined && typeof offset === 'string') {
262283
encoding = offset

README.md

+13-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ bl.pipe(fs.createWriteStream('gibberish.txt'))
9090
* <a href="#isBufferList"><code><b>BufferList.isBufferList(obj)</b></code></a>
9191
* <a href="#length"><code>bl.<b>length</b></code></a>
9292
* <a href="#append"><code>bl.<b>append(buffer)</b></code></a>
93+
* <a href="#prepend"><code>bl.<b>append(buffer)</b></code></a>
9394
* <a href="#get"><code>bl.<b>get(index)</b></code></a>
9495
* <a href="#indexOf"><code>bl.<b>indexOf(value[, byteOffset][, encoding])</b></code></a>
9596
* <a href="#slice"><code>bl.<b>slice([ start[, end ] ])</b></code></a>
@@ -100,7 +101,8 @@ bl.pipe(fs.createWriteStream('gibberish.txt'))
100101
* <a href="#toString"><code>bl.<b>toString([encoding, [ start, [ end ]]])</b></code></a>
101102
* <a href="#readXX"><code>bl.<b>readDoubleBE()</b></code>, <code>bl.<b>readDoubleLE()</b></code>, <code>bl.<b>readFloatBE()</b></code>, <code>bl.<b>readFloatLE()</b></code>, <code>bl.<b>readBigInt64BE()</b></code>, <code>bl.<b>readBigInt64LE()</b></code>, <code>bl.<b>readBigUInt64BE()</b></code>, <code>bl.<b>readBigUInt64LE()</b></code>, <code>bl.<b>readInt32BE()</b></code>, <code>bl.<b>readInt32LE()</b></code>, <code>bl.<b>readUInt32BE()</b></code>, <code>bl.<b>readUInt32LE()</b></code>, <code>bl.<b>readInt16BE()</b></code>, <code>bl.<b>readInt16LE()</b></code>, <code>bl.<b>readUInt16BE()</b></code>, <code>bl.<b>readUInt16LE()</b></code>, <code>bl.<b>readInt8()</b></code>, <code>bl.<b>readUInt8()</b></code></a>
102103
* <a href="#ctorStream"><code><b>new BufferListStream([ callback ])</b></code></a>
103-
104+
* <a href="#getBuffers"><code>bl.<b>getBuffers()</b></code></a>
105+
104106
--------------------------------------------------------
105107
<a name="ctor"></a>
106108
### new BufferList([ Buffer | Buffer array | BufferList | BufferList array | String ])
@@ -135,6 +137,11 @@ Get the length of the list in bytes. This is the sum of the lengths of all of th
135137
### bl.append(Buffer | Buffer array | BufferList | BufferList array | String)
136138
`append(buffer)` adds an additional buffer or BufferList to the internal list. `this` is returned so it can be chained.
137139

140+
--------------------------------------------------------
141+
<a name="prepend"></a>
142+
### bl.prepend(Buffer | Buffer array | BufferList | BufferList array | String)
143+
`prepend(buffer)` adds an additional buffer or BufferList at the beginning of the internal list. `this` is returned so it can be chained.
144+
138145
--------------------------------------------------------
139146
<a name="get"></a>
140147
### bl.get(index)
@@ -230,6 +237,11 @@ const BufferListStream = require('bl')
230237
```
231238

232239
--------------------------------------------------------
240+
<a name="getBuffers"></a>
241+
### bl.getBuffers()
242+
243+
`getBuffers()` returns the internal list of buffers.
244+
233245

234246
## Contributors
235247

test/test.js

+84
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,78 @@ tape('append chainable (test results)', function (t) {
249249
t.end()
250250
})
251251

252+
tape('prepend accepts arrays of Buffers', function (t) {
253+
const bl = new BufferListStream()
254+
255+
bl.prepend(Buffer.from('abc'))
256+
bl.prepend([Buffer.from('def')])
257+
bl.prepend([Buffer.from('ghi'), Buffer.from('jkl')])
258+
bl.prepend([Buffer.from('mnop'), Buffer.from('qrstu'), Buffer.from('vwxyz')])
259+
t.equal(bl.length, 26)
260+
t.equal(bl.slice().toString('ascii'), 'mnopqrstuvwxyzghijkldefabc')
261+
262+
t.end()
263+
})
264+
265+
tape('prepend accepts arrays of Uint8Arrays', function (t) {
266+
const bl = new BufferListStream()
267+
268+
bl.prepend(new Uint8Array([97, 98, 99]))
269+
bl.prepend([Uint8Array.from([100, 101, 102])])
270+
bl.prepend([new Uint8Array([103, 104, 105]), new Uint8Array([106, 107, 108])])
271+
bl.prepend([new Uint8Array([109, 110, 111, 112]), new Uint8Array([113, 114, 115, 116, 117]), new Uint8Array([118, 119, 120, 121, 122])])
272+
t.equal(bl.length, 26)
273+
t.equal(bl.slice().toString('ascii'), 'mnopqrstuvwxyzghijkldefabc')
274+
275+
t.end()
276+
})
277+
278+
tape('prepend accepts arrays of BufferLists', function (t) {
279+
const bl = new BufferListStream()
280+
281+
bl.prepend(Buffer.from('abc'))
282+
bl.prepend([new BufferListStream('def')])
283+
bl.prepend(
284+
new BufferListStream([Buffer.from('ghi'), new BufferListStream('jkl')])
285+
)
286+
bl.prepend([
287+
Buffer.from('mnop'),
288+
new BufferListStream([Buffer.from('qrstu'), Buffer.from('vwxyz')])
289+
])
290+
t.equal(bl.length, 26)
291+
t.equal(bl.slice().toString('ascii'), 'mnopqrstuvwxyzghijkldefabc')
292+
293+
t.end()
294+
})
295+
296+
tape('prepend chainable', function (t) {
297+
const bl = new BufferListStream()
298+
299+
t.ok(bl.prepend(Buffer.from('abcd')) === bl)
300+
t.ok(bl.prepend([Buffer.from('abcd')]) === bl)
301+
t.ok(bl.prepend(new BufferListStream(Buffer.from('abcd'))) === bl)
302+
t.ok(bl.prepend([new BufferListStream(Buffer.from('abcd'))]) === bl)
303+
304+
t.end()
305+
})
306+
307+
tape('prepend chainable (test results)', function (t) {
308+
const bl = new BufferListStream('abc')
309+
.prepend([new BufferListStream('def')])
310+
.prepend(
311+
new BufferListStream([Buffer.from('ghi'), new BufferListStream('jkl')])
312+
)
313+
.prepend([
314+
Buffer.from('mnop'),
315+
new BufferListStream([Buffer.from('qrstu'), Buffer.from('vwxyz')])
316+
])
317+
318+
t.equal(bl.length, 26)
319+
t.equal(bl.slice().toString('ascii'), 'mnopqrstuvwxyzghijkldefabc')
320+
321+
t.end()
322+
})
323+
252324
tape('consuming from multiple buffers', function (t) {
253325
const bl = new BufferListStream()
254326

@@ -555,6 +627,18 @@ tape('test toString encoding', function (t) {
555627
t.end()
556628
})
557629

630+
tape('getBuffers', function (t) {
631+
const bl = new BufferListStream([Buffer.from('First'), Buffer.from('Second'), Buffer.from('Third')])
632+
633+
t.deepEquals(
634+
bl.getBuffers(),
635+
// @ts-ignore
636+
bl._bufs
637+
)
638+
639+
t.end()
640+
})
641+
558642
tape('uninitialized memory', function (t) {
559643
const secret = crypto.randomBytes(256)
560644
for (let i = 0; i < 1e6; i++) {

0 commit comments

Comments
 (0)