Function read_files

Source
pub fn read_files(
    workspace_path: &Path,
    progress_callback: SharedProgressCallback,
) -> Result<HashMap<String, Machine>, Box<dyn Error + Send + Sync>>
Expand description

Reads and processes all MAME data files available for the specified workspace path.

This function manages the concurrent reading of multiple MAME data files. For each MameDataType, it spawns a separate thread to handle the file reading process. The function waits for all threads to complete and then combines the results into a single HashMap of machine details. Progress updates and messages are provided via a shared callback function.

§Parameters

  • workspace_path: A reference to a Path representing the base directory where all data files are located.
  • progress_callback: A shared callback function of type SharedProgressCallback that tracks progress and provides status updates. The callback receives a ProgressInfo struct containing progress, total, message, and callback_type.

§Returns

Returns a Result<HashMap<String, Machine>, Box<dyn Error + Send + Sync>>:

  • On success: Contains a HashMap where the keys are machine names and the values are Machine structs representing detailed information about each MAME machine.
  • On failure: Contains an error if any data file cannot be read, or if there are issues joining the threads.

§Errors

This function will return an error if:

  • Any thread fails to complete successfully or panics.
  • There are issues reading any data file due to permission problems, file corruption, or missing files.
  • There are errors during the merging of machine data, such as data inconsistencies.

§Concurrency

This function uses multiple threads to read MAME data files concurrently. Each thread handles the reading of a specific data type file (MameDataType). The function waits for all threads to complete using join(), and any errors encountered are captured and logged. The shared progress callback is used to provide real-time updates across all threads.

§Callback

The shared progress callback function provides real-time updates on the reading process for each data type and other status information. It receives:

  • progress: The current progress of the operation for a specific data type (e.g., number of files processed).
  • total: The total number of items to be processed (if available).
  • message: A status message indicating the current operation (e.g., “Reading file”, “Processing data”).
  • callback_type: The type of callback, such as CallbackType::Info, CallbackType::Error, CallbackType::Progress, or CallbackType::Finish.

§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: Arc<MultiProgress> = Arc::new(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<_>>(),
    );

    // Create a shared progress callback
    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);
                    }
                }
            }
        },
    );

    let handle = thread::spawn(move || {
        multi_progress.join().unwrap();
    });

    // Read the files
    let machines = read_files(workspace_path, shared_progress_callback);

    handle.join().unwrap();

    // Print the result
    match machines {
        Ok(machines) => {
            println!("Machines loaded: {}", machines.len());
        }
        Err(e) => {
            eprintln!("Error reading data files: {}", e);
        }
    }

    Ok(())
}