refactor: remove encoding functions
This commit is contained in:
parent
282c431021
commit
40eedf2817
131
src/encoding.ts
131
src/encoding.ts
|
@ -1,131 +0,0 @@
|
||||||
import { addContextToErr } from "./err.js";
|
|
||||||
import { Err } from "./types.js";
|
|
||||||
import { bytesToHex } from "@noble/hashes/utils";
|
|
||||||
|
|
||||||
const MAX_UINT_64 = 18446744073709551615n;
|
|
||||||
|
|
||||||
// b64ToBuf will take an untrusted base64 string and convert it into a
|
|
||||||
// Uin8Array, returning an error if the input is not valid base64.
|
|
||||||
const b64regex = /^[0-9a-zA-Z-_/+=]*$/;
|
|
||||||
function b64ToBuf(b64: string): [Uint8Array, Err] {
|
|
||||||
// Check that the final string is valid base64.
|
|
||||||
if (!b64regex.test(b64)) {
|
|
||||||
return [new Uint8Array(0), "provided string is not valid base64"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap any '-' characters for '+', and swap any '_' characters for '/'
|
|
||||||
// for use in the atob function.
|
|
||||||
b64 = b64.replaceAll("-", "+").replaceAll("_", "/");
|
|
||||||
|
|
||||||
// Perform the conversion.
|
|
||||||
const binStr = atob(b64);
|
|
||||||
const len = binStr.length;
|
|
||||||
const buf = new Uint8Array(len);
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
buf[i] = binStr.charCodeAt(i);
|
|
||||||
}
|
|
||||||
return [buf, null];
|
|
||||||
}
|
|
||||||
|
|
||||||
// bufToHex takes a Uint8Array as input and returns the hex encoding of those
|
|
||||||
// bytes as a string.
|
|
||||||
function bufToHex(buf: Uint8Array): string {
|
|
||||||
return bytesToHex(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bufToB64 will convert a Uint8Array to a base64 string with URL encoding and
|
|
||||||
// no padding characters.
|
|
||||||
function bufToB64(buf: Uint8Array): string {
|
|
||||||
const b64Str = btoa(String.fromCharCode(...buf));
|
|
||||||
return b64Str.replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// bufToStr takes an ArrayBuffer as input and returns a text string. bufToStr
|
|
||||||
// will check for invalid characters.
|
|
||||||
function bufToStr(buf: ArrayBuffer): [string, Err] {
|
|
||||||
try {
|
|
||||||
const text = new TextDecoder("utf-8", { fatal: true }).decode(buf);
|
|
||||||
return [text, null];
|
|
||||||
} catch (err: any) {
|
|
||||||
return [
|
|
||||||
"",
|
|
||||||
addContextToErr(err.toString(), "unable to decode ArrayBuffer to string"),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// decodeU64 is the opposite of encodeU64, it takes a uint64 encoded as 8 bytes
|
|
||||||
// and decodes them into a BigInt.
|
|
||||||
function decodeU64(u8: Uint8Array): [bigint, Err] {
|
|
||||||
// Check the input.
|
|
||||||
if (u8.length !== 8) {
|
|
||||||
return [0n, "input should be 8 bytes"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the input.
|
|
||||||
let num = 0n;
|
|
||||||
for (let i = u8.length - 1; i >= 0; i--) {
|
|
||||||
num *= 256n;
|
|
||||||
num += BigInt(u8[i]);
|
|
||||||
}
|
|
||||||
return [num, null];
|
|
||||||
}
|
|
||||||
|
|
||||||
// encodeU64 will encode a bigint in the range of a uint64 to an 8 byte
|
|
||||||
// Uint8Array.
|
|
||||||
function encodeU64(num: bigint): [Uint8Array, Err] {
|
|
||||||
// Check the bounds on the bigint.
|
|
||||||
if (num < 0) {
|
|
||||||
return [new Uint8Array(0), "expected a positive integer"];
|
|
||||||
}
|
|
||||||
if (num > MAX_UINT_64) {
|
|
||||||
return [new Uint8Array(0), "expected a number no larger than a uint64"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode the bigint into a Uint8Array.
|
|
||||||
const encoded = new Uint8Array(8);
|
|
||||||
for (let i = 0; i < encoded.length; i++) {
|
|
||||||
encoded[i] = Number(num & 0xffn);
|
|
||||||
num = num >> 8n;
|
|
||||||
}
|
|
||||||
return [encoded, null];
|
|
||||||
}
|
|
||||||
|
|
||||||
// hexToBuf takes an untrusted string as input, verifies that the string is
|
|
||||||
// valid hex, and then converts the string to a Uint8Array.
|
|
||||||
const allHex = /^[0-9a-f]+$/i;
|
|
||||||
function hexToBuf(hex: string): [Uint8Array, Err] {
|
|
||||||
// The rest of the code doesn't handle zero length input well, so we handle
|
|
||||||
// that separately. It's not an error, we just return an empty array.
|
|
||||||
if (hex.length === 0) {
|
|
||||||
return [new Uint8Array(0), null];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the length makes sense.
|
|
||||||
if (hex.length % 2 !== 0) {
|
|
||||||
return [new Uint8Array(0), "input has incorrect length"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that all of the characters are legal.
|
|
||||||
if (!allHex.test(hex)) {
|
|
||||||
return [new Uint8Array(0), "input has invalid character"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the buffer and fill it.
|
|
||||||
const matches = hex.match(/.{2}/g);
|
|
||||||
if (matches === null) {
|
|
||||||
return [new Uint8Array(0), "input is incomplete"];
|
|
||||||
}
|
|
||||||
const u8 = new Uint8Array(matches.map((byte) => parseInt(byte, 16)));
|
|
||||||
return [u8, null];
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
b64ToBuf,
|
|
||||||
bufToB64,
|
|
||||||
bufToStr,
|
|
||||||
decodeU64,
|
|
||||||
encodeU64,
|
|
||||||
bufToHex,
|
|
||||||
hexToBuf,
|
|
||||||
};
|
|
|
@ -28,7 +28,6 @@ export * from "./err.js";
|
||||||
export * from "./errTracker.js";
|
export * from "./errTracker.js";
|
||||||
export * from "./types.js";
|
export * from "./types.js";
|
||||||
export * from "./cid.js";
|
export * from "./cid.js";
|
||||||
export * from "./encoding.js";
|
|
||||||
export * from "./keys.js";
|
export * from "./keys.js";
|
||||||
export * from "./download.js";
|
export * from "./download.js";
|
||||||
export * from "./upload.js";
|
export * from "./upload.js";
|
||||||
|
|
Loading…
Reference in New Issue