File: //lib/node_modules/npm/node_modules/readable-stream/lib/internal/streams/buffer_list.js
'use strict'
const { StringPrototypeSlice, SymbolIterator, TypedArrayPrototypeSet, Uint8Array } = require('../../ours/primordials')
const { Buffer } = require('buffer')
const { inspect } = require('../../ours/util')
module.exports = class BufferList {
constructor() {
this.head = null
this.tail = null
this.length = 0
}
push(v) {
const entry = {
data: v,
next: null
}
if (this.length > 0) this.tail.next = entry
else this.head = entry
this.tail = entry
++this.length
}
unshift(v) {
const entry = {
data: v,
next: this.head
}
if (this.length === 0) this.tail = entry
this.head = entry
++this.length
}
shift() {
if (this.length === 0) return
const ret = this.head.data
if (this.length === 1) this.head = this.tail = null
else this.head = this.head.next
--this.length
return ret
}
clear() {
this.head = this.tail = null
this.length = 0
}
join(s) {
if (this.length === 0) return ''
let p = this.head
let ret = '' + p.data
while ((p = p.next) !== null) ret += s + p.data
return ret
}
concat(n) {
if (this.length === 0) return Buffer.alloc(0)
const ret = Buffer.allocUnsafe(n >>> 0)
let p = this.head
let i = 0
while (p) {
TypedArrayPrototypeSet(ret, p.data, i)
i += p.data.length
p = p.next
}
return ret
}
// Consumes a specified amount of bytes or characters from the buffered data.
consume(n, hasStrings) {
const data = this.head.data
if (n < data.length) {
// `slice` is the same for buffers and strings.
const slice = data.slice(0, n)
this.head.data = data.slice(n)
return slice
}
if (n === data.length) {
// First chunk is a perfect match.
return this.shift()
}
// Result spans more than one buffer.
return hasStrings ? this._getString(n) : this._getBuffer(n)
}
first() {
return this.head.data
}
*[SymbolIterator]() {
for (let p = this.head; p; p = p.next) {
yield p.data
}
}
// Consumes a specified amount of characters from the buffered data.
_getString(n) {
let ret = ''
let p = this.head
let c = 0
do {
const str = p.data
if (n > str.length) {
ret += str
n -= str.length
} else {
if (n === str.length) {
ret += str
++c
if (p.next) this.head = p.next
else this.head = this.tail = null
} else {
ret += StringPrototypeSlice(str, 0, n)
this.head = p
p.data = StringPrototypeSlice(str, n)
}
break
}
++c
} while ((p = p.next) !== null)
this.length -= c
return ret
}
// Consumes a specified amount of bytes from the buffered data.
_getBuffer(n) {
const ret = Buffer.allocUnsafe(n)
const retLen = n
let p = this.head
let c = 0
do {
const buf = p.data
if (n > buf.length) {
TypedArrayPrototypeSet(ret, buf, retLen - n)
n -= buf.length
} else {
if (n === buf.length) {
TypedArrayPrototypeSet(ret, buf, retLen - n)
++c
if (p.next) this.head = p.next
else this.head = this.tail = null
} else {
TypedArrayPrototypeSet(ret, new Uint8Array(buf.buffer, buf.byteOffset, n), retLen - n)
this.head = p
p.data = buf.slice(n)
}
break
}
++c
} while ((p = p.next) !== null)
this.length -= c
return ret
}
// Make sure the linked list only shows the minimal necessary information.
[Symbol.for('nodejs.util.inspect.custom')](_, options) {
return inspect(this, {
...options,
// Only inspect one level.
depth: 0,
// It should not recurse.
customInspect: false
})
}
}