use crate::{get_path, Arguments, FileInfo, Key, MyResult};
use jwalk::{DirEntry, Parallelism, WalkDirGeneric};
use std::{ops::RangeInclusive, path::PathBuf, process};
pub fn get_all_files(arguments: &Arguments) -> MyResult<Vec<FileInfo>> {
let path: PathBuf = get_path(arguments)?;
let min_depth: usize = arguments.min_depth.unwrap_or(0);
let max_depth: usize = arguments.max_depth.unwrap_or(std::usize::MAX);
let size_range: RangeInclusive<u64> = arguments.get_size_range();
let jwalk = WalkDirGeneric::<((), Option<FileInfo>)>::new(path)
.min_depth(min_depth)
.max_depth(max_depth)
.parallelism(Parallelism::RayonNewPool(rayon::current_num_threads()))
.skip_hidden(arguments.omit_hidden)
.process_read_dir(move |_depth, _path, _read_dir_state, dir_entry_results| {
analyze_dir_entry_results(dir_entry_results, &size_range);
});
let all_files: MyResult<Vec<FileInfo>> = jwalk
.into_iter()
.map_while(|result| match result {
Ok(dir_entry) => Some(dir_entry),
Err(why) => {
eprintln!("Error: {why}");
process::exit(1)
}
})
.filter_map(|dir_entry| dir_entry.client_state.map(Ok))
.collect();
all_files
}
type JwalkResults = Vec<Result<DirEntry<((), Option<FileInfo>)>, jwalk::Error>>;
fn analyze_dir_entry_results(
dir_entry_results: &mut JwalkResults,
size_range: &RangeInclusive<u64>,
) {
dir_entry_results
.iter_mut()
.map_while(|result| match result {
Ok(dir_entry) => Some(dir_entry),
Err(why) => {
eprintln!("Error: {why}");
process::exit(1)
}
})
.filter(|dir_entry| dir_entry.file_type().is_file())
.for_each(|dir_entry| {
if let Ok(metadata) = dir_entry.metadata() {
let size_u64: u64 = metadata.len();
if size_range.contains(&size_u64) {
let key = Key::new(size_u64, None);
let path = dir_entry.path();
dir_entry.client_state = Some(FileInfo { key, path });
} else {
dir_entry.client_state = None;
};
}
});
}