@vandeurenglenn/base16 1.0.0 → 1.1.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/README.md CHANGED
@@ -1,21 +1,21 @@
1
- # bs32
2
-
3
- module compatible base16
4
-
5
- ## Usage
6
-
7
- ``` js
8
- import base16 from '@vandeurenglenn/base16'
9
-
10
- const uint8Array = new TextEncoder().encode('hi')
11
-
12
- const base16Encoded = base16.encode(uint8Array)
13
-
14
- console.log(base16Encoded) // 2dj
15
-
16
- const base16Decoded = base16.decode(base16Encoded)
17
-
18
- const string = new TextDecoder().decode(base16Decoded)
19
-
20
- console.log(string) // hi
21
- ```
1
+ # bs32
2
+
3
+ module compatible base16
4
+
5
+ ## Usage
6
+
7
+ ``` js
8
+ import base16 from '@vandeurenglenn/base16'
9
+
10
+ const uint8Array = new TextEncoder().encode('hi')
11
+
12
+ const base16Encoded = base16.encode(uint8Array)
13
+
14
+ console.log(base16Encoded) // 2dj
15
+
16
+ const base16Decoded = base16.decode(base16Encoded)
17
+
18
+ const string = new TextDecoder().decode(base16Decoded)
19
+
20
+ console.log(string) // hi
21
+ ```
package/index.d.ts CHANGED
@@ -1,13 +1,12 @@
1
- /**
2
- * A base16String only contains [0-9][a-f]
3
- */
4
- type base16String = string;
5
- export declare const decode: (source: string) => Uint8Array;
6
- export declare const encode: (source: Uint8Array | ArrayBuffer) => string;
7
- export declare const isBase16: (string: base16String) => boolean;
8
- declare const _default: {
9
- encode: (source: Uint8Array | ArrayBuffer) => string;
10
- decode: (source: string) => Uint8Array;
11
- isBase16: (string: string) => boolean;
12
- };
13
- export default _default;
1
+ declare const encodeJS: (buffer: Uint8Array) => string;
2
+ declare const decodeJS: (string: string) => Uint8Array;
3
+ declare const isBase16JS: (string: string) => boolean;
4
+ export declare const encode: typeof encodeJS;
5
+ export declare const decode: typeof decodeJS;
6
+ export declare const isBase16: typeof isBase16JS;
7
+ declare const index: {
8
+ encode: typeof encodeJS;
9
+ decode: typeof decodeJS;
10
+ isBase16: typeof isBase16JS;
11
+ };
12
+ export default index;
package/index.js CHANGED
@@ -1,22 +1,87 @@
1
- import baseX from '@vandeurenglenn/base-x';
2
-
3
- const ALPHABET = '0123456789abcdef';
4
- const base32 = baseX(ALPHABET);
5
- const decode = base32.decode;
6
- const encode = base32.encode;
7
- const isBase16 = (string) => {
8
- try {
9
- decode(string);
10
- return true;
11
- }
12
- catch (e) {
13
- return false;
14
- }
15
- };
16
- var index = {
17
- encode,
18
- decode,
19
- isBase16
1
+ const ALPHABET = "0123456789ABCDEF";
2
+ const INVALID_BASE16 = /[^0-9a-f]/i;
3
+ const BYTE_TO_HEX = Array.from({ length: 256 }, (_, byte) => ALPHABET[byte >> 4] + ALPHABET[byte & 0xf]);
4
+ const PAIR_LOOKUP_THRESHOLD = 512 * 1024;
5
+ const PAIR_LOOKUP_MIN_LENGTH = 1024;
6
+ const LOOKUP = new Uint8Array(256).fill(255);
7
+ let BYTE_PAIR_TO_HEX;
8
+ for (let i = 0; i < 16; i++) {
9
+ const code = ALPHABET.charCodeAt(i);
10
+ LOOKUP[code] = i;
11
+ // Initialize lowercase if it's a letter (A=65, a=97, diff=32)
12
+ if (i > 9)
13
+ LOOKUP[code + 32] = i;
14
+ }
15
+ const encodePairsJS = (buffer, lookup) => {
16
+ let str = "";
17
+ for (let start = 0; start < buffer.length; start += 8192) {
18
+ let chunk = "";
19
+ const end = Math.min(start + 8192, buffer.length);
20
+ let i = start;
21
+ for (; i + 1 < end; i += 2) {
22
+ chunk += lookup[(buffer[i] << 8) | buffer[i + 1]];
23
+ }
24
+ if (i < end)
25
+ chunk += BYTE_TO_HEX[buffer[i]];
26
+ str += chunk;
27
+ }
28
+ return str;
20
29
  };
21
-
22
- export { decode, index as default, encode, isBase16 };
30
+ const encodeJS = (buffer) => {
31
+ if (!BYTE_PAIR_TO_HEX && buffer.length >= PAIR_LOOKUP_THRESHOLD) {
32
+ BYTE_PAIR_TO_HEX = Array.from({ length: 65536 }, (_, pair) => BYTE_TO_HEX[pair >> 8] + BYTE_TO_HEX[pair & 0xff]);
33
+ }
34
+ if (BYTE_PAIR_TO_HEX && buffer.length >= PAIR_LOOKUP_MIN_LENGTH) {
35
+ return encodePairsJS(buffer, BYTE_PAIR_TO_HEX);
36
+ }
37
+ let str = "";
38
+ for (let start = 0; start < buffer.length; start += 4096) {
39
+ let chunk = "";
40
+ const end = Math.min(start + 4096, buffer.length);
41
+ for (let i = start; i < end; i++) {
42
+ chunk += BYTE_TO_HEX[buffer[i]];
43
+ }
44
+ str += chunk;
45
+ }
46
+ return str;
47
+ };
48
+ const decodeJS = (string) => {
49
+ if (string.length % 2 !== 0)
50
+ throw new Error("Invalid base16 string length");
51
+ const buffer = new Uint8Array(string.length / 2);
52
+ for (let i = 0, output = 0; i < string.length; i += 2, output++) {
53
+ const a = LOOKUP[string.charCodeAt(i)];
54
+ const b = LOOKUP[string.charCodeAt(i + 1)];
55
+ if (a === undefined || b === undefined || a === 255 || b === 255)
56
+ throw new Error("Invalid base16 character");
57
+ buffer[output] = (a << 4) | b;
58
+ }
59
+ return buffer;
60
+ };
61
+ const isBase16JS = (string) => {
62
+ if (typeof string !== "string")
63
+ return false;
64
+ return string.length % 2 === 0 && !INVALID_BASE16.test(string);
65
+ };
66
+ const hasBuffer = typeof Buffer !== "undefined";
67
+ export const encode = hasBuffer
68
+ ? (buffer) => Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength).toString("hex").toUpperCase()
69
+ : encodeJS;
70
+ export const decode = hasBuffer
71
+ ? (string) => {
72
+ const buffer = Buffer.from(string, "hex");
73
+ if (buffer.length !== string.length / 2) {
74
+ if (string.length % 2 !== 0)
75
+ throw new Error("Invalid base16 string length");
76
+ throw new Error("Invalid base16 character");
77
+ }
78
+ return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
79
+ }
80
+ : decodeJS;
81
+ export const isBase16 = isBase16JS;
82
+ const index = {
83
+ encode,
84
+ decode,
85
+ isBase16,
86
+ };
87
+ export default index;
package/package.json CHANGED
@@ -1,36 +1,35 @@
1
- {
2
- "name": "@vandeurenglenn/base16",
3
- "version": "1.0.0",
4
- "description": "Base16",
5
- "keywords": [
6
- "base",
7
- "32",
8
- "base16",
9
- "bs32"
10
- ],
11
- "types": "index.d.ts",
12
- "license": "MIT",
13
- "repository": "git://github.com/vandeurenglenn/base16.git",
14
- "homepage": "https://github.com/vandeurenglenn/base16",
15
- "bugs": {
16
- "url": "https://github.com/vandeurenglenn/base16/issues"
17
- },
18
- "author": "Vanduren Glenn <vandeurenglenn@gmail.com>",
19
- "exports": {
20
- ".": "./index.js"
21
- },
22
- "type": "module",
23
- "scripts": {
24
- "build": "rollup -c",
25
- "test": "node test.js"
26
- },
27
- "dependencies": {
28
- "@vandeurenglenn/base-x": "^1.1.0"
29
- },
30
- "devDependencies": {
31
- "@rollup/plugin-typescript": "^10.0.1",
32
- "rollup": "^2.70.2",
33
- "tape": "^5.6.1",
34
- "tslib": "^2.4.1"
35
- }
36
- }
1
+ {
2
+ "name": "@vandeurenglenn/base16",
3
+ "version": "1.1.0",
4
+ "description": "Base16",
5
+ "keywords": [
6
+ "base",
7
+ "32",
8
+ "base16",
9
+ "bs32"
10
+ ],
11
+ "license": "MIT",
12
+ "repository": "git://github.com/vandeurenglenn/base16.git",
13
+ "homepage": "https://github.com/vandeurenglenn/base16",
14
+ "bugs": {
15
+ "url": "https://github.com/vandeurenglenn/base16/issues"
16
+ },
17
+ "author": "Vanduren Glenn <vandeurenglenn@gmail.com>",
18
+ "exports": {
19
+ ".": {
20
+ "import": "./index.js",
21
+ "types": "./index.d.ts"
22
+ }
23
+ },
24
+ "type": "module",
25
+ "scripts": {
26
+ "build": "npx typescript",
27
+ "test": "node test.js"
28
+ },
29
+ "dependencies": {
30
+ "typescript": "^7.0.2"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^26.6.6"
34
+ }
35
+ }
package/src/index.ts CHANGED
@@ -1,29 +1,112 @@
1
- import baseX from '@vandeurenglenn/base-x'
1
+ const ALPHABET = "0123456789ABCDEF";
2
+ const INVALID_BASE16 = /[^0-9a-f]/i;
3
+ const BYTE_TO_HEX = Array.from(
4
+ { length: 256 },
5
+ (_, byte) => ALPHABET[byte >> 4] + ALPHABET[byte & 0xf],
6
+ );
7
+ const PAIR_LOOKUP_THRESHOLD = 512 * 1024;
8
+ const PAIR_LOOKUP_MIN_LENGTH = 1024;
9
+ const LOOKUP = new Uint8Array(256).fill(255);
10
+ let BYTE_PAIR_TO_HEX: string[] | undefined;
11
+ for (let i = 0; i < 16; i++) {
12
+ const code = ALPHABET.charCodeAt(i);
13
+ LOOKUP[code] = i;
14
+ // Initialize lowercase if it's a letter (A=65, a=97, diff=32)
15
+ if (i > 9) LOOKUP[code + 32] = i;
16
+ }
2
17
 
3
- /**
4
- * A base16String only contains [0-9][a-f]
5
- */
6
- type base16String = string
18
+ const encodePairsJS = (
19
+ buffer: Uint8Array,
20
+ lookup: string[],
21
+ ): string => {
22
+ let str = "";
23
+ for (let start = 0; start < buffer.length; start += 8192) {
24
+ let chunk = "";
25
+ const end = Math.min(start + 8192, buffer.length);
26
+ let i = start;
27
+ for (; i + 1 < end; i += 2) {
28
+ chunk += lookup[(buffer[i] << 8) | buffer[i + 1]];
29
+ }
30
+ if (i < end) chunk += BYTE_TO_HEX[buffer[i]];
31
+ str += chunk;
32
+ }
33
+ return str;
34
+ };
7
35
 
8
- const ALPHABET = '0123456789abcdef'
36
+ const encodeJS = (buffer: Uint8Array): string => {
37
+ if (!BYTE_PAIR_TO_HEX && buffer.length >= PAIR_LOOKUP_THRESHOLD) {
38
+ BYTE_PAIR_TO_HEX = Array.from(
39
+ { length: 65536 },
40
+ (_, pair) => BYTE_TO_HEX[pair >> 8] + BYTE_TO_HEX[pair & 0xff],
41
+ );
42
+ }
43
+ if (BYTE_PAIR_TO_HEX && buffer.length >= PAIR_LOOKUP_MIN_LENGTH) {
44
+ return encodePairsJS(buffer, BYTE_PAIR_TO_HEX);
45
+ }
9
46
 
10
- const base32 = baseX(ALPHABET)
47
+ let str = "";
48
+ for (let start = 0; start < buffer.length; start += 4096) {
49
+ let chunk = "";
50
+ const end = Math.min(start + 4096, buffer.length);
51
+ for (let i = start; i < end; i++) {
52
+ chunk += BYTE_TO_HEX[buffer[i]];
53
+ }
54
+ str += chunk;
55
+ }
56
+ return str;
57
+ };
11
58
 
12
- export const decode = base32.decode
59
+ const decodeJS = (string: string): Uint8Array => {
60
+ if (string.length % 2 !== 0) throw new Error("Invalid base16 string length");
61
+ const buffer = new Uint8Array(string.length / 2);
62
+ for (let i = 0, output = 0; i < string.length; i += 2, output++) {
63
+ const a = LOOKUP[string.charCodeAt(i)];
64
+ const b = LOOKUP[string.charCodeAt(i + 1)];
65
+ if (a === undefined || b === undefined || a === 255 || b === 255)
66
+ throw new Error("Invalid base16 character");
67
+ buffer[output] = (a << 4) | b;
68
+ }
69
+ return buffer;
70
+ };
13
71
 
14
- export const encode = base32.encode
72
+ const isBase16JS = (string: string): boolean => {
73
+ if (typeof string !== "string") return false;
74
+ return string.length % 2 === 0 && !INVALID_BASE16.test(string);
75
+ };
15
76
 
16
- export const isBase16 = (string: base16String): boolean => {
17
- try {
18
- decode(string)
19
- return true;
20
- } catch (e) {
21
- return false;
22
- }
23
- }
77
+ const hasBuffer = typeof Buffer !== "undefined";
78
+
79
+ export const encode = hasBuffer
80
+ ? (buffer: Uint8Array): string =>
81
+ Buffer.from(
82
+ buffer.buffer,
83
+ buffer.byteOffset,
84
+ buffer.byteLength,
85
+ ).toString("hex").toUpperCase()
86
+ : encodeJS;
87
+
88
+ export const decode = hasBuffer
89
+ ? (string: string): Uint8Array => {
90
+ const buffer = Buffer.from(string, "hex");
91
+ if (buffer.length !== string.length / 2) {
92
+ if (string.length % 2 !== 0)
93
+ throw new Error("Invalid base16 string length");
94
+ throw new Error("Invalid base16 character");
95
+ }
96
+ return new Uint8Array(
97
+ buffer.buffer,
98
+ buffer.byteOffset,
99
+ buffer.byteLength,
100
+ );
101
+ }
102
+ : decodeJS;
24
103
 
25
- export default {
104
+ export const isBase16 = isBase16JS;
105
+
106
+ const index = {
26
107
  encode,
27
108
  decode,
28
- isBase16
29
- }
109
+ isBase16,
110
+ };
111
+
112
+ export default index;
package/tsconfig.json CHANGED
@@ -1,12 +1,17 @@
1
- {
2
- "compilerOptions": {
3
- "outDir": "./",
4
- "allowJs": true,
5
- "target": "es2022",
6
- "declaration": true
7
- },
8
- "include": [
9
- "./src/**/*"
10
- ],
11
- "exclude": ["./tsconfig.json"]
1
+ {
2
+ "compilerOptions": {
3
+ "target": "esnext",
4
+ "moduleResolution":"NodeNext",
5
+ "module": "nodenext",
6
+ "outDir": "./",
7
+ "rootDir": "./src",
8
+ "allowJs": true,
9
+ "declaration": true,
10
+ "types": ["node"]
11
+ },
12
+
13
+ "include": [
14
+ "./src/**/*"
15
+ ],
16
+ "exclude": ["./tsconfig.json"]
12
17
  }
package/dist/base32.js DELETED
@@ -1,35 +0,0 @@
1
- import baseX from '@vandeurenglenn/base-x';
2
-
3
- const ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
4
- const ALPHABET_HEX = '0123456789abcdefghijklmnopqrstuv';
5
- const base32 = baseX(ALPHABET);
6
- const base32Hex = baseX(ALPHABET_HEX);
7
- const decode = base32.decode;
8
- const decodeHex = base32Hex.decode;
9
- const encode = base32.encode;
10
- const encodeHex = base32Hex.encode;
11
- const isBase32 = (string, hex = false) => {
12
- try {
13
- if (hex)
14
- decodeHex(string);
15
- else
16
- decode(string);
17
- return true;
18
- }
19
- catch (e) {
20
- return false;
21
- }
22
- };
23
- const isBase32Hex = (string) => {
24
- return isBase32(string, true);
25
- };
26
- var base32$1 = {
27
- encode,
28
- decode,
29
- encodeHex,
30
- decodeHex,
31
- isBase32,
32
- isBase32Hex
33
- };
34
-
35
- export { decode, decodeHex, base32$1 as default, encode, encodeHex, isBase32, isBase32Hex };
package/rollup.config.js DELETED
@@ -1,20 +0,0 @@
1
- import typescript from '@rollup/plugin-typescript';
2
-
3
- export default [{
4
- input: ['./src/index.ts'],
5
- output: [{
6
- dir: './',
7
- format: 'es'
8
- }],
9
- external: [
10
- '@vandeurenglenn/base-x'
11
- ],
12
- plugins: [
13
- typescript({
14
- "outDir": "./",
15
- "allowJs": true,
16
- "target": "es2022",
17
- "declaration": true
18
- })
19
- ]
20
- }]