@kikuchan/binary-reader 0.1.0-alpha.2 → 0.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,`__esModule`,{value:!0});var e=class{#e;#t;#n;#r={};constructor(e,t){ArrayBuffer.isView(e)?this.#e=new DataView(e.buffer,e.byteOffset,e.byteLength):this.#e=new DataView(e),this.#t=0,this.#n=t?.littleEndian}get position(){return this.#t}get size(){return this.#e.byteLength}get remain(){return this.size-this.position}eof(){return this.remain<=0}seek(e){if(typeof e==`string`){let t=this.#r[e];if(t===void 0)throw Error(`seek: no such bookmark`);e=t}return typeof e==`number`&&(this.#t=Math.min(Math.max(e,0),this.size)),this}bookmark(e){return this.#r[e]=this.#t,this}rewind(){return this.seek(0)}skip(e){return this.seek(this.#t+(e??1))}align(e){if(!(e>0))throw RangeError(`align(n): n must be > 0`);return this.position%e?this.skip(e-this.position%e):this}peekBytes(e){e===void 0&&(e=this.remain);let t=this.#e.byteOffset+this.position;return new Uint8Array(this.#e.buffer.slice(t,t+e))}readUint8(){let e=this.#e.getUint8(this.position);return this.skip(1),e}readUint16(e){let t=this.#e.getUint16(this.position,e??this.#n);return this.skip(2),t}readUint16le(){return this.readUint16(!0)}readUint16be(){return this.readUint16(!1)}readUint32(e){let t=this.#e.getUint32(this.position,e??this.#n);return this.skip(4),t}readUint32le(){return this.readUint32(!0)}readUint32be(){return this.readUint32(!1)}readUint64(e){let t=this.#e.getBigUint64(this.position,e??this.#n);return this.skip(8),t}readUint64le(){return this.readUint64(!0)}readUint64be(){return this.readUint64(!1)}readInt8(){let e=this.#e.getInt8(this.position);return this.skip(1),e}readInt16(e){let t=this.#e.getInt16(this.position,e??this.#n);return this.skip(2),t}readInt16le(){return this.readInt16(!0)}readInt16be(){return this.readInt16(!1)}readInt32(e){let t=this.#e.getInt32(this.position,e??this.#n);return this.skip(4),t}readInt32le(){return this.readInt32(!0)}readInt32be(){return this.readInt32(!1)}readInt64(e){let t=this.#e.getBigInt64(this.position,e??this.#n);return this.skip(8),t}readInt64le(){return this.readInt64(!0)}readInt64be(){return this.readInt64(!1)}readFloat16(e){let t=this.#e.getFloat16(this.position,e??this.#n);return this.skip(2),t}readFloat16le(){return this.readFloat16(!0)}readFloat16be(){return this.readFloat16(!1)}readFloat32(e){let t=this.#e.getFloat32(this.position,e??this.#n);return this.skip(4),t}readFloat32le(){return this.readFloat32(!0)}readFloat32be(){return this.readFloat32(!1)}readFloat64(e){let t=this.#e.getFloat64(this.position,e??this.#n);return this.skip(8),t}readFloat64le(){return this.readFloat64(!0)}readFloat64be(){return this.readFloat64(!1)}#i(){let e=this.remain;for(let t=0;t<e;t++)if(this.#e.getUint8(this.position+t)===0)return t}readBytes(e){let t=this.peekBytes(e);return t&&this.skip(t.byteLength),t}readString(e,t){let n=this.remain,r=0;if(e===void 0&&(e=this.#i(),r=1),e===void 0||n<e)return;let i=this.peekBytes(e);try{if(typeof t==`function`){let n=t(i);return this.skip(e+r),n}else{let n=new TextDecoder(t??`utf-8`,{fatal:!0}).decode(i);return this.skip(e+r),n}}catch{return}}},t=e;exports.BinaryReader=e,exports.default=t;
package/index.d.cts ADDED
@@ -0,0 +1,55 @@
1
+ //#region src/index.d.ts
2
+ type BinaryLike = Uint8Array | Uint8ClampedArray | ArrayBufferLike | DataView;
3
+ type Options = {
4
+ littleEndian?: boolean;
5
+ };
6
+ declare class BinaryReader {
7
+ #private;
8
+ constructor(u8: BinaryLike, opts?: Options);
9
+ get position(): number;
10
+ get size(): number;
11
+ get remain(): number;
12
+ eof(): boolean;
13
+ seek(n: number | string): this;
14
+ bookmark(s: string): this;
15
+ rewind(): this;
16
+ skip(n?: number): this;
17
+ align(n: number): this;
18
+ peekBytes(n?: number): Uint8Array<ArrayBuffer | SharedArrayBuffer>;
19
+ readUint8(): number;
20
+ readUint16(littleEndian?: boolean): number;
21
+ readUint16le(): number;
22
+ readUint16be(): number;
23
+ readUint32(littleEndian?: boolean): number;
24
+ readUint32le(): number;
25
+ readUint32be(): number;
26
+ readUint64(littleEndian?: boolean): bigint;
27
+ readUint64le(): bigint;
28
+ readUint64be(): bigint;
29
+ readInt8(): number;
30
+ readInt16(littleEndian?: boolean): number;
31
+ readInt16le(): number;
32
+ readInt16be(): number;
33
+ readInt32(littleEndian?: boolean): number;
34
+ readInt32le(): number;
35
+ readInt32be(): number;
36
+ readInt64(littleEndian?: boolean): bigint;
37
+ readInt64le(): bigint;
38
+ readInt64be(): bigint;
39
+ readFloat16(littleEndian?: boolean): number;
40
+ readFloat16le(): number;
41
+ readFloat16be(): number;
42
+ readFloat32(littleEndian?: boolean): number;
43
+ readFloat32le(): number;
44
+ readFloat32be(): number;
45
+ readFloat64(littleEndian?: boolean): number;
46
+ readFloat64le(): number;
47
+ readFloat64be(): number;
48
+ readBytes(n?: number): Uint8Array<ArrayBuffer | SharedArrayBuffer>;
49
+ /**
50
+ * @returns string. undefined on oversize or EOF.
51
+ */
52
+ readString(len?: number, encoding?: string | ((u8: Uint8Array) => string)): string | undefined;
53
+ }
54
+ //#endregion
55
+ export { BinaryLike, BinaryReader, BinaryReader as default };
package/index.d.ts ADDED
@@ -0,0 +1,55 @@
1
+ //#region src/index.d.ts
2
+ type BinaryLike = Uint8Array | Uint8ClampedArray | ArrayBufferLike | DataView;
3
+ type Options = {
4
+ littleEndian?: boolean;
5
+ };
6
+ declare class BinaryReader {
7
+ #private;
8
+ constructor(u8: BinaryLike, opts?: Options);
9
+ get position(): number;
10
+ get size(): number;
11
+ get remain(): number;
12
+ eof(): boolean;
13
+ seek(n: number | string): this;
14
+ bookmark(s: string): this;
15
+ rewind(): this;
16
+ skip(n?: number): this;
17
+ align(n: number): this;
18
+ peekBytes(n?: number): Uint8Array<ArrayBuffer | SharedArrayBuffer>;
19
+ readUint8(): number;
20
+ readUint16(littleEndian?: boolean): number;
21
+ readUint16le(): number;
22
+ readUint16be(): number;
23
+ readUint32(littleEndian?: boolean): number;
24
+ readUint32le(): number;
25
+ readUint32be(): number;
26
+ readUint64(littleEndian?: boolean): bigint;
27
+ readUint64le(): bigint;
28
+ readUint64be(): bigint;
29
+ readInt8(): number;
30
+ readInt16(littleEndian?: boolean): number;
31
+ readInt16le(): number;
32
+ readInt16be(): number;
33
+ readInt32(littleEndian?: boolean): number;
34
+ readInt32le(): number;
35
+ readInt32be(): number;
36
+ readInt64(littleEndian?: boolean): bigint;
37
+ readInt64le(): bigint;
38
+ readInt64be(): bigint;
39
+ readFloat16(littleEndian?: boolean): number;
40
+ readFloat16le(): number;
41
+ readFloat16be(): number;
42
+ readFloat32(littleEndian?: boolean): number;
43
+ readFloat32le(): number;
44
+ readFloat32be(): number;
45
+ readFloat64(littleEndian?: boolean): number;
46
+ readFloat64le(): number;
47
+ readFloat64be(): number;
48
+ readBytes(n?: number): Uint8Array<ArrayBuffer | SharedArrayBuffer>;
49
+ /**
50
+ * @returns string. undefined on oversize or EOF.
51
+ */
52
+ readString(len?: number, encoding?: string | ((u8: Uint8Array) => string)): string | undefined;
53
+ }
54
+ //#endregion
55
+ export { BinaryLike, BinaryReader, BinaryReader as default };
package/index.js ADDED
@@ -0,0 +1 @@
1
+ var e=class{#e;#t;#n;#r={};constructor(e,t){ArrayBuffer.isView(e)?this.#e=new DataView(e.buffer,e.byteOffset,e.byteLength):this.#e=new DataView(e),this.#t=0,this.#n=t?.littleEndian}get position(){return this.#t}get size(){return this.#e.byteLength}get remain(){return this.size-this.position}eof(){return this.remain<=0}seek(e){if(typeof e==`string`){let t=this.#r[e];if(t===void 0)throw Error(`seek: no such bookmark`);e=t}return typeof e==`number`&&(this.#t=Math.min(Math.max(e,0),this.size)),this}bookmark(e){return this.#r[e]=this.#t,this}rewind(){return this.seek(0)}skip(e){return this.seek(this.#t+(e??1))}align(e){if(!(e>0))throw RangeError(`align(n): n must be > 0`);return this.position%e?this.skip(e-this.position%e):this}peekBytes(e){e===void 0&&(e=this.remain);let t=this.#e.byteOffset+this.position;return new Uint8Array(this.#e.buffer.slice(t,t+e))}readUint8(){let e=this.#e.getUint8(this.position);return this.skip(1),e}readUint16(e){let t=this.#e.getUint16(this.position,e??this.#n);return this.skip(2),t}readUint16le(){return this.readUint16(!0)}readUint16be(){return this.readUint16(!1)}readUint32(e){let t=this.#e.getUint32(this.position,e??this.#n);return this.skip(4),t}readUint32le(){return this.readUint32(!0)}readUint32be(){return this.readUint32(!1)}readUint64(e){let t=this.#e.getBigUint64(this.position,e??this.#n);return this.skip(8),t}readUint64le(){return this.readUint64(!0)}readUint64be(){return this.readUint64(!1)}readInt8(){let e=this.#e.getInt8(this.position);return this.skip(1),e}readInt16(e){let t=this.#e.getInt16(this.position,e??this.#n);return this.skip(2),t}readInt16le(){return this.readInt16(!0)}readInt16be(){return this.readInt16(!1)}readInt32(e){let t=this.#e.getInt32(this.position,e??this.#n);return this.skip(4),t}readInt32le(){return this.readInt32(!0)}readInt32be(){return this.readInt32(!1)}readInt64(e){let t=this.#e.getBigInt64(this.position,e??this.#n);return this.skip(8),t}readInt64le(){return this.readInt64(!0)}readInt64be(){return this.readInt64(!1)}readFloat16(e){let t=this.#e.getFloat16(this.position,e??this.#n);return this.skip(2),t}readFloat16le(){return this.readFloat16(!0)}readFloat16be(){return this.readFloat16(!1)}readFloat32(e){let t=this.#e.getFloat32(this.position,e??this.#n);return this.skip(4),t}readFloat32le(){return this.readFloat32(!0)}readFloat32be(){return this.readFloat32(!1)}readFloat64(e){let t=this.#e.getFloat64(this.position,e??this.#n);return this.skip(8),t}readFloat64le(){return this.readFloat64(!0)}readFloat64be(){return this.readFloat64(!1)}#i(){let e=this.remain;for(let t=0;t<e;t++)if(this.#e.getUint8(this.position+t)===0)return t}readBytes(e){let t=this.peekBytes(e);return t&&this.skip(t.byteLength),t}readString(e,t){let n=this.remain,r=0;if(e===void 0&&(e=this.#i(),r=1),e===void 0||n<e)return;let i=this.peekBytes(e);try{if(typeof t==`function`){let n=t(i);return this.skip(e+r),n}else{let n=new TextDecoder(t??`utf-8`,{fatal:!0}).decode(i);return this.skip(e+r),n}}catch{return}}},t=e;export{e as BinaryReader,t as default};
package/package.json CHANGED
@@ -4,13 +4,21 @@
4
4
  "keywords": [
5
5
  "binary-reader"
6
6
  ],
7
- "version": "0.1.0-alpha.2",
7
+ "version": "0.1.0-alpha.4",
8
8
  "type": "module",
9
- "main": "./src/index.ts",
9
+ "main": "./index.js",
10
10
  "author": "kikuchan <kikuchan98@gmail.com>",
11
11
  "homepage": "https://github.com/kikuchan/utils-on-npm#readme",
12
12
  "license": "MIT",
13
- "scripts": {
14
- "build": "tsdown"
13
+ "types": "./index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./index.d.ts",
17
+ "import": "./index.js",
18
+ "require": "./index.cjs"
19
+ }
20
+ },
21
+ "repository": {
22
+ "url": "https://github.com/kikuchan/utils-on-npm"
15
23
  }
16
24
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 kikuchan
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/src/index.ts DELETED
@@ -1,268 +0,0 @@
1
- export type BinaryLike = Uint8Array | Uint8ClampedArray | ArrayBufferLike | DataView;
2
-
3
- type Options = {
4
- littleEndian?: boolean;
5
- };
6
- export class BinaryReader {
7
- #view: DataView;
8
- #pos: number;
9
- #littleEndian: boolean | undefined;
10
- #bookmarks: Record<string, number> = {};
11
-
12
- constructor(u8: BinaryLike, opts?: Options) {
13
- if (!ArrayBuffer.isView(u8)) {
14
- this.#view = new DataView(u8);
15
- } else {
16
- this.#view = new DataView(u8.buffer, u8.byteOffset, u8.byteLength);
17
- }
18
- this.#pos = 0;
19
- this.#littleEndian = opts?.littleEndian;
20
- }
21
-
22
- get position() {
23
- return this.#pos;
24
- }
25
-
26
- get size() {
27
- return this.#view.byteLength;
28
- }
29
-
30
- get remain() {
31
- return this.size - this.position;
32
- }
33
-
34
- eof() {
35
- return this.remain <= 0;
36
- }
37
-
38
- seek(n: number | string) {
39
- if (typeof n === 'string') {
40
- const b = this.#bookmarks[n];
41
- if (typeof b === 'undefined') throw new Error('seek: no such bookmark');
42
- n = b;
43
- }
44
- if (typeof n === 'number') {
45
- this.#pos = Math.min(Math.max(n, 0), this.size);
46
- }
47
- return this;
48
- }
49
-
50
- bookmark(s: string) {
51
- this.#bookmarks[s] = this.#pos;
52
- return this;
53
- }
54
-
55
- rewind() {
56
- return this.seek(0);
57
- }
58
-
59
- skip(n?: number) {
60
- return this.seek(this.#pos + (n ?? 1));
61
- }
62
-
63
- align(n: number) {
64
- if (!(n > 0)) throw new RangeError('align(n): n must be > 0');
65
- if (this.position % n) {
66
- return this.skip(n - (this.position % n));
67
- }
68
- return this;
69
- }
70
-
71
- peekBytes(n?: number) {
72
- if (n === undefined) n = this.remain;
73
-
74
- const pos = this.#view.byteOffset + this.position;
75
- return new Uint8Array(this.#view.buffer.slice(pos, pos + n));
76
- }
77
-
78
- readUint8() {
79
- const r = this.#view.getUint8(this.position);
80
- this.skip(1);
81
- return r;
82
- }
83
-
84
- readUint16(littleEndian?: boolean) {
85
- const r = this.#view.getUint16(this.position, littleEndian ?? this.#littleEndian);
86
- this.skip(2);
87
- return r;
88
- }
89
-
90
- readUint16le() {
91
- return this.readUint16(true);
92
- }
93
-
94
- readUint16be() {
95
- return this.readUint16(false);
96
- }
97
-
98
- readUint32(littleEndian?: boolean) {
99
- const r = this.#view.getUint32(this.position, littleEndian ?? this.#littleEndian);
100
- this.skip(4);
101
- return r;
102
- }
103
-
104
- readUint32le() {
105
- return this.readUint32(true);
106
- }
107
-
108
- readUint32be() {
109
- return this.readUint32(false);
110
- }
111
-
112
- readUint64(littleEndian?: boolean) {
113
- const r = this.#view.getBigUint64(this.position, littleEndian ?? this.#littleEndian);
114
- this.skip(8);
115
- return r;
116
- }
117
-
118
- readUint64le() {
119
- return this.readUint64(true);
120
- }
121
-
122
- readUint64be() {
123
- return this.readUint64(false);
124
- }
125
-
126
- readInt8() {
127
- const r = this.#view.getInt8(this.position);
128
- this.skip(1);
129
- return r;
130
- }
131
-
132
- readInt16(littleEndian?: boolean) {
133
- const r = this.#view.getInt16(this.position, littleEndian ?? this.#littleEndian);
134
- this.skip(2);
135
- return r;
136
- }
137
-
138
- readInt16le() {
139
- return this.readInt16(true);
140
- }
141
-
142
- readInt16be() {
143
- return this.readInt16(false);
144
- }
145
-
146
- readInt32(littleEndian?: boolean) {
147
- const r = this.#view.getInt32(this.position, littleEndian ?? this.#littleEndian);
148
- this.skip(4);
149
- return r;
150
- }
151
-
152
- readInt32le() {
153
- return this.readInt32(true);
154
- }
155
-
156
- readInt32be() {
157
- return this.readInt32(false);
158
- }
159
-
160
- readInt64(littleEndian?: boolean) {
161
- const r = this.#view.getBigInt64(this.position, littleEndian ?? this.#littleEndian);
162
- this.skip(8);
163
- return r;
164
- }
165
-
166
- readInt64le() {
167
- return this.readInt64(true);
168
- }
169
-
170
- readInt64be() {
171
- return this.readInt64(false);
172
- }
173
-
174
- readFloat16(littleEndian?: boolean) {
175
- const r = this.#view.getFloat16(this.position, littleEndian ?? this.#littleEndian);
176
- this.skip(2);
177
- return r;
178
- }
179
-
180
- readFloat16le() {
181
- return this.readFloat16(true);
182
- }
183
-
184
- readFloat16be() {
185
- return this.readFloat16(false);
186
- }
187
-
188
- readFloat32(littleEndian?: boolean) {
189
- const r = this.#view.getFloat32(this.position, littleEndian ?? this.#littleEndian);
190
- this.skip(4);
191
- return r;
192
- }
193
-
194
- readFloat32le() {
195
- return this.readFloat32(true);
196
- }
197
-
198
- readFloat32be() {
199
- return this.readFloat32(false);
200
- }
201
-
202
- readFloat64(littleEndian?: boolean) {
203
- const r = this.#view.getFloat64(this.position, littleEndian ?? this.#littleEndian);
204
- this.skip(8);
205
- return r;
206
- }
207
-
208
- readFloat64le() {
209
- return this.readFloat64(true);
210
- }
211
-
212
- readFloat64be() {
213
- return this.readFloat64(false);
214
- }
215
-
216
- #strlen() {
217
- const remain = this.remain;
218
- for (let i = 0; i < remain; i++) {
219
- if (this.#view.getUint8(this.position + i) === 0) {
220
- return i;
221
- }
222
- }
223
- return undefined; // No termination
224
- }
225
-
226
- readBytes(n?: number) {
227
- const buffer = this.peekBytes(n);
228
- if (buffer) this.skip(buffer.byteLength);
229
- return buffer;
230
- }
231
-
232
- /**
233
- * @returns string. undefined on oversize or EOF.
234
- */
235
- readString(len?: number, encoding?: string | ((u8: Uint8Array) => string)) {
236
- const remain = this.remain;
237
- let extraLength = 0;
238
-
239
- if (len === undefined) {
240
- // C String Mode
241
- len = this.#strlen();
242
- extraLength = 1;
243
- }
244
- if (len === undefined || remain < len) return undefined; // EOF
245
-
246
- const buffer = this.peekBytes(len);
247
- try {
248
- if (typeof encoding === 'function') {
249
- const string = encoding(buffer);
250
-
251
- this.skip(len + extraLength);
252
- return string;
253
- } else {
254
- // XXX: encoding
255
- const string = new TextDecoder((encoding ?? 'utf-8') as 'utf-8', {
256
- fatal: true,
257
- }).decode(buffer);
258
-
259
- this.skip(len + extraLength);
260
- return string;
261
- }
262
- } catch {
263
- return undefined;
264
- }
265
- }
266
- }
267
-
268
- export default BinaryReader;
@@ -1,461 +0,0 @@
1
- import { BinaryReader } from '@kikuchan/binary-reader';
2
- import { describe, expect, it } from 'vitest';
3
-
4
- describe('Core State', () => {
5
- it('positions, sizes, and computes eof', () => {
6
- const u8 = new Uint8Array([1, 2, 3, 4]);
7
- const br = new BinaryReader(u8);
8
- expect(br.position).toBe(0);
9
- expect(br.size).toBe(4);
10
- expect(br.remain).toBe(4);
11
- expect(br.eof()).toBe(false);
12
- br.skip(4);
13
- expect(br.position).toBe(4);
14
- expect(br.remain).toBe(0);
15
- expect(br.eof()).toBe(true);
16
- });
17
-
18
- it('seeks, bookmarks, and rewinds', () => {
19
- const u8 = new Uint8Array([0, 1, 2, 3, 4, 5]);
20
- const br = new BinaryReader(u8);
21
- br.skip(2);
22
- expect(br.bookmark('here')).toBe(br);
23
- br.skip(3);
24
- expect(br.position).toBe(5);
25
- br.seek('here');
26
- expect(br.position).toBe(2);
27
- expect(br.rewind()).toBe(br);
28
- expect(br.position).toBe(0);
29
- });
30
-
31
- it('skips within bounds and aligns', () => {
32
- const u8 = new Uint8Array(10);
33
- const br = new BinaryReader(u8);
34
- br.seek(3);
35
- br.align(4);
36
- expect(br.position).toBe(4);
37
- br.align(4);
38
- expect(br.position).toBe(4);
39
- br.seek(9);
40
- br.skip(5); // should clamp at end
41
- expect(br.position).toBe(10);
42
- });
43
- });
44
-
45
- describe('Buffer Access', () => {
46
- it('peeks and reads byte ranges', () => {
47
- const u8 = new Uint8Array([10, 20, 30, 40]);
48
- const br = new BinaryReader(u8);
49
- const peek2 = br.peekBytes(2)!;
50
- expect(peek2.byteLength).toBe(2);
51
- expect(Array.from(new Uint8Array(peek2))).toEqual([10, 20]);
52
- expect(br.position).toBe(0);
53
-
54
- const read2 = br.readBytes(2)!;
55
- expect(read2.byteLength).toBe(2);
56
- expect(Array.from(new Uint8Array(read2))).toEqual([10, 20]);
57
- expect(br.position).toBe(2);
58
-
59
- const readRemain = br.readBytes();
60
- expect(readRemain).toBeDefined();
61
- expect(readRemain!.byteLength).toBe(2);
62
- expect(Array.from(new Uint8Array(readRemain!))).toEqual([30, 40]);
63
- expect(br.position).toBe(4);
64
- });
65
- });
66
-
67
- describe('Construction', () => {
68
- it('handles views with offsets', () => {
69
- const base = new Uint8Array([99, 1, 2, 3, 4, 100]);
70
- const view = base.subarray(1, 5); // [1,2,3,4]
71
- const br = new BinaryReader(view);
72
- expect(br.size).toBe(4);
73
- expect(br.readUint8()).toBe(1);
74
- expect(br.readUint8()).toBe(2);
75
- expect(br.readUint8()).toBe(3);
76
- expect(br.readUint8()).toBe(4);
77
- expect(br.eof()).toBe(true);
78
- });
79
- });
80
-
81
- describe('Unsigned Integers', () => {
82
- it('reads big-endian by default', () => {
83
- const bytes = new Uint8Array([
84
- 0xab, // u8
85
- 0x12,
86
- 0x34, // u16 BE = 0x1234
87
- 0x89,
88
- 0xab,
89
- 0xcd,
90
- 0xef, // u32 BE = 0x89ABCDEF
91
- 0x01,
92
- 0x02,
93
- 0x03,
94
- 0x04,
95
- 0x05,
96
- 0x06,
97
- 0x07,
98
- 0x08, // u64 BE = 0x0102030405060708n
99
- ]);
100
- const br = new BinaryReader(bytes);
101
- expect(br.readUint8()).toBe(0xab);
102
- expect(br.readUint16be()).toBe(0x1234);
103
- expect(br.readUint32be()).toBe(0x89abcdef);
104
- expect(br.readUint64be()).toBe(0x0102030405060708n);
105
-
106
- // Default endianness (no explicit arg, no option) should be big-endian.
107
- const be16 = new BinaryReader(new Uint8Array([0x12, 0x34]));
108
- expect(be16.readUint16()).toBe(0x1234);
109
- const be32 = new BinaryReader(new Uint8Array([0x89, 0xab, 0xcd, 0xef]));
110
- expect(be32.readUint32()).toBe(0x89abcdef);
111
- const be64 = new BinaryReader(new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]));
112
- expect(be64.readUint64()).toBe(0x0102030405060708n);
113
- });
114
-
115
- it('reads little-endian when defaulted via options', () => {
116
- const bytesLE = new Uint8Array([
117
- 0x34,
118
- 0x12, // 0x1234
119
- 0xef,
120
- 0xcd,
121
- 0xab,
122
- 0x89, // 0x89ABCDEF
123
- 0x08,
124
- 0x07,
125
- 0x06,
126
- 0x05,
127
- 0x04,
128
- 0x03,
129
- 0x02,
130
- 0x01, // 0x0102030405060708n
131
- ]);
132
- const br = new BinaryReader(bytesLE, { littleEndian: true });
133
- expect(br.readUint16()).toBe(0x1234);
134
- expect(br.readUint32()).toBe(0x89abcdef);
135
- expect(br.readUint64()).toBe(0x0102030405060708n);
136
- });
137
-
138
- it('overrides default endianness explicitly', () => {
139
- const bytes = new Uint8Array([0x34, 0x12]);
140
- const br = new BinaryReader(bytes, { littleEndian: true });
141
- expect(br.readUint16(false)).toBe(0x3412); // force BE
142
- });
143
- });
144
-
145
- describe('Signed Integers', () => {
146
- it('reads signed 8/16/32/64', () => {
147
- // For signed tests, craft BE values
148
- const bytes = new Uint8Array([
149
- 0xfe, // int8 = -2
150
- 0xff,
151
- 0xfe, // int16 = -2
152
- 0xff,
153
- 0xff,
154
- 0xff,
155
- 0xfe, // int32 = -2
156
- 0xff,
157
- 0xff,
158
- 0xff,
159
- 0xff,
160
- 0xff,
161
- 0xff,
162
- 0xff,
163
- 0xfe, // int64 = -2n
164
- ]);
165
- const br = new BinaryReader(bytes);
166
- expect(br.readInt8()).toBe(-2);
167
- expect(br.readInt16()).toBe(-2);
168
- expect(br.readInt32()).toBe(-2);
169
- expect(br.readInt64()).toBe(-2n);
170
- });
171
-
172
- it('reads signed via LE/BE methods', () => {
173
- // int16le(-2) bytes: 0xFE 0xFF
174
- const br16 = new BinaryReader(new Uint8Array([0xfe, 0xff]));
175
- expect(br16.readInt16le()).toBe(-2);
176
-
177
- // int32be(-2) bytes: 0xFF 0xFF 0xFF 0xFE
178
- const br32 = new BinaryReader(new Uint8Array([0xff, 0xff, 0xff, 0xfe]));
179
- expect(br32.readInt32be()).toBe(-2);
180
-
181
- // int64le(-2n) bytes: 0xFE 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
182
- const br64 = new BinaryReader(new Uint8Array([0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]));
183
- expect(br64.readInt64le()).toBe(-2n);
184
- });
185
- });
186
-
187
- describe('Floating Point', () => {
188
- it('reads float32/float64', () => {
189
- // BE: float32(1.0) = 0x3F800000, float64(1.5) = 0x3FF8000000000000
190
- const bytes = new Uint8Array([0x3f, 0x80, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
191
- const br = new BinaryReader(bytes);
192
- expect(br.readFloat32()).toBeCloseTo(1.0);
193
- expect(br.readFloat64()).toBeCloseTo(1.5);
194
- });
195
-
196
- it('reads float32/64 via LE/BE methods', () => {
197
- // float32(1.0) LE = 00 00 80 3F
198
- const br32le = new BinaryReader(new Uint8Array([0x00, 0x00, 0x80, 0x3f]));
199
- expect(br32le.readFloat32le()).toBeCloseTo(1.0);
200
-
201
- // float64(1.5) BE = 3F F8 00 00 00 00 00 00
202
- const br64be = new BinaryReader(new Uint8Array([0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
203
- expect(br64be.readFloat64be()).toBeCloseTo(1.5);
204
- });
205
- });
206
-
207
- describe('Strings', () => {
208
- it('reads fixed-length strings', () => {
209
- const bytes = new TextEncoder().encode('Hi!');
210
- const br = new BinaryReader(bytes);
211
- const s = br.readString(2);
212
- expect(s).toBe('Hi');
213
- expect(br.position).toBe(2);
214
- });
215
-
216
- it('reads a C-string and consumes NUL', () => {
217
- const bytes = new Uint8Array([...new TextEncoder().encode('Hi'), 0x00, 0x41]);
218
- const br = new BinaryReader(bytes);
219
- const s = br.readString();
220
- expect(s).toBe('Hi');
221
- // should consume terminating null as well
222
- expect(br.position).toBe(3);
223
- // Next byte should be 'A'
224
- expect(br.readUint8()).toBe(0x41);
225
- });
226
-
227
- it('returns undefined and does not advance when C-string has no terminator', () => {
228
- const bytes = new TextEncoder().encode('NoTerminator');
229
- const br = new BinaryReader(bytes);
230
- const s = br.readString();
231
- expect(s).toBeUndefined();
232
- expect(br.position).toBe(0);
233
- });
234
-
235
- it('returns undefined and does not advance when oversize', () => {
236
- const bytes = new TextEncoder().encode('Hi');
237
- const br = new BinaryReader(bytes);
238
- const s = br.readString(5);
239
- expect(s).toBeUndefined();
240
- expect(br.position).toBe(0);
241
- });
242
- });
243
-
244
- describe('Construction - more', () => {
245
- it('reads from ArrayBuffer', () => {
246
- const buf = new Uint8Array([1, 2, 3, 4]).buffer;
247
- const br = new BinaryReader(buf);
248
- expect(br.readUint8()).toBe(1);
249
- expect(br.readUint8()).toBe(2);
250
- expect(br.readUint8()).toBe(3);
251
- expect(br.readUint8()).toBe(4);
252
- expect(br.eof()).toBe(true);
253
- });
254
-
255
- it('reads from Uint8ClampedArray', () => {
256
- const clamped = new Uint8ClampedArray([5, 6, 7, 8]);
257
- const br = new BinaryReader(clamped);
258
- expect(br.size).toBe(4);
259
- expect(br.readUint8()).toBe(5);
260
- expect(br.readUint8()).toBe(6);
261
- expect(br.readUint8()).toBe(7);
262
- expect(br.readUint8()).toBe(8);
263
- expect(br.eof()).toBe(true);
264
- });
265
-
266
- it('reads from DataView', () => {
267
- const u8 = new Uint8Array([9, 10, 11, 12]);
268
- const view = new DataView(u8.buffer);
269
- const br = new BinaryReader(view);
270
- expect(br.readUint8()).toBe(9);
271
- expect(br.readUint8()).toBe(10);
272
- expect(br.readUint8()).toBe(11);
273
- expect(br.readUint8()).toBe(12);
274
- });
275
- });
276
-
277
- describe('Unsigned Integers - more', () => {
278
- it('reads uint16/32/64 via little-endian methods', () => {
279
- const br16 = new BinaryReader(new Uint8Array([0x34, 0x12]));
280
- expect(br16.readUint16le()).toBe(0x1234);
281
-
282
- const br32 = new BinaryReader(new Uint8Array([0xef, 0xcd, 0xab, 0x89]));
283
- expect(br32.readUint32le()).toBe(0x89abcdef);
284
-
285
- const br64 = new BinaryReader(new Uint8Array([0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]));
286
- expect(br64.readUint64le()).toBe(0x0102030405060708n);
287
- });
288
- });
289
-
290
- describe('Buffer Access - more', () => {
291
- it('returns remain when peekBytes length omitted', () => {
292
- const u8 = new Uint8Array([1, 2, 3, 4, 5]);
293
- const br = new BinaryReader(u8);
294
- br.seek(2);
295
- const buf = br.peekBytes();
296
- expect(buf.byteLength).toBe(3);
297
- expect(Array.from(new Uint8Array(buf))).toEqual([3, 4, 5]);
298
- expect(br.position).toBe(2);
299
- });
300
-
301
- it('clamps oversize readBytes to remain and advances to end', () => {
302
- const u8 = new Uint8Array([1, 2, 3, 4, 5]);
303
- const br = new BinaryReader(u8);
304
- br.seek(1);
305
- const buf = br.readBytes(999)!;
306
- expect(buf.byteLength).toBe(4);
307
- expect(Array.from(new Uint8Array(buf))).toEqual([2, 3, 4, 5]);
308
- expect(br.position).toBe(5);
309
- });
310
- });
311
-
312
- describe('Floating Point - float16', () => {
313
- if ('getFloat16' in DataView.prototype) {
314
- it('reads float16 (if supported)', () => {
315
- // 1.0 in IEEE 754 half precision = 0x3C00
316
- const bytes = new Uint8Array([0x3c, 0x00]);
317
- const br = new BinaryReader(bytes);
318
- expect(br.readFloat16()).toBeCloseTo(1.0);
319
- });
320
-
321
- it('reads float16 via LE/BE methods (if supported)', () => {
322
- // 1.0 in IEEE 754 half precision = 0x3C00
323
- const brLE = new BinaryReader(new Uint8Array([0x00, 0x3c]));
324
- expect(brLE.readFloat16le()).toBeCloseTo(1.0);
325
-
326
- const brBE = new BinaryReader(new Uint8Array([0x3c, 0x00]));
327
- expect(brBE.readFloat16be()).toBeCloseTo(1.0);
328
- });
329
- } else {
330
- it.skip('float16 (not supported in this runtime)', () => {});
331
- }
332
- });
333
-
334
- describe('Strings - more', () => {
335
- it('returns empty and does not advance with len=0', () => {
336
- const bytes = new TextEncoder().encode('Hi');
337
- const br = new BinaryReader(bytes);
338
- const s = br.readString(0);
339
- expect(s).toBe('');
340
- expect(br.position).toBe(0);
341
- });
342
-
343
- it('consumes NUL when C-string is empty at start', () => {
344
- const bytes = new Uint8Array([0x00, 0x41]);
345
- const br = new BinaryReader(bytes);
346
- const s = br.readString();
347
- expect(s).toBe('');
348
- expect(br.position).toBe(1);
349
- expect(br.readUint8()).toBe(0x41);
350
- });
351
-
352
- it('returns undefined and does not advance on partial UTF-8', () => {
353
- const bytes = new TextEncoder().encode('あ'); // 3 bytes in UTF-8
354
- const br = new BinaryReader(bytes);
355
- const s = br.readString(2);
356
- expect(s).toBeUndefined();
357
- expect(br.position).toBe(0);
358
- });
359
-
360
- it('decodes multibyte when length matches exactly', () => {
361
- const bytes = new TextEncoder().encode('あ');
362
- const br = new BinaryReader(bytes);
363
- const s = br.readString(3);
364
- expect(s).toBe('あ');
365
- expect(br.position).toBe(3);
366
- });
367
-
368
- it('decodes utf-16le when supported by TextDecoder', () => {
369
- // 'A' in UTF-16LE is [0x41, 0x00]
370
- const bytes = new Uint8Array([0x41, 0x00]);
371
- const br = new BinaryReader(bytes);
372
- const s = br.readString(2, 'utf-16le');
373
- // Some runtimes may not support utf-16le and return undefined
374
- if (s !== undefined) {
375
- expect(s).toBe('A');
376
- expect(br.position).toBe(2);
377
- } else {
378
- expect(br.position).toBe(0);
379
- }
380
- });
381
- });
382
-
383
- describe('Bounds and Errors', () => {
384
- it('throws on read beyond end (Uint16)', () => {
385
- const br = new BinaryReader(new Uint8Array([0x01]));
386
- expect(() => br.readUint16()).toThrow(RangeError);
387
- });
388
-
389
- it('throws on read beyond end (Float64)', () => {
390
- const br = new BinaryReader(new Uint8Array([0x00, 0x00, 0x00]));
391
- expect(() => br.readFloat64()).toThrow(RangeError);
392
- });
393
-
394
- it('throws on seek to unknown bookmark and leaves position unchanged', () => {
395
- const br = new BinaryReader(new Uint8Array([1, 2, 3]));
396
- br.seek(2);
397
- expect(() => br.seek('nope')).toThrow(Error);
398
- expect(br.position).toBe(2);
399
- });
400
-
401
- it('clamps negative seek to 0', () => {
402
- const br = new BinaryReader(new Uint8Array([1, 2, 3]));
403
- br.seek(-1 as unknown as number);
404
- expect(br.position).toBe(0);
405
- expect(br.readUint8()).toBe(1);
406
- });
407
-
408
- it('advances by 1 on default skip and stays at end', () => {
409
- const br = new BinaryReader(new Uint8Array([1]));
410
- expect(br.position).toBe(0);
411
- br.skip();
412
- expect(br.position).toBe(1);
413
- br.skip(); // already at end
414
- expect(br.position).toBe(1);
415
- });
416
- });
417
-
418
- describe('Alignment', () => {
419
- it('throws on non-positive alignment (0)', () => {
420
- const br = new BinaryReader(new Uint8Array([1, 2, 3]));
421
- // @ts-expect-error runtime should throw RangeError
422
- expect(() => br.align(0)).toThrow(RangeError);
423
- });
424
-
425
- it('throws on non-positive alignment (negative)', () => {
426
- const br = new BinaryReader(new Uint8Array([1, 2, 3]));
427
- // @ts-expect-error runtime should throw RangeError
428
- expect(() => br.align(-4)).toThrow(RangeError);
429
- });
430
- });
431
-
432
- describe('Specific endianness methods', () => {
433
- it('reads int16be as expected', () => {
434
- const br = new BinaryReader(new Uint8Array([0xff, 0xfe])); // -2
435
- expect(br.readInt16be()).toBe(-2);
436
- });
437
-
438
- it('reads int32le as expected', () => {
439
- // -2 in LE: fe ff ff ff
440
- const br = new BinaryReader(new Uint8Array([0xfe, 0xff, 0xff, 0xff]));
441
- expect(br.readInt32le()).toBe(-2);
442
- });
443
-
444
- it('reads int64be as expected', () => {
445
- // -2n in BE
446
- const br = new BinaryReader(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe]));
447
- expect(br.readInt64be()).toBe(-2n);
448
- });
449
-
450
- it('reads float32be as expected', () => {
451
- // 1.0 BE: 3f 80 00 00
452
- const br = new BinaryReader(new Uint8Array([0x3f, 0x80, 0x00, 0x00]));
453
- expect(br.readFloat32be()).toBeCloseTo(1.0);
454
- });
455
-
456
- it('reads float64le as expected', () => {
457
- // 1.5 LE: 00 00 00 00 00 00 f8 3f
458
- const br = new BinaryReader(new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f]));
459
- expect(br.readFloat64le()).toBeCloseTo(1.5);
460
- });
461
- });
package/tsconfig.json DELETED
@@ -1 +0,0 @@
1
- { "extends": "../../tsconfig.common.json" }