realm-js/lib/browser/base64.js

92 lines
2.7 KiB
JavaScript

////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
'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;
}
}