serde_hkx_features/verify/
dir.rs

1use super::verify_inner;
2use crate::error::{FailedReproduceFilesSnafu, Result};
3use crate::progress::ProgressHandler;
4use rayon::prelude::*;
5use std::path::{Path, PathBuf};
6
7/// Parallel checks reproduction for hkx files.
8///
9/// # Errors
10/// If an error occurs, returns an array of error paths.
11pub fn verify_dir<D, P>(dir: D, progress: P) -> Result<()>
12where
13    D: AsRef<Path>,
14    P: ProgressHandler + Send + Sync,
15{
16    let dir = dir.as_ref();
17    verify_dir_(dir, progress)
18}
19
20fn filter_hkx_files(dir: &Path) -> Vec<PathBuf> {
21    jwalk::WalkDir::new(dir)
22        .into_iter()
23        .filter_map(|entry| entry.ok())
24        .filter(|entry| {
25            entry
26                .path()
27                .extension()
28                .is_some_and(|ext| ext.eq_ignore_ascii_case("hkx"))
29        })
30        .map(|entry| entry.path())
31        .collect()
32}
33
34fn verify_dir_<P>(dir: &Path, mut progress: P) -> Result<()>
35where
36    P: ProgressHandler + Sync + Send,
37{
38    let filtered_entries = filter_hkx_files(dir);
39    let total_files = filtered_entries.len();
40
41    if total_files == 0 {
42        progress.on_empty();
43        return Ok(());
44    }
45
46    progress.on_set_total(total_files);
47
48    let results: Vec<_> = filtered_entries
49        .into_par_iter()
50        .map(|path| {
51            let result = verify_inner(&path);
52
53            let is_valid = if let Ok((expected_bytes, actual_bytes)) = &result {
54                expected_bytes == actual_bytes
55            } else {
56                false
57            };
58
59            if is_valid {
60                progress.success_inc(1);
61                #[cfg(feature = "tracing")]
62                tracing::info!("Passed Reproduction: {}", path.display());
63            } else {
64                progress.failure_inc(1);
65            }
66
67            progress.inc(1);
68            progress.on_processing_path(path.as_path());
69
70            (path, is_valid)
71        })
72        .collect();
73
74    progress.on_finish();
75
76    let err_paths: Vec<PathBuf> = results
77        .into_par_iter()
78        .filter_map(|(path, is_valid)| if !is_valid { Some(path) } else { None })
79        .collect();
80
81    if err_paths.is_empty() {
82        Ok(())
83    } else {
84        FailedReproduceFilesSnafu {
85            path: dir.to_path_buf(),
86            total_files,
87            err_paths,
88        }
89        .fail()
90    }
91}