mame_parser/core/file_handling/
file_writer.rs

1use crate::{
2    core::writers::{csv_writer, json_writer, sqlite_writer},
3    helpers::file_system_helpers::{ensure_folder_exists, WORKSPACE_PATHS},
4    models::Machine,
5    progress::ProgressCallback,
6};
7use std::{
8    collections::HashMap,
9    error::Error,
10    fmt,
11    path::{Path, PathBuf},
12};
13
14/// Writes machine data to the specified export file type.
15///
16/// This function handles the export of machine data to the chosen format (`SQLite`, `JSON`, or `CSV`)
17/// by creating the necessary export folder in the workspace path and invoking the appropriate writer function.
18/// It ensures that the target directory exists, then delegates the writing task to the relevant module
19/// based on the selected `ExportFileType`. Progress updates and messages are provided via a callback function.
20///
21/// # Parameters
22/// - `export_file_type`: An `ExportFileType` enum specifying the format for data export. Supported types are:
23///   - `ExportFileType::Sqlite`: Exports data to a SQLite database file.
24///   - `ExportFileType::Json`: Exports data to a JSON file.
25///   - `ExportFileType::Csv`: Exports data to a CSV file.
26/// - `workspace_path`: A reference to a `Path` representing the base directory where the exported files will be stored.
27/// - `machines`: A reference to a `HashMap` where keys are machine names and values are `Machine` structs containing
28///   detailed information about each MAME machine.
29/// - `progress_callback`: A callback function of type `ProgressCallback` that provides status updates and progress
30///   information during the export process. The callback receives a `ProgressInfo` struct containing `progress`, `total`,
31///   `message`, and `callback_type`.
32///
33/// # Returns
34/// Returns a `Result<PathBuf, Box<dyn Error + Send + Sync>>`:
35/// - On success: Contains a `PathBuf` representing the path to the folder where the export files are stored.
36/// - On failure: Contains an error if the export folder cannot be created or if there is an issue during the writing process.
37///
38/// # Errors
39/// This function will return an error if:
40/// - The export folder cannot be created due to permission issues or file system errors.
41/// - The writing process fails for the selected export file type due to data formatting issues or I/O errors.
42///
43/// # Callback
44/// The progress callback function provides real-time updates on the export process. It receives:
45/// - `progress`: The current progress of the export operation (e.g., number of records processed).
46/// - `total`: The total number of items to be exported.
47/// - `message`: A status message indicating the current operation (e.g., "Creating export folder", "Writing to file").
48/// - `callback_type`: The type of callback, such as `CallbackType::Info`, `CallbackType::Error`, `CallbackType::Progress`, or `CallbackType::Finish`.
49///
50/// # Example Sqlite
51#[doc = docify::embed!("examples/write_sqlite.rs", main)]
52///
53/// # Example Csv
54#[doc = docify::embed!("examples/write_csv.rs", main)]
55///
56/// # Example Json
57#[doc = docify::embed!("examples/write_json.rs", main)]
58///
59pub fn write_files(
60    export_file_type: ExportFileType,
61    workspace_path: &Path,
62    machines: &HashMap<String, Machine>,
63    progress_callback: ProgressCallback,
64) -> Result<PathBuf, Box<dyn Error + Send + Sync>> {
65    let export_folder = workspace_path
66        .join(WORKSPACE_PATHS.export_path)
67        .join(export_file_type.to_string().to_lowercase());
68
69    let folder_created = ensure_folder_exists(&export_folder);
70    if let Err(err) = folder_created {
71        return Err(Box::new(err));
72    }
73
74    match export_file_type {
75        ExportFileType::Sqlite => {
76            let data_base_path = export_folder.join("machines.db");
77            sqlite_writer::write_sqlite(
78                &data_base_path.to_string_lossy(),
79                &machines,
80                progress_callback,
81            )?;
82        }
83        ExportFileType::Json => {
84            json_writer::write_json(
85                &export_folder.to_string_lossy(),
86                &machines,
87                progress_callback,
88            )?;
89        }
90        ExportFileType::Csv => {
91            csv_writer::write_csv(
92                &export_folder.to_string_lossy(),
93                &machines,
94                progress_callback,
95            )?;
96        }
97    }
98
99    Ok(export_folder)
100}
101
102/// Represents the file type to be used for data export.
103///
104/// The `ExportFileType` enum defines the different formats supported for exporting data,
105/// allowing the caller to choose between database, structured data, and tabular formats.
106/// This is particularly useful in scenarios where data needs to be shared, stored, or analyzed
107/// in various ways.
108///
109/// # Variants
110/// - `Sqlite`: Exports the data to a SQLite database file, suitable for structured storage and complex queries.
111/// - `Json`: Exports the data to a JSON (JavaScript Object Notation) file, ideal for web applications and data interchange.
112/// - `Csv`: Exports the data to a CSV (Comma-Separated Values) file, useful for spreadsheet applications and basic data analysis.
113///
114#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum ExportFileType {
116    /// Exports data to a SQLite database file.
117    Sqlite,
118    /// Exports data to a JSON file.
119    Json,
120    /// Exports data to a CSV file.
121    Csv,
122}
123
124/// Implements the `fmt::Display` trait for `ExportFileType`.
125///
126/// This allows instances of `ExportFileType` to be formatted as strings,
127/// making it easy to display or print the enum values in a user-friendly way.
128impl fmt::Display for ExportFileType {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        // Match each variant to its corresponding string representation
131        let as_str = match self {
132            ExportFileType::Sqlite => "sqlite",
133            ExportFileType::Json => "json",
134            ExportFileType::Csv => "csv",
135        };
136        // Write the string representation to the formatter
137        write!(f, "{}", as_str)
138    }
139}