diff --git a/frontend/js/worker.js b/frontend/js/worker.js index 317b1d8..99f7a58 100644 --- a/frontend/js/worker.js +++ b/frontend/js/worker.js @@ -7,12 +7,10 @@ onmessage = async function(e) { let result = []; let res; for (let file of files) { - // for communication with exported function 'get_file' - self.readFile = file; console.debug(file) try { - res = JSON.parse(wasm.run_json_exported("application/x-gzip" == file.type || "application/gzip" == file.type)); + res = JSON.parse(wasm.run_json_exported(file)); // the server depends on the 'name' field to be present res['name'] = file['name']; // retrieve the sample name result.push(res); diff --git a/frontend/src/extract_comp.rs b/frontend/src/extract_comp.rs index 1ea57e9..ce90b75 100644 --- a/frontend/src/extract_comp.rs +++ b/frontend/src/extract_comp.rs @@ -6,9 +6,9 @@ use crate::{io_utils::get_reader, utils::set_panic_hook}; // Entry points here #[wasm_bindgen] -pub fn run_json_exported(compressed: bool) -> String { +pub fn run_json_exported(f: web_sys::File) -> String { set_panic_hook(); - let fastq_reader = FASTQReader::new(SampleArgs::default(), get_reader(compressed)); + let fastq_reader = FASTQReader::new(SampleArgs::default(), get_reader(f.into())); run_json(fastq_reader) } diff --git a/frontend/src/lib.rs b/frontend/src/lib.rs index 0d116ed..ca3aaf1 100644 --- a/frontend/src/lib.rs +++ b/frontend/src/lib.rs @@ -16,43 +16,60 @@ pub mod io_utils { use wasm_bindgen::prelude::*; use web_sys::FileReaderSync; - #[wasm_bindgen(module = "/js/exports.js")] - extern "C" { - pub fn get_file() -> web_sys::File; - } - #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] pub fn debug(msg: &str); + + #[cfg(debug_assertions)] + // get js time + #[wasm_bindgen(js_namespace = Date, js_name = now)] + pub fn now() -> f64; } - use std::io::{self, BufRead, Read}; + use std::io::{self, BufReader, Read}; - // Credit to: mstange on GitHub - // See: https://github.com/rustwasm/wasm-bindgen/issues/1079#issuecomment-508577627 #[derive(Debug)] - pub struct WasmMemBuffer { + pub struct JSFileReader { pos: u64, + file_reader: FileReaderSync, file: File, + + #[cfg(debug_assertions)] + thresh: u64, + #[cfg(debug_assertions)] + time_start: f64, } #[allow(clippy::new_without_default)] - impl WasmMemBuffer { - pub fn new() -> WasmMemBuffer { - WasmMemBuffer { - file: File::from(unsafe { get_file() }), + impl JSFileReader { + pub fn new(f: File) -> JSFileReader { + JSFileReader { pos: 0, + file_reader: FileReaderSync::new().unwrap(), + file: f, + #[cfg(debug_assertions)] + time_start: now(), + #[cfg(debug_assertions)] + thresh: 0, } } } - impl Read for WasmMemBuffer { + impl Read for JSFileReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { - let fr = FileReaderSync::new().unwrap(); let sl = self.file.slice(self.pos, self.pos + buf.len() as u64); - let arr = Uint8Array::new(unsafe { &fr.read_as_array_buffer(sl.as_ref()).unwrap() }); + let arr = Uint8Array::new(&self.file_reader.read_as_array_buffer(sl.as_ref()).unwrap()); let len = std::cmp::min(buf.len(), arr.length() as usize); + #[cfg(debug_assertions)] { + self.thresh += len as u64; + if self.thresh > 100_000_000 { + let new_time = now(); + debug(format!("Read {} bytes, {} elapsed", self.thresh, new_time - self.time_start).as_str()); + self.thresh = 0; + } + } + arr.slice(0, len as u32).copy_to(&mut buf[..len]); self.pos += len as u64; @@ -62,9 +79,12 @@ pub mod io_utils { // Reader is a wrapper over BufRead // And provides an interface over the actual reading. - pub fn get_reader(compressed: bool) -> Box { + pub fn get_reader(file: File) -> BufReader> { + let typ = file.raw_mime_type(); + let compressed = typ == "application/gzip" || typ == "application/x-gzip"; + fastq2comp::io_utils::compressed_reader( - Box::new(WasmMemBuffer::new()) as Box, + Box::new(JSFileReader::new(file)) as Box, compressed, ) }