Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 

Repository files navigation

bytecursor.js – Cursor-Based Binary Data Reader/Writer

A zero-dependency, immutable, and bounds-safe wrapper around JavaScript’s DataView, designed for sequential binary parsing and serialization with an internal cursor.

Unlike raw DataView, bytecursor tracks your position automatically, supports UTF-8 strings out of the box, and enforces strict bounds checking - making binary protocol implementation safer and more readable.


✅ Key Features

  • Automatic cursor: Read/write sequentially without manual offsets
  • 🛡️ Strict bounds checking: Prevents out-of-range access at runtime
  • 🔤 UTF-8 string support: Encode/decode strings seamlessly via TextEncoder/TextDecoder
  • 📏 View slicing: Work with subsections of an ArrayBuffer
  • 🔄 Method chaining: All write operations return the instance for fluent APIs
  • 🧊 Immutable & frozen: The API object and its properties are Object.freezed for safety
  • 📦 Pure ES module: No dependencies, modern JavaScript only

⚠️ Note: All operations happen at the current cursor position.


📦 Installation

Place src/bytecursor.js in your project and import it:

import bytecursor from './bytecursor.js';

🧪 Quick Example

import bytecursor from './bytecursor.js';

// Create a 16-byte buffer
const cursor = bytecursor(new ArrayBuffer(16));

// Write data sequentially
cursor.writeString("OK")        // UTF-8 encoded → 2 bytes
      .writeUint8(200)          // → 1 byte
      .writeInt32(12345, true); // little-endian → 4 bytes

console.log(cursor.tell()); // 7

// Read it back
cursor.rewind();
console.log(cursor.getString(2));    // "OK"
console.log(cursor.getUint8());      // 200
console.log(cursor.getInt32(true));  // 12345

📚 API Reference

🔧 Initialization

bytecursor(buffer, [viewOffset = 0], [viewLength])
  • buffer: Must be an ArrayBuffer (throws TypeError otherwise)
  • Returns a frozen API object with a cursor starting at 0 (relative to the view)

Public Properties (Immutable)

Property Description
.buffer The original ArrayBuffer
.view The underlying DataView (with offset/length as provided)
.length Byte length of the active view (number, not a method)

🧭 Cursor Control

Method Description
.tell() Returns current cursor position (0-based, relative to view start)
.seek(pos) Move cursor to absolute position pos (within view bounds)
.rewind() Reset cursor to 0
.skip(n) Advance cursor by n bytes
.eof() Returns true if cursor ≥ view length

All cursor methods (except tell and eof) return the API instance for chaining.


🔢 Reading Numeric Values

All read methods advance the cursor by the size of the type.

Method Size Description
.getUint8() 1 Unsigned 8-bit integer
.getInt8() 1 Signed 8-bit integer
.getUint16(littleEndian?) 2 Unsigned 16-bit integer
.getInt16(littleEndian?) 2 Signed 16-bit integer
.getUint32(littleEndian?) 4 Unsigned 32-bit integer
.getInt32(littleEndian?) 4 Signed 32-bit integer
.getFloat32(littleEndian?) 4 32-bit float
.getFloat64(littleEndian?) 8 64-bit float

✍️ Writing Numeric Values

All write methods advance the cursor and return the API for chaining.

Method Example
.writeUint8(v) cursor.writeUint8(255)
.writeInt8(v) cursor.writeInt8(-128)
.writeUint16(v, littleEndian?) cursor.writeUint16(65535, true)
.writeInt16(v, littleEndian?) cursor.writeInt16(-32768, true)
.writeUint32(v, littleEndian?) cursor.writeUint32(4294967295, true)
.writeInt32(v, littleEndian?) cursor.writeInt32(-2147483648, true)
.writeFloat32(v, littleEndian?) cursor.writeFloat32(3.14159, true)
.writeFloat64(v, littleEndian?) cursor.writeFloat64(2.718281828, true)

📄 Bytes & Strings (UTF-8)

Method Description
.getBytes([length]) Reads length bytes from cursor as Uint8Array (default: to end of view)
.getString(length) Decodes length bytes as UTF-8 string
.writeBytes(uint8Array) Writes a Uint8Array at cursor
.writeString(str) Encodes and writes a UTF-8 string

🌐 Uses browser-native TextEncoder and TextDecoder with UTF-8 encoding.


✂️ Buffer Extraction

Method Description
.slice(start?, end?) Returns a copy of the underlying buffer from view.byteOffset + start to view.byteOffset + end (defaults to entire view)

⚠️ This slices the original buffer, not relative to the cursor.


🧪 Testing

This library includes a zero-dependency, comprehensive browser-based verification suite (82 assertions covering 100% of methods, boundary guards, and error conditions).

To run the test suite:

  1. Serve the repository using any static web server (e.g., Nginx, Caddy, or Python's http.server).
  2. Open tests/index.html in your browser (e.g., http://localhost/tests/index.html).
  3. View results visually on the page or open Developer Tools (F12 -> Console) to inspect grouped log outputs and execution metrics.

🚫 What It Doesn’t Do

  • ❌ No random-access reading/writing (e.g., getUint32(12))
  • ❌ No support for non-UTF-8 encodings
  • ❌ No automatic length-prefix handling (you manage string/byte lengths)

This keeps the API minimal, predictable, and focused on stream-like binary parsing.


📄 License

See LICENSE for details.

About

A clean binary buffer cursor and DataView wrapper for reading/writing typed data in JavaScript.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages