UNPKG

2.64 kBJavaScriptView Raw
1const encode = bytes => {
2 var base64 = ''
3 var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
4
5 var byteLength = bytes.byteLength
6 var byteRemainder = byteLength % 3
7 var mainLength = byteLength - byteRemainder
8
9 var a, b, c, d
10 var chunk
11
12 // Main loop deals with bytes in chunks of 3
13 for (var i = 0; i < mainLength; i = i + 3) {
14 // Combine the three bytes into a single integer
15 chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
16
17 // Use bitmasks to extract 6-bit segments from the triplet
18 a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
19 b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
20 c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
21 d = chunk & 63 // 63 = 2^6 - 1
22
23 // Convert the raw binary segments to the appropriate ASCII encoding
24 base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
25 }
26
27 // Deal with the remaining bytes and padding
28 if (byteRemainder == 1) {
29 chunk = bytes[mainLength]
30
31 a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
32
33 // Set the 4 least significant bits to zero
34 b = (chunk & 3) << 4 // 3 = 2^2 - 1
35
36 base64 += encodings[a] + encodings[b] + '=='
37 } else if (byteRemainder == 2) {
38 chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
39
40 a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
41 b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
42
43 // Set the 2 least significant bits to zero
44 c = (chunk & 15) << 2 // 15 = 2^4 - 1
45
46 base64 += encodings[a] + encodings[b] + encodings[c] + '='
47 }
48
49 return base64
50};
51const decode = sB64Enc => {
52 function _b64ToUint6(nChr) {
53 return nChr > 64 && nChr < 91 ?
54 nChr - 65
55 : nChr > 96 && nChr < 123 ?
56 nChr - 71
57 : nChr > 47 && nChr < 58 ?
58 nChr + 4
59 : nChr === 43 ?
60 62
61 : nChr === 47 ?
62 63
63 :
64 0;
65 }
66
67 const nInLen = sB64Enc.length;
68 const nOutLen = ((nInLen * 3) >> 2) - +(sB64Enc[sB64Enc.length - 1] === '=') - +(sB64Enc[sB64Enc.length - 2] === '=');
69 const taBytes = new Uint8Array(nOutLen);
70
71 for (let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
72 nMod4 = nInIdx & 3;
73 nUint24 |= _b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
74 if (nMod4 === 3 || nInLen - nInIdx === 1) {
75 for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
76 taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
77 }
78 nUint24 = 0;
79 }
80 }
81
82 return taBytes;
83};
84
85module.exports = {
86 encode,
87 decode,
88};