rusttauri

Storing struct in Rust backend, and making it usable in Tauri commands


I am making a Pokemon save file editor, and I've already written the backend for reading the file in Rust, and I want to use Tauri for my GUI/frontend. I have a struct PKRust::Save that stores all the relevant details of the save file, and so far in Tauri I've created a command that allows the user to select a file, and create a Save struct from it:

lib.rs:

//...
pub struct Save {
    trainer: Name,
    money: u32,
    id: i32,
    // Pokemon is its own struct
    party: Vec<Pokemon>,
    pc: Vec<Vec<Pokemon>>
}
//...

main.rs:

#[tauri::command]
async fn getSaveFile() -> String {
        
    // **TODO**: Get proper error handling on this
    let filePath = FileDialogBuilder::new()
                    .add_filter("Save",&["sav"])
                    .pick_file()
                    .unwrap()
                    ;
    
    let saveFile = PKRust::Save::load(&filePath);
    saveFile.print();
                        
    return saveFile.to_string();
}   

Now the issue arises with storing this save file. My original thought was to create a UI with editable fields, and every time the user edits details of the save file, the struct would be updated to store those changes. If the user chooses to save their file, I would call a function to write the struct into the file itself.

But the question is how to store the Save in the backend. The plan after testing this functionality in getSaveFile() was to make saveFile a global variable, stored in main and accessible to the command, but I had trouble doing that, even trying to use a tauri::State, with no success:

#[tauri::command]
async fn getSaveFile(saveState: State<'_, PKRust::Save>) -> String {
        
    // **TODO**: Get proper error handling on this
    let filePath = FileDialogBuilder::new()
                    .add_filter("Save",&["sav"])
                    .pick_file()
                    .unwrap()
                    ;
    
    saveState = PKRust::Save::load(&filePath);
    saveState.print();
                        
    return saveState.to_string();
}

fn main() {
    tauri::Builder::default()
        .manage(PKRust::Save::new())
        .invoke_handler(tauri::generate_handler![greet,test,getSaveFile])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}   

Making the Save a static variable does not work either, so I'm left confused on what to do. Is there any way to have this struct accessible to all Tauri functions? I would prefer not to pass the save data between front and backend.


Solution

  • I wrote about this topic before here and here

    You want to use Mutex

    use std::sync::Mutex;
    use tauri::State;
    
    struct Save {
        save: Mutex<String>,
    }
    

    And then inside the command you can get a mutable version of a state:

    fn update_save(new_save: String, state: State<Save>) {
            let mut save = state.save.lock().unwrap();
            *save = new_save;
    

    If you'd want to run your commands in async, you'll need to use a slightly different mutex configuration (with Arc).