serde_hkx_features/convert/
tokio.rs1use super::{OutFormat, get_output_path, get_supported_files, process_serde};
3use crate::{
4 error::Result,
5 fs::{ReadExt as _, write},
6 progress::{DefaultProgressMonitor, ProgressHandler},
7};
8use std::{
9 io::{self},
10 path::{Path, PathBuf},
11};
12
13pub async fn convert<I, O>(input: I, output: Option<O>, format: OutFormat) -> Result<()>
21where
22 I: AsRef<Path>,
23 O: AsRef<Path>,
24{
25 convert_progress(input, output, format, DefaultProgressMonitor).await
26}
27
28pub async fn convert_progress<I, O, P>(
36 input: I,
37 output: Option<O>,
38 format: OutFormat,
39 progress: P,
40) -> Result<()>
41where
42 I: AsRef<Path>,
43 O: AsRef<Path>,
44 P: ProgressHandler + Send + Clone + 'static,
45{
46 let input = input.as_ref();
47 if input.is_dir() {
48 convert_dir(input, output, format, progress).await?;
49 } else if input.is_file() {
50 convert_file(input, output, format).await?;
51 } else {
52 return Err(io::Error::new(
53 io::ErrorKind::NotFound,
54 format!("The path does not exist: {}", input.display()),
55 ))?;
56 }
57
58 Ok(())
59}
60
61pub async fn convert_dir<I, O, P>(
69 input_dir: I,
70 output_dir: Option<O>,
71 format: OutFormat,
72 mut progress: P,
73) -> Result<()>
74where
75 I: AsRef<Path>,
76 O: AsRef<Path>,
77 P: ProgressHandler + Send + Clone + 'static,
78{
79 let mut task_handles: Vec<tokio::task::JoinHandle<Result<()>>> = Vec::new();
80
81 let input_dir = input_dir.as_ref();
82 let files: Vec<PathBuf> = get_supported_files(input_dir);
83
84 if files.is_empty() {
85 progress.on_empty();
86 return Ok(());
87 }
88
89 progress.on_set_total(files.len());
90
91 for input in files {
92 progress.on_processing_path(&input);
94
95 let output = get_output_path(input_dir, &input, &output_dir, format);
97
98 let progress = progress.clone();
99 task_handles.push(tokio::spawn(async move {
100 match convert_file(&input, output, format).await {
101 Ok(_) => {
102 progress.success_inc(1);
103 Ok(())
104 }
105 Err(err) => {
106 progress.failure_inc(1);
107 #[cfg(feature = "tracing")]
108 tracing::error!("Failed to convert: {}", input.display());
109 Err(err)
110 }
111 }?;
112 progress.inc(1);
113 Result::Ok(())
114 }));
115 }
116
117 for task_handle in task_handles {
118 task_handle.await??;
119 }
120
121 progress.on_finish();
122 Ok(())
123}
124
125pub async fn convert_file<I, O>(input: I, output: Option<O>, format: OutFormat) -> Result<()>
133where
134 I: AsRef<Path>,
135 O: AsRef<Path>,
136{
137 let input = input.as_ref();
138 let in_bytes = input.read_bytes().await?;
139 let out_bytes = process_serde(&in_bytes, input, format)?;
140
141 Ok(write(input, output, format.as_extension(), out_bytes).await?)
142}