@tgsnake/bytesio 1.0.0 → 2.0.0-browser.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 tgsnake
3
+ Copyright (c) 2026 tgsnake
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,28 +1,213 @@
1
- # BytesIO 🚀
1
+ # `@tgsnake/bytesio` 🚀
2
2
 
3
- A simple Buffer implementation inspired by Python's `BytesIO`.
4
- This project was originally based on the source code from [`@tgsnake/core`](https://github.com/tgsnake/core). 🐍
3
+ A high-performance, lightweight, seekable in-memory binary stream library for JavaScript and TypeScript, heavily inspired by Python's `io.BytesIO`.
5
4
 
6
- ## Features ✨
5
+ Originally decoupled from [`@tgsnake/core`](https://github.com/tgsnake/core) to serve as a high-performance standalone module for Node.js, Deno, Bun, and browser environments.
7
6
 
8
- - In-memory byte stream operations 💾
9
- - Read and write bytes efficiently ⚡
10
- - Python-like API for ease of use 🐍
7
+ [![JSR Badge](https://jsr.io/badges/@tgsnake/bytesio)](https://jsr.io/@tgsnake/bytesio) [![NPM Version](https://img.shields.io/npm/v/@tgsnake/bytesio.svg)](https://www.npmjs.com/package/@tgsnake/bytesio) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
11
8
 
12
- ## Installation 📦
9
+ ---
10
+
11
+ ## ⚡ Key Features
12
+
13
+ - 💾 **Seekable In-Memory Streams**: Track pointer position automatically with sequential or random-access seek operations (`0` absolute, `1` relative, `2` from-end).
14
+ - ⚙️ **Direct Node.js Buffer API**: Provides highly optimized operations to read and write integers, floats, doubles, bigints, and subarrays directly from/to memory.
15
+ - ⚡ **Cross-Platform**: Fully compatible with Node.js, Deno, Bun, and browsers with a centralized polyfill layer.
16
+ - 🚀 **Zero Dependencies**: Lightweight and fast footprint designed for modern high-performance networking, protocol parsing, and binary serialization.
17
+ - 📦 **Modern ESM & Typescript**: Written in TypeScript with first-class JSR support, full type safety, and clean ESM packaging.
18
+
19
+ ---
20
+
21
+ ## ⚠️ Requirements & Compatibility in v2.0.0
22
+
23
+ Version `2.0.0` introduces modern packaging improvements to align with the current JS/TS ecosystem:
24
+
25
+ - **Pure ESM (EcmaScript Modules)**: The package is now fully ESM. Since Node 20+ has support `require(ESM)`, this package now has fully writen to ESM. Minimum Node.js version is now **>= 22.0.0**. Formal support has been added for **Deno (>= 1.0.0)** and **Bun (>= 1.0.0)**.
26
+ - **First-class JSR & Deno Support**: Native Deno integration and standard JSR publishing.
27
+
28
+ ---
29
+
30
+ ## 📦 Installation
31
+
32
+ Install `@tgsnake/bytesio` using your favorite package manager:
33
+
34
+ ### Node.js / Bun (via NPM, Yarn, PNPM, Bun)
13
35
 
14
36
  ```bash
15
- # Example installation command
37
+ # Using npm
16
38
  npm install @tgsnake/bytesio
39
+
40
+ # Using yarn
41
+ yarn add @tgsnake/bytesio
42
+
43
+ # Using pnpm
44
+ pnpm add @tgsnake/bytesio
45
+
46
+ # Using bun
47
+ bun add @tgsnake/bytesio
48
+ ```
49
+
50
+ ### Deno / JSR (Native Deno Import)
51
+
52
+ ```bash
53
+ # Add the dependency via JSR
54
+ deno add jsr:@tgsnake/bytesio
17
55
  ```
18
56
 
19
- ## Usage 🛠️
57
+ ---
58
+
59
+ ## 🛠️ Detailed Usage & Examples
60
+
61
+ ### 1. In-Memory Write & Read Operations
20
62
 
21
- ```ts
63
+ ```typescript
22
64
  import { BytesIO } from '@tgsnake/bytesio';
65
+ import { Buffer } from 'node:buffer'; // or standard global Buffer in modern environments
23
66
 
67
+ // 1. Create a stream and write binary data
24
68
  const stream = new BytesIO();
25
- stream.write(Buffer.from([1, 2, 3]));
69
+ stream.write(Buffer.from([0x10, 0x20]));
70
+ stream.write(Buffer.from([0x30, 0x40]));
71
+
72
+ // Check pointer and stream length
73
+ console.log('Stream length:', stream.length); // Output: 4 bytes
74
+ console.log('Current pointer:', stream.post); // Output: 0 (write does not advance the seek pointer)
75
+
76
+ // 2. Seek and read sequentially
26
77
  stream.seek(0);
27
- console.log(stream.read(3)); // Output: <Buffer 01 02 03>
78
+ const allBytes = stream.read();
79
+ console.log(allBytes); // Output: <Buffer 10 20 30 40>
80
+
81
+ // 3. Read specific slice size
82
+ stream.seek(1); // Seek to offset 1
83
+ const chunk = stream.read(2);
84
+ console.log(chunk); // Output: <Buffer 20 30>
85
+ console.log('Pointer position:', stream.post); // Output: 3 (advanced by 2)
28
86
  ```
87
+
88
+ ### 2. Reading Binary Data Types (Integers, BigInts, Floats)
89
+
90
+ `BytesIO` provides built-in wrapper methods for Node.js `Buffer` integer, bigint, and float parsing. They automatically advance the stream pointer by the number of read bytes (or a customized step size).
91
+
92
+ ```typescript
93
+ import { BytesIO } from '@tgsnake/bytesio';
94
+
95
+ // Setup buffer containing mixed data: [Int32LE, BigInt64BE, FloatLE]
96
+ const dataStream = BytesIO.alloc(20);
97
+
98
+ // Allocate and write manually or instantiate from array
99
+ const stream = BytesIO.from([
100
+ 0x78,
101
+ 0x56,
102
+ 0x34,
103
+ 0x12, // 305419896 (Int32LE)
104
+ 0x00,
105
+ 0x00,
106
+ 0x00,
107
+ 0x00,
108
+ 0x00,
109
+ 0x00,
110
+ 0x00,
111
+ 0x0a, // 10n (BigInt64BE)
112
+ 0x00,
113
+ 0x00,
114
+ 0xa0,
115
+ 0x40, // 5.0 (FloatLE)
116
+ ]);
117
+
118
+ // Read 32-bit signed integer (little-endian)
119
+ const val1 = stream.readInt32LE(); // Reads 4 bytes and advances pointer by 4
120
+ console.log(val1); // Output: 305419896
121
+ console.log(stream.post); // Output: 4
122
+
123
+ // Read 64-bit signed BigInt (big-endian)
124
+ const val2 = stream.readBigInt64BE(); // Reads 8 bytes and advances pointer by 8
125
+ console.log(val2); // Output: 10n
126
+ console.log(stream.post); // Output: 12
127
+
128
+ // Read 32-bit float (little-endian)
129
+ const val3 = stream.readFloatLE(); // Reads 4 bytes and advances pointer by 4
130
+ console.log(val3); // Output: 5.0
131
+ console.log(stream.post); // Output: 16
132
+ ```
133
+
134
+ ### 3. Seeking Modes
135
+
136
+ You can control stream tracking with standard file-seek positioning (`whence` options):
137
+
138
+ ```typescript
139
+ import { BytesIO } from '@tgsnake/bytesio';
140
+
141
+ const stream = BytesIO.from('Hello, Advanced BytesIO!', 'utf-8');
142
+
143
+ // whence = 0 (Absolute seek relative to the beginning of the stream)
144
+ stream.seek(7, 0);
145
+ console.log(stream.read(8).toString('utf-8')); // Output: 'Advanced'
146
+
147
+ // whence = 1 (Relative seek from the current pointer location)
148
+ stream.seek(-8, 1); // Move backward 8 bytes
149
+ console.log(stream.read(8).toString('utf-8')); // Output: 'Advanced'
150
+
151
+ // whence = 2 (Seek relative to the end of the stream - expects a negative offset)
152
+ stream.seek(-1, 2); // Move to the last byte
153
+ console.log(stream.read().toString('utf-8')); // Output: '!'
154
+ ```
155
+
156
+ ---
157
+
158
+ ## 📖 API Documentation
159
+
160
+ ### Constructor
161
+
162
+ - `new BytesIO(buffer?: Buffer)`: Creates an in-memory stream wrapper around an optional initial Node.js `Buffer`.
163
+
164
+ ### Instance Properties
165
+
166
+ - `length`: `number` (Read-only) — The total size of the underlying buffer in bytes.
167
+ - `buffer`: `Buffer` (Read-only) — Access the underlying raw `Buffer` object.
168
+ - `post`: `number` (Read-only) — The current read/write pointer (byte index) of the stream.
169
+
170
+ ### Instance Methods
171
+
172
+ - `seek(offset: number, whence?: number): number` — Moves the internal pointer. `whence` supports:
173
+ - `0`: Seek from start (absolute).
174
+ - `1`: Seek relative to current position.
175
+ - `2`: Seek relative to the end (requires negative offset).
176
+ - `read(length?: number): Buffer` — Reads up to `length` bytes from the current pointer position and advances the pointer. If `length` is omitted, reads to the end.
177
+ - `slice(start?: number, end?: number): BytesIO` — Returns a new `BytesIO` instance referencing a subarray slice of the original buffer (shared memory).
178
+ - `write(data: Buffer): this` — Appends binary data to the absolute end of the buffer (increases length, doesn't change `post`).
179
+ - `toJSON(): { type: 'Buffer'; data: number[] }` — Serializes the underlying buffer data to JSON format.
180
+ - `toString(encoding?: string, start?: number, end?: number): string` — Decodes the buffer to a string.
181
+
182
+ #### Custom Decoders (Integer/Float/BigInt)
183
+
184
+ Every decoder reads the specified data type at the current pointer position and advances the pointer by `size` bytes (defaults to the type size):
185
+
186
+ - `readInt32LE(size?: number): number`
187
+ - `readInt32BE(size?: number): number`
188
+ - `readUInt32LE(size?: number): number`
189
+ - `readUInt32BE(size?: number): number`
190
+ - `readBigInt64LE(size?: number): bigint`
191
+ - `readBigInt64BE(size?: number): bigint`
192
+ - `readBigUInt64LE(size?: number): bigint`
193
+ - `readBigUInt64BE(size?: number): bigint`
194
+ - `readDoubleLE(size?: number): number`
195
+ - `readDoubleBE(size?: number): number`
196
+ - `readFloatLE(size?: number): number`
197
+ - `readFloatBE(size?: number): number`
198
+
199
+ ### Static Methods
200
+
201
+ - `BytesIO.alloc(size: number): BytesIO` — Creates a new instance with a zero-filled buffer of the specified size.
202
+ - `BytesIO.from(input: any, encoding?: string): BytesIO` — Creates a new instance from an array, string, buffer, or ArrayBuffer.
203
+ - `BytesIO.concat(list: Buffer[]): BytesIO` — Joins an array of buffers into a single `BytesIO` instance.
204
+
205
+ ---
206
+
207
+ ## 📄 License
208
+
209
+ Distributed under the [MIT License](LICENSE).
210
+
211
+ ---
212
+
213
+ Built with ♥️ by the **tgsnake** team. Contributions and issues are welcome!
package/package.json CHANGED
@@ -1,35 +1,48 @@
1
- {
2
- "name": "@tgsnake/bytesio",
3
- "packageManager": "yarn@4.9.2",
4
- "version": "1.0.0",
5
- "description": "A simple BytesIO implementation for Typescript",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "scripts": {
9
- "build": "tsc",
10
- "clean": "rm -rf dist",
11
- "prepare": "yarn build",
12
- "prettier": "NODE_OPTIONS=--max_old_space_size=4096 prettier -w .",
13
- "docs": "typedoc --out docs src/BytesIO.ts --excludePrivate --excludeProtected --excludeInternal --theme default --readme none"
14
- },
15
- "homepage": "https://tgsnake.js.org",
16
- "keywords": [
17
- "tgsnake",
18
- "BytesIO",
19
- "Buffer"
20
- ],
21
- "bugs": "https://github.com/tgsnake/bytesio/issues",
22
- "repository": "https://github.com/tgsnake/bytesio",
23
- "author": "butthx",
24
- "files": [
25
- "dist/**/**"
26
- ],
27
- "license": "MIT",
28
- "devDependencies": {
29
- "@types/bun": "^1.2.18",
30
- "@types/node": "^24.0.13",
31
- "prettier": "^3.6.2",
32
- "typedoc": "^0.28.7",
33
- "typescript": "^5.8.3"
34
- }
35
- }
1
+ {
2
+ "name": "@tgsnake/bytesio",
3
+ "packageManager": "yarn@4.9.2",
4
+ "version": "2.0.0-browser.0",
5
+ "description": "A simple BytesIO implementation for Typescript",
6
+ "main": "./browser/mod.js",
7
+ "types": "./browser/mod.d.ts",
8
+ "type": "module",
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "build:jsr": "node ./generator/jsr_version/index.js",
12
+ "clean": "rm -rf dist",
13
+ "prepare": "yarn build",
14
+ "prettier": "NODE_OPTIONS=--max_old_space_size=4096 prettier -w .",
15
+ "docs": "typedoc --out docs src/BytesIO.ts --excludePrivate --excludeProtected --excludeInternal --theme default --readme none"
16
+ },
17
+ "homepage": "https://tgsnake.js.org",
18
+ "keywords": [
19
+ "tgsnake",
20
+ "BytesIO",
21
+ "Buffer"
22
+ ],
23
+ "bugs": "https://github.com/tgsnake/bytesio/issues",
24
+ "repository": "https://github.com/tgsnake/bytesio",
25
+ "author": "butthx",
26
+ "files": [
27
+ "browser/**/**"
28
+ ],
29
+ "license": "MIT",
30
+ "devDependencies": {
31
+ "@types/bun": "^1.3.14",
32
+ "@types/node": "^25.9.1",
33
+ "prettier": "^3.8.3",
34
+ "typedoc": "^0.28.19",
35
+ "typescript": "^6.0.3"
36
+ },
37
+ "engineStrict": true,
38
+ "engines": {
39
+ "node": ">=22.0.0",
40
+ "npm": ">=6.0.0",
41
+ "yarn": ">=1.0.0",
42
+ "deno": ">=1.0.0",
43
+ "bun": ">=1.0.0"
44
+ },
45
+ "dependencies": {
46
+ "buffer": "^6.0.3"
47
+ }
48
+ }
package/dist/BytesIO.d.ts DELETED
@@ -1,33 +0,0 @@
1
- import { Buffer } from 'node:buffer';
2
- export declare class BytesIO {
3
- private _buffer;
4
- private _post;
5
- constructor(buffer?: Buffer);
6
- seek(offset: number, whence?: number): number;
7
- slice(...args: Array<any>): BytesIO;
8
- toJSON(): {
9
- type: "Buffer";
10
- data: number[];
11
- };
12
- toString(...args: Array<any>): string;
13
- read(length?: number): Buffer;
14
- readInt32LE(size?: number): number;
15
- readInt32BE(size?: number): number;
16
- readUInt32LE(size?: number): number;
17
- readUInt32BE(size?: number): number;
18
- readBigInt64LE(size?: number): bigint;
19
- readBigInt64BE(size?: number): bigint;
20
- readBigUInt64LE(size?: number): bigint;
21
- readBigUInt64BE(size?: number): bigint;
22
- readDoubleLE(size?: number): number;
23
- readDoubleBE(size?: number): number;
24
- readFloatLE(size?: number): number;
25
- readFloatBE(size?: number): number;
26
- write(data: Buffer): BytesIO;
27
- static alloc(size: number): BytesIO;
28
- static from(input: any, encode?: any): BytesIO;
29
- static concat(data: Array<Buffer>): BytesIO;
30
- get length(): number;
31
- get buffer(): Buffer;
32
- get post(): number;
33
- }
package/dist/BytesIO.js DELETED
@@ -1,145 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BytesIO = void 0;
4
- const node_buffer_1 = require("node:buffer");
5
- class BytesIO {
6
- _buffer;
7
- _post;
8
- constructor(buffer = node_buffer_1.Buffer.alloc(0)) {
9
- this._post = 0;
10
- this._buffer = buffer;
11
- return this;
12
- }
13
- seek(offset, whence = 0) {
14
- if (whence === 0) {
15
- if (offset < 0) {
16
- throw new Error(`offset of BytesIO.seek must be zero or positive value when whence is 0`);
17
- }
18
- this._post = whence;
19
- }
20
- else if (whence === 1) {
21
- this._post += offset;
22
- }
23
- else if (whence === 2) {
24
- if (offset >= 0) {
25
- throw new Error(`offset of BytesIO.seek must be less than zero or negative value when whence is 2`);
26
- }
27
- if (node_buffer_1.Buffer.byteLength(this._buffer) + offset < 0) {
28
- throw new Error(`offset out of range, offset ${offset} is less than the available buffer length.`);
29
- }
30
- this._post = node_buffer_1.Buffer.byteLength(this._buffer) + offset;
31
- }
32
- else {
33
- throw new Error(`whence must be 0 or 1 or 2, but receive ${whence}`);
34
- }
35
- return this._post;
36
- }
37
- slice(...args) {
38
- return new BytesIO(this._buffer.subarray(...args));
39
- }
40
- toJSON() {
41
- return this._buffer.toJSON();
42
- }
43
- toString(...args) {
44
- return this._buffer.toString(...args);
45
- }
46
- read(length) {
47
- if (length === undefined) {
48
- const results = this._buffer.subarray(this._post);
49
- this.seek(node_buffer_1.Buffer.byteLength(results), 1);
50
- return results;
51
- }
52
- if (length >= 1 && this._post <= node_buffer_1.Buffer.byteLength(this._buffer)) {
53
- const results = this._buffer.subarray(this._post, this._post + length);
54
- this.seek(length, 1);
55
- return results;
56
- }
57
- return node_buffer_1.Buffer.alloc(0);
58
- }
59
- readInt32LE(size = 4) {
60
- const results = this._buffer.readInt32LE(this._post);
61
- this.seek(size, 1);
62
- return results;
63
- }
64
- readInt32BE(size = 4) {
65
- const results = this._buffer.readInt32BE(this._post);
66
- this.seek(size, 1);
67
- return results;
68
- }
69
- readUInt32LE(size = 4) {
70
- const results = this._buffer.readUInt32LE(this._post);
71
- this.seek(size, 1);
72
- return results;
73
- }
74
- readUInt32BE(size = 4) {
75
- const results = this._buffer.readInt32BE(this._post);
76
- this.seek(size, 1);
77
- return results;
78
- }
79
- readBigInt64LE(size = 8) {
80
- const results = this._buffer.readBigInt64LE(this._post);
81
- this.seek(size, 1);
82
- return results;
83
- }
84
- readBigInt64BE(size = 8) {
85
- const results = this._buffer.readBigInt64BE(this._post);
86
- this.seek(size, 1);
87
- return results;
88
- }
89
- readBigUInt64LE(size = 8) {
90
- const results = this._buffer.readBigUInt64LE(this._post);
91
- this.seek(size, 1);
92
- return results;
93
- }
94
- readBigUInt64BE(size = 8) {
95
- const results = this._buffer.readBigUInt64BE(this._post);
96
- this.seek(size, 1);
97
- return results;
98
- }
99
- readDoubleLE(size = 8) {
100
- const results = this._buffer.readDoubleLE(this._post);
101
- this.seek(size, 1);
102
- return results;
103
- }
104
- readDoubleBE(size = 8) {
105
- const results = this._buffer.readDoubleBE(this._post);
106
- this.seek(size, 1);
107
- return results;
108
- }
109
- readFloatLE(size = 4) {
110
- const results = this._buffer.readFloatLE(this._post);
111
- this.seek(size, 1);
112
- return results;
113
- }
114
- readFloatBE(size = 4) {
115
- const results = this._buffer.readFloatBE(this._post);
116
- this.seek(size, 1);
117
- return results;
118
- }
119
- write(data) {
120
- this._buffer = node_buffer_1.Buffer.concat([
121
- this._buffer,
122
- data,
123
- ]);
124
- return this;
125
- }
126
- static alloc(size) {
127
- return new BytesIO(node_buffer_1.Buffer.alloc(size));
128
- }
129
- static from(input, encode) {
130
- return new BytesIO(node_buffer_1.Buffer.from(input, encode));
131
- }
132
- static concat(data) {
133
- return new BytesIO(node_buffer_1.Buffer.concat(data));
134
- }
135
- get length() {
136
- return node_buffer_1.Buffer.byteLength(this._buffer);
137
- }
138
- get buffer() {
139
- return this._buffer;
140
- }
141
- get post() {
142
- return this._post;
143
- }
144
- }
145
- exports.BytesIO = BytesIO;
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export { BytesIO } from './BytesIO.js';
2
- export { BytesIO as default } from './BytesIO.js';
package/dist/index.js DELETED
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = exports.BytesIO = void 0;
4
- var BytesIO_js_1 = require("./BytesIO.js");
5
- Object.defineProperty(exports, "BytesIO", { enumerable: true, get: function () { return BytesIO_js_1.BytesIO; } });
6
- var BytesIO_js_2 = require("./BytesIO.js");
7
- Object.defineProperty(exports, "default", { enumerable: true, get: function () { return BytesIO_js_2.BytesIO; } });