0

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(&current_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(&current_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!

6
  • 1
    You seem to be implying that your code doesn’t work when the file size is over 2.8G, but you have not said what problem/error you are experiencing.
    – James
    Commented Jul 1 at 10:33
  • Ah sorry if that wasn't clear. In the working code section, I have a thing that just outputs number of bytes that the file is, but what I want to achieve is to be able to work with that file in a similar way to the one opened with File::open in process_emails() (second code block). Perhaps I should edit the post to better reflect that? Commented Jul 1 at 10:45
  • 1
    This is quite a problem, since std's files are synchronous but on the web everything must be async. Commented Jul 1 at 17:10
  • Perhaps I should write some kind of wrapper? Commented Jul 1 at 20:45
  • 1
    You have a function which requires a File. You can get this from File::open or by passing the File 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. Commented Jul 2 at 15:44

0