Created
May 7, 2021 10:16
-
-
Save TransparentLC/dbd3b72dc0cdbe10539d4a58dbdeb38a to your computer and use it in GitHub Desktop.
Base85 编码和解码
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~'; | |
const charsetReverse = charset | |
.split('') | |
.reduce((acc, cur, idx) => { | |
acc[cur] = idx; | |
return acc; | |
}, {}); | |
/** | |
* @param {Uint8Array} data | |
* @returns {String} | |
*/ | |
const base85Encode = data => { | |
const paddingLength = 4 - (data.length % 4 || 4); | |
const paddedData = new Uint8Array(data.length + paddingLength); | |
paddedData.set(data); | |
let result = ''; | |
for (let i = 0; i < paddedData.length; i += 4) { | |
let group4 = 0; | |
for (let j = 0; j < 4; j++) { | |
group4 |= paddedData[i + j] << ((3 - j) << 3); | |
group4 >>>= 0; | |
} | |
let part85 = ''; | |
for (let j = 0; j < 5; j++) { | |
let k = group4 % 85; | |
group4 = (group4 - k) / 85; | |
part85 = charset[k] + part85; | |
} | |
result += part85; | |
} | |
return result.substr(0, result.length - paddingLength); | |
}; | |
/** | |
* @param {String} data | |
* @returns {Uint8Array} | |
*/ | |
const base85Decode = data => { | |
const paddingLength = 5 - (data.length % 5 || 5); | |
data += '~'.repeat(paddingLength); | |
const result = new Uint8Array(data.length / 5 * 4 - paddingLength); | |
for (let i = 0, j = 0; i < data.length; i += 5, j += 4) { | |
let group5 = 0; | |
let base = 52200625; // 85 ** 4 | |
for (let k = 0; k < 5; k++) { | |
group5 += base * charsetReverse[data[i + k]]; | |
base /= 85; | |
} | |
for (let k = 0; k < 4; k++) { | |
result[j + k] = group5 >> ((3 - k) << 3); | |
} | |
} | |
return result; | |
}; | |
for (let i = 0; i < 256; i++) { | |
const a = new Uint8Array(Math.random() * 262144); | |
for (let j = 0; j < a.length; j++) { | |
a[j] = Math.random() * 256; | |
} | |
const b = base85Decode(base85Encode(a)); | |
if (a.length !== b.length) throw new Error('test failed'); | |
for (let j = 0; j < a.length; j++) { | |
if (a[j] !== b[j]) throw new Error('test failed'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment