base64-encoding
Version:
Fast Base64 encoding and decoding powered by WebAssembly.
135 lines (117 loc) • 3.31 kB
text/typescript
import { jsImpl, WASMImpl } from './base64.js';
interface Impl {
encode(bs: BufferSource, url: boolean): string;
decode(str: string): Uint8Array;
}
class Base64Provider {
impl: Impl;
constructor() {
if (typeof Uint8Array === 'undefined' || typeof DataView === 'undefined') {
throw Error(
'Platform unsupported. Make sure Uint8Array and DataView exist.'
);
}
this.impl = jsImpl;
}
async init() {
if (typeof WebAssembly !== 'undefined') {
try {
this.impl = await new WASMImpl().init();
} catch (err) {
throw new Error('WASM instantiation failed: ' + err.message);
}
} else {
throw new Error('WebAssembly missing in global scope.');
}
}
encode(input: BufferSource, url: boolean): string {
return this.impl.encode(input, url);
}
decode(input: string): Uint8Array {
return this.impl.decode(input);
}
}
export interface Base64EncoderOptions {
/**
* Whether this encoder is set to encode data as URL-friendly Base64.
*
* URL-friendly here means that `+` maps to `-`, `/` maps to `_`, and
* the padding characters `=` are is omitted,
* while the rest of the alphabet is shared.
*/
url?: boolean;
/** @deprecated Use `url` instead. */
urlFriendly?: boolean;
}
/**
* Base64 encoder class to encode binary data in Base64 strings,
* similar to `TextEncoder`.
*/
export class Base64Encoder {
#provider: Base64Provider = new Base64Provider();
#urlFriendly: boolean;
/**
* Whether this encoder is set to encode data as URL-friendly Base64.
*/
get url() {
return this.#urlFriendly;
};
/**
* @deprecated Use `url` instead.
*/
get urlFriendly() {
return this.url;
};
/**
* Creates a new encoder object with underlying WebAssembly instance.
*
* Note that the WASM instance might grow its internal memory to fit large
* array buffers.
*/
constructor(options: Base64EncoderOptions = {}) {
const { url, urlFriendly } = options;
this.#urlFriendly = url ?? urlFriendly ?? false;
}
/**
* Optimize this encoder to use the faster WASM implementation.
* @returns This encoder after WASM initialization has completed.
*/
async optimize() {
await this.#provider.init();
return this;
}
/**
* Encodes an array buffer into a Base64 string.
*
* @param input Binary data to be Base64 encoded
* @returns The provided array buffer encoded as a Base64 string
*/
encode(input: BufferSource): string {
return this.#provider.encode(input, this.url);
}
}
/**
* Base64 Decoder class to convert Base64 strings into array buffers,
* similar to `TextDecoder`.
*/
export class Base64Decoder {
#provider = new Base64Provider();
/**
* Optimize this decoder to use the faster WASM implementation.
* @returns This decoder after WASM initialization has completed.
*/
async optimize() {
await this.#provider.init();
return this;
}
/**
* Decodes a Base64 string and returns a new array buffer.
*
* @param input A Base64 string. Can be either URL friendly or not and
* padding may be omitted.
* @returns The binary data as an array buffer.
*/
decode(input: string): Uint8Array {
return this.#provider.decode(input);
}
}