use std::path::Path;
pub fn process_files_batch<P, F, R>(paths: &[P], processor: F) -> Vec<R>
where
P: AsRef<Path> + Sync,
F: Fn(&Path) -> R + Sync + Send,
R: Send,
{
#[cfg(feature = "parallel")]
{
use rayon::prelude::*;
paths.par_iter().map(|p| processor(p.as_ref())).collect()
}
#[cfg(not(feature = "parallel"))]
{
paths.iter().map(|p| processor(p.as_ref())).collect()
}
}
pub fn process_batch<T, F, R>(items: &[T], processor: F) -> Vec<R>
where
T: Sync,
F: Fn(&T) -> R + Sync + Send,
R: Send,
{
#[cfg(feature = "parallel")]
{
use rayon::prelude::*;
items.par_iter().map(processor).collect()
}
#[cfg(not(feature = "parallel"))]
{
items.iter().map(|item| processor(item)).collect()
}
}
pub fn try_process_files_batch<P, F, R, E>(paths: &[P], processor: F) -> Vec<Result<R, E>>
where
P: AsRef<Path> + Sync,
F: Fn(&Path) -> Result<R, E> + Sync + Send,
R: Send,
E: Send,
{
#[cfg(feature = "parallel")]
{
use rayon::prelude::*;
paths.par_iter().map(|p| processor(p.as_ref())).collect()
}
#[cfg(not(feature = "parallel"))]
{
paths.iter().map(|p| processor(p.as_ref())).collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_process_batch_simple() {
let numbers = vec![1, 2, 3, 4, 5];
let results = process_batch(&numbers, |n| n * 2);
assert_eq!(results, vec![2, 4, 6, 8, 10]);
}
#[test]
fn test_process_files_batch() {
let paths = vec![
PathBuf::from("file1.txt"),
PathBuf::from("file2.txt"),
PathBuf::from("file3.txt"),
];
let results = process_files_batch(&paths, |path| {
path.file_name()
.and_then(|s| s.to_str())
.unwrap_or("unknown")
.to_string()
});
assert_eq!(results, vec!["file1.txt", "file2.txt", "file3.txt"]);
}
#[test]
fn test_try_process_files_batch_with_errors() {
let paths = vec![
PathBuf::from("good1.txt"),
PathBuf::from("bad.txt"),
PathBuf::from("good2.txt"),
];
let results = try_process_files_batch(&paths, |path| {
let name = path
.file_name()
.and_then(|s| s.to_str())
.ok_or("invalid path")?;
if name.starts_with("bad") {
Err("processing failed")
} else {
Ok(name.to_string())
}
});
assert!(results[0].is_ok());
assert!(results[1].is_err());
assert!(results[2].is_ok());
}
#[cfg(feature = "parallel")]
#[test]
fn test_parallel_feature_enabled() {
let items: Vec<i32> = (0..100).collect();
let results = process_batch(&items, |n| n * n);
assert_eq!(results.len(), 100);
assert_eq!(results[10], 100);
}
}