mirror of
https://github.com/status-im/realm-js.git
synced 2025-01-12 15:24:18 +00:00
7b115a934b
Previously we were not accounting for the byte offsets and misunderstood how the Uint8Array constructor worked. The tests now confirm everything works as expected with multiple different typed arrays and slices of the data.
78 lines
2.0 KiB
JavaScript
78 lines
2.0 KiB
JavaScript
/* Copyright 2015 Realm Inc - All Rights Reserved
|
|
* Proprietary and Confidential
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
const CHAR_MAP = {};
|
|
|
|
Array.from(CHARS, (char, i) => CHAR_MAP[char] = i);
|
|
|
|
module.exports = {
|
|
decode,
|
|
encode,
|
|
};
|
|
|
|
function decode(base64) {
|
|
let length = base64.length;
|
|
let byteCount = length * 0.75;
|
|
|
|
if (base64[length - 1] === '=') {
|
|
byteCount--;
|
|
if (base64[length - 2] === '=') {
|
|
byteCount--;
|
|
}
|
|
}
|
|
|
|
let buffer = new ArrayBuffer(byteCount);
|
|
let bytes = new Uint8Array(buffer);
|
|
|
|
for (let i = 0, j = 0; i < length; i += 4) {
|
|
let index1 = CHAR_MAP[base64[i]];
|
|
let index2 = CHAR_MAP[base64[i + 1]];
|
|
let index3 = CHAR_MAP[base64[i + 2]];
|
|
let index4 = CHAR_MAP[base64[i + 3]];
|
|
|
|
bytes[j++] = (index1 << 2) + ((index2 & 0x30) >> 4);
|
|
bytes[j++] = ((index2 & 0x0f) << 4) + ((index3 & 0x3c) >> 2);
|
|
bytes[j++] = ((index3 & 0x03) << 6) + index4;
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
|
|
function encode(data) {
|
|
var byteOffset = 0;
|
|
var buffer;
|
|
|
|
if (data instanceof ArrayBuffer) {
|
|
buffer = data;
|
|
} else if (ArrayBuffer.isView(data)) {
|
|
buffer = data.buffer;
|
|
byteOffset = data.byteOffset;
|
|
} else {
|
|
throw new TypeError('Can only base64 encode ArrayBuffer and ArrayBufferView objects');
|
|
}
|
|
|
|
let byteCount = data.byteLength;
|
|
let bytes = new Uint8Array(buffer, byteOffset, byteCount);
|
|
let base64 = '';
|
|
|
|
for (let i = 0; i < byteCount; i += 3) {
|
|
base64 += CHARS[(bytes[i] & 0xfc) >> 2];
|
|
base64 += CHARS[((bytes[i] & 0x03) << 4) + ((bytes[i + 1] & 0xf0) >> 4)];
|
|
base64 += CHARS[((bytes[i + 1] & 0x0f) << 2) + ((bytes[i + 2] & 0xc0) >> 6)];
|
|
base64 += CHARS[bytes[i + 2] & 0x3f];
|
|
}
|
|
|
|
switch (byteCount % 3) {
|
|
case 1:
|
|
return base64.slice(0, -2) + '==';
|
|
case 2:
|
|
return base64.slice(0, -1) + '=';
|
|
default:
|
|
return base64;
|
|
}
|
|
}
|