-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathreader.ts
60 lines (50 loc) · 1.4 KB
/
reader.ts
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
import { concatUint8Array, readInt32BE } from "./util.ts";
interface Options {
headerSize?: number;
lengthSize?: number;
}
export default class Reader {
#header!: string;
#length!: number;
private offset = 0;
private chunk: Uint8Array;
private chunkLength: number = 0;
private headerSize: number;
private lengthSize: number;
private decoder = new TextDecoder();
constructor(chunk: Uint8Array, options?: Options) {
this.chunk = chunk;
this.chunkLength = chunk.byteLength;
this.headerSize = options?.headerSize ?? 1;
this.lengthSize = options?.lengthSize ?? 4;
}
get header() {
return this.#header;
}
get length() {
return this.#length;
}
addChunk(chunk: Uint8Array) {
this.chunk = concatUint8Array([this.chunk, chunk]);
this.chunkLength += chunk.byteLength;
}
read(): Uint8Array | null {
if (
this.chunkLength < this.headerSize + this.lengthSize + this.offset
) {
return null;
}
this.#header = this.decoder.decode(
this.chunk.subarray(this.offset, this.offset += this.headerSize),
);
this.#length = readInt32BE(this.chunk, this.offset);
const remaining = this.chunkLength - this.offset;
if (this.#length > remaining) return null;
const result = this.chunk.subarray(
this.offset + this.lengthSize,
this.offset + this.#length,
);
this.offset += this.#length;
return result;
}
}