-
Notifications
You must be signed in to change notification settings - Fork 2
/
dataBuffer.js
86 lines (72 loc) · 1.73 KB
/
dataBuffer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
A wrapper around ArrayBuffers and DataView, as we don't
actually know how much space we need, and we also write
to our data sequentially, so we should be able to just
ask for a write, without specifying an offset explicitly.
*/
class DataBuffer
{
constructor(blockSize)
{
// data blocks making up the buffer
this.blocks = [];
// size of new blocks
this.blockSize = blockSize;
// add the initial block to start writing into
this.#addBlock();
}
#addBlock()
{
let newBlock =
{
view: new DataView(new ArrayBuffer(this.blockSize)),
offset: 0
};
this.blocks.push(newBlock);
return newBlock;
}
// returns a DataView of size `bytesNeeded` starting at the
// current position in the DataBuffer
getChunk(bytesNeeded)
{
let block = this.#getBlockFor(bytesNeeded);
let start = block.offset;
block.offset += bytesNeeded;
return new DataView(block.view.buffer, start, bytesNeeded);
}
getBufferSize()
{
return this.blocks.reduce((acc, block) => {
return acc + block.offset;
}, 0);
}
// returns an ArrayBuffer of the final result
getFullBuffer()
{
const size = this.getBufferSize();
const result = new Uint8Array(size);
this.blocks.reduce((offset, block) => {
result.set(
// convert DataArray.buffer (ArrayBuffer) to Uint8Array,
// then slice by the size of the used buffer
new Uint8Array(block.view.buffer)
.slice(0, block.offset),
offset);
return offset + block.offset;
}, 0);
return result.buffer;
}
#lastBlock()
{
return this.blocks[this.blocks.length - 1];
}
#getBlockFor(bytesNeeded)
{
let lastBlock = this.#lastBlock();
if (lastBlock.offset + bytesNeeded >= lastBlock.view.byteLength)
{
lastBlock = this.#addBlock();
}
return lastBlock;
}
}