-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbrowser.js
69 lines (69 loc) · 2.44 KB
/
browser.js
1
2
3
4
5
6
7
8
9
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
const HEX_STRINGS = "0123456789abcdefABCDEF";
const HEX_CODES = HEX_STRINGS.split("").map((c) => c.codePointAt(0));
const HEX_CODEPOINTS = Array(256)
.fill(true)
.map((_, i) => {
const s = String.fromCodePoint(i);
const index = HEX_STRINGS.indexOf(s);
// ABCDEF will use 10 - 15
return index < 0 ? undefined : index < 16 ? index : index - 6;
});
const ENCODER = new TextEncoder();
const DECODER = new TextDecoder();
export function toUtf8(bytes) {
return DECODER.decode(bytes);
}
// There are two implementations.
// One optimizes for length of the bytes, and uses TextDecoder.
// One optimizes for iteration count, and appends strings.
// This removes the overhead of TextDecoder.
export function toHex(bytes) {
const b = bytes || new Uint8Array();
return b.length > 512 ? _toHexLengthPerf(b) : _toHexIterPerf(b);
}
function _toHexIterPerf(bytes) {
let s = "";
for (let i = 0; i < bytes.length; ++i) {
s += HEX_STRINGS[HEX_CODEPOINTS[HEX_CODES[bytes[i] >> 4]]];
s += HEX_STRINGS[HEX_CODEPOINTS[HEX_CODES[bytes[i] & 15]]];
}
return s;
}
function _toHexLengthPerf(bytes) {
const hexBytes = new Uint8Array(bytes.length * 2);
for (let i = 0; i < bytes.length; ++i) {
hexBytes[i * 2] = HEX_CODES[bytes[i] >> 4];
hexBytes[i * 2 + 1] = HEX_CODES[bytes[i] & 15];
}
return DECODER.decode(hexBytes);
}
export function fromUtf8(utf8String) {
return ENCODER.encode(utf8String);
}
// Mimics Buffer.from(x, 'hex') logic
// Stops on first non-hex string and returns
// https://github.com/nodejs/node/blob/v14.18.1/src/string_bytes.cc#L246-L261
export function fromHex(hexString) {
const hexBytes = ENCODER.encode(hexString || "");
const resultBytes = new Uint8Array(Math.floor(hexBytes.length / 2));
let i;
for (i = 0; i < resultBytes.length; i++) {
const a = HEX_CODEPOINTS[hexBytes[i * 2]];
const b = HEX_CODEPOINTS[hexBytes[i * 2 + 1]];
if (a === undefined || b === undefined) {
break;
}
resultBytes[i] = (a << 4) | b;
}
return i === resultBytes.length ? resultBytes : resultBytes.slice(0, i);
}
// Same behavior as Buffer.compare()
export function compare(v1, v2) {
const minLength = Math.min(v1.length, v2.length);
for (let i = 0; i < minLength; ++i) {
if (v1[i] !== v2[i]) {
return v1[i] < v2[i] ? -1 : 1;
}
}
return v1.length === v2.length ? 0 : v1.length > v2.length ? 1 : -1;
}