@bitblit/asyncglk
Version:
A Typescript Glk library
62 lines (58 loc) • 1.99 kB
JavaScript
/*
Common file processing functions
================================
Copyright (c) 2024 Dannii Willis
MIT licenced
https://github.com/curiousdannii/asyncglk
*/
/** Parse Base 64 into a Uint8Array */
export async function parse_base64(data) {
// Firefox has a data URL limit of 32MB, so we have to chunk large data
const chunk_length = 30_000_000;
if (data.length < chunk_length) {
return parse_base64_with_data_url(data);
}
const chunks = [];
let i = 0;
while (i < data.length) {
chunks.push(await parse_base64_with_data_url(data.substring(i, i += chunk_length)));
}
const blob = new Blob(chunks);
return new Uint8Array(await blob.arrayBuffer());
}
async function parse_base64_with_data_url(data) {
// Parse base64 using a trick from https://stackoverflow.com/a/54123275/2854284
const response = await fetch(`data:application/octet-stream;base64,${data}`);
if (!response.ok) {
throw new Error(`Could not parse base64: ${response.status}`);
}
return new Uint8Array(await response.arrayBuffer());
}
/** Read a response, with optional progress notifications */
export async function read_response(response, progress_callback) {
if (!response.ok) {
throw new Error(`Could not fetch ${response.url}, got ${response.status}`);
}
if (!progress_callback) {
return new Uint8Array(await response.arrayBuffer());
}
// Read the response, calling the callback with each chunk
const chunks = [];
let length = 0;
const reader = response.body.getReader();
for (;;) {
const { done, value } = await reader.read();
if (done) {
break;
}
chunks.push([length, value]);
progress_callback(value.length);
length += value.length;
}
// Join the chunks together
const result = new Uint8Array(length);
for (const [offset, chunk] of chunks) {
result.set(chunk, offset);
}
return result;
}