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!