Function unpack_files

Source
pub fn unpack_files(
    workspace_path: &Path,
    progress_callback: SharedProgressCallback,
) -> Vec<JoinHandle<Result<PathBuf, Box<dyn Error + Send + Sync>>>>
Expand description

Unpacks multiple data files concurrently for all MameDataType variants into a designated workspace folder.

This function spawns a new thread for each data type to unpack its respective file, allowing for concurrent unpacking operations. Progress for each unpacking operation is reported via a provided shared callback function. The function returns a list of thread handles, each of which can be used to join and retrieve the result of the unpacking operation.

§Parameters

  • workspace_path: A reference to a Path representing the base directory where the data files will be unpacked.
  • progress_callback: A shared callback function of type SharedProgressCallback that tracks the progress of each file unpacking operation. The callback receives the data_type and a ProgressInfo struct containing progress, total, message, and callback_type.

§Returns

Returns a Vec<thread::JoinHandle<Result<PathBuf, Box<dyn Error + Send + Sync>>>>:

  • Each handle represents a thread responsible for unpacking a specific file. The result of the unpacking can be accessed by joining the thread handle.
  • On success: Each thread handle contains the path where the unpacked file is located.
  • On failure: Each thread handle contains an error if the unpacking fails or if there are issues accessing or creating the destination folder.

§Errors

This function does not directly return errors, but errors may be encountered and reported through the thread handles. The following errors might occur during the unpacking process:

  • The destination folder cannot be created.
  • The required ZIP file is not found in the download folder.
  • The unpacking process fails due to reading or writing errors.

§Callback

The shared progress callback function can be used to monitor the unpacking process of each file in real-time. It receives:

  • data_type: An enum value of MameDataType, indicating the type of data being unpacked.
  • progress: The number of entries processed so far.
  • total: The total entries of the file being unpacked (if available).
  • message: A status message indicating the current operation (e.g., “Unpacking file”, “Checking if file already unpacked”).
  • callback_type: The type of callback, typically CallbackType::Progress for ongoing updates, CallbackType::Info for informational messages, CallbackType::Finish for completion, or CallbackType::Error for errors.

§Example

fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
    // Define the workspace path
    let workspace_path = Path::new("playground");

    // Create a multi progress bar
    let multi_progress = MultiProgress::new();

    // Create progress bars for each data type
    let progress_bars = Arc::new(
        MameDataType::all_variants()
            .iter()
            .map(|&data_type| {
                let progress_bar = multi_progress.add(ProgressBar::new(100));
                progress_bar.set_style(
                    ProgressStyle::default_bar()
                        .template(&format!("{{spinner:.green}} [{{elapsed_precise}}] [{{bar:20.cyan/blue}}] {{pos}}/{{len}} ({{eta}}) {{msg}}"))
                        .progress_chars("#>-"),
                );
                (data_type, progress_bar)
            })
            .collect::<Vec<_>>(),
    );

    let shared_progress_callback: SharedProgressCallback = Arc::new(
        move |data_type: MameDataType, progress_info: ProgressInfo| {
            if let Some((_, progress_bar)) = progress_bars.iter().find(|(dt, _)| *dt == data_type) {
                // Update the progress bar
                match progress_info.callback_type {
                    CallbackType::Progress => {
                        progress_bar.set_length(progress_info.total);
                        progress_bar.set_position(progress_info.progress);
                    }
                    CallbackType::Info => {
                        progress_bar.set_message(progress_info.message);
                    }
                    CallbackType::Finish => {
                        progress_bar.set_length(progress_info.total);
                        progress_bar.set_position(progress_info.progress);
                        progress_bar.finish_with_message(progress_info.message);
                    }
                    CallbackType::Error => {
                        progress_bar.finish_with_message(progress_info.message);
                    }
                }
            }
        },
    );

    // Unpack the files
    let handles = unpack_files(workspace_path, shared_progress_callback);

    // Wait for all threads to finish
    multi_progress.join().unwrap();

    // Print the result
    for handle in handles {
        match handle.join().unwrap() {
            Ok(path) => {
                println!("Unpacked data file: {}", path.display());
            }
            Err(e) => {
                eprintln!("Error during unpacking: {}", e);
            }
        }
    }

    Ok(())
}