From 970f83813264c7258242a60d7217f312baf87ec3 Mon Sep 17 00:00:00 2001 From: Will Scullin Date: Sat, 5 Aug 2023 19:08:59 -0700 Subject: [PATCH] Convert base64 to Typescript --- js/base64.js | 110 -------------------------------- js/base64.ts | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++ js/types.ts | 2 + 3 files changed, 174 insertions(+), 110 deletions(-) delete mode 100644 js/base64.js create mode 100644 js/base64.ts diff --git a/js/base64.js b/js/base64.js deleted file mode 100644 index f40cf2e..0000000 --- a/js/base64.js +++ /dev/null @@ -1,110 +0,0 @@ -export function base64_encode (data) { - // Twacked by Will Scullin to handle arrays of "bytes" - - // http://kevin.vanzonneveld.net - // + original by: Tyler Akins (http://rumkin.com) - // + improved by: Bayron Guevara - // + improved by: Thunder.m - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + bugfixed by: Pellentesque Malesuada - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // - depends on: utf8_encode - // * example 1: base64_encode('Kevin van Zonneveld'); - // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' - - // mozilla has this native - // - but breaks in 2.0.0.12! - //if (typeof this.window['atob'] == 'function') { - // return atob(data); - //} - - var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc='', tmp_arr = []; - - if (!data) { - return data; - } - - do { // pack three octets into four hexets - o1 = data[i++]; - o2 = data[i++]; - o3 = data[i++]; - - bits = o1<<16 | o2<<8 | o3; - - h1 = bits>>18 & 0x3f; - h2 = bits>>12 & 0x3f; - h3 = bits>>6 & 0x3f; - h4 = bits & 0x3f; - - // use hexets to index into b64, and append result to encoded string - tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); - } while (i < data.length); - - enc = tmp_arr.join(''); - - switch (data.length % 3) { - case 1: - enc = enc.slice(0, -2) + '=='; - break; - case 2: - enc = enc.slice(0, -1) + '='; - break; - } - - return enc; -} - -export function base64_decode(data) { - // Twacked by Will Scullin to handle arrays of "bytes" - - // http://kevin.vanzonneveld.net - // + original by: Tyler Akins (http://rumkin.com) - // + improved by: Thunder.m - // + input by: Aman Gupta - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + bugfixed by: Onno Marsman - // + bugfixed by: Pellentesque Malesuada - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + input by: Brett Zamir (http://brett-zamir.me) - // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // - depends on: utf8_decode - // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); - // * returns 1: 'Kevin van Zonneveld' - - // mozilla has this native - // - but breaks in 2.0.0.12! - //if (typeof this.window['btoa'] == 'function') { - // return btoa(data); - //} - - var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, tmp_arr = []; - - if (!data) { - return data; - } - - do { // unpack four hexets into three octets using index points in b64 - h1 = b64.indexOf(data.charAt(i++)); - h2 = b64.indexOf(data.charAt(i++)); - h3 = b64.indexOf(data.charAt(i++)); - h4 = b64.indexOf(data.charAt(i++)); - - bits = h1<<18 | h2<<12 | h3<<6 | h4; - - o1 = bits>>16 & 0xff; - o2 = bits>>8 & 0xff; - o3 = bits & 0xff; - - tmp_arr[ac++] = o1; - if (h3 != 64) { - tmp_arr[ac++] = o2; - } - if (h4 != 64) { - tmp_arr[ac++] = o3; - } - } while (i < data.length); - - return tmp_arr; -} diff --git a/js/base64.ts b/js/base64.ts new file mode 100644 index 0000000..80ef9d2 --- /dev/null +++ b/js/base64.ts @@ -0,0 +1,172 @@ +import { memory } from "./types"; + +const B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +/** Encode an array of bytes in base64. */ +export function base64_encode(data: null | undefined): undefined; +export function base64_encode(data: memory): string; +export function base64_encode( + data: memory | null | undefined +): string | undefined { + // Twacked by Will Scullin to handle arrays of 'bytes' + + // http://kevin.vanzonneveld.net + // + original by: Tyler Akins (http://rumkin.com) + // + improved by: Bayron Guevara + // + improved by: Thunder.m + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Pellentesque Malesuada + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // - depends on: utf8_encode + // * example 1: base64_encode('Kevin van Zonneveld'); + // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' + + // mozilla has this native + // - but breaks in 2.0.0.12! + //if (typeof this.window['atob'] == 'function') { + // return atob(data); + //} + + let o1, + o2, + o3, + h1, + h2, + h3, + h4, + bits, + i = 0, + ac = 0, + enc = ""; + const tmp_arr = []; + + if (!data) { + return undefined; + } + + do { + // pack three octets into four hexets + o1 = data[i++]; + o2 = data[i++]; + o3 = data[i++]; + + bits = (o1 << 16) | (o2 << 8) | o3; + + h1 = (bits >> 18) & 0x3f; + h2 = (bits >> 12) & 0x3f; + h3 = (bits >> 6) & 0x3f; + h4 = bits & 0x3f; + + // use hexets to index into b64, and append result to encoded string + tmp_arr[ac++] = + B64.charAt(h1) + B64.charAt(h2) + B64.charAt(h3) + B64.charAt(h4); + } while (i < data.length); + + enc = tmp_arr.join(""); + + switch (data.length % 3) { + case 1: + enc = enc.slice(0, -2) + "=="; + break; + case 2: + enc = enc.slice(0, -1) + "="; + break; + } + + return enc; +} + +/** Returns undefined if the input is null or undefined. */ +export function base64_decode(data: null | undefined): undefined; +/** Returns an array of bytes from the given base64-encoded string. */ +export function base64_decode(data: string): memory; +/** Returns an array of bytes from the given base64-encoded string. */ +export function base64_decode( + data: string | null | undefined +): memory | undefined { + // Twacked by Will Scullin to handle arrays of 'bytes' + + // http://kevin.vanzonneveld.net + // + original by: Tyler Akins (http://rumkin.com) + // + improved by: Thunder.m + // + input by: Aman Gupta + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Onno Marsman + // + bugfixed by: Pellentesque Malesuada + // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + input by: Brett Zamir (http://brett-zamir.me) + // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // - depends on: utf8_decode + // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); + // * returns 1: 'Kevin van Zonneveld' + + // mozilla has this native + // - but breaks in 2.0.0.12! + //if (typeof this.window['btoa'] == 'function') { + // return btoa(data); + //} + + let o1, + o2, + o3, + h1, + h2, + h3, + h4, + bits, + i = 0, + ac = 0; + const tmp_arr = []; + + if (!data) { + return undefined; + } + + do { + // unpack four hexets into three octets using index points in B64 + h1 = B64.indexOf(data.charAt(i++)); + h2 = B64.indexOf(data.charAt(i++)); + h3 = B64.indexOf(data.charAt(i++)); + h4 = B64.indexOf(data.charAt(i++)); + + bits = (h1 << 18) | (h2 << 12) | (h3 << 6) | h4; + + o1 = (bits >> 16) & 0xff; + o2 = (bits >> 8) & 0xff; + o3 = bits & 0xff; + + tmp_arr[ac++] = o1; + if (h3 !== 64) { + tmp_arr[ac++] = o2; + } + if (h4 !== 64) { + tmp_arr[ac++] = o3; + } + } while (i < data.length); + + return new Uint8Array(tmp_arr); +} + +const DATA_URL_PREFIX = "data:application/octet-stream;base64,"; + +export function base64_json_parse(json: string): unknown { + const reviver = (_key: string, value: unknown) => { + if (typeof value === "string" && value.startsWith(DATA_URL_PREFIX)) { + return base64_decode(value.slice(DATA_URL_PREFIX.length)); + } + return value; + }; + + return JSON.parse(json, reviver); +} + +export function base64_json_stringify(json: unknown) { + const replacer = (_key: string, value: unknown) => { + if (value instanceof Uint8Array) { + return DATA_URL_PREFIX + base64_encode(value); + } + return value; + }; + + return JSON.stringify(json, replacer); +} diff --git a/js/types.ts b/js/types.ts index 91b2795..96e0bc9 100644 --- a/js/types.ts +++ b/js/types.ts @@ -14,3 +14,5 @@ export type byte = number; export type word = number; export type address = word; + +export type memory = Uint8Array | byte[];