#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileStats {
pub path: String,
pub size_bytes: u64,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SplitPlanAdvice {
pub task_groups: Vec<Vec<String>>,
}
pub struct SmallFilePlanner {
target_bytes: u64,
}
impl SmallFilePlanner {
pub fn new(target_bytes: u64) -> Self {
Self { target_bytes }
}
pub fn plan(&self, files: &[FileStats]) -> SplitPlanAdvice {
if files.is_empty() {
return SplitPlanAdvice {
task_groups: Vec::new(),
};
}
let mut groups: Vec<Vec<String>> = Vec::new();
let mut current: Vec<String> = Vec::new();
let mut current_bytes = 0u128;
let target_bytes = u128::from(self.target_bytes);
for file in files {
let file_bytes = u128::from(file.size_bytes);
if !current.is_empty() && current_bytes + file_bytes > target_bytes {
groups.push(std::mem::take(&mut current));
current_bytes = 0;
}
current.push(file.path.clone());
current_bytes += file_bytes;
}
if !current.is_empty() {
groups.push(current);
}
SplitPlanAdvice {
task_groups: groups,
}
}
}