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}