Skip to content

Commit

Permalink
Merge pull request #8 from Nesopie/feat/buffer-utils
Browse files Browse the repository at this point in the history
Feat/buffer utils
  • Loading branch information
junderw authored Jul 25, 2024
2 parents 00419c7 + c70e256 commit 8f9696a
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 4 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
"node": {
"module": "./src/mjs/index.js",
"require": "./src/cjs/index.cjs",
"import": "./src/mjs/index.js"
"import": "./src/mjs/index.js",
"types": "./src/cjs/index.d.ts"
},
"browser": "./src/mjs/browser.js",
"default": "./src/mjs/browser.js"
"default": "./src/mjs/browser.js",
"types": "./src/cjs/index.d.ts"
},
"types": "src/cjs/index.d.ts",
"type": "module",
Expand Down
30 changes: 29 additions & 1 deletion src/cjs/browser.cjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.readUInt64 = exports.readUInt32 = exports.readUInt16 = exports.readUInt8 = exports.writeUInt64 = exports.writeUInt32 = exports.writeUInt16 = exports.writeUInt8 = exports.compare = exports.fromHex = exports.toHex = exports.toUtf8 = void 0;
exports.readUInt64 = exports.readUInt32 = exports.readUInt16 = exports.readUInt8 = exports.writeUInt64 = exports.writeUInt32 = exports.writeUInt16 = exports.writeUInt8 = exports.compare = exports.fromBase64 = exports.toBase64 = exports.fromHex = exports.toHex = exports.concat = exports.fromUtf8 = exports.toUtf8 = void 0;
const HEX_STRINGS = "0123456789abcdefABCDEF";
const HEX_CODES = HEX_STRINGS.split("").map((c) => c.codePointAt(0));
const HEX_CODEPOINTS = Array(256)
Expand All @@ -17,6 +17,21 @@ function toUtf8(bytes) {
return DECODER.decode(bytes);
}
exports.toUtf8 = toUtf8;
function fromUtf8(s) {
return ENCODER.encode(s);
}
exports.fromUtf8 = fromUtf8;
function concat(arrays) {
const totalLength = arrays.reduce((a, b) => a + b.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const array of arrays) {
result.set(array, offset);
offset += array.length;
}
return result;
}
exports.concat = concat;
// There are two implementations.
// One optimizes for length of the bytes, and uses TextDecoder.
// One optimizes for iteration count, and appends strings.
Expand Down Expand Up @@ -60,6 +75,19 @@ function fromHex(hexString) {
return i === resultBytes.length ? resultBytes : resultBytes.slice(0, i);
}
exports.fromHex = fromHex;
function toBase64(bytes) {
return btoa(String.fromCharCode(...bytes));
}
exports.toBase64 = toBase64;
function fromBase64(base64) {
const binaryString = atob(base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}
exports.fromBase64 = fromBase64;
// Same behavior as Buffer.compare()
function compare(v1, v2) {
const minLength = Math.min(v1.length, v2.length);
Expand Down
18 changes: 17 additions & 1 deletion src/cjs/index.cjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.readUInt64 = exports.readUInt32 = exports.readUInt16 = exports.readUInt8 = exports.writeUInt64 = exports.writeUInt32 = exports.writeUInt16 = exports.writeUInt8 = exports.compare = exports.fromHex = exports.toHex = exports.toUtf8 = void 0;
exports.readUInt64 = exports.readUInt32 = exports.readUInt16 = exports.readUInt8 = exports.writeUInt64 = exports.writeUInt32 = exports.writeUInt16 = exports.writeUInt8 = exports.compare = exports.fromBase64 = exports.toBase64 = exports.fromHex = exports.toHex = exports.concat = exports.fromUtf8 = exports.toUtf8 = void 0;
function toUtf8(bytes) {
return Buffer.from(bytes || []).toString();
}
exports.toUtf8 = toUtf8;
function fromUtf8(s) {
return Uint8Array.from(Buffer.from(s || "", "utf8"));
}
exports.fromUtf8 = fromUtf8;
function concat(arrays) {
return Uint8Array.from(Buffer.concat(arrays));
}
exports.concat = concat;
function toHex(bytes) {
return Buffer.from(bytes || []).toString("hex");
}
Expand All @@ -13,6 +21,14 @@ function fromHex(hexString) {
return Uint8Array.from(Buffer.from(hexString || "", "hex"));
}
exports.fromHex = fromHex;
function toBase64(bytes) {
return Buffer.from(bytes).toString("base64");
}
exports.toBase64 = toBase64;
function fromBase64(base64) {
return Uint8Array.from(Buffer.from(base64 || "", "base64"));
}
exports.fromBase64 = fromBase64;
function compare(v1, v2) {
return Buffer.from(v1).compare(Buffer.from(v2));
}
Expand Down
4 changes: 4 additions & 0 deletions src/cjs/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export declare function toUtf8(bytes: Uint8Array): string;
export declare function fromUtf8(s: string): Uint8Array;
export declare function concat(arrays: Uint8Array[]): Uint8Array;
export declare function toHex(bytes: Uint8Array): string;
export declare function fromHex(hexString: string): Uint8Array;
export declare function toBase64(bytes: Uint8Array): string;
export declare function fromBase64(base64: string): Uint8Array;
export declare type CompareResult = -1 | 0 | 1;
export declare function compare(v1: Uint8Array, v2: Uint8Array): CompareResult;
export declare type endian = "LE" | "BE" | "le" | "be";
Expand Down
24 changes: 24 additions & 0 deletions src/mjs/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ const DECODER = new TextDecoder();
export function toUtf8(bytes) {
return DECODER.decode(bytes);
}
export function fromUtf8(s) {
return ENCODER.encode(s);
}
export function concat(arrays) {
const totalLength = arrays.reduce((a, b) => a + b.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const array of arrays) {
result.set(array, offset);
offset += array.length;
}
return result;
}
// There are two implementations.
// One optimizes for length of the bytes, and uses TextDecoder.
// One optimizes for iteration count, and appends strings.
Expand Down Expand Up @@ -54,6 +67,17 @@ export function fromHex(hexString) {
}
return i === resultBytes.length ? resultBytes : resultBytes.slice(0, i);
}
export function toBase64(bytes) {
return btoa(String.fromCharCode(...bytes));
}
export function fromBase64(base64) {
const binaryString = atob(base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}
// Same behavior as Buffer.compare()
export function compare(v1, v2) {
const minLength = Math.min(v1.length, v2.length);
Expand Down
12 changes: 12 additions & 0 deletions src/mjs/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
export function toUtf8(bytes) {
return Buffer.from(bytes || []).toString();
}
export function fromUtf8(s) {
return Uint8Array.from(Buffer.from(s || "", "utf8"));
}
export function concat(arrays) {
return Uint8Array.from(Buffer.concat(arrays));
}
export function toHex(bytes) {
return Buffer.from(bytes || []).toString("hex");
}
export function fromHex(hexString) {
return Uint8Array.from(Buffer.from(hexString || "", "hex"));
}
export function toBase64(bytes) {
return Buffer.from(bytes).toString("base64");
}
export function fromBase64(base64) {
return Uint8Array.from(Buffer.from(base64 || "", "base64"));
}
export function compare(v1, v2) {
return Buffer.from(v1).compare(Buffer.from(v2));
}
Expand Down
28 changes: 28 additions & 0 deletions ts_src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ export function toUtf8(bytes: Uint8Array): string {
return DECODER.decode(bytes);
}

export function fromUtf8(s: string): Uint8Array {
return ENCODER.encode(s);
}

export function concat(arrays: Uint8Array[]): Uint8Array {
const totalLength = arrays.reduce((a, b) => a + b.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const array of arrays) {
result.set(array, offset);
offset += array.length;
}
return result;
}

// There are two implementations.
// One optimizes for length of the bytes, and uses TextDecoder.
// One optimizes for iteration count, and appends strings.
Expand Down Expand Up @@ -58,6 +73,19 @@ export function fromHex(hexString: string): Uint8Array {
return i === resultBytes.length ? resultBytes : resultBytes.slice(0, i);
}

export function toBase64(bytes: Uint8Array): string {
return btoa(String.fromCharCode(...bytes));
}

export function fromBase64(base64: string): Uint8Array {
const binaryString = atob(base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}

export type CompareResult = -1 | 0 | 1;
// Same behavior as Buffer.compare()
export function compare(v1: Uint8Array, v2: Uint8Array): CompareResult {
Expand Down
16 changes: 16 additions & 0 deletions ts_src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ export function toUtf8(bytes: Uint8Array): string {
return Buffer.from(bytes || []).toString();
}

export function fromUtf8(s: string): Uint8Array {
return Uint8Array.from(Buffer.from(s || "", "utf8"));
}

export function concat(arrays: Uint8Array[]): Uint8Array {
return Uint8Array.from(Buffer.concat(arrays));
}

export function toHex(bytes: Uint8Array): string {
return Buffer.from(bytes || []).toString("hex");
}
Expand All @@ -10,6 +18,14 @@ export function fromHex(hexString: string): Uint8Array {
return Uint8Array.from(Buffer.from(hexString || "", "hex"));
}

export function toBase64(bytes: Uint8Array): string {
return Buffer.from(bytes).toString("base64");
}

export function fromBase64(base64: string): Uint8Array {
return Uint8Array.from(Buffer.from(base64 || "", "base64"));
}

export type CompareResult = -1 | 0 | 1;
export function compare(v1: Uint8Array, v2: Uint8Array): CompareResult {
return Buffer.from(v1).compare(Buffer.from(v2)) as CompareResult;
Expand Down
71 changes: 71 additions & 0 deletions ts_src/tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ describe(`Uint8Array tools`, () => {
expect(tools.toUtf8(longBytes2)).toEqual(longUtf8);
expect((tools.toUtf8 as any)()).toEqual("");
});
it("should read utf8 with fromUtf8", () => {
expect(tools.fromUtf8(utf8)).toEqual(bytes3);
expect(tools.fromUtf8(str)).toEqual(testBytes);
expect(tools.fromUtf8(longUtf8)).toEqual(longBytes2);
expect((tools.fromUtf8 as any)()).toEqual(f([]));
});
it(`should compare Uint8Arrays`, () => {
expect(tools.compare(bytes, bytes2)).toBe(-1);
expect(tools.compare(bytes, bytes)).toBe(0);
Expand All @@ -62,6 +68,71 @@ describe(`Uint8Array tools`, () => {
expect(tools.compare(bytes2, bytes2LargerLeft)).toBe(1);
expect(tools.compare(bytes2LargerLeft, bytes2)).toBe(-1);
});
it("should concat Uint8Arrays", () => {
const fixtures = [
[new Uint8Array([]), new Uint8Array([])],
[new Uint8Array([1]), new Uint8Array([1])],
[new Uint8Array([])],
[new Uint8Array()],
[...new Array(1000)].map(() => new Uint8Array([123])),
];

for (const fixture of fixtures) {
expect(new Uint8Array(Buffer.concat(fixture))).toEqual(
tools.concat(fixture)
);
}
});
it("should read from base64", () => {
const fixtures = [
Buffer.from("").toString("base64"),
Buffer.from("a").toString("base64"),
Buffer.from("ab").toString("base64"),
Buffer.from("abc").toString("base64"),
Buffer.from("abcd").toString("base64"),
Buffer.from("abcde").toString("base64"),
Buffer.from("abcdef").toString("base64"),
Buffer.from("abcdefg").toString("base64"),
Buffer.from("abcdefgh").toString("base64"),
Buffer.from("abcdefghi").toString("base64"),
Buffer.from("abcdefghij").toString("base64"),
Buffer.from("abcdefghijk").toString("base64"),
Buffer.from("abcdefghijkl").toString("base64"),
Buffer.from("abcdefghijklm").toString("base64"),
Buffer.from("abcdefghijklmn").toString("base64"),
];

for (const fixture of fixtures) {
expect(tools.fromBase64(fixture)).toEqual(
Uint8Array.from(Buffer.from(fixture, "base64"))
);
}
});

it("should write to base64", () => {
const fixtures = [
Buffer.from("").toString("base64"),
Buffer.from("a").toString("base64"),
Buffer.from("ab").toString("base64"),
Buffer.from("abc").toString("base64"),
Buffer.from("abcd").toString("base64"),
Buffer.from("abcde").toString("base64"),
Buffer.from("abcdef").toString("base64"),
Buffer.from("abcdefg").toString("base64"),
Buffer.from("abcdefgh").toString("base64"),
Buffer.from("abcdefghi").toString("base64"),
Buffer.from("abcdefghij").toString("base64"),
Buffer.from("abcdefghijk").toString("base64"),
Buffer.from("abcdefghijkl").toString("base64"),
Buffer.from("abcdefghijklm").toString("base64"),
Buffer.from("abcdefghijklmn").toString("base64"),
];

for (const fixture of fixtures) {
expect(tools.toBase64(tools.fromBase64(fixture))).toEqual(fixture);
}
});

it("should writeUint8", () => {
const hexs = ["03", "fd"];

Expand Down

0 comments on commit 8f9696a

Please sign in to comment.