pub fn write_files(
export_file_type: ExportFileType,
workspace_path: &Path,
machines: &HashMap<String, Machine>,
progress_callback: ProgressCallback,
) -> Result<PathBuf, Box<dyn Error + Send + Sync>>
Expand description
Writes machine data to the specified export file type.
This function handles the export of machine data to the chosen format (SQLite
, JSON
, or CSV
)
by creating the necessary export folder in the workspace path and invoking the appropriate writer function.
It ensures that the target directory exists, then delegates the writing task to the relevant module
based on the selected ExportFileType
. Progress updates and messages are provided via a callback function.
§Parameters
export_file_type
: AnExportFileType
enum specifying the format for data export. Supported types are:ExportFileType::Sqlite
: Exports data to a SQLite database file.ExportFileType::Json
: Exports data to a JSON file.ExportFileType::Csv
: Exports data to a CSV file.
workspace_path
: A reference to aPath
representing the base directory where the exported files will be stored.machines
: A reference to aHashMap
where keys are machine names and values areMachine
structs containing detailed information about each MAME machine.progress_callback
: A callback function of typeProgressCallback
that provides status updates and progress information during the export process. The callback receives aProgressInfo
struct containingprogress
,total
,message
, andcallback_type
.
§Returns
Returns a Result<PathBuf, Box<dyn Error + Send + Sync>>
:
- On success: Contains a
PathBuf
representing the path to the folder where the export files are stored. - On failure: Contains an error if the export folder cannot be created or if there is an issue during the writing process.
§Errors
This function will return an error if:
- The export folder cannot be created due to permission issues or file system errors.
- The writing process fails for the selected export file type due to data formatting issues or I/O errors.
§Callback
The progress callback function provides real-time updates on the export process. It receives:
progress
: The current progress of the export operation (e.g., number of records processed).total
: The total number of items to be exported.message
: A status message indicating the current operation (e.g., “Creating export folder”, “Writing to file”).callback_type
: The type of callback, such asCallbackType::Info
,CallbackType::Error
,CallbackType::Progress
, orCallbackType::Finish
.
§Example Sqlite
ⓘ
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) => {
let progress_bar = ProgressBar::new(100);
progress_bar.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{elapsed_precise}] [{bar:20.cyan/blue}] {pos}/{len} ({eta}) {msg}")
.progress_chars("#>-"),
);
// Create a progress callback
let progress_callback: ProgressCallback =
Box::new(move |progress_info: ProgressInfo| {
// 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);
}
}
});
// Write the machines to a SQLite database
let result = write_files(
ExportFileType::Sqlite,
workspace_path,
&machines,
progress_callback,
);
match result {
Ok(result) => {
println!("Machines written to {}.", result.to_string_lossy());
}
Err(e) => {
eprintln!("Error writing data files: {}", e);
}
}
}
Err(e) => {
eprintln!("Error reading data files: {}", e);
}
}
Ok(())
}
§Example Csv
ⓘ
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) => {
let progress_bar = ProgressBar::new(100);
progress_bar.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{elapsed_precise}] [{bar:20.cyan/blue}] {pos}/{len} ({eta}) {msg}")
.progress_chars("#>-"),
);
// Create a progress callback
let progress_callback: ProgressCallback =
Box::new(move |progress_info: ProgressInfo| {
// 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);
}
}
});
// Write the machines to CSV files
let result = write_files(
ExportFileType::Csv,
workspace_path,
&machines,
progress_callback,
);
match result {
Ok(result) => {
println!("Machines written to {}.", result.to_string_lossy());
}
Err(e) => {
eprintln!("Error writing data files: {}", e);
}
}
}
Err(e) => {
eprintln!("Error reading data files: {}", e);
}
}
Ok(())
}
§Example Json
ⓘ
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) => {
let progress_bar = ProgressBar::new(100);
progress_bar.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{elapsed_precise}] [{bar:20.cyan/blue}] {pos}/{len} ({eta}) {msg}")
.progress_chars("#>-"),
);
// Create a progress callback
let progress_callback: ProgressCallback =
Box::new(move |progress_info: ProgressInfo| {
// 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);
}
}
});
// Write the machines to Json files
let result = write_files(
ExportFileType::Json,
workspace_path,
&machines,
progress_callback,
);
match result {
Ok(result) => {
println!("Machines written to {}.", result.to_string_lossy());
}
Err(e) => {
eprintln!("Error writing data files: {}", e);
}
}
}
Err(e) => {
eprintln!("Error reading data files: {}", e);
}
}
Ok(())
}