UNPKG

as-base64

Version:

Base64 encoder / decoder for AssemblyScript.

257 lines (238 loc) 4.64 kB
// adapted from https://gist.github.com/Juszczak/63e6d9e01decc850de03 /** * base64 encoding/decoding */ // @ts-ignore: decorator @lazy const PADCHAR = "="; // @ts-ignore: decorator @lazy const ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // @ts-ignore: decorator @lazy const ALPHAVALUES = StaticArray.fromArray<u8>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, ]); /** * Decode a base64-encoded string and return a Uint8Array. * @param s Base64 encoded string. */ export function decode(s: string): Uint8Array { let i: u32, b10: u32; let pads = 0, imax = s.length as u32; if (imax == 0) { return new Uint8Array(0); } if (s.charAt(imax - 1) == PADCHAR) { pads = 1; if (s.charAt(imax - 2) == PADCHAR) { pads = 2; } imax -= 4; } let main_chunk = imax % 4 == 0 ? (imax / 4) * 3 : (imax / 4 + 1) * 3; let pad_size = pads > 0 ? 3 - pads : 0; let size = main_chunk + pad_size; let x = new Uint8Array(size), index = 0; for (i = 0; i < imax; i += 4) { b10 = (getByte64(s, i) << 18) | (getByte64(s, i + 1) << 12) | (getByte64(s, i + 2) << 6) | getByte64(s, i + 3); x[index++] = b10 >> 16; x[index++] = (b10 >> 8) & 255; x[index++] = b10 & 255; } switch (pads) { case 1: b10 = (getByte64(s, i) << 18) | (getByte64(s, i + 1) << 12) | (getByte64(s, i + 2) << 6); x[index++] = b10 >> 16; x[index++] = (b10 >> 8) & 255; break; case 2: b10 = (getByte64(s, i) << 18) | (getByte64(s, i + 1) << 12); x[index++] = b10 >> 16; break; } return x; } /** * Encode Uint8Array as a base64 string. * @param bytes Byte array of type Uint8Array. */ export function encode(bytes: Uint8Array): string { let i: i32, b10: u32; const extrabytes = (bytes.length % 3); let imax = bytes.length - extrabytes; const len = ((bytes.length / 3) as i32) * 4 + (extrabytes == 0 ? 0 : 4); let x = changetype<string>(__new(<usize>(len << 1), idof<string>())); if (bytes.length == 0) { return ""; } let ptr = changetype<usize>(x) - 2; for (i = 0; i < imax; i += 3) { b10 = ((bytes[i] as u32) << 16) | ((bytes[i + 1] as u32) << 8) | (bytes[i + 2] as u32); store<u16>(ptr+=2, (ALPHA.charCodeAt(b10 >> 18) as u16)); store<u16>(ptr+=2, (ALPHA.charCodeAt(((b10 >> 12) & 63)) as u16)); store<u16>(ptr+=2, (ALPHA.charCodeAt(((b10 >> 6) & 63)) as u16)); store<u16>(ptr+=2, (ALPHA.charCodeAt((b10 & 63)) as u16)); } switch (bytes.length - imax) { case 1: b10 = (bytes[i] as u32) << 16; store<u16>(ptr+=2, ((ALPHA.charCodeAt(b10 >> 18)) as u16)); store<u16>(ptr+=2, ((ALPHA.charCodeAt((b10 >> 12) & 63)) as u16)); store<u16>(ptr+=2, ((PADCHAR.charCodeAt(0)) as u16)); store<u16>(ptr+=2, ((PADCHAR.charCodeAt(0)) as u16)); break; case 2: b10 = ((bytes[i] as u32) << 16) | ((bytes[i + 1] as u32) << 8); store<u16>(ptr+=2, ((ALPHA.charCodeAt(b10 >> 18)) as u16)); store<u16>(ptr+=2, ((ALPHA.charCodeAt((b10 >> 12) & 63)) as u16)); store<u16>(ptr+=2, ((ALPHA.charCodeAt((b10 >> 6) & 63)) as u16)); store<u16>(ptr+=2, ((PADCHAR.charCodeAt(0)) as u16)); break; } return x; } // @ts-ignore: decorator @inline function getByte64(s: string, i: u32): u32 { return ALPHAVALUES[s.charCodeAt(i)]; }