binutils64 0.1.4 → 0.3.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,65 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.3.0] - 2026-07-04
9
+
10
+ ### Added
11
+
12
+ - `BinaryReader.ReadString(count)` and `BinaryWriter.WriteString(value)`: read and
13
+ write strings using the instance's `Encoding` (`'ascii'` by default). Reading
14
+ past the end returns an empty string without advancing; writing a non-string
15
+ throws.
16
+
17
+ ## [0.2.0] - 2026-07-02
18
+
19
+ ### Added
20
+
21
+ - MIT license (`LICENSE` file and `license` field in `package.json`).
22
+ - Bundled TypeScript type definitions (`binutils.d.ts`).
23
+ - `CHANGELOG.md` (this file).
24
+ - ESLint configuration that locks `binutils.js` to ES5 syntax, an `npm run lint`
25
+ script, and a CI lint job.
26
+ - GitHub Actions publish workflow that releases to npm with provenance.
27
+ - Package metadata: `files` whitelist, `exports` map, `keywords`, `bugs`, `homepage`.
28
+ - `.editorconfig`.
29
+
30
+ ### Changed
31
+
32
+ - Raised the declared Node.js floor (`engines.node`) from `>=0.12` to `>=12`,
33
+ matching the actual requirement of the 64-bit `BigInt` methods.
34
+ - Replaced the deprecated `new Buffer(...)` constructor with
35
+ `Buffer.alloc()`/`Buffer.from()`; the `DEP0005` deprecation warning is gone.
36
+ No behavior change.
37
+ - `repository.url` now uses `git+https://` instead of the retired `git://` protocol.
38
+
39
+ ## [0.1.4] - 2026-05-28
40
+
41
+ ### Added
42
+
43
+ - Test suite using the built-in `node:test` runner: reader, writer, round-trip,
44
+ edge-case and README-example coverage.
45
+ - GitHub Actions CI running the tests on Node.js 20, 22 and 24.
46
+
47
+ ## [0.1.3] - 2024-11-01
48
+
49
+ ### Fixed
50
+
51
+ - `ReadInt64` returning incorrect values.
52
+
53
+ ## [0.1.2] - 2018-06-15
54
+
55
+ ### Changed
56
+
57
+ - README updates.
58
+
59
+ ## [0.1.1] - 2018-06-15
60
+
61
+ ### Added
62
+
63
+ - First release of `binutils64`: `BinaryReader` and `BinaryWriter` with selectable
64
+ endianness, signed/unsigned 8/16/32-bit integers, floats, doubles, raw byte runs,
65
+ and 64-bit integers via `BigInt`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2013-2026 Mihail Shumilov
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/README.md CHANGED
@@ -3,13 +3,18 @@
3
3
  > A .NET-style `BinaryReader` and `BinaryWriter` for Node.js, with selectable endianness.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/binutils64.svg)](https://www.npmjs.com/package/binutils64)
6
+ [![npm downloads](https://img.shields.io/npm/dm/binutils64.svg)](https://www.npmjs.com/package/binutils64)
6
7
  [![Tests](https://github.com/mihailShumilov/node-binutils/actions/workflows/test.yml/badge.svg)](https://github.com/mihailShumilov/node-binutils/actions/workflows/test.yml)
8
+ [![node version](https://img.shields.io/node/v/binutils64.svg)](https://www.npmjs.com/package/binutils64)
9
+ [![license](https://img.shields.io/github/license/mihailShumilov/node-binutils.svg)](https://github.com/mihailShumilov/node-binutils/blob/master/LICENSE)
10
+ [![types](https://img.shields.io/npm/types/binutils64.svg)](https://www.npmjs.com/package/binutils64)
11
+ [![install size](https://packagephobia.com/badge?p=binutils64)](https://packagephobia.com/result?p=binutils64)
7
12
 
8
13
  `binutils64` provides two small classes — `BinaryReader` and `BinaryWriter` — that
9
14
  make it easy to parse and produce binary data sequentially, with an API modelled on
10
15
  the corresponding .NET classes. Both classes let you choose the byte order
11
16
  (`big`- or `little`-endian) and support 8-, 16-, 32- and 64-bit integers, floats,
12
- doubles, and raw byte runs.
17
+ doubles, raw byte runs, and encoded strings.
13
18
 
14
19
  ## Table of contents
15
20
 
@@ -24,14 +29,17 @@ doubles, and raw byte runs.
24
29
  - [Requirements and compatibility](#requirements-and-compatibility)
25
30
  - [Testing](#testing)
26
31
  - [Contributing](#contributing)
32
+ - [License](#license)
27
33
 
28
34
  ## Features
29
35
 
30
36
  - Sequential `Read*` / `Write*` methods for every common fixed-width type.
31
37
  - Per-instance endianness (`big` by default, or `little`).
32
38
  - 64-bit integers via JavaScript `BigInt`.
33
- - Signed and unsigned integers, IEEE-754 `float` and `double`, and raw byte runs.
39
+ - Signed and unsigned integers, IEEE-754 `float` and `double`, raw byte runs, and
40
+ strings in any `Buffer` encoding.
34
41
  - Zero runtime dependencies.
42
+ - Bundled TypeScript type definitions.
35
43
 
36
44
  ## Installation
37
45
 
@@ -83,7 +91,7 @@ you read.
83
91
  | ------------ | ----------------------------- | ------- | ------------------------------------------------------------------ |
84
92
  | `input` | `Buffer` \| `number[]` \| `string` | — | The data to read. A `Buffer` is **copied** so the source is never mutated. |
85
93
  | `endianness` | `'big'` \| `'little'` | `'big'` | Byte order used by all multi-byte reads. |
86
- | `encoding` | `string` | `'ascii'` | Used only when `input` is a `string`, to turn it into bytes. |
94
+ | `encoding` | `string` | `'ascii'` | Used to turn a `string` input into bytes, and by `ReadString`. |
87
95
 
88
96
  Throws `Error` if `input` is not a `Buffer`, array, or string.
89
97
 
@@ -102,10 +110,11 @@ Throws `Error` if `input` is not a `Buffer`, array, or string.
102
110
  | `ReadFloat()` | 4 | `number` | IEEE-754 single precision. |
103
111
  | `ReadDouble()` | 8 | `number` | IEEE-754 double precision. |
104
112
  | `ReadBytes(count)`| `count` | `Buffer`| Copies `count` bytes into a new `Buffer`. |
113
+ | `ReadString(count)`| `count` | `string`| Decodes `count` bytes using the instance's `Encoding`. |
105
114
 
106
115
  If fewer than the required number of bytes remain, integer/float reads return `0`
107
- (or `0.0`), and `ReadBytes` returns an empty `Buffer` — **without** throwing or
108
- advancing the position. See [Behavior and best practices](#behavior-and-best-practices).
116
+ (or `0.0`), and `ReadBytes`/`ReadString` return an empty `Buffer`/`string` — **without**
117
+ throwing or advancing the position. See [Behavior and best practices](#behavior-and-best-practices).
109
118
 
110
119
  #### Reader properties
111
120
 
@@ -126,7 +135,7 @@ A writer accumulates bytes in an internal buffer that grows with every write.
126
135
  | Parameter | Type | Default | Description |
127
136
  | ------------ | --------------------- | --------- | ---------------------------------------- |
128
137
  | `endianness` | `'big'` \| `'little'` | `'big'` | Byte order used by all multi-byte writes.|
129
- | `encoding` | `string` | `'ascii'` | Stored on the instance; reserved. |
138
+ | `encoding` | `string` | `'ascii'` | Used by `WriteString` to encode strings. |
130
139
 
131
140
  #### Write methods
132
141
 
@@ -143,6 +152,7 @@ A writer accumulates bytes in an internal buffer that grows with every write.
143
152
  | `WriteFloat(value)` | 4 | `number` | IEEE-754 single precision. |
144
153
  | `WriteDouble(value)` | 8 | `number` | IEEE-754 double precision. |
145
154
  | `WriteBytes(value)` | varies| `Buffer` \| `number[]` \| `string` | Strings are written as one byte per character code. Throws on any other type. |
155
+ | `WriteString(value)` | varies| `string` | Encodes the string using the instance's `Encoding`. Throws on any other type. |
146
156
 
147
157
  Writing a value outside the target type's range throws a `RangeError` (the standard
148
158
  Node.js `Buffer` write behavior) — e.g. `WriteUInt8(256)`.
@@ -184,6 +194,11 @@ Node.js `Buffer` write behavior) — e.g. `WriteUInt8(256)`.
184
194
  - **Constructing a reader from a string?** Pass the encoding explicitly
185
195
  (e.g. `new BinaryReader(text, 'big', 'utf8')`) so the bytes are interpreted the
186
196
  way you expect.
197
+ - **The default `'ascii'` encoding is 7-bit only.** Node.js clears the high bit of
198
+ every byte when decoding `'ascii'`, so text containing characters above `0x7F`
199
+ does **not** round-trip through `WriteString`/`ReadString` with the default
200
+ encoding. Pass `'utf8'` (or `'latin1'`) to both constructors when handling
201
+ non-ASCII text.
187
202
 
188
203
  ## Examples
189
204
 
@@ -213,6 +228,21 @@ const reader = new BinaryReader(writer.ByteBuffer, 'little');
213
228
  console.log(reader.ReadUInt32().toString(16)); // "1020304"
214
229
  ```
215
230
 
231
+ ### Writing and reading strings
232
+
233
+ ```javascript
234
+ const { BinaryReader, BinaryWriter } = require('binutils64');
235
+
236
+ const text = 'héllo';
237
+ const writer = new BinaryWriter('big', 'utf8');
238
+ writer.WriteUInt8(Buffer.byteLength(text, 'utf8')); // length prefix: 6
239
+ writer.WriteString(text);
240
+
241
+ const reader = new BinaryReader(writer.ByteBuffer, 'big', 'utf8');
242
+ const length = reader.ReadUInt8(); // 6
243
+ console.log(reader.ReadString(length)); // "héllo"
244
+ ```
245
+
216
246
  ### Parsing a structured record
217
247
 
218
248
  ```javascript
@@ -232,11 +262,11 @@ console.log(record, 'read', reader.Position, 'of', reader.Length, 'bytes');
232
262
 
233
263
  ## Requirements and compatibility
234
264
 
235
- - **Node.js.** The 8-, 16- and 32-bit methods run on very old Node.js versions, but
236
- the 64-bit methods (`ReadUInt64`, `ReadInt64`, `WriteUInt64`, `WriteInt64`) rely on
237
- `BigInt` and the `Buffer` big-integer methods, which require **Node.js 12 or newer**.
238
- - The library uses the legacy `Buffer` constructor internally; on modern Node.js you
239
- may see a one-time `DEP0005` deprecation warning. This does not affect behavior.
265
+ - **Node.js 12 or newer** (declared in `package.json` `engines`). The 64-bit methods
266
+ (`ReadUInt64`, `ReadInt64`, `WriteUInt64`, `WriteInt64`) rely on `BigInt` and the
267
+ `Buffer` big-integer methods introduced in Node.js 12.
268
+ - **TypeScript typings are bundled** (`binutils.d.ts`) no separate `@types`
269
+ package is needed.
240
270
  - Running the test suite uses the built-in `node:test` runner, which requires
241
271
  **Node.js 18 or newer**.
242
272
 
@@ -253,4 +283,10 @@ the documented examples. Continuous integration runs it on Node.js 20, 22 and 24
253
283
  ## Contributing
254
284
 
255
285
  Issues and pull requests are welcome. Please add or update tests for any behavioral
256
- change and make sure `npm test` passes before opening a pull request.
286
+ change, note it in `CHANGELOG.md` under *Unreleased*, and make sure `npm test` and
287
+ `npm run lint` pass before opening a pull request (run `npm ci` once to install the
288
+ linter).
289
+
290
+ ## License
291
+
292
+ [MIT](LICENSE)
package/binutils.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ /// <reference types="node" />
2
+
3
+ export = binutils;
4
+
5
+ declare namespace binutils {
6
+ type Endianness = 'big' | 'little';
7
+
8
+ class BinaryReader {
9
+ /**
10
+ * Wraps a copy of the input data and consumes it from the front as you read.
11
+ * A `Buffer` input is copied, so the source is never mutated.
12
+ * Throws if `input` is not a `Buffer`, array, or string.
13
+ */
14
+ constructor(
15
+ input: Buffer | ReadonlyArray<number> | string,
16
+ endianness?: Endianness,
17
+ encoding?: BufferEncoding
18
+ );
19
+
20
+ /** The remaining unread bytes. Shrinks as `Read*` methods consume it. */
21
+ ByteBuffer: Buffer;
22
+ /** Byte order used by all multi-byte reads. */
23
+ Endianness: Endianness;
24
+ /** Encoding used to turn a string input into bytes and to decode `ReadString`. */
25
+ Encoding: BufferEncoding;
26
+ /** Length of the original input in bytes. Never changes as you read. */
27
+ Length: number;
28
+ /** Number of bytes consumed so far. */
29
+ Position: number;
30
+
31
+ /** Reads 1 byte. Returns 0 (without advancing) if no bytes remain. */
32
+ ReadUInt8(): number;
33
+ /** Reads 2 bytes. Returns 0 (without advancing) if fewer than 2 bytes remain. */
34
+ ReadUInt16(): number;
35
+ /** Reads 4 bytes. Returns 0 (without advancing) if fewer than 4 bytes remain. */
36
+ ReadUInt32(): number;
37
+ /** Reads 8 bytes as an unsigned BigInt. Returns the number 0 (without advancing) if fewer than 8 bytes remain. */
38
+ ReadUInt64(): bigint | 0;
39
+ /** Reads 1 byte, signed. Returns 0 (without advancing) if no bytes remain. */
40
+ ReadInt8(): number;
41
+ /** Reads 2 bytes, signed. Returns 0 (without advancing) if fewer than 2 bytes remain. */
42
+ ReadInt16(): number;
43
+ /** Reads 4 bytes, signed. Returns 0 (without advancing) if fewer than 4 bytes remain. */
44
+ ReadInt32(): number;
45
+ /** Reads 8 bytes as a signed BigInt. Returns the number 0 (without advancing) if fewer than 8 bytes remain. */
46
+ ReadInt64(): bigint | 0;
47
+ /** Reads 4 bytes as an IEEE-754 single. Returns 0 (without advancing) if fewer than 4 bytes remain. */
48
+ ReadFloat(): number;
49
+ /** Reads 8 bytes as an IEEE-754 double. Returns 0 (without advancing) if fewer than 8 bytes remain. */
50
+ ReadDouble(): number;
51
+ /** Copies `count` bytes into a new Buffer. Returns an empty Buffer (without advancing) if fewer than `count` bytes remain. */
52
+ ReadBytes(count: number): Buffer;
53
+ /** Decodes `count` bytes as a string using the instance's `Encoding`. Returns an empty string (without advancing) if fewer than `count` bytes remain. */
54
+ ReadString(count: number): string;
55
+ }
56
+
57
+ class BinaryWriter {
58
+ /** Accumulates bytes in an internal buffer that grows with every write. */
59
+ constructor(endianness?: Endianness, encoding?: BufferEncoding);
60
+
61
+ /** All bytes written so far. */
62
+ ByteBuffer: Buffer;
63
+ /** Byte order used by all multi-byte writes. */
64
+ Endianness: Endianness;
65
+ /** Encoding used by `WriteString`. */
66
+ Encoding: BufferEncoding;
67
+ /** The current length of `ByteBuffer`. */
68
+ Length: number;
69
+
70
+ WriteUInt8(value: number): void;
71
+ WriteUInt16(value: number): void;
72
+ WriteUInt32(value: number): void;
73
+ /** Accepts a number or BigInt; the value is coerced with `BigInt(value)`. */
74
+ WriteUInt64(value: number | bigint): void;
75
+ WriteInt8(value: number): void;
76
+ WriteInt16(value: number): void;
77
+ WriteInt32(value: number): void;
78
+ /** Accepts a number or BigInt; the value is coerced with `BigInt(value)`. */
79
+ WriteInt64(value: number | bigint): void;
80
+ WriteFloat(value: number): void;
81
+ WriteDouble(value: number): void;
82
+ /** Strings are written as one byte per character code. Throws on any other input type. */
83
+ WriteBytes(value: Buffer | ReadonlyArray<number> | string): void;
84
+ /** Encodes the string using the instance's `Encoding`. Throws on any other input type. */
85
+ WriteString(value: string): void;
86
+ }
87
+ }
package/binutils.js CHANGED
@@ -1,9 +1,9 @@
1
1
  var BinaryReader = function(p_InputBuffer, p_Endianness, p_Encoding) {
2
2
  // Instantiate the buffer (if needed)
3
3
  if (p_InputBuffer instanceof Buffer) {
4
- this.ByteBuffer = new Buffer(p_InputBuffer);
4
+ this.ByteBuffer = Buffer.from(p_InputBuffer);
5
5
  } else if (p_InputBuffer instanceof Array || typeof p_InputBuffer == 'string') {
6
- this.ByteBuffer = new Buffer(p_InputBuffer, p_Encoding);
6
+ this.ByteBuffer = Buffer.from(p_InputBuffer, p_Encoding);
7
7
  } else {
8
8
  throw new Error('Invalid buffer input for BinaryReader (' + typeof p_InputBuffer + ')');
9
9
  }
@@ -134,14 +134,25 @@ BinaryReader.prototype = {
134
134
 
135
135
  ReadBytes: function(p_Count) {
136
136
  if (p_Count > this.ByteBuffer.length) {
137
- return new Buffer(0);
137
+ return Buffer.alloc(0);
138
138
  }
139
139
 
140
- var s_Val = new Buffer(p_Count);
140
+ var s_Val = Buffer.alloc(p_Count);
141
141
  this.ByteBuffer.copy(s_Val, 0, 0, p_Count);
142
142
 
143
143
  this.ByteBuffer = this.ByteBuffer.slice(p_Count);
144
144
 
145
+ this.Position += p_Count;
146
+ return s_Val;
147
+ },
148
+
149
+ ReadString: function(p_Count) {
150
+ if (p_Count <= 0 || p_Count > this.ByteBuffer.length) {
151
+ return '';
152
+ }
153
+
154
+ var s_Val = this.ByteBuffer.toString(this.Encoding, 0, p_Count);
155
+ this.ByteBuffer = this.ByteBuffer.slice(p_Count);
145
156
  this.Position += p_Count;
146
157
  return s_Val;
147
158
  }
@@ -151,7 +162,7 @@ BinaryReader.prototype = {
151
162
 
152
163
  var BinaryWriter = function(p_Endianness, p_Encoding) {
153
164
  // Instantiate the buffer
154
- this.ByteBuffer = new Buffer(0);
165
+ this.ByteBuffer = Buffer.alloc(0);
155
166
 
156
167
  // Set the endianness
157
168
  this.Endianness = p_Endianness || 'big';
@@ -165,14 +176,14 @@ var BinaryWriter = function(p_Endianness, p_Encoding) {
165
176
 
166
177
  BinaryWriter.prototype = {
167
178
  WriteUInt8: function(p_Value) {
168
- var s_TempBuffer = new Buffer(1);
179
+ var s_TempBuffer = Buffer.alloc(1);
169
180
  s_TempBuffer.writeUInt8(p_Value, 0);
170
181
  this.Length += 1;
171
182
  this.ByteBuffer = Buffer.concat([this.ByteBuffer, s_TempBuffer], this.Length);
172
183
  },
173
184
 
174
185
  WriteUInt16: function(p_Value) {
175
- var s_TempBuffer = new Buffer(2);
186
+ var s_TempBuffer = Buffer.alloc(2);
176
187
  if (this.Endianness == 'little') {
177
188
  s_TempBuffer.writeUInt16LE(p_Value, 0);
178
189
  } else {
@@ -183,7 +194,7 @@ BinaryWriter.prototype = {
183
194
  },
184
195
 
185
196
  WriteUInt32: function(p_Value) {
186
- var s_TempBuffer = new Buffer(4);
197
+ var s_TempBuffer = Buffer.alloc(4);
187
198
  if (this.Endianness == 'little') {
188
199
  s_TempBuffer.writeUInt32LE(p_Value, 0);
189
200
  } else {
@@ -194,7 +205,7 @@ BinaryWriter.prototype = {
194
205
  },
195
206
 
196
207
  WriteUInt64: function(p_Value) {
197
- var s_TempBuffer = new Buffer(8);
208
+ var s_TempBuffer = Buffer.alloc(8);
198
209
  var s_Value = BigInt(p_Value);
199
210
  if (this.Endianness == 'little') {
200
211
  s_TempBuffer.writeBigUInt64LE(s_Value, 0);
@@ -206,14 +217,14 @@ BinaryWriter.prototype = {
206
217
  },
207
218
 
208
219
  WriteInt8: function(p_Value) {
209
- var s_TempBuffer = new Buffer(1);
220
+ var s_TempBuffer = Buffer.alloc(1);
210
221
  s_TempBuffer.writeInt8(p_Value, 0);
211
222
  this.Length += 1;
212
223
  this.ByteBuffer = Buffer.concat([this.ByteBuffer, s_TempBuffer], this.Length);
213
224
  },
214
225
 
215
226
  WriteInt16: function(p_Value) {
216
- var s_TempBuffer = new Buffer(2);
227
+ var s_TempBuffer = Buffer.alloc(2);
217
228
  if (this.Endianness == 'little') {
218
229
  s_TempBuffer.writeInt16LE(p_Value, 0);
219
230
  } else {
@@ -224,7 +235,7 @@ BinaryWriter.prototype = {
224
235
  },
225
236
 
226
237
  WriteInt32: function(p_Value) {
227
- var s_TempBuffer = new Buffer(4);
238
+ var s_TempBuffer = Buffer.alloc(4);
228
239
  if (this.Endianness == 'little') {
229
240
  s_TempBuffer.writeInt32LE(p_Value, 0);
230
241
  } else {
@@ -235,7 +246,7 @@ BinaryWriter.prototype = {
235
246
  },
236
247
 
237
248
  WriteInt64: function(p_Value) {
238
- var s_TempBuffer = new Buffer(8);
249
+ var s_TempBuffer = Buffer.alloc(8);
239
250
  var s_Value = BigInt(p_Value);
240
251
  if (this.Endianness == 'little') {
241
252
  s_TempBuffer.writeBigInt64LE(s_Value, 0);
@@ -247,7 +258,7 @@ BinaryWriter.prototype = {
247
258
  },
248
259
 
249
260
  WriteFloat: function(p_Value) {
250
- var s_TempBuffer = new Buffer(4);
261
+ var s_TempBuffer = Buffer.alloc(4);
251
262
  if (this.Endianness == 'little') {
252
263
  s_TempBuffer.writeFloatLE(p_Value, 0);
253
264
  } else {
@@ -258,7 +269,7 @@ BinaryWriter.prototype = {
258
269
  },
259
270
 
260
271
  WriteDouble: function(p_Value) {
261
- var s_TempBuffer = new Buffer(8);
272
+ var s_TempBuffer = Buffer.alloc(8);
262
273
  if (this.Endianness == 'little') {
263
274
  s_TempBuffer.writeDoubleLE(p_Value, 0);
264
275
  } else {
@@ -285,8 +296,18 @@ BinaryWriter.prototype = {
285
296
  throw new Error("Invalid Buffer object provided.");
286
297
  }
287
298
 
288
- var s_TempBuffer = (p_Value instanceof Buffer) ? p_Value : new Buffer(p_Value);
299
+ var s_TempBuffer = (p_Value instanceof Buffer) ? p_Value : Buffer.from(p_Value);
300
+
301
+ this.Length += s_TempBuffer.length;
302
+ this.ByteBuffer = Buffer.concat([this.ByteBuffer, s_TempBuffer], this.Length);
303
+ },
304
+
305
+ WriteString: function(p_Value) {
306
+ if (typeof p_Value != 'string') {
307
+ throw new Error("Invalid string provided.");
308
+ }
289
309
 
310
+ var s_TempBuffer = Buffer.from(p_Value, this.Encoding);
290
311
  this.Length += s_TempBuffer.length;
291
312
  this.ByteBuffer = Buffer.concat([this.ByteBuffer, s_TempBuffer], this.Length);
292
313
  }
package/package.json CHANGED
@@ -1,17 +1,54 @@
1
- {
2
- "name": "binutils64",
3
- "version": "0.1.4",
4
- "author": "Mihail Shumilov <mschumilow@gmail.com>",
5
- "description": "A .NET-like BinaryReader and BinaryWriter with endianness support.",
6
- "main": "./binutils.js",
7
- "scripts": {
8
- "test": "node --test"
9
- },
10
- "engines": {
11
- "node": ">=0.12"
12
- },
13
- "repository": {
14
- "type" : "git",
15
- "url" : "git://github.com/mihailShumilov/node-binutils.git"
16
- }
17
- }
1
+ {
2
+ "name": "binutils64",
3
+ "version": "0.3.0",
4
+ "author": "Mihail Shumilov <mschumilow@gmail.com>",
5
+ "description": "A .NET-like BinaryReader and BinaryWriter with endianness support.",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "binary",
9
+ "buffer",
10
+ "binaryreader",
11
+ "binarywriter",
12
+ "reader",
13
+ "writer",
14
+ "endianness",
15
+ "endian",
16
+ "bigint",
17
+ "int64",
18
+ "uint64",
19
+ "parse",
20
+ "serialize"
21
+ ],
22
+ "main": "./binutils.js",
23
+ "types": "./binutils.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./binutils.d.ts",
27
+ "default": "./binutils.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "binutils.js",
32
+ "binutils.d.ts",
33
+ "CHANGELOG.md"
34
+ ],
35
+ "scripts": {
36
+ "test": "node --test",
37
+ "lint": "eslint ."
38
+ },
39
+ "engines": {
40
+ "node": ">=12"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/mihailShumilov/node-binutils.git"
45
+ },
46
+ "bugs": {
47
+ "url": "https://github.com/mihailShumilov/node-binutils/issues"
48
+ },
49
+ "homepage": "https://github.com/mihailShumilov/node-binutils#readme",
50
+ "devDependencies": {
51
+ "@eslint/js": "^10.0.1",
52
+ "eslint": "^10.6.0"
53
+ }
54
+ }
@@ -1,58 +0,0 @@
1
- ---
2
- name: binutils-reviewer
3
- description: Reviews changes to the binutils64 library (binutils.js, README.md, tests) for binary-correctness bugs and convention adherence. Use proactively after any edit to binutils.js or when asked to review a Read/Write change, a new type, or a PR touching this library.
4
- tools: Read, Grep, Glob, Bash
5
- model: sonnet
6
- ---
7
-
8
- You are a focused code reviewer for **binutils64**, a single-file ES5 CommonJS
9
- library (`binutils.js`) providing .NET-style `BinaryReader` and `BinaryWriter`
10
- with selectable endianness. Your job is to catch binary-correctness bugs and
11
- convention drift in changes to this library. Be precise and skeptical — this code
12
- already shipped a real width-mismatch bug (the 64-bit writers emit only 32 bits).
13
-
14
- ## What to review
15
-
16
- Read `binutils.js`, the relevant `README.md` sections, and any `test/` files. Use
17
- `git diff` (via Bash) to scope the change when reviewing edits. If a round-trip is
18
- in doubt, actually run it: `node -e "..."` or `node --test`.
19
-
20
- ## Correctness checklist (highest priority)
21
-
22
- 1. **Write width == read width.** For every `WriteX`/`ReadX` pair, the number of
23
- bytes written must equal the bytes read and the declared width `N`. Flag any
24
- writer using a narrower method than its buffer size (e.g. `writeUInt32LE` into
25
- an 8-byte buffer — this was the original `WriteUInt64`/`WriteInt64` bug, since
26
- fixed). 64-bit writers use `writeBigUInt64*`/`writeBigInt64*` and coerce with
27
- `BigInt(p_Value)`. Prefer confirming with a real round-trip.
28
- 2. **Endianness branches** present and correct for every multi-byte method: the
29
- `'little'` branch uses the `*LE` variant, the else branch uses `*BE`. Single-byte
30
- methods (`*UInt8`/`*Int8`) must NOT have an endianness branch.
31
- 3. **Reader is destructive and consistent**: each `ReadX` slices exactly `N` bytes
32
- off `this.ByteBuffer` and advances `this.Position` by exactly `N`. `this.Length`
33
- must NOT change on reads (it reflects the original buffer length).
34
- 4. **Writer accounting**: each `WriteX` increases `this.Length` by exactly `N` and
35
- passes the updated `this.Length` as the `Buffer.concat` total-length argument.
36
- 5. **Out-of-range reads return the zero value** (`0`, `0.0`, or empty `Buffer`) and
37
- never throw. Verify the length guard matches the width.
38
- 6. **Signed/unsigned and BigInt**: signed types use the signed Buffer methods;
39
- 64-bit reads return `bigint` (`readBig*64*`). Watch for sign/precision errors.
40
-
41
- ## Convention checklist
42
-
43
- - ES5 only: `var`, prototype assignment. No `let`/`const`/classes/arrow functions.
44
- - `PascalCase` method and property names; parameters prefixed `p_`; locals `s_`.
45
- - `new Buffer(...)` is intentional for `node >=0.12`. Do NOT recommend
46
- `Buffer.alloc`/`Buffer.from` unless the change also raises `engines.node`.
47
- - New/changed public methods must have matching `README.md` entries with the
48
- existing phrasing, and a round-trip test.
49
- - Methods placed beside their family in the file, ordered consistently.
50
-
51
- ## Output format
52
-
53
- Report findings grouped by severity. For each: a one-line title, the
54
- `binutils.js:line` reference, why it is wrong, and the concrete fix. Lead with
55
- **Correctness** issues, then **Conventions**, then **Docs/Tests**. State a
56
- confidence level and only raise convention nits if no correctness issue is
57
- outstanding. If you ran a round-trip to confirm, show the command and result. If
58
- nothing is wrong, say so plainly — do not invent issues.
@@ -1,21 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(git checkout *)",
5
- "Bash(node *)",
6
- "Bash(echo \"exit code: $?\")",
7
- "Read(//tmp/**)",
8
- "Bash(echo \"exit: $?\")",
9
- "mcp__claude_ai_Context7__resolve-library-id",
10
- "mcp__claude_ai_Context7__query-docs",
11
- "Bash(python3 -c \"import yaml,sys; yaml.safe_load\\(open\\('.github/workflows/test.yml'\\)\\); print\\('YAML OK'\\)\")",
12
- "Bash(git add *)",
13
- "Bash(git commit -m 'fix 64-bit writers and WriteBytes type guard *)",
14
- "Bash(git commit -m 'add test suite using node:test *)",
15
- "Bash(git commit -m 'add github actions workflow to run tests *)",
16
- "Bash(git commit -m 'add project docs and claude tooling *)",
17
- "Bash(git push *)",
18
- "Bash(git commit -m 'rewrite readme with full api reference and examples *)"
19
- ]
20
- }
21
- }