@vandeurenglenn/base16 1.0.1 → 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 +21 -21
- package/index.d.ts +12 -13
- package/index.js +86 -21
- package/package.json +35 -36
- package/src/index.ts +103 -20
- package/tsconfig.json +16 -12
- package/rollup.config.js +0 -20
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare const decode:
|
|
6
|
-
export declare const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
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
|
|
4
|
-
"description": "Base16",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"base",
|
|
7
|
-
"32",
|
|
8
|
-
"base16",
|
|
9
|
-
"bs32"
|
|
10
|
-
],
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
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,13 +1,17 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
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"]
|
|
13
17
|
}
|
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
|
-
}]
|