Skip to content

refactor: support Uint8Array - #260

Open
SukkaW wants to merge 4 commits into
runk:masterfrom
SukkaW:uint8array
Open

refactor: support Uint8Array#260
SukkaW wants to merge 4 commits into
runk:masterfrom
SukkaW:uint8array

Conversation

@SukkaW

@SukkaW SukkaW commented Jul 27, 2026

Copy link
Copy Markdown

The PR refactors the library to accept Uint8Array.

Existing Buffer usage won't be broken, as Buffer is a subclass of Uint8Array, and feross's buffer polyfill is also built upon Uint8Array.

A new bytes.ts is introduced to bridge the gap in support for readUint16, readUint32, readInt32, readFloat32, and readFloat64 for Uint8Array.

Comment thread src/metadata.ts

// Look for [0xff, 0xff, 0xff] metadata delimiter
if (delim[0] === 255 && delim[1] === 255 && delim[2] === 255) {
const offset = db.length - 3 - i;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, thanks for replacing the slice

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the mmdb reader pipeline to operate on Uint8Array rather than Node-specific Buffer, enabling first-class usage in browser-like environments while keeping Node compatibility.

Changes:

  • Replaced Buffer-specific read APIs (readUInt*, readFloat*, toString('utf8')) with Uint8Array-compatible helpers and TextDecoder.
  • Updated core reader components (Reader, Decoder, Walker, metadata parsing) to accept Uint8Array.
  • Updated unit + integration tests and README examples to use Uint8Array.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/reader/walker.ts Switches node traversal reads to Uint8Array via new byte helpers.
src/metadata.ts Refactors metadata marker/search logic to Uint8Array indexing.
src/ip.ts Updates bit-level address access to accept Uint8Array.
src/ip.test.ts Updates bitAt test to use Uint8Array.
src/index.ts Changes Reader to accept Uint8Array and updates validation/cloning.
src/index.test.ts Updates test DB loading to provide Uint8Array.
src/decoder.ts Replaces Buffer read methods with bytes.ts helpers and TextDecoder.
src/decoder.test.ts Updates decoder tests to build inputs/expectations as Uint8Array.
src/bytes.ts Introduces Uint8Array helpers for integer/float reads.
src/test/integration.test.ts Updates integration expectations for decoded byte fields to Uint8Array.
README.md Updates public docs to describe Uint8Array usage (browser + Node).
Comments suppressed due to low confidence (1)

src/bytes.ts:36

  • readFloat32/readFloat64 allocate a new DataView on every call. These functions can be called many times during decoding, so this adds avoidable per-value allocations. Caching the DataView per Uint8Array avoids repeated object creation while keeping the same semantics.
export const readFloat32 = (bytes: Uint8Array, offset: number): number =>
  new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getFloat32(
    offset,
    false
  );

export const readFloat64 = (bytes: Uint8Array, offset: number): number =>
  new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getFloat64(
    offset,
    false
  );

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/decoder.ts
Comment thread src/index.ts Outdated
Comment thread src/decoder.ts Outdated
Comment thread src/bytes.ts Outdated
Comment thread src/metadata.ts
@runk

runk commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Could you please rebase with master, I've added a benchmark to avoid nasty regressions

Comment thread src/index.ts Outdated
);
}
this.db = db;
this.db = new Uint8Array(db.buffer, db.byteOffset, db.byteLength);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you doing it? Is it really necessary?

@SukkaW SukkaW Jul 28, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will double-check again. I was worried about potentially mutating the input, and also just normalizing the input (turning the Buffer into a plain Uint8Array), but this might indeed not be necessary. Will get back after I double-check.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped the Uint8Array clone and updated the test cases in fdc0ddf (this PR).

Comment thread src/decoder.ts Outdated
constructor(db: Uint8Array, baseOffset = 0, cache: Cache = noCache) {
utils.assert(Boolean(db), 'Database buffer is required');
this.db = db;
this.db = new Uint8Array(db.buffer, db.byteOffset, db.byteLength);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped the Uint8Array clone and updated the test cases in fdc0ddf (this PR).

@runk

runk commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Hmm, there's about 20% performance degradation with this change. Do you have a feel of where it could be coming from?

My local run:

master: 157k lookups/sec
this branch: 127k

@SukkaW

SukkaW commented Jul 28, 2026

Copy link
Copy Markdown
Author

Hmm, there's about 20% performance degradation with this change. Do you have a feel of where it could be coming from?

My local run:

master: 157k lookups/sec this branch: 127k

Weird. I will look into this. In the mean time I will also fix unit test type mismatch issue here.

@SukkaW

SukkaW commented Jul 28, 2026

Copy link
Copy Markdown
Author

@runk I have optimized db read in 7f6646f (this PR) by re-using the same data view here. This grants us 9% performance back.

However, the short string TextDecoder#decode appears to be the biggest bottleneck here, see nodejs/node#61041, which appears to be the core reason for our 20% performance regression.

@runk

runk commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Hmm.. I'm wondering if a thin wrapper on top of byte array source can be the solution here. It'd maintain the baseline for nodejs env and do the trick for browser env - I'm talking about two adapters with simialr interface

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants