-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinary_reader.ts
176 lines (154 loc) · 5.3 KB
/
binary_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
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
export class BinaryReader {
#position = 0;
private dataView: DataView;
constructor(private buffer: Uint8Array) {
this.dataView = new DataView(
this.buffer.buffer,
this.buffer.byteOffset,
this.buffer.byteLength,
);
}
/**
* Rewinds the buffer/DataView byteOffset by numBytes bytes.
* @param numBytes The number of bytes to rewind.
*/
rewind(numBytes: number): void {
if (this.#position - numBytes < 0) {
return;
}
this.#position -= numBytes;
}
/**
* Moves the buffer/DataView byteOffset to the specified position.
* @param position The position to move the buffer/DataView to.
*/
seek(position: number): void {
if (position > this.buffer.length) {
return;
}
this.#position = position;
}
/**
* Returns the current position in the buffer.
*/
get position(): number {
return this.#position;
}
/**
* Reads `length` unsigned 8-bit integers from the current position in the buffer.
* @param length The number of bytes to read.
*/
readBytes(length: number): Uint8Array {
if (length === 0) {
return new Uint8Array(0);
}
const buffer = new Uint8Array(length);
for (let i = 0; i < length; i++) {
buffer[i] = this.readUint8();
}
return buffer;
}
/**
* Reads a signed 8-bit integer (byte) from the current position in the buffer.
*/
readInt8(): number {
const data = this.dataView.getInt8(this.#position);
this.#position += 1;
return data;
}
/**
* Reads an unsigned 8-bit integer (byte) from the current position in the buffer.
*/
readUint8(): number {
const data = this.dataView.getUint8(this.#position);
this.#position += 1;
return data;
}
/**
* Reads a signed 16-bit integer (short) from the current position in the buffer.
* @param littleEndian Indicates if the 16-bit integer is stored in little- or big-endian. Reads big-endian if `false` or `undefined`.
*/
readInt16(littleEndian?: boolean): number {
const data = this.dataView.getInt16(this.#position, littleEndian);
this.#position += 2;
return data;
}
/**
* Reads an unsigned 16-bit integer (unsigned short) from the current position in the buffer.
* @param littleEndian Indicates if the 16-bit integer is stored in little- or big-endian. Reads big-endian if `false` or `undefined`.
*/
readUint16(littleEndian?: boolean): number {
const data = this.dataView.getUint16(this.#position, littleEndian);
this.#position += 2;
return data;
}
/**
* Reads a signed 32-bit integer (long) from the current position in the buffer.
* @param littleEndian Indicates if the 32-bit integer is stored in little- or big-endian. Reads big-endian if `false` or `undefined`.
*/
readInt32(littleEndian?: boolean): number {
const data = this.dataView.getInt32(this.#position, littleEndian);
this.#position += 4;
return data;
}
/**
* Reads an unsigned 32-bit integer (unsigned long) from the current position in the buffer.
* @param littleEndian Indicates if the 32-bit integer is stored in little- or big-endian. Reads big-endian if `false` or `undefined`.
*/
readUint32(littleEndian?: boolean): number {
const data = this.dataView.getUint32(this.#position, littleEndian);
this.#position += 4;
return data;
}
/**
* Reads a signed 32-bit float (float) from the current position in the buffer.
* @param littleEndian Indicates if the 32-bit float is stored in little- or big-endian. Reads big-endian if `false` or `undefined`.
*/
readFloat32(littleEndian?: boolean): number {
let data = this.dataView.getFloat32(this.#position, littleEndian);
this.#position += 4;
return data;
}
/**
* Reads a signed 64-bit float (double) from the current position in the buffer.
* @param littleEndian Indicates if the 64-bit float is stored in little- or big-endian. Reads big-endian if `false` or `undefined`.
*/
readFloat64(littleEndian?: boolean): number {
let data = this.dataView.getFloat64(this.#position, littleEndian);
this.#position += 8;
return data;
}
/**
* Reads a signed 64-bit integer (long long) from the current position in the buffer.
* @param littleEndian Indicates if the 64-bit integer is stored in little- or big-endian. Reads big-endian if `false` or `undefined`.
*/
readBigInt64(littleEndian?: boolean): bigint {
let data = this.dataView.getBigInt64(this.#position, littleEndian);
this.#position += 8;
return data;
}
/**
* Reads an unsigned 64-bit integer (unsigned long long) from the current position in the buffer.
* @param littleEndian Indicates if the 64-bit integer is stored in little- or big-endian. Reads big-endian if `false` or `undefined`.
*/
readBigUint64(littleEndian?: boolean): bigint {
let data = this.dataView.getBigUint64(this.#position, littleEndian);
this.#position += 8;
return data;
}
/**
* Reads a single utf8 encoded character from the current position in the buffer.
*/
readChar(): string {
return this.readString(1);
}
/**
* Reads a utf8 encoded string from the current position in the buffer.
* @param length The length of the string.
*/
readString(length: number): string {
const bytes = this.readBytes(length);
const decoder = new TextDecoder();
return decoder.decode(bytes);
}
}