A bit of background:
I would like to avoid using stdweb
, because it seems to be unmaintained.
use web_sys::{File as WebFile};
// What I get
pub fn process_emails(file: WebFile, json_file_path: &str, json_headers_file_path: &str) {
// ...
}
// What I would like to work with
let file = File::open(mbox_file_path).expect("Failed to open mbox file");
I would like to be able to work with the received file (WebFile) as if I am working with a file opened from the file system. I know that the types are very different, but is there a way to 'convert' them?
For context, here's what I do with the file (the full function from above). Imports and referenced variables excluded:
pub fn process_emails(mbox_file_path: &str, json_file_path: &str, json_headers_file_path: &str) {
let file = File::open(mbox_file_path).expect("Failed to open mbox file");
let reader = BufReader::new(file);
let mut emails = Vec::new();
let mut email_headers = Vec::new();
let mut current_email = Vec::new();
let mut id_counter = 0;
for line in reader.lines() {
let line = line.expect("Failed to read line");
if line.starts_with("From ") && !current_email.is_empty() {
extract_and_process_email(¤t_email, &mut emails, &mut email_headers, id_counter);
current_email.clear();
id_counter += 1;
}
current_email.push(line);
}
if !current_email.is_empty() {
extract_and_process_email(¤t_email, &mut emails, &mut email_headers, id_counter);
}
write_to_json(json_file_path, &emails).expect("Failed to write JSON file");
write_to_json(json_headers_file_path, &email_headers).expect("Failed to write JSON file");
println!("Conversion complete. JSON data saved to {} and {}", json_file_path, json_headers_file_path);
}
I'm pretty new to rust and web assembly, so I'm sorry if this is a stupid question! Any help would be greatly appreciated!
Current Working Code
// vite.config.ts
import {defineConfig} from 'vite'
import react from '@vitejs/plugin-react-swc'
import wasm from "vite-plugin-wasm";
import topLevelAwait from "vite-plugin-top-level-await";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
wasm(),
topLevelAwait()
],
build: {
target: 'esnext',
},
optimizeDeps: {
esbuildOptions: {
target: 'esnext',
},
},
})
// src/App.tsx
import './App.css'
import * as wasm from '../pkg';
import {useState} from "react";
function App() {
const [result, setResult] = useState('');
const handleFileChange = (e) => {
const files = e.target.files;
if (files.length === 0) return;
const file = files[0];
const result = wasm.read_file(file);
setResult(result);
};
return (
<div className="App">
<h1>hi</h1>
<input type="file" onChange={handleFileChange}/>
{result && <div>Result: {result}</div>}
</div>
);
}
export default App;
// rust used
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{File};
#[wasm_bindgen]
pub fn read_file(file: File) -> String {
let blob_result = file.slice();
let len = match blob_result {
Ok(blob) => blob.size() as f64,
Err(_) => 0.0,
};
let result = format!("Processed {} bytes", len);
result
}
There is no issue (that I can see) with the way the webassembly is used in react, because the code above works fine, even with a 2.8gb file. I'm happy to provide further details and more code if needed. Thanks for your help!
File::open
inprocess_emails()
(second code block). Perhaps I should edit the post to better reflect that?File
. You can get this fromFile::open
or by passing theFile
parameter directly to the function via wasm from JS. What does the size of the file have to do with this? What does stdweb have to do with this? Either File or Blob are iterable so just iterate over those, I'm not sure if Read is implemented for those types but if not I guess you have to do so yourself.